mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-31 00:15:55 -04:00
Store call stack addresses at pointer width
DebugHelp::getCallStack() handed the caller's uint32 buffer straight to backtrace(), which writes void* entries. Under LP64 that wrote 8 bytes per frame into a 4-byte-per-frame array, overrunning every buffer by 2x: Fatal.cpp uint32[68] = 272 bytes, up to 544 written (stack) CallStack uint32[32] = 128 bytes, 208 written (heap) CallStackCollector uint32[26] = 104 bytes, 208 written (heap) Fatal.cpp's formatMessage() backs every WARNING and FATAL, so any warning that captured a stack corrupted memory. Observed as SIGSEGV inside cfree() with si_addr 0x8 after an unrelated warning fired. Capture into a native void* array and widen into a uint64 buffer, which is correct under both ILP32 and LP64, and widen the storage and printing to match. lookupAddress() already took uint64 on linux; win32 now agrees and no longer truncates StackWalk's DWORD64 address to 32 bits. Also fixes CallStackCollector copying only one element instead of the whole call stack, and CRCing only half the buffer.
This commit is contained in:
@@ -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<void **>(callStack), sizeOfCallStack));
|
||||
|
||||
if (sizeOfCallStack > static_cast<int>(cs_maximumFrameCount))
|
||||
sizeOfCallStack = static_cast<int>(cs_maximumFrameCount);
|
||||
|
||||
void *frames[cs_maximumFrameCount];
|
||||
int const frameCount = backtrace(frames, sizeOfCallStack);
|
||||
|
||||
for (int i = 0; i < frameCount; ++i)
|
||||
callStack[i] = reinterpret_cast<uint64>(frames[i]);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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<int>(m_callStack[i]), fileName, line, i - 1));
|
||||
DEBUG_REPORT_PRINT(true, (" (0x%016llX) %s(%d) : caller %d\n", static_cast<unsigned long long>(m_callStack[i]), fileName, line, i - 1));
|
||||
else
|
||||
DEBUG_REPORT_PRINT(true, (" unknown(0x%08X) : caller %d\n", static_cast<int>(m_callStack[i]), i - 1));
|
||||
DEBUG_REPORT_PRINT(true, (" unknown(0x%016llX) : caller %d\n", static_cast<unsigned long long>(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<int>(m_callStack[i]), fileName, line, i - 1));
|
||||
DEBUG_REPORT_LOG(true, (" (0x%016llX) %s(%d) : caller %d\n", static_cast<unsigned long long>(m_callStack[i]), fileName, line, i - 1));
|
||||
else
|
||||
DEBUG_REPORT_LOG(true, (" unknown(0x%08X) : caller %d\n", static_cast<int>(m_callStack[i]), i - 1));
|
||||
DEBUG_REPORT_LOG(true, (" unknown(0x%016llX) : caller %d\n", static_cast<unsigned long long>(m_callStack[i]), i - 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -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<int>(callStackEntry->m_callStack[j]), j - 1));
|
||||
REPORT_LOG(true, (" unknown(0x%016llX) : caller %d\n", static_cast<unsigned long long>(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
|
||||
|
||||
@@ -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<uint64>(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<uint32 *>(_alloca((callStackOffset + maxStackDepth) * sizeof(uint32)));
|
||||
uint64 * callStack = static_cast<uint64 *>(_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<int>(callStack[i]), i-callStackOffset));
|
||||
REPORT_LOG(true, ("\tunknown(0x%016llX) : caller %d\n", static_cast<unsigned long long>(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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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<int>(Crc::calculate(format)));
|
||||
else
|
||||
snprintf(buffer, bufferLength, "(0x%08X) : %s %08x: \n", static_cast<int>(callStack[callStackOffset]), type, static_cast<int>(Crc::calculate(format)));
|
||||
snprintf(buffer, bufferLength, "(0x%016llX) : %s %08x: \n", static_cast<unsigned long long>(callStack[callStackOffset]), type, static_cast<int>(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<int>(callStack[i]), i-callStackOffset);
|
||||
snprintf(buffer, bufferLength, " (0x%016llX) : caller %d\n", static_cast<unsigned long long>(callStack[i]), i-callStackOffset);
|
||||
|
||||
const int length = strlen(buffer);
|
||||
buffer += length;
|
||||
|
||||
Reference in New Issue
Block a user