unsigned dbgsymengine::symbol(char * buf, unsigned len, unsigned * pdisplacement) { if (!len || !buf || IsBadWritePtr(buf, len) || (pdisplacement && IsBadWritePtr(pdisplacement, sizeof(unsigned)))) return 0; if (!check()) return 0; BYTE symbol [ 512 ] ; PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&symbol; memset(pSym, 0, sizeof(symbol)) ; pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL) ; pSym->MaxNameLength = sizeof(symbol) - sizeof(IMAGEHLP_SYMBOL); HANDLE hProc = SymGetProcessHandle(); DWORD displacement = 0; int r = SymGetSymFromAddr(hProc, m_address, &displacement, pSym); if (!r) return 0; if (pdisplacement) *pdisplacement = displacement; r = _snprintf(buf, len, "%s()", pSym->Name); r = r == -1 ? len - 1 : r; buf[r] = 0; return r; }
LONG CALLBACK MJCore_Exception_Filter(_EXCEPTION_POINTERS *ex) { CodeConv::tostringstream dmsg, lmsg; #ifdef _MSC_VER PIMAGEHLP_SYMBOL pSymbol; #endif DWORD disp; ErrorInfo *errinf = nullptr; lmsg << _T("ハンドルされていない例外 ") << std::hex << std::setw(8) << std::setfill(_T('0')) << ex->ExceptionRecord->ExceptionCode << _T(" が発生したため、強制終了されます。"); fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); CONTEXT context; memcpy(&context, ex->ContextRecord, sizeof(CONTEXT)); switch (ex->ExceptionRecord->ExceptionCode) { case EXCEPTION_MJCORE_SUBSCRIPT_OUT_OF_RANGE: case EXCEPTION_MJCORE_INVALID_ARGUMENT: case EXCEPTION_MJCORE_INVALID_DATA: case EXCEPTION_MJCORE_OVERFLOW: case EXCEPTION_MJCORE_DECOMPRESSION_FAILURE: case EXCEPTION_MJCORE_HASH_MISMATCH: errinf = (ErrorInfo *)(ex->ExceptionRecord->ExceptionInformation[0]); lmsg << _T(">>> ") << errinf->msg; fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); #if defined(_MSC_VER) && defined(_DEBUG) lmsg << _T(">>> ファイル: ") << errinf->file << _T(" 行: ") << errinf->line << _T(" 関数名: ") << errinf->func; fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); pSymbol = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); pSymbol->SizeOfStruct = 16384; pSymbol->MaxNameLength = 16384 - sizeof(IMAGEHLP_SYMBOL); SymInitialize(GetCurrentProcess(), nullptr, TRUE); for (unsigned int i = 0; true; i++) { if (i >= ADDRBUF) break; if (errinf->traceBack[i] == 0) break; if (SymGetSymFromAddr(GetCurrentProcess(), errinf->traceBack[i], &disp, pSymbol)) lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << errinf->traceBack[i] << _T(" ") << pSymbol->Name << _T("() + ") << std::setfill(_T('0')) << disp; else lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << errinf->traceBack[i] << _T(" Unknown"); debug(lmsg.str().c_str()); lmsg.str(_T("")); } SymCleanup(GetCurrentProcess()); GlobalFree(pSymbol); #endif break; #ifdef _MSC_VER default: traceLog(ex->ContextRecord, nullptr, 0); #endif } #ifdef _MSC_VER terminate(); #else abort(); #endif }
static void dumpFrame(void* processId, void* frameAddr) { MEMORY_BASIC_INFORMATION mbi; char moduleName[MAX_PATH]; HMODULE moduleAddr; DWORD symDisplacement; IMAGEHLP_SYMBOL* pSymbol; if (VirtualQuery(frameAddr, &mbi, sizeof(mbi))) { moduleName[0] = 0; moduleAddr = (HMODULE)mbi.AllocationBase; GetModuleFileName(moduleAddr, moduleName, MAX_PATH); printf("%s(", moduleName); if (SymGetSymFromAddr(processId, (uint32_t)frameAddr, &symDisplacement, pSymbol)) printf("%s", pSymbol->Name); else printf("<unknown>"); printf("+0x%X) [0x%08X]\n", (uint32_t)frameAddr - (uint32_t)moduleAddr, frameAddr); fflush(stdout); } }
BOOL CallStack::symFunctionInfoFromAddresses(ULONG fnAddress, ULONG stackAddress, /*LPTSTR*/TCHAR * lpszSymbol, UINT BufSizeTCHARs) { stackAddress; DWORD dwDisp = 0; ::ZeroMemory(m_pSymbol, m_dwsymBufSize ); m_pSymbol->SizeOfStruct = m_dwsymBufSize; m_pSymbol->MaxNameLength = m_dwsymBufSize - sizeof(IMAGEHLP_SYMBOL); // Set the default to unknown _tcscpy_s( lpszSymbol, BufSizeTCHARs, MLD_TRACEINFO_NOSYMBOL); // Get symbol info for IP if ( SymGetSymFromAddr( m_hProcess, (ULONG)fnAddress, &dwDisp, m_pSymbol ) ) { #ifdef UNICODE int len = strlen(m_pSymbol->Name) + 1 ; wchar_t dest[1024] = {}; MultiByteToWideChar(CP_ACP, 0, m_pSymbol->Name, len, dest, len ); _tcscpy_s(lpszSymbol, BufSizeTCHARs, dest); #else _tcscpy_s(lpszSymbol, BufSizeTCHARs, m_pSymbol->Name); #endif return TRUE; } //create the symbol using the address because we have no symbol _stprintf_s(lpszSymbol, BufSizeTCHARs, _T("0x%08X"), fnAddress); return FALSE; }
BOOL AddressToName(DWORD Addr, LPTSTR Str, int Max) { DWORD base; if (!InitialiseImageHelp()) return FALSE; base = SymGetModuleBase(s_hProcess, Addr); if (base) { struct { IMAGEHLP_SYMBOL ihs; char NameBuf[256]; } SymInfo; DWORD Displacement = 0; SymInfo.ihs.SizeOfStruct = sizeof(SymInfo); SymInfo.ihs.MaxNameLength = sizeof(SymInfo.NameBuf); if (SymGetSymFromAddr(s_hProcess, Addr, &Displacement, &SymInfo.ihs)) { if (Displacement) _snprintf(Str, Max-1, "%s+%x", SymInfo.ihs.Name, Displacement); else _snprintf(Str, Max-1, "%s", SymInfo.ihs.Name); return TRUE; } else { _snprintf(Str, Max, "SymGetSymFromAddr failed (%d)", GetLastError()); } } else { _snprintf(Str, Max, "SymGetModuleBase failed (%d)", GetLastError()); } return FALSE; }
BOOL CMemLeakDetect::symFunctionInfoFromAddresses( ADDR fnAddress, ADDR stackAddress, TCHAR *lpszSymbol, UINT BufSizeTCHARs) { ADDR dwDisp = 0; ::ZeroMemory(m_pSymbol, m_dwsymBufSize ); m_pSymbol->SizeOfStruct = m_dwsymBufSize; m_pSymbol->MaxNameLength = MLD_MAX_NAME_LENGTH; // = DWORD64 - sizeof(IMAGEHLP_SYMBOL64); // Set the default to unknown _tcscpy_s( lpszSymbol, MLD_MAX_NAME_LENGTH, MLD_TRACEINFO_NOSYMBOL); // Get symbol info for IP if ( SymGetSymFromAddr( m_hProcess, (ADDR)fnAddress, &dwDisp, m_pSymbol ) ) { #ifdef UNICODE int len = (int)strlen(m_pSymbol->Name) + 1 ; wchar_t dest[1024] ; MultiByteToWideChar(CP_ACP, 0, m_pSymbol->Name, len, dest, len ); _tcscpy_s(lpszSymbol, BufSizeTCHARs, dest); #else _tcscpy_s(lpszSymbol, BufSizeTCHARs, m_pSymbol->Name); #endif return TRUE; } //create the symbol using the address because we have no symbol _stprintf_s(lpszSymbol, BufSizeTCHARs, _T("0x%08X"), fnAddress); return FALSE; }
void Stacktrace(LPEXCEPTION_POINTERS e, std::stringstream& ss) { PIMAGEHLP_SYMBOL pSym; STACKFRAME sf; HANDLE process, thread; ULONG_PTR dwModBase, Disp; BOOL more = FALSE; DWORD machineType; int count = 0; char modname[MAX_PATH]; char symBuffer[sizeof(IMAGEHLP_SYMBOL) + 255]; pSym = (PIMAGEHLP_SYMBOL)symBuffer; ZeroMemory(&sf, sizeof(sf)); #ifdef _WIN64 sf.AddrPC.Offset = e->ContextRecord->Rip; sf.AddrStack.Offset = e->ContextRecord->Rsp; sf.AddrFrame.Offset = e->ContextRecord->Rbp; machineType = IMAGE_FILE_MACHINE_AMD64; #else sf.AddrPC.Offset = e->ContextRecord->Eip; sf.AddrStack.Offset = e->ContextRecord->Esp; sf.AddrFrame.Offset = e->ContextRecord->Ebp; machineType = IMAGE_FILE_MACHINE_I386; #endif sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; process = GetCurrentProcess(); thread = GetCurrentThread(); while(1) { more = StackWalk(machineType, process, thread, &sf, e->ContextRecord, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL); if(!more || sf.AddrFrame.Offset == 0) break; dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset); if(dwModBase) GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH); else strcpy(modname, "Unknown"); Disp = 0; pSym->SizeOfStruct = sizeof(symBuffer); pSym->MaxNameLength = 254; if(SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym)) ss << stdext::format(" %d: %s(%s+%#0lx) [0x%016lX]\n", count, modname, pSym->Name, Disp, sf.AddrPC.Offset); else ss << stdext::format(" %d: %s [0x%016lX]\n", count, modname, sf.AddrPC.Offset); ++count; } GlobalFree(pSym); }
BOOL CmdStackTrace( LPSTR CmdBuf, HANDLE hProcess, HANDLE hThread, PEXCEPTION_RECORD ExceptionRecord ) { CONTEXT Context; STACKFRAME StackFrame = {0}; BOOL rVal = FALSE; CopyMemory( &Context, &CurrContext, sizeof(CONTEXT) ); #if defined(_M_IX86) StackFrame.AddrPC.Offset = Context.Eip; StackFrame.AddrPC.Mode = AddrModeFlat; StackFrame.AddrFrame.Offset = Context.Ebp; StackFrame.AddrFrame.Mode = AddrModeFlat; StackFrame.AddrStack.Offset = Context.Esp; StackFrame.AddrStack.Mode = AddrModeFlat; #endif printf( "\n" ); do { rVal = StackWalk( MACHINE_TYPE, hProcess, 0, &StackFrame, &Context, ReadProcessMemory, SymFunctionTableAccess, SymGetModuleBase, NULL ); if (rVal) { ULONG Displacement; printf( "%08x %08x ", StackFrame.AddrFrame.Offset, StackFrame.AddrReturn.Offset ); if (SymGetSymFromAddr( hProcess, StackFrame.AddrPC.Offset, &Displacement, sym )) { printf( "%s\n", sym->Name ); } else { printf( "0x%08x\n", StackFrame.AddrPC.Offset ); } } } while( rVal ); printf( "\n" ); return TRUE; }
void stack_walk(CString& strStack, PCONTEXT p_context) { CONTEXT * pContext = p_context; HANDLE hCurrentProcess = ::GetCurrentProcess(); HANDLE hCurrentThread = ::GetCurrentThread(); STACKFRAME64 sStackFrame; memset(&sStackFrame,0,sizeof(STACKFRAME64)); sStackFrame.AddrPC.Offset = pContext->Eip; sStackFrame.AddrPC.Mode = AddrModeFlat; sStackFrame.AddrStack.Offset= pContext->Esp; sStackFrame.AddrStack.Mode = AddrModeFlat; sStackFrame.AddrFrame.Offset= pContext->Ebp; sStackFrame.AddrFrame.Mode = AddrModeFlat; USES_CONVERSION; //TCHAR atszCallbackBuffer[1024]; //DWORD dwLen = 0; SymInitialize(GetCurrentProcess(),NULL,TRUE); while(StackWalk64(IMAGE_FILE_MACHINE_I386,hCurrentProcess,hCurrentThread,&sStackFrame,pContext,0,0,0,0)) { if( sStackFrame.AddrFrame.Offset == 0 ) { break; } strStack.Format(L"%s[%08X]", strStack,sStackFrame.AddrPC.Offset); BYTE sym_buffer[sizeof(IMAGEHLP_SYMBOL) + 512]; PIMAGEHLP_SYMBOL p_symbol = (PIMAGEHLP_SYMBOL)sym_buffer; p_symbol->SizeOfStruct = sizeof(sym_buffer); p_symbol->MaxNameLength = 512; // Displacement of the input address, relative to the start of the symbol DWORD sym_displacement = 0; if (!SymGetSymFromAddr(::GetCurrentProcess(), sStackFrame.AddrPC.Offset, &sym_displacement, p_symbol)) { p_symbol->Name[0] = 0; } TCHAR sz_module[MAX_PATH] = {0}; UINT_PTR section = 0, offset = 0; get_logical_address((PVOID)(UINT_PTR)sStackFrame.AddrPC.Offset, sz_module, sizeof(sz_module)); strStack.Format(L"%s\t%s\t%s\r\n",strStack,A2T(p_symbol->Name),sz_module); } SymCleanup(GetCurrentProcess()); }
void KImageModule::ShowSysCallTable(const char * tablename, unsigned base) { const IMAGEHLP_SYMBOL * pSymbol = ImageGetSymbol(tablename); if ( pSymbol==NULL ) Output("Unable to locate symbol %s\n", tablename); else { int count = base; const unsigned * p = (const unsigned *) Address2ImagePointer(pSymbol->Address); while ( ! IsBadReadPtr(p, sizeof(unsigned)) ) { unsigned q = * p; if ( q > (unsigned) (m_image.FileHeader->OptionalHeader.ImageBase) ) { DWORD displacement; // IMAGEHLP_SYMBOL symbol; memset(m_is, 0, sizeof(m_is)); m_is[0].SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); m_is[0].MaxNameLength = sizeof(m_is) - sizeof(m_is[0]); unsigned q1 = q; // W2k RC1 imagehlp does not need translation if ( m_symbolbase ) q1 = q1 - m_imagebase_default + m_symbolbase; if ( SymGetSymFromAddr(m_hProcess, q1, & displacement, m_is) ) { IMAGEHLP_LINE line; line.SizeOfStruct = sizeof(line); if ( SymGetLineFromAddr(m_hProcess, q1, & displacement, & line) ) { } Output("syscall(%4x) %s\n", count, m_is[0].Name); count ++; } } else break; p++; } Output("%d system calls found\n", count - base); } }
DWORD CCallStackTrace::ConvertAddress(HANDLE hProcess, DWORD address, LPSTR output_buffer) { char* current_pointer = output_buffer; IMAGEHLP_MODULE imagehlp_module; memset(&imagehlp_module, 0, sizeof(imagehlp_module)); imagehlp_module.SizeOfStruct = sizeof(imagehlp_module); if ( SymGetModuleInfo(hProcess, address, &imagehlp_module) != FALSE ) { char * image_name = strrchr(imagehlp_module.ImageName, '\\'); if ( image_name != NULL ) image_name += 1; else image_name = imagehlp_module.ImageName; current_pointer += sprintf(current_pointer, "%s : ", image_name); } else { current_pointer += sprintf(current_pointer, "<unknown module> : "); } DWORD displacement; char temp[0x11c]; IMAGEHLP_SYMBOL * imagehlp_symbol = (IMAGEHLP_SYMBOL *)temp; memset(imagehlp_symbol, 0, sizeof(temp)); imagehlp_symbol->SizeOfStruct = 24; imagehlp_symbol->Address = address; imagehlp_symbol->MaxNameLength = 0x104; if ( SymGetSymFromAddr(hProcess, address, &displacement, imagehlp_symbol) != FALSE ) { current_pointer += sprintf(current_pointer, "%s() ", imagehlp_symbol->Name); IMAGEHLP_LINE imagehlp_line; memset(&imagehlp_line, 0, sizeof(imagehlp_line)); imagehlp_line.SizeOfStruct = sizeof(IMAGEHLP_LINE); if ( SymGetLineFromAddr(hProcess, address, &displacement, &imagehlp_line) != FALSE ) { current_pointer += sprintf(current_pointer, "// %s(%i)", imagehlp_line.FileName, imagehlp_line.LineNumber); } } else { current_pointer += sprintf(current_pointer, "<unknown symbol>"); } current_pointer += sprintf(current_pointer, "\r\n"); return current_pointer - output_buffer; }
/* ================== Sym_GetFuncInfo ================== */ void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) { MEMORY_BASIC_INFORMATION mbi; VirtualQuery( (void*)addr, &mbi, sizeof(mbi) ); if ( (DWORD) mbi.AllocationBase != lastAllocationBase ) { Sym_Init( addr ); } BYTE symbolBuffer[ sizeof(IMAGEHLP_SYMBOL) + MAX_STRING_CHARS ]; PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)&symbolBuffer[0]; pSymbol->SizeOfStruct = sizeof(symbolBuffer); pSymbol->MaxNameLength = 1023; pSymbol->Address = 0; pSymbol->Flags = 0; pSymbol->Size =0; DWORD symDisplacement = 0; if ( SymGetSymFromAddr( processHandle, addr, &symDisplacement, pSymbol ) ) { // clean up name, throwing away decorations that don't affect uniqueness char undName[MAX_STRING_CHARS]; if ( UnDecorateSymbolName( pSymbol->Name, undName, sizeof(undName), UNDECORATE_FLAGS ) ) { funcName = undName; } else { funcName = pSymbol->Name; } module = lastModule; } else { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); LocalFree( lpMsgBuf ); // Couldn't retrieve symbol (no debug info?, can't load dbghelp.dll?) sprintf( funcName, "0x%08x", addr ); module = ""; } }
void CallStack::getFuncInfo(LPVOID dwFunc, FuncInfo& info) { memset(szBuffer, 0, sizeof(szBuffer)); #ifdef WIN32 #ifdef X64 PIMAGEHLP_SYMBOL64 symbol = (PIMAGEHLP_SYMBOL64)szBuffer; symbol->SizeOfStruct = sizeof(szBuffer); symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL64); DWORD64 dwDisplacement = 0; if (SymGetSymFromAddr64(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol)) { strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))); info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0; } IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr64(hProcess, (DWORD)dwFunc, (PDWORD)&dwDisplacement, &imageHelpLine)) { strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))); info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0; info.dwLineNumber = imageHelpLine.LineNumber; } #else PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)szBuffer; symbol->SizeOfStruct = sizeof(szBuffer); symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL); DWORD dwDisplacement = 0; if (SymGetSymFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol)) { strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))); info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0; } IMAGEHLP_LINE imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, &imageHelpLine)) { strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))); info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0; info.dwLineNumber = imageHelpLine.LineNumber; } #endif #endif }
void traceLog(CONTEXT* ex, int* const addrList, int addrListSize) { #ifdef _DEBUG #ifdef _M_IX86 /* スタックトレース(I386専用です) */ CodeConv::tostringstream lmsg; if (addrList != nullptr) memset(addrList, 0, addrListSize); HANDLE hProcess = GetCurrentProcess(); DWORD disp; HANDLE hThread = GetCurrentThread(); PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); pSymbol->SizeOfStruct = 16384; pSymbol->MaxNameLength = 16384 - sizeof(IMAGEHLP_SYMBOL); SymInitialize(GetCurrentProcess(), nullptr, TRUE); STACKFRAME stackFrame; memset(&stackFrame, 0, sizeof(stackFrame)); stackFrame.AddrPC.Offset = ex->Eip; stackFrame.AddrFrame.Offset = ex->Ebp; stackFrame.AddrStack.Offset = ex->Esp; stackFrame.AddrPC.Mode = stackFrame.AddrFrame.Mode = stackFrame.AddrStack.Mode = AddrModeFlat; CONTEXT context; memcpy(&context, ex, sizeof(CONTEXT)); context.ContextFlags = CONTEXT_FULL; for (unsigned int i = 0; true; i++) { if (!StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stackFrame, &context, nullptr, SymFunctionTableAccess, SymGetModuleBase, nullptr)) break; if (stackFrame.AddrPC.Offset == 0) break; if (addrList != nullptr) { addrList[i] = stackFrame.AddrPC.Offset; if (i >= (addrListSize / sizeof(int))) break; } else { if (SymGetSymFromAddr(hProcess, stackFrame.AddrPC.Offset, &disp, pSymbol)) lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << stackFrame.AddrPC.Offset << _T(" ") << pSymbol->Name << _T("() + ") << std::setfill(_T('0')) << disp; else lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << stackFrame.AddrPC.Offset << _T(" Unknown"); debug(lmsg.str().c_str()); lmsg.str(_T("")); } } SymCleanup(hProcess); GlobalFree(pSymbol); #endif #endif }
void Stacktrace(LPEXCEPTION_POINTERS e, std::stringstream& ss) { PIMAGEHLP_SYMBOL pSym; STACKFRAME sf; HANDLE process, thread; DWORD dwModBase, Disp; BOOL more = FALSE; int count = 0; char modname[MAX_PATH]; pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); ZeroMemory(&sf, sizeof(sf)); sf.AddrPC.Offset = e->ContextRecord->Eip; sf.AddrStack.Offset = e->ContextRecord->Esp; sf.AddrFrame.Offset = e->ContextRecord->Ebp; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; process = GetCurrentProcess(); thread = GetCurrentThread(); while(1) { more = StackWalk(IMAGE_FILE_MACHINE_I386, process, thread, &sf, e->ContextRecord, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL); if(!more || sf.AddrFrame.Offset == 0) break; dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset); if(dwModBase) GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH); else strcpy(modname, "Unknown"); pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pSym->MaxNameLength = MAX_PATH; if(SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym)) ss << stdext::format(" %d: %s(%s+%#0lx) [0x%08lX]\n", count, modname, pSym->Name, Disp, sf.AddrPC.Offset); else ss << stdext::format(" %d: %s [0x%08lX]\n", count, modname, sf.AddrPC.Offset); ++count; } GlobalFree(pSym); }
size_t DisAddrToSymbol( struct DIS *pdis, ULONG addr, char *buf, size_t bufsize, DWORD *displacement ) { if (SymGetSymFromAddr( CurrProcess, addr, displacement, sym )) { strncpy( buf, sym->Name, bufsize ); } else { *displacement = 0; buf[0] = 0; } return strlen(buf); }
void StackTrack_x86(PCSTR dir, DWORD dwEIP, DWORD dwEBP, DWORD dwESP) { HANDLE hHandle = NULL; HANDLE hThread = NULL; PIMAGEHLP_SYMBOL pSymInfo = NULL; CONTEXT context = {0}; STACKFRAME sf = { 0 }; DWORD dwDisplament = 0; IMAGEHLP_LINE ImageLine = { 0 }; hHandle = GetCurrentProcess(); hThread = GetCurrentThread(); SymInitialize(hHandle, dir, TRUE); pSymInfo = (PIMAGEHLP_SYMBOL)malloc(sizeof(IMAGEHLP_SYMBOL) + MAX_PATH); if (pSymInfo == NULL) { return ; } context.Eip = dwEIP; context.Ebp = dwEBP; context.Esp = dwESP; sf.AddrPC.Mode = AddrModeFlat; //EIP sf.AddrFrame.Mode = AddrModeFlat; //EBP sf.AddrStack.Mode = AddrModeFlat; //ESP pSymInfo->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pSymInfo->MaxNameLength = MAX_PATH; ImageLine.SizeOfStruct = sizeof(IMAGEHLP_LINE); while (StackWalk(IMAGE_FILE_MACHINE_I386, hHandle, hThread, &sf, &context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) { SymGetSymFromAddr(hHandle, sf.AddrPC.Offset, &dwDisplament, pSymInfo); SymGetLineFromAddr(hHandle, sf.AddrPC.Offset, &dwDisplament, &ImageLine); printf("%08x %s():%s(%d)\n", pSymInfo->Address, pSymInfo->Name, ImageLine.FileName, ImageLine.LineNumber); } free(pSymInfo); SymCleanup(hHandle); }
void StackTraceUtils::Impl::getSymbolName( StackTraceHandler &handler, void *address) { #ifdef _WIN64 typedef DWORD64 DWORDX; #else typedef DWORD DWORDX; #endif HANDLE process = ::GetCurrentProcess(); if (!process) { handler("", -1); return; } IMAGEHLP_MODULE imageModule = { sizeof(IMAGEHLP_MODULE) }; IMAGEHLP_LINE line ={ sizeof(IMAGEHLP_LINE) }; DWORDX dispSym = 0; DWORD dispLine = 0; char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_PATH] = {0}; IMAGEHLP_SYMBOL * imageSymbol = (IMAGEHLP_SYMBOL*) symbolBuffer; imageSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); imageSymbol->MaxNameLength = MAX_PATH; const DWORDX intAddress = static_cast<DWORDX>(reinterpret_cast<uintptr_t>(address)); if(!SymGetModuleInfo(process, intAddress, &imageModule)) { util::detail::RawNumberFormatter formatter; handler(formatter(static_cast<uint64_t>(intAddress)), -1); } else if(!SymGetSymFromAddr(process, intAddress, &dispSym, imageSymbol)) { util::detail::RawNumberFormatter formatter; handler(formatter(static_cast<uint64_t>(intAddress)), -1); } else if(!SymGetLineFromAddr(process, intAddress, &dispLine, &line)) { handler(imageSymbol->Name, -1); } else { handler(imageSymbol->Name, line.LineNumber); } }
BOOL CmdListNear( LPSTR CmdBuf, HANDLE hProcess, HANDLE hThread, PEXCEPTION_RECORD ExceptionRecord ) { SKIP_NONWHITE( CmdBuf ); SKIP_WHITE( CmdBuf ); ULONG Address; GetAddress( CmdBuf, &Address ); if (Address) { ULONG Displacement; if (SymGetSymFromAddr( hProcess, Address, &Displacement, sym )) { printf( "0x%08x %s\n", sym->Address, sym->Name ); } } return TRUE; }
size_t GetSymbolNameFromAddress(void* address, char* symbolName, size_t size, size_t* offsetBytes) { if (size) *symbolName = 0; if (offsetBytes) *offsetBytes = 0; __try { ULONG_ADDR dwOffset = 0; union { IMAGEHLP_SYMBOL sym; char symNameBuffer[sizeof(IMAGEHLP_SYMBOL) + MAX_SYM_NAME]; } u; u.sym.SizeOfStruct = sizeof(u.sym); u.sym.MaxNameLength = sizeof(u.symNameBuffer) - sizeof(u.sym); if (!SymGetSymFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &u.sym)) { return 0; } else { const char* sourceName = u.sym.Name; char undName[1024]; if (UnDecorateSymbolName(u.sym.Name, undName, sizeof(undName), UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) { sourceName = undName; } else if (SymUnDName(&u.sym, undName, sizeof(undName))) { sourceName = undName; } if (offsetBytes) { *offsetBytes = dwOffset; } if (size) { strncpy(symbolName, sourceName, size)[size - 1] = 0; } return strlen(sourceName); } } __except (EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); } return 0; }
static bool DumpFrame(void *process, DWORD_PTR frameAddress) { const int functionLength = 255; IMAGEHLP_SYMBOL *symbol = (IMAGEHLP_SYMBOL*)malloc(sizeof(IMAGEHLP_SYMBOL) + functionLength); DWORD_PTR moduleBase = SymGetModuleBase(process, frameAddress); const char *moduleName = NULL, *functionName = NULL; DWORD_PTR displacement; char moduleFilename[MAX_PATH]; symbol->SizeOfStruct = (sizeof(*symbol)) + functionLength; symbol->MaxNameLength = functionLength - 1; if (moduleBase && GetModuleFileName((HINSTANCE)moduleBase, moduleFilename, MAX_PATH)) moduleName = moduleFilename; if (SymGetSymFromAddr(process, frameAddress, &displacement, symbol)) functionName = symbol->Name; PrintFunction(moduleName, functionName, frameAddress, displacement); free(symbol); }
size_t DisFixupToSymbol( struct DIS *pdis, ULONG addr, size_t fixup, char *buf, size_t bufsize, DWORD *displacement ) { if (!ReadMemory( CurrProcess, (PVOID)addr, &addr, 4 )) { *displacement = 0; return 0; } if (SymGetSymFromAddr( CurrProcess, addr, displacement, sym )) { strncpy( buf, sym->Name, bufsize ); } else { *displacement = 0; buf[0] = 0; } return strlen(buf); }
//************************************************************************* // Method: GetStackInfo // Description: Gets the call stack for the specified thread // // Parameters: // hThread - the handle to the target thread // threadContext - the context of the target thread // // Return Value: (FrameInfo *) An array containing stack trace data //************************************************************************* SiUtils::SiArray <FrameInfo *> StackWalker::GetStackInfo(HANDLE hThread, CONTEXT &threadContext) { //Clear the frame array of any previous data frameArray.Clear(); DWORD imageType = IMAGE_FILE_MACHINE_I386; HANDLE hProcess = GetCurrentProcess(); int frameNum; // counts walked frames DWORD offsetFromSymbol; // tells us how far from the symbol we were DWORD symOptions; // symbol handler settings IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN ); char undName[MAXNAMELEN]; // undecorated name char undFullName[MAXNAMELEN]; // undecorated name with all shenanigans IMAGEHLP_MODULE Module; IMAGEHLP_LINE Line; std::string symSearchPath; char *tt = 0, *p; STACKFRAME s; // in/out stackframe memset( &s, '\0', sizeof s ); tt = new char[TTBUFLEN]; // build symbol search path from: symSearchPath = ""; // current directory if (GetCurrentDirectory(TTBUFLEN, tt )) symSearchPath += tt + std::string( ";" ); // dir with executable if (GetModuleFileName(0, tt, TTBUFLEN)) { for ( p = tt + strlen( tt ) - 1; p >= tt; -- p ) { // locate the rightmost path separator if ( *p == '\\' || *p == '/' || *p == ':' ) break; } if ( p != tt ) { if ( *p == ':' ) // we leave colons in place ++ p; *p = '\0'; // eliminate the exe name and last path sep symSearchPath += tt + std::string( ";" ); } } // environment variable _NT_SYMBOL_PATH if ( GetEnvironmentVariable( "_NT_SYMBOL_PATH", tt, TTBUFLEN ) ) symSearchPath += tt + std::string( ";" ); // environment variable _NT_ALTERNATE_SYMBOL_PATH if ( GetEnvironmentVariable( "_NT_ALTERNATE_SYMBOL_PATH", tt, TTBUFLEN ) ) symSearchPath += tt + std::string( ";" ); // environment variable SYSTEMROOT if ( GetEnvironmentVariable( "SYSTEMROOT", tt, TTBUFLEN ) ) symSearchPath += tt + std::string( ";" ); if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 ); strncpy( tt, symSearchPath.c_str(), TTBUFLEN ); tt[TTBUFLEN - 1] = '\0'; // if strncpy() overruns, it doesn't add the null terminator // init symbol handler stuff (SymInitialize()) if (!SymInitialize(hProcess, tt, false )) goto cleanup; // SymGetOptions() symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES; symOptions &= ~SYMOPT_UNDNAME; SymSetOptions( symOptions ); // Enumerate modules and tell imagehlp.dll about them. enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() ); // init STACKFRAME for first call // Notes: AddrModeFlat is just an assumption. I hate VDM debugging. // Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway, // and good riddance. s.AddrPC.Offset = threadContext.Eip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = threadContext.Ebp; s.AddrFrame.Mode = AddrModeFlat; memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN ); pSym->SizeOfStruct = IMGSYMLEN; pSym->MaxNameLength = MAXNAMELEN; memset( &Line, '\0', sizeof Line ); Line.SizeOfStruct = sizeof Line; memset( &Module, '\0', sizeof Module ); Module.SizeOfStruct = sizeof Module; offsetFromSymbol = 0; for ( frameNum = 0; ; ++ frameNum ) { FrameInfo * frameInfo = new FrameInfo(); if (!StackWalk( imageType, hProcess, hThread, &s, &threadContext, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL ) ) break; frameInfo->frameNumber = frameNum; frameInfo->IsWOWFarCall = s.Far; frameInfo->IsVirtualFrame = s.Virtual; frameInfo->Eip = s.AddrPC.Offset; //if 0, the no symbols frameInfo->ReturnAddr = s.AddrReturn.Offset; frameInfo->FramePtr = s.AddrFrame.Offset; frameInfo->StackPtr = s.AddrStack.Offset; if (s.AddrPC.Offset == 0) { //printf( "(-nosymbols- PC == 0)\n" ); } else { // we seem to have a valid PC // show procedure info (SymGetSymFromAddr()) if ( ! SymGetSymFromAddr( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) ) { /*if ( GetLastError() != 487 ) printf( "SymGetSymFromAddr(): GetLastError() = %lu\n", GetLastError() );*/ } else { // UnDecorateSymbolName() UnDecorateSymbolName( pSym->Name, undName, MAXNAMELEN, UNDNAME_NAME_ONLY ); UnDecorateSymbolName( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE ); strcpy (frameInfo->undecoratedName, undName); strcpy (frameInfo->undecoratedFullName, undFullName); strcpy (frameInfo->signature, pSym->Name ); frameInfo->offsetFromSymbol = offsetFromSymbol; } // show module info (SymGetModuleInfo()) if (SymGetModuleInfo( hProcess, s.AddrPC.Offset, &Module ) ) { strcpy (frameInfo->ModuleName, Module.ModuleName); strcpy (frameInfo->ImageName, Module.ImageName); frameInfo->BaseOfImage = Module.BaseOfImage; } } // we seem to have a valid PC // no return address means no deeper stackframe if ( s.AddrReturn.Offset == 0 ) { // avoid misunderstandings in the printf() following the loop SetLastError( 0 ); break; } this->frameArray.Add (frameInfo); } // for ( frameNum ) cleanup: // de-init symbol handler etc. (SymCleanup()) SymCleanup( hProcess ); free( pSym ); delete [] tt; return frameArray; }
/** Print out a stacktrace. */ static void Stacktrace(const char *threadName, LPEXCEPTION_POINTERS e, HANDLE hThread = INVALID_HANDLE_VALUE) { PIMAGEHLP_SYMBOL pSym; STACKFRAME sf; HANDLE process, thread; DWORD dwModBase, Disp, dwModAddrToPrint; BOOL more = FALSE; int count = 0; char modname[MAX_PATH]; process = GetCurrentProcess(); if(threadName) PRINT("Stacktrace (%s):", threadName); else PRINT("Stacktrace:"); bool suspended = false; CONTEXT c; if (e) { c = *e->ContextRecord; thread = GetCurrentThread(); } else { SuspendThread(hThread); suspended = true; memset(&c, 0, sizeof(CONTEXT)); c.ContextFlags = CONTEXT_FULL; // FIXME: This does not work if you want to dump the current thread's stack if (!GetThreadContext(hThread, &c)) { ResumeThread(hThread); return; } thread = hThread; } ZeroMemory(&sf, sizeof(sf)); sf.AddrPC.Offset = c.Eip; sf.AddrStack.Offset = c.Esp; sf.AddrFrame.Offset = c.Ebp; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; // use globalalloc to reduce risk for allocator related deadlock pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); char* printstrings = (char*)GlobalAlloc(GMEM_FIXED, 0); bool containsOglDll = false; while (true) { more = StackWalk( IMAGE_FILE_MACHINE_I386, // TODO: fix this for 64 bit windows? process, thread, &sf, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL ); if (!more || sf.AddrFrame.Offset == 0 || count > MAX_STACK_DEPTH) { break; } dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset); if (dwModBase) { GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH); } else { strcpy(modname, "Unknown"); } pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pSym->MaxNameLength = MAX_PATH; char* printstringsnew = (char*) GlobalAlloc(GMEM_FIXED, (count + 1) * BUFFER_SIZE); memcpy(printstringsnew, printstrings, count * BUFFER_SIZE); GlobalFree(printstrings); printstrings = printstringsnew; if (SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym)) { // This is the code path taken on VC if debugging syms are found. SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s(%s+%#0lx) [0x%08lX]", count, modname, pSym->Name, Disp, sf.AddrPC.Offset); } else { // This is the code path taken on MinGW, and VC if no debugging syms are found. if (strstr(modname, ".exe")) { // for the .exe, we need the absolute address dwModAddrToPrint = sf.AddrPC.Offset; } else { // for DLLs, we need the module-internal/relative address dwModAddrToPrint = sf.AddrPC.Offset - dwModBase; } SNPRINTF(printstrings + count * BUFFER_SIZE, BUFFER_SIZE, "(%d) %s [0x%08lX]", count, modname, dwModAddrToPrint); } // OpenGL lib names (ATI): "atioglxx.dll" "atioglx2.dll" containsOglDll = containsOglDll || strstr(modname, "atiogl"); // OpenGL lib names (Nvidia): "nvoglnt.dll" "nvoglv32.dll" "nvoglv64.dll" (last one is a guess) containsOglDll = containsOglDll || strstr(modname, "nvogl"); // OpenGL lib names (Intel): "ig4dev32.dll" "ig4dev64.dll" containsOglDll = containsOglDll || strstr(modname, "ig4dev"); ++count; } if (suspended) { ResumeThread(hThread); } if (containsOglDll) { PRINT("This stack trace indicates a problem with your graphic card driver. " "Please try upgrading or downgrading it. " "Specifically recommended is the latest driver, and one that is as old as your graphic card. " "Make sure to use a driver removal utility, before installing other drivers."); } for (int i = 0; i < count; ++i) { PRINT("%s", printstrings + i * BUFFER_SIZE); } GlobalFree(printstrings); GlobalFree(pSym); }
/* ================ Sys_PrintStackTrace Occurs when we encounter a fatal error. Prints the stack trace as well as some other data. ================ */ LONG WINAPI Sys_PrintStackTrace(EXCEPTION_POINTERS* exception) { STACKFRAME frame = {}; #ifdef WIN32 DWORD machine = IMAGE_FILE_MACHINE_I386; #else DWORD machine = IMAGE_FILE_MACHINE_AMD64; #endif HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); int i = 0; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; #ifdef WIN32 frame.AddrPC.Offset = exception->ContextRecord->Eip; frame.AddrFrame.Offset = exception->ContextRecord->Ebp; frame.AddrStack.Offset = exception->ContextRecord->Esp; #else frame.AddrPC.Offset = exception->ContextRecord->Rip; frame.AddrFrame.Offset = exception->ContextRecord->Rbp; frame.AddrStack.Offset = exception->ContextRecord->Rsp; #endif Com_Printf("------------------------\n"); Com_Printf("Enumerate Modules:\n"); Com_Printf("------------------------\n"); SymRefreshModuleList(process); SymEnumerateModules(process, Sys_PrintModule, nullptr); Com_Printf("\n\n"); Com_Printf("------------------------\n"); Com_Printf("Stack trace : \n"); Com_Printf("------------------------\n"); while (StackWalk(machine, process, thread, &frame, exception->ContextRecord, nullptr, SymFunctionTableAccess, SymGetModuleBase, nullptr)) { DWORD moduleBase = SymGetModuleBase(process, frame.AddrPC.Offset); char moduleName[MAX_PATH]; char funcName[MAX_PATH]; char fileName[MAX_PATH]; DWORD address = frame.AddrPC.Offset; char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 255]; PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)symbolBuffer; IMAGEHLP_LINE line; DWORD offset = 0; line.SizeOfStruct = sizeof(IMAGEHLP_LINE); symbol->SizeOfStruct = (sizeof IMAGEHLP_SYMBOL) + 255; symbol->MaxNameLength = 254; if (moduleBase && GetModuleFileNameA((HINSTANCE)moduleBase, moduleName, MAX_PATH)) { Sys_CleanModuleName(moduleName, MAX_PATH); } else { moduleName[0] = '\0'; } if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &offset, symbol)) { Q_strncpyz(funcName, symbol->Name, MAX_PATH); } else { funcName[0] = '\0'; } if (SymGetLineFromAddr(process, frame.AddrPC.Offset, &offset, &line)) { Q_strncpyz(fileName, line.FileName, MAX_PATH); Sys_CleanModuleName(fileName, MAX_PATH); Com_sprintf(fileName, MAX_PATH, "%s:%i", fileName, line.LineNumber); } else { fileName[0] = '\0'; } Com_Printf("%03i %20s 0x%08X | %s (%s)\n", i, moduleName, address, funcName, fileName); i++; } Sys_Error("Unhanded Exception: 0x%08X", exception->ExceptionRecord->ExceptionCode); #ifdef _DEBUG return EXCEPTION_CONTINUE_SEARCH; #else return EXCEPTION_EXECUTE_HANDLER; #endif }
static BOOL ResolveSymbol(HANDLE hProcess, DWORD dwAddress, SYMBOL_INFO &siSymbol) { BOOL fRetval = TRUE; siSymbol.dwAddress = dwAddress; union { CHAR rgchSymbol[sizeof(IMAGEHLP_SYMBOL) + 255]; IMAGEHLP_SYMBOL sym; }; CHAR szUndec[256]; CHAR szWithOffset[256]; LPSTR pszSymbol = NULL; IMAGEHLP_MODULE mi; memset(&siSymbol, 0, sizeof(SYMBOL_INFO)); mi.SizeOfStruct = sizeof(IMAGEHLP_MODULE); if (!SymGetModuleInfo(hProcess, dwAddress, &mi)) lstrcpyA(siSymbol.szModule, "<no module>"); else { LPSTR pszModule = strchr(mi.ImageName, '\\'); if (pszModule == NULL) pszModule = mi.ImageName; else pszModule++; lstrcpynA(siSymbol.szModule, pszModule, _countof(siSymbol.szModule)); lstrcatA(siSymbol.szModule, "! "); } __try { sym.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); sym.Address = dwAddress; sym.MaxNameLength = 255; if (SymGetSymFromAddr(hProcess, dwAddress, &(siSymbol.dwOffset), &sym)) { pszSymbol = sym.Name; if (UnDecorateSymbolName(sym.Name, szUndec, _countof(szUndec), UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS)) { pszSymbol = szUndec; } else if (SymUnDName(&sym, szUndec, _countof(szUndec))) { pszSymbol = szUndec; } if (siSymbol.dwOffset != 0) { wsprintfA(szWithOffset, "%s + %d bytes", pszSymbol, siSymbol.dwOffset); pszSymbol = szWithOffset; } } else pszSymbol = "<no symbol>"; } __except (EXCEPTION_EXECUTE_HANDLER) { pszSymbol = "<EX: no symbol>"; siSymbol.dwOffset = dwAddress - mi.BaseOfImage; } lstrcpynA(siSymbol.szSymbol, pszSymbol, _countof(siSymbol.szSymbol)); return fRetval; }
// Get function prototype and parameter info from ip address and stack address static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol ) { BOOL ret = FALSE; DWORD dwSymSize = 10000; TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?"); CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?"; LPTSTR lpszParamSep = nullptr; LPTSTR lpszParsed = lpszUnDSymbol; PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize ); ::ZeroMemory( pSym, dwSymSize ); pSym->SizeOfStruct = dwSymSize; pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL); // Set the default to unknown _tcscpy( lpszSymbol, _T("?") ); // Get symbol info for IP DWORD64 dwDisp = 0; if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) { // Make the symbol readable for humans UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, UNDNAME_COMPLETE | UNDNAME_NO_THISTYPE | UNDNAME_NO_SPECIAL_SYMS | UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ACCESS_SPECIFIERS ); // Symbol information is ANSI string PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol ); // I am just smarter than the symbol file :) if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 ) _tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)")); else if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 ) _tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)")); else if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 ) _tcscpy(lpszUnDSymbol, _T("mainCRTStartup()")); else if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 ) _tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)")); else if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 ) _tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()")); lpszSymbol[0] = _T('\0'); // Let's go through the stack, and modify the function prototype, and insert the actual // parameter values from the stack if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr) { ULONG index = 0; for ( ; ; index++ ) { lpszParamSep = _tcschr( lpszParsed, _T(',') ); if ( lpszParamSep == nullptr ) break; *lpszParamSep = _T('\0'); _tcscat( lpszSymbol, lpszParsed ); _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) ); lpszParsed = lpszParamSep + 1; } lpszParamSep = _tcschr( lpszParsed, _T(')') ); if ( lpszParamSep != nullptr ) { *lpszParamSep = _T('\0'); _tcscat( lpszSymbol, lpszParsed ); _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) ); lpszParsed = lpszParamSep + 1; } } _tcscat( lpszSymbol, lpszParsed ); ret = TRUE; } GlobalFree( pSym ); return ret; }
LONG WINAPI MyExceptionFilter ( EXCEPTION_POINTERS * lpep) { BOOL rVal; STACKFRAME StackFrame; CONTEXT Context; IMAGEHLP_SYMBOL *pImagehlpSymbol; ULONG Displacement; BOOL fReturn; CHAR szUndecoratedName[MAXSYMBOLNAMELENGTH]; FILE * flog; SymSetOptions(0); SymInitialize(SYM_HANDLE, NULL, TRUE); flog = fopen("c:\\Except.log","a"); if (!flog) return EXCEPTION_CONTINUE_SEARCH; printf("\ndumping stack trace\n"); ZeroMemory(&StackFrame, sizeof(StackFrame)); Context = *lpep->ContextRecord; #if defined(_M_IX86) StackFrame.AddrPC.Offset = Context.Eip; StackFrame.AddrPC.Mode = AddrModeFlat; StackFrame.AddrFrame.Offset = Context.Ebp; StackFrame.AddrFrame.Mode = AddrModeFlat; StackFrame.AddrStack.Offset = Context.Esp; StackFrame.AddrStack.Mode = AddrModeFlat; #endif pImagehlpSymbol = (IMAGEHLP_SYMBOL *) xmalloc(sizeof(IMAGEHLP_SYMBOL) + MAXSYMBOLNAMELENGTH - 1); ZeroMemory(pImagehlpSymbol, sizeof(IMAGEHLP_SYMBOL) + MAXSYMBOLNAMELENGTH - 1); pImagehlpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pImagehlpSymbol->MaxNameLength = MAXSYMBOLNAMELENGTH; do { rVal = StackWalk ( MACHINE_TYPE, SYM_HANDLE, 0, &StackFrame, &Context, ReadProcessMemory, SymFunctionTableAccess, SymGetModuleBase, NULL); if (rVal) { pImagehlpSymbol->Address = StackFrame.AddrPC.Offset; fReturn = SymGetSymFromAddr ( SYM_HANDLE, StackFrame.AddrPC.Offset, &Displacement, pImagehlpSymbol ); fprintf(flog,"%08x %08x ", StackFrame.AddrFrame.Offset, StackFrame.AddrReturn.Offset); printf("%08x %08x ", StackFrame.AddrFrame.Offset, StackFrame.AddrReturn.Offset); if (fReturn) { fReturn = SymUnDName ( pImagehlpSymbol, szUndecoratedName, MAXSYMBOLNAMELENGTH); if (fReturn) { fprintf(flog,"%s", szUndecoratedName); printf("%s", szUndecoratedName); if (Displacement){ fprintf(flog,"+%x", Displacement); printf("+%x", Displacement); } } } else{ fprintf(flog,"0x%08x", StackFrame.AddrPC.Offset); printf("0x%08x", StackFrame.AddrPC.Offset); } fprintf(flog,"\n"); printf("\n"); } } while (rVal); SymCleanup(SYM_HANDLE); fprintf(flog,"----Hit ^c to exit----\n"); fclose(flog); ExitProcess((DWORD)-1); return EXCEPTION_CONTINUE_SEARCH;//EXCEPTION_EXECUTE_HANDLER; }
static void _backtrace(struct output_buffer *ob, struct bfd_set *set, int depth , LPCONTEXT context) { char procname[MAX_PATH]; GetModuleFileNameA(NULL, procname, sizeof procname); struct bfd_ctx *bc = NULL; STACKFRAME frame; memset(&frame,0,sizeof(frame)); frame.AddrPC.Offset = context->Eip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrStack.Offset = context->Esp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Offset = context->Ebp; frame.AddrFrame.Mode = AddrModeFlat; HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); char symbol_buffer[sizeof(IMAGEHLP_SYMBOL) + 255]; char module_name_raw[MAX_PATH]; while(StackWalk(IMAGE_FILE_MACHINE_I386, process, thread, &frame, context, 0, SymFunctionTableAccess, SymGetModuleBase, 0)) { --depth; if (depth < 0) break; IMAGEHLP_SYMBOL *symbol = (IMAGEHLP_SYMBOL *)symbol_buffer; symbol->SizeOfStruct = (sizeof *symbol) + 255; symbol->MaxNameLength = 254; DWORD module_base = SymGetModuleBase(process, frame.AddrPC.Offset); const char * module_name = "[unknown module]"; if (module_base && GetModuleFileNameA((HINSTANCE)module_base, module_name_raw, MAX_PATH)) { module_name = module_name_raw; bc = get_bc(ob, set, module_name); } const char * file = NULL; const char * func = NULL; unsigned line = 0; if (bc) { find(bc,frame.AddrPC.Offset,&file,&func,&line); } if (file == NULL) { DWORD dummy = 0; if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &dummy, symbol)) { file = symbol->Name; } else { file = "[unknown file]"; } } if (func == NULL) { output_print(ob,"0x%x : %s : %s \n", frame.AddrPC.Offset, module_name, file); } else { output_print(ob,"0x%x : %s : %s (%d) : in function (%s) \n", frame.AddrPC.Offset, module_name, file, line, func); } } }
void backtrace() { static struct sym_t { HANDLE proc; sym_t() { proc = GetCurrentProcess(); SymSetOptions( SYMOPT_DEFERRED_LOADS | // シンボルを参照する必要があるときまで読み込まない SYMOPT_LOAD_LINES | // 行番号情報を読み込む SYMOPT_UNDNAME // すべてのシンボルを装飾されていない形式で表します ); if(!SymInitialize(proc, 0, true)){ throw exception("error : SymInitialize"); } // cout << "<SymInitialize>" << endl; } ~sym_t() { SymCleanup(proc); // cout << "<SymCleanup>" << endl; } } s_sym; array<void*,8> addr; int count = RtlCaptureStackBackTrace(0, addr.size(), &addr[0], 0); cout << "---- BEGIN BACKTRACE ----" << endl; for(int Li = 1; Li < count; ++Li){ auto p = reinterpret_cast<uintptr_t>(addr[Li]); IMAGEHLP_MODULE module; ::memset(&module, 0, sizeof(module)); module.SizeOfStruct = sizeof(module); if(!SymGetModuleInfo(s_sym.proc, p, &module)){ throw exception("error : SymGetModuleInfo"); } char buffer[sizeof(IMAGEHLP_SYMBOL) + MAX_PATH]; ::memset(buffer, 0, sizeof(buffer)); auto symbol = reinterpret_cast<IMAGEHLP_SYMBOL*>(buffer); symbol->SizeOfStruct = sizeof(*symbol); symbol->MaxNameLength = MAX_PATH; DWORDx disp = 0; if(!SymGetSymFromAddr(s_sym.proc, p, &disp, symbol)){ throw exception("error : SymGetSymFromAddr"); } if(!strcmp(symbol->Name, "__tmainCRTStartup")){ break; } string text = "?"; IMAGEHLP_LINE line; ::memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); DWORD disp2 = 0; if(!SymGetLineFromAddr(s_sym.proc, p, &disp2, &line)){ line.FileName = "?"; line.LineNumber = 0; text = "?"; } else { text = getline(line.FileName, line.LineNumber); } cout << Li << " : 0x" << hex << setw(sizeof(uintptr_t) * 2) << setfill('0') << p << " : " << module.ModuleName << " : " << symbol->Name << " : " << line.FileName << "(" << dec << line.LineNumber << ")" << " : " << text.c_str() << endl; } cout << "---- END BACKTRACE ----" << endl << endl; }