split out do_backtrace
This commit is contained in:
@@ -624,39 +624,28 @@ static bool PointsToValidCall( unsigned long ptr )
|
|||||||
return IsValidCall(buf+7, len);
|
return IsValidCall(buf+7, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTERS *const pExc)
|
static void do_backtrace( const void **buf, size_t size,
|
||||||
|
HANDLE hProcess, HANDLE hThread, const CONTEXT *pContext )
|
||||||
{
|
{
|
||||||
if (!g_debugInfo.pRVAHeap) {
|
|
||||||
Report(hwnd, hFile, "Could not open debug resource file (StepMania.vdi).");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_debugInfo.nBuildNumber != int(version_num)) {
|
|
||||||
Report(hwnd, hFile, "Incorrect StepMania.vdi file (build %d, expected %d) for this version of StepMania -- call stack unavailable.", g_debugInfo.nBuildNumber, int(version_num));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve stack pointers.
|
// Retrieve stack pointers.
|
||||||
// Not sure if NtCurrentTeb() is available on Win95....
|
const char *pStackBase;
|
||||||
|
{
|
||||||
NT_TIB *pTib;
|
LDT_ENTRY sel;
|
||||||
|
GetThreadSelectorEntry( hThread, pContext->SegFs, &sel );
|
||||||
__asm {
|
const NT_TIB *tib = (NT_TIB *) ((sel.HighWord.Bits.BaseHi<<24)+(sel.HighWord.Bits.BaseMid<<16)+sel.BaseLow);
|
||||||
mov eax, fs:[0]_NT_TIB.Self
|
const NT_TIB *pTib = tib->Self;
|
||||||
mov pTib, eax
|
pStackBase = (char *)pTib->StackBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pStackBase = (char *)pTib->StackBase;
|
// Walk up the stack.
|
||||||
|
|
||||||
const CONTEXT *const pContext = (const CONTEXT *)pExc->ContextRecord;
|
|
||||||
const HANDLE hprMe = GetCurrentProcess();
|
|
||||||
const char *lpAddr = (const char *)pContext->Esp;
|
const char *lpAddr = (const char *)pContext->Esp;
|
||||||
int limit = 100;
|
|
||||||
|
|
||||||
// Walk up the stack. Hopefully it wasn't fscked.
|
const void *data = (void *) pContext->Eip;
|
||||||
|
size_t i = 0;
|
||||||
unsigned long data = pContext->Eip;
|
|
||||||
do {
|
do {
|
||||||
|
if( i+1 >= size )
|
||||||
|
break;
|
||||||
|
|
||||||
bool fValid = true;
|
bool fValid = true;
|
||||||
MEMORY_BASIC_INFORMATION meminfo;
|
MEMORY_BASIC_INFORMATION meminfo;
|
||||||
|
|
||||||
@@ -665,44 +654,72 @@ static bool ReportCrashCallStack(HWND hwnd, HANDLE hFile, const EXCEPTION_POINTE
|
|||||||
if (!IsExecutableProtection(meminfo.Protect) || meminfo.State!=MEM_COMMIT)
|
if (!IsExecutableProtection(meminfo.Protect) || meminfo.State!=MEM_COMMIT)
|
||||||
fValid = false;
|
fValid = false;
|
||||||
|
|
||||||
if ( data != pContext->Eip && !PointsToValidCall(data) )
|
if ( data != (void *) pContext->Eip && !PointsToValidCall((unsigned long)data) )
|
||||||
fValid = false;
|
fValid = false;
|
||||||
|
|
||||||
if (fValid) {
|
if( fValid )
|
||||||
|
buf[i++] = data;
|
||||||
|
|
||||||
|
if (lpAddr >= pStackBase)
|
||||||
|
break;
|
||||||
|
|
||||||
|
lpAddr += 4;
|
||||||
|
} while( ReadProcessMemory(hProcess, lpAddr-4, &data, 4, NULL));
|
||||||
|
|
||||||
|
buf[i++] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool ReportCrashCallStack( HWND hwnd, HANDLE hFile, const CONTEXT *pContext )
|
||||||
|
{
|
||||||
|
if( !g_debugInfo.pRVAHeap )
|
||||||
|
{
|
||||||
|
Report(hwnd, hFile, "Could not open debug resource file (StepMania.vdi).");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( g_debugInfo.nBuildNumber != int(version_num) )
|
||||||
|
{
|
||||||
|
Report(hwnd, hFile, "Incorrect StepMania.vdi file (build %d, expected %d) for this version of StepMania -- call stack unavailable.", g_debugInfo.nBuildNumber, int(version_num));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BACKTRACE_MAX_SIZE 100
|
||||||
|
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||||
|
do_backtrace( BacktracePointers, BACKTRACE_MAX_SIZE, GetCurrentProcess(), GetCurrentThread(), pContext );
|
||||||
|
|
||||||
|
for( int i = 0; BacktracePointers[i]; ++i )
|
||||||
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION meminfo;
|
||||||
|
VirtualQuery( BacktracePointers[i], &meminfo, sizeof meminfo );
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
if (VDDebugInfoLookupRVA(&g_debugInfo, data, buf, sizeof buf) >= 0) {
|
if( VDDebugInfoLookupRVA(&g_debugInfo, (unsigned int)BacktracePointers[i], buf, sizeof(buf)) >= 0 )
|
||||||
Report(hwnd, hFile, "%08lx: %s", data, Demangle(buf));
|
{
|
||||||
--limit;
|
Report(hwnd, hFile, "%08p: %s", BacktracePointers[i], Demangle(buf));
|
||||||
} else {
|
} else {
|
||||||
char szName[MAX_PATH];
|
char szName[MAX_PATH];
|
||||||
if( !CrashGetModuleBaseName((HMODULE)meminfo.AllocationBase, szName) )
|
if( !CrashGetModuleBaseName((HMODULE)meminfo.AllocationBase, szName) )
|
||||||
strcpy( szName, "???" );
|
strcpy( szName, "???" );
|
||||||
|
|
||||||
DWORD64 disp;
|
DWORD64 disp;
|
||||||
SYMBOL_INFO *pSymbol = GetSym( data, disp );
|
SYMBOL_INFO *pSymbol = GetSym( (unsigned int)BacktracePointers[i], disp );
|
||||||
|
|
||||||
if( pSymbol )
|
if( pSymbol )
|
||||||
{
|
{
|
||||||
Report(hwnd, hFile, "%08lx: %s!%s [%08lx+%lx+%lx]",
|
Report(hwnd, hFile, "%08lx: %s!%s [%08lx+%lx+%lx]",
|
||||||
(unsigned long) data, szName, pSymbol->Name,
|
(unsigned long) BacktracePointers[i], szName, pSymbol->Name,
|
||||||
(unsigned long) meminfo.AllocationBase,
|
(unsigned long) meminfo.AllocationBase,
|
||||||
(unsigned long) (pSymbol->Address) - (unsigned long) (meminfo.AllocationBase),
|
(unsigned long) (pSymbol->Address) - (unsigned long) (meminfo.AllocationBase),
|
||||||
(unsigned long) disp);
|
(unsigned long) disp);
|
||||||
} else {
|
} else {
|
||||||
Report(hwnd, hFile, "%08lx: %s!%08lx",
|
Report(hwnd, hFile, "%08lx: %s!%08lx",
|
||||||
(unsigned long) data, szName,
|
(unsigned long) BacktracePointers[i], szName,
|
||||||
(unsigned long) meminfo.AllocationBase );
|
(unsigned long) meminfo.AllocationBase );
|
||||||
}
|
}
|
||||||
--limit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpAddr >= pStackBase)
|
|
||||||
break;
|
|
||||||
|
|
||||||
lpAddr += 4;
|
|
||||||
} while(limit > 0 && ReadProcessMemory(hprMe, lpAddr-4, &data, 4, NULL));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +751,7 @@ static void DoSave(const EXCEPTION_POINTERS *pExc)
|
|||||||
WriteBuf( hFile, Checkpoints::GetLogs("\r\n") );
|
WriteBuf( hFile, Checkpoints::GetLogs("\r\n") );
|
||||||
Report(NULL, hFile, "");
|
Report(NULL, hFile, "");
|
||||||
|
|
||||||
ReportCrashCallStack(NULL, hFile, pExc);
|
ReportCrashCallStack( NULL, hFile, pExc->ContextRecord );
|
||||||
Report(NULL, hFile, "");
|
Report(NULL, hFile, "");
|
||||||
|
|
||||||
Report(NULL, hFile, "Static log:");
|
Report(NULL, hFile, "Static log:");
|
||||||
@@ -797,7 +814,7 @@ BOOL APIENTRY CrashDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|||||||
SendMessage(hwndList, WM_SETFONT, (WPARAM)hFontMono, MAKELPARAM(TRUE, 0));
|
SendMessage(hwndList, WM_SETFONT, (WPARAM)hFontMono, MAKELPARAM(TRUE, 0));
|
||||||
|
|
||||||
ReportReason(hwndReason, NULL, pExc);
|
ReportReason(hwndReason, NULL, pExc);
|
||||||
s_bHaveCallstack = ReportCrashCallStack(hwndList, NULL, pExc);
|
s_bHaveCallstack = ReportCrashCallStack( hwndList, NULL, pExc->ContextRecord );
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user