diff --git a/cmake/linux/FindOracle.cmake b/cmake/linux/FindOracle.cmake index d6074ead..73cc9329 100644 --- a/cmake/linux/FindOracle.cmake +++ b/cmake/linux/FindOracle.cmake @@ -37,10 +37,11 @@ if(DEFINED ENV{ORACLE_HOME}) ${ORACLE_HOME}/OCI/include) # Oracle XE on Windows set(ORACLE_OCI_NAMES clntsh libclntsh oci) - set(ORACLE_NNZ_NAMES libnnz18 nnz18 libnnz21 nnz21 ociw32) + set(ORACLE_NNZ_NAMES libnnz18 nnz18 libnnz19 nnz19 libnnz21 nnz21 ociw32) set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11) set(ORACLE_LIB_DIR + ${ORACLE_HOME} ${ORACLE_HOME}/lib ${ORACLE_HOME}/sdk/lib # Oracle SDK ${ORACLE_HOME}/sdk/lib/msvc @@ -76,4 +77,4 @@ endif(DEFINED ENV{ORACLE_HOME}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Oracle DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR) -mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) \ No newline at end of file +mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY) diff --git a/engine/server/library/serverScript/src/shared/JavaLibrary.cpp b/engine/server/library/serverScript/src/shared/JavaLibrary.cpp index f5f415b7..ecfedd95 100755 --- a/engine/server/library/serverScript/src/shared/JavaLibrary.cpp +++ b/engine/server/library/serverScript/src/shared/JavaLibrary.cpp @@ -781,16 +781,26 @@ void JavaLibrary::fatalHandler(int signum) { // try to see if our call stack came from C or Java void *frameAddress = __builtin_frame_address(0); - // the address that generated the segfault is stored at an offset of 0x44 from - // the frame address - // @todo: find documentation on the offset to verify it is stable - void *crashAddress1 = *((void**)((static_cast(frameAddress)) + 0x44)); + // pass the crash address to addr2line to get the file name where the crash occurred + // These are zero initialized because the strstr() checks below read them + // whenever a lookup fails. static const int BUFLEN = 2048; - char lib1[BUFLEN], lib2[BUFLEN]; - char file1[BUFLEN], file2[BUFLEN]; - int line1, line2; - bool result1 = DebugHelp::lookupAddress(reinterpret_cast(crashAddress1), lib1, file1, BUFLEN, line1); + char lib1[BUFLEN] = { '\0' }, lib2[BUFLEN] = { '\0' }; + char file1[BUFLEN] = { '\0' }, file2[BUFLEN] = { '\0' }; + int line1 = 0, line2 = 0; + bool result1 = false; + + // The faulting address used to be read from a fixed 0x44 byte offset into + // this frame. That constant describes the 32-bit x86 frame layout only; on + // x86-64 it is both misaligned and meaningless, and dereferencing it from + // inside a SIGSEGV handler risks a recursive fault that loses the crash + // report entirely. The __builtin_return_address() probe below is portable + // and already covers this case. +#if defined(__i386__) + void *crashAddress1 = *((void**)((static_cast(frameAddress)) + 0x44)); + result1 = DebugHelp::lookupAddress(reinterpret_cast(crashAddress1), lib1, file1, BUFLEN, line1); +#endif // do a second test based on the return address // it turns out that in some java crashes we don't even have 2 return diff --git a/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp b/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp index e7a2fb7b..0f84b864 100755 --- a/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp +++ b/engine/shared/library/sharedDebug/src/linux/DebugHelp.cpp @@ -682,11 +682,30 @@ bool DebugHelp::lookupAddress(uint64 address, char *libName, char *fileName, int // ---------------------------------------------------------------------- -void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack) +void DebugHelp::getCallStack(uint64 *callStack, int sizeOfCallStack) { + //-- backtrace() writes sizeOfCallStack void* entries. Handing it the + // caller's buffer directly only works when sizeof(void*) happens to + // equal the element size; under LP64 it wrote 8 bytes per entry into a + // 4-byte-per-entry array and overran the buffer by 2x. Capture into a + // native pointer array and widen instead, which is correct for both + // ILP32 and LP64. + enum { cs_maximumFrameCount = 256 }; + + if (sizeOfCallStack <= 0) + return; + for (int i = 0; i < sizeOfCallStack; ++i) callStack[i] = 0; - IGNORE_RETURN(backtrace(reinterpret_cast(callStack), sizeOfCallStack)); + + if (sizeOfCallStack > static_cast(cs_maximumFrameCount)) + sizeOfCallStack = static_cast(cs_maximumFrameCount); + + void *frames[cs_maximumFrameCount]; + int const frameCount = backtrace(frames, sizeOfCallStack); + + for (int i = 0; i < frameCount; ++i) + callStack[i] = reinterpret_cast(frames[i]); } // ====================================================================== diff --git a/engine/shared/library/sharedDebug/src/linux/DebugHelp.h b/engine/shared/library/sharedDebug/src/linux/DebugHelp.h index e297f8eb..973c07be 100755 --- a/engine/shared/library/sharedDebug/src/linux/DebugHelp.h +++ b/engine/shared/library/sharedDebug/src/linux/DebugHelp.h @@ -19,7 +19,10 @@ public: static void install(); static void remove(); - static void getCallStack(uint32 *callStack, int sizeOfCallStack); + //-- Entries are instruction addresses, so the buffer must be pointer-width + // capable. uint64 matches lookupAddress() below and is wide enough on + // both ILP32 and LP64. + static void getCallStack(uint64 *callStack, int sizeOfCallStack); static bool lookupAddress(uint64 address, char *libName, char *fileName, int fileNameLength, int &line); }; diff --git a/engine/shared/library/sharedDebug/src/shared/CallStack.cpp b/engine/shared/library/sharedDebug/src/shared/CallStack.cpp index 1df90532..2acb5ab9 100755 --- a/engine/shared/library/sharedDebug/src/shared/CallStack.cpp +++ b/engine/shared/library/sharedDebug/src/shared/CallStack.cpp @@ -59,9 +59,9 @@ void CallStack::debugPrint() const for (size_t i = 2; i < CALLSTACK_DEPTH; ++i) { if (DebugHelp::lookupAddress(m_callStack[i], libName, fileName, sizeof(fileName), line)) - DEBUG_REPORT_PRINT(true, (" (0x%08X) %s(%d) : caller %d\n", static_cast(m_callStack[i]), fileName, line, i - 1)); + DEBUG_REPORT_PRINT(true, (" (0x%016llX) %s(%d) : caller %d\n", static_cast(m_callStack[i]), fileName, line, i - 1)); else - DEBUG_REPORT_PRINT(true, (" unknown(0x%08X) : caller %d\n", static_cast(m_callStack[i]), i - 1)); + DEBUG_REPORT_PRINT(true, (" unknown(0x%016llX) : caller %d\n", static_cast(m_callStack[i]), i - 1)); } } @@ -76,9 +76,9 @@ void CallStack::debugLog() const for (size_t i = 2; i < CALLSTACK_DEPTH && m_callStack[i]!=0; ++i) { if (DebugHelp::lookupAddress(m_callStack[i], libName, fileName, sizeof(fileName), line)) - DEBUG_REPORT_LOG(true, (" (0x%08X) %s(%d) : caller %d\n", static_cast(m_callStack[i]), fileName, line, i - 1)); + DEBUG_REPORT_LOG(true, (" (0x%016llX) %s(%d) : caller %d\n", static_cast(m_callStack[i]), fileName, line, i - 1)); else - DEBUG_REPORT_LOG(true, (" unknown(0x%08X) : caller %d\n", static_cast(m_callStack[i]), i - 1)); + DEBUG_REPORT_LOG(true, (" unknown(0x%016llX) : caller %d\n", static_cast(m_callStack[i]), i - 1)); } } diff --git a/engine/shared/library/sharedDebug/src/shared/CallStack.h b/engine/shared/library/sharedDebug/src/shared/CallStack.h index 376f0ed3..120791d0 100755 --- a/engine/shared/library/sharedDebug/src/shared/CallStack.h +++ b/engine/shared/library/sharedDebug/src/shared/CallStack.h @@ -40,7 +40,8 @@ private: private: - uint32 m_callStack[S_callStack]; + //-- Instruction addresses; must be pointer-width capable (see DebugHelp::getCallStack). + uint64 m_callStack[S_callStack]; }; // ====================================================================== diff --git a/engine/shared/library/sharedDebug/src/shared/CallStackCollector.cpp b/engine/shared/library/sharedDebug/src/shared/CallStackCollector.cpp index 9e91cbb4..8162421a 100755 --- a/engine/shared/library/sharedDebug/src/shared/CallStackCollector.cpp +++ b/engine/shared/library/sharedDebug/src/shared/CallStackCollector.cpp @@ -49,7 +49,7 @@ namespace CallStackCollectorNamespace ~Node(); CrcString const & getName() const; - void addCallStack(uint32 * callStack); + void addCallStack(uint64 * callStack); void debugReport() const; @@ -63,7 +63,7 @@ namespace CallStackCollectorNamespace public: - uint32 * m_callStack; + uint64 * m_callStack; int m_calls; }; @@ -125,10 +125,10 @@ CrcString const & CallStackCollectorNamespace::Node::getName() const // ---------------------------------------------------------------------- -void CallStackCollectorNamespace::Node::addCallStack(uint32 * const callStack) +void CallStackCollectorNamespace::Node::addCallStack(uint64 * const callStack) { //-- Compute crc of memory - uint32 const crc = Crc::calculate(callStack, (sizeof(uint32) * CALLSTACK_DEPTH)); + uint32 const crc = Crc::calculate(callStack, (sizeof(*callStack) * CALLSTACK_DEPTH)); //-- Find callstack in list CallStackEntryMap::iterator iter = m_callStackEntryMap.find(crc); @@ -140,8 +140,8 @@ void CallStackCollectorNamespace::Node::addCallStack(uint32 * const callStack) else { //-- Create new callstack - uint32 * const newCallStack = new uint32[CALLSTACK_DEPTH]; - memcpy(newCallStack, callStack, sizeof(*newCallStack)); + uint64 * const newCallStack = new uint64[CALLSTACK_DEPTH]; + memcpy(newCallStack, callStack, sizeof(*newCallStack) * CALLSTACK_DEPTH); CallStackEntry callStackEntry; callStackEntry.m_callStack = newCallStack; @@ -180,7 +180,7 @@ void CallStackCollectorNamespace::Node::debugReport() const if (DebugHelp::lookupAddress(callStackEntry->m_callStack[j], libName, fileName, sizeof(fileName), line)) REPORT_LOG(true, (" %s(%d) : caller %d\n", fileName, line, j - 1)); else - REPORT_LOG(true, (" unknown(0x%08X) : caller %d\n", static_cast(callStackEntry->m_callStack[j]), j - 1)); + REPORT_LOG(true, (" unknown(0x%016llX) : caller %d\n", static_cast(callStackEntry->m_callStack[j]), j - 1)); } } } @@ -218,7 +218,7 @@ void CallStackCollector::sample(char const * const name) } //-- Sample the callstack - uint32 callStack[CALLSTACK_DEPTH]; + uint64 callStack[CALLSTACK_DEPTH]; DebugHelp::getCallStack(&callStack[0], CALLSTACK_DEPTH); //-- Add to the node diff --git a/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp b/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp index b80a6a45..a138d781 100755 --- a/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp +++ b/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp @@ -481,7 +481,7 @@ bool DebugHelp::loadSymbolsForDll(const char *name) // ---------------------------------------------------------------------- #pragma warning (disable: 4740 4748) -void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack) +void DebugHelp::getCallStack(uint64 *callStack, int sizeOfCallStack) { { for (int i = 0; i < sizeOfCallStack; ++i) @@ -525,7 +525,7 @@ void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack) if (stackWalk64(IMAGE_FILE_MACHINE_I386, process, process, &stackFrame, &context, NULL, functionTableAccess, getModuleBase, NULL)) { const DWORD64 Offset = stackFrame.AddrPC.Offset; - *callStack = DWORD(Offset); + *callStack = static_cast(Offset); } } } @@ -537,7 +537,7 @@ void DebugHelp::reportCallStack(int const maxStackDepth) // look up the call stack information int const callStackOffset = 2; int const callStackSize = callStackOffset + maxStackDepth; - uint32 * callStack = static_cast(_alloca((callStackOffset + maxStackDepth) * sizeof(uint32))); + uint64 * callStack = static_cast(_alloca((callStackOffset + maxStackDepth) * sizeof(uint64))); getCallStack(callStack, callStackOffset + maxStackDepth); // look up the caller's file and line @@ -553,7 +553,7 @@ void DebugHelp::reportCallStack(int const maxStackDepth) if (lookupAddress(callStack[i], lib, file, sizeof(file), line)) REPORT_LOG(true, ("\t%s(%d) : caller %d\n", file, line, i-callStackOffset)); else - REPORT_LOG(true, ("\tunknown(0x%08X) : caller %d\n", static_cast(callStack[i]), i-callStackOffset)); + REPORT_LOG(true, ("\tunknown(0x%016llX) : caller %d\n", static_cast(callStack[i]), i-callStackOffset)); } } } @@ -561,7 +561,7 @@ void DebugHelp::reportCallStack(int const maxStackDepth) // ---------------------------------------------------------------------- -bool DebugHelp::lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line) +bool DebugHelp::lookupAddress(uint64 address, char *libName, char *fileName, int fileNameLength, int &line) { UNREF(libName); diff --git a/engine/shared/library/sharedDebug/src/win32/DebugHelp.h b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h index 74e379ab..bb7483bb 100755 --- a/engine/shared/library/sharedDebug/src/win32/DebugHelp.h +++ b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h @@ -23,9 +23,9 @@ public: static bool loadSymbolsForDll(const char *name); - static void getCallStack(uint32 *callStack, int sizeOfCallStack); + static void getCallStack(uint64 *callStack, int sizeOfCallStack); static void reportCallStack(int const maxStackDepth = 4); - static bool lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line); + static bool lookupAddress(uint64 address, char *libName, char *fileName, int fileNameLength, int &line); static bool writeMiniDump(char const *miniDumpFileName=0, PEXCEPTION_POINTERS exceptionPointers=0); }; diff --git a/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.cpp b/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.cpp index 7937a2a7..9577df85 100755 --- a/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.cpp +++ b/engine/shared/library/sharedFoundation/src/linux/PlatformGlue.cpp @@ -27,10 +27,23 @@ char* _itoa(int value, char* stringOut, int radix) bool QueryPerformanceCounter(__int64* time) { - struct timeval tv; - gettimeofday(&tv, nullptr); - *time = static_cast(tv.tv_sec); - *time = (*time * 1000000) + static_cast(tv.tv_usec); + // Must be monotonic. gettimeofday() reports CLOCK_REALTIME, which NTP can + // slew or step backwards; callers subtract successive samples to derive + // frame time, so a backwards step produced negative elapsed times (see + // AlterScheduler "no forward time movement"). CLOCK_MONOTONIC never goes + // backwards. Units stay microseconds to match QueryPerformanceFrequency(). + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) + { + struct timeval tv; + gettimeofday(&tv, nullptr); + *time = static_cast(tv.tv_sec); + *time = (*time * 1000000) + static_cast(tv.tv_usec); + return TRUE; + } + + *time = static_cast(ts.tv_sec); + *time = (*time * 1000000) + static_cast(ts.tv_nsec / 1000); return TRUE; } diff --git a/engine/shared/library/sharedFoundation/src/shared/AutoDeltaNetworkIdPackedMap.h b/engine/shared/library/sharedFoundation/src/shared/AutoDeltaNetworkIdPackedMap.h index 62d073ad..eeed4ede 100755 --- a/engine/shared/library/sharedFoundation/src/shared/AutoDeltaNetworkIdPackedMap.h +++ b/engine/shared/library/sharedFoundation/src/shared/AutoDeltaNetworkIdPackedMap.h @@ -32,8 +32,8 @@ namespace Archive char temp[200]; AutoDeltaMap::Command c; - Archive::put(target, countCharacter(buffer,':')); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(countCharacter(buffer,':'))); + Archive::put(target, static_cast(0)); // baselineCommandCount int tempPos = 0; for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i) @@ -64,8 +64,8 @@ namespace Archive char temp[200]; AutoDeltaMap::Command c; - size_t commandCount; - size_t baselineCommandCount; + int32_t commandCount; + int32_t baselineCommandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); @@ -76,7 +76,7 @@ namespace Archive } else { - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); Archive::get(source, c.key); diff --git a/engine/shared/library/sharedFoundation/src/shared/Fatal.cpp b/engine/shared/library/sharedFoundation/src/shared/Fatal.cpp index c684c6e4..a82a7160 100755 --- a/engine/shared/library/sharedFoundation/src/shared/Fatal.cpp +++ b/engine/shared/library/sharedFoundation/src/shared/Fatal.cpp @@ -62,7 +62,7 @@ static void formatMessage(char *buffer, int bufferLength, int stackDepth, const // look up the call stack information const int callStackSize = callStackOffset + stackDepth; - uint32 callStack[callStackOffset + maxStackDepth]; + uint64 callStack[callStackOffset + maxStackDepth]; // allow complete disable of the call stack lookup if (stackDepth < 0) @@ -82,7 +82,7 @@ static void formatMessage(char *buffer, int bufferLength, int stackDepth, const if (ConfigSharedFoundation::getLookUpCallStackNames() && DebugHelp::lookupAddress(callStack[callStackOffset], lib, file, sizeof(file), line)) snprintf(buffer, bufferLength, "%s(%d) : %s %08x: \n", file, line, type, static_cast(Crc::calculate(format))); else - snprintf(buffer, bufferLength, "(0x%08X) : %s %08x: \n", static_cast(callStack[callStackOffset]), type, static_cast(Crc::calculate(format))); + snprintf(buffer, bufferLength, "(0x%016llX) : %s %08x: \n", static_cast(callStack[callStackOffset]), type, static_cast(Crc::calculate(format))); } else { @@ -126,7 +126,7 @@ static void formatMessage(char *buffer, int bufferLength, int stackDepth, const if (ConfigSharedFoundation::getLookUpCallStackNames() && DebugHelp::lookupAddress(callStack[i], lib, file, sizeof(file), line)) snprintf(buffer, bufferLength, " %s(%d) : caller %d\n", file, line, i-callStackOffset); else - snprintf(buffer, bufferLength, " (0x%08X) : caller %d\n", static_cast(callStack[i]), i-callStackOffset); + snprintf(buffer, bufferLength, " (0x%016llX) : caller %d\n", static_cast(callStack[i]), i-callStackOffset); const int length = strlen(buffer); buffer += length; diff --git a/engine/shared/library/sharedUtility/src/shared/NetworkIdAutoDeltaPackedMap.cpp b/engine/shared/library/sharedUtility/src/shared/NetworkIdAutoDeltaPackedMap.cpp index d1ba7a66..6e4c58fe 100755 --- a/engine/shared/library/sharedUtility/src/shared/NetworkIdAutoDeltaPackedMap.cpp +++ b/engine/shared/library/sharedUtility/src/shared/NetworkIdAutoDeltaPackedMap.cpp @@ -21,8 +21,8 @@ namespace Archive char value[200]; Command c; - Archive::put(target, countCharacter(buffer,':')); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(countCharacter(buffer,':'))); + Archive::put(target, static_cast(0)); // baselineCommandCount int tempPos = 0; for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i) @@ -52,8 +52,8 @@ namespace Archive char temp[200]; Command c; - size_t commandCount; - size_t baselineCommandCount; + int32_t commandCount; + int32_t baselineCommandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); @@ -64,7 +64,7 @@ namespace Archive } else { - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); Archive::get(source, c.key); diff --git a/external/ours/library/unicodeArchive/src/shared/UnicodeAutoDeltaPackedMap.cpp b/external/ours/library/unicodeArchive/src/shared/UnicodeAutoDeltaPackedMap.cpp index 8138fdbb..513d0690 100755 --- a/external/ours/library/unicodeArchive/src/shared/UnicodeAutoDeltaPackedMap.cpp +++ b/external/ours/library/unicodeArchive/src/shared/UnicodeAutoDeltaPackedMap.cpp @@ -21,8 +21,8 @@ namespace Archive char temp[200]; Command c; - Archive::put(target, countCharacter(buffer,':')); - Archive::put(target, static_cast(0)); // baselineCommandCount + Archive::put(target, static_cast(countCharacter(buffer,':'))); + Archive::put(target, static_cast(0)); // baselineCommandCount int tempPos = 0; for (std::string::const_iterator i=buffer.begin(); i!=buffer.end(); ++i) @@ -55,8 +55,8 @@ namespace Archive char temp[200]; Command c; - size_t commandCount; - size_t baselineCommandCount; + int32_t commandCount; + int32_t baselineCommandCount; Archive::get(source, commandCount); Archive::get(source, baselineCommandCount); @@ -67,7 +67,7 @@ namespace Archive } else { - for (size_t i = 0; i < commandCount; ++i) + for (int32_t i = 0; i < commandCount; ++i) { Archive::get(source, c.cmd); assert(c.cmd == Command::ADD); // only add is valid in unpack