bool dbgsymengine::get_line_from_addr (HANDLE hProc, unsigned addr, unsigned * pdisplacement, IMAGEHLP_LINE * pLine) { #ifdef WORK_AROUND_SRCLINE_BUG // "Debugging Applications" John Robbins // The problem is that the symbol engine finds only those source // line addresses (after the first lookup) that fall exactly on // a zero displacement. I'll walk backward 100 bytes to // find the line and return the proper displacement. DWORD displacement = 0 ; while (!SymGetLineFromAddr (hProc, addr - displacement, (DWORD*)pdisplacement, pLine)) { if (100 == ++displacement) return false; } // "Debugging Applications" John Robbins // I found the line, and the source line information is correct, so // change the displacement if I had to search backward to find the source line. if (displacement) *pdisplacement = displacement; return true; #else return 0 != SymGetLineFromAddr (hProc, addr, (DWORD *) pdisplacement, pLine); #endif }
/*********************************************************************** * print_address * * Print an 16- or 32-bit address, with the nearest symbol if any. */ void print_address(const ADDRESS64* addr, BOOLEAN with_line) { char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; void* lin = memory_to_linear_addr(addr); DWORD64 disp64; DWORD disp; print_bare_address(addr); si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; if (!SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si)) return; dbg_printf(" %s", si->Name); if (disp64) dbg_printf("+0x%lx", (DWORD_PTR)disp64); if (with_line) { IMAGEHLP_LINE il; IMAGEHLP_MODULE im; il.SizeOfStruct = sizeof(il); if (SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il)) dbg_printf(" [%s:%lu]", il.FileName, il.LineNumber); im.SizeOfStruct = sizeof(im); if (SymGetModuleInfo(dbg_curr_process->handle, (DWORD_PTR)lin, &im)) dbg_printf(" in %s", im.ModuleName); } }
bool CBDTWxFrame::FilterTest(uint32_t eip, IMAGEHLP_LINE& info, bool& getAddrSuccess) { DWORD displacement = 0; getAddrSuccess = SymGetLineFromAddr(GetCurrentProcess(), eip, &displacement, &info) == TRUE; //TODO: Try to catch a mystery crash. bool bLineNumberMayOverFlow = getAddrSuccess && info.LineNumber > 100000; bool bFileNameMayBroken = getAddrSuccess && (uint32_t)info.FileName < 10; if (bLineNumberMayOverFlow || bFileNameMayBroken) { BEATS_ASSERT(false); } bool filter = false; if (getAddrSuccess) { for (uint32_t i = 0; i < m_pFilterTextComboBox->GetCount(); ++i) { if (strstr(info.FileName, m_pFilterTextComboBox->GetString(i).c_str().AsChar()) != 0) { filter = true; break; } } } return filter; }
void CBDTWxFrame::OnGridCellSelected( wxGridEvent& event ) { if ( m_memoryViewType == eMVT_Addr || m_memoryViewType == eMVT_Size || m_memoryViewType == eMVT_AllocTime) { m_pCallStackListBox->Clear(); long value = 0; uint32_t addressValueColIndex = m_memoryViewType == eMVT_Addr ? 0 : 1;//it's hard code here. wxString cellStr = m_pMemoryDataGrid->GetCellValue(event.GetRow(), addressValueColIndex); if (cellStr.IsEmpty() == false) { cellStr.ToLong(&value, 16); std::vector<uint32_t> callStack; CMemoryDetector::GetInstance()->GetCallStack(value, callStack); DWORD displacement = 0; IMAGEHLP_LINE info; char temp[256]; for (uint32_t i = 0; i < callStack.size(); ++i) { bool getAddrSuccess = SymGetLineFromAddr(GetCurrentProcess(), callStack[i], &displacement, &info) == TRUE; if (getAddrSuccess) { sprintf_s(temp, "%s line:%d", info.FileName, info.LineNumber); m_pCallStackListBox->Append(temp); } else { m_pCallStackListBox->Append("未知!"); } } } } }
size_t GetFileLineFromAddress(void* address, char* fileName, size_t size, size_t* lineNumber, size_t* offsetBytes) { if (size) *fileName = 0; if (lineNumber) *lineNumber = 0; if (offsetBytes) *offsetBytes = 0; { char* sourceName; IMAGEHLP_LINE line = { sizeof (line) }; GC_ULONG_PTR dwOffset = 0; if (!SymGetLineFromAddr(GetSymHandle(), CheckAddress(address), &dwOffset, &line)) { return 0; } if (lineNumber) { *lineNumber = line.LineNumber; } if (offsetBytes) { *offsetBytes = dwOffset; } sourceName = line.FileName; /* TODO: resolve relative filenames, found in 'source directories' */ /* registered with MSVC IDE. */ if (size) { strncpy(fileName, sourceName, size)[size - 1] = 0; } return strlen(sourceName); } }
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); } }
void P_APIENTRY pDebugPrintStack(pint32 skip) { typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG); CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(TEXT("kernel32.dll")), "RtlCaptureStackBackTrace")); if (func == NULL) { return ; } // Quote from Microsoft Documentation: // ## Windows Server 2003 and Windows XP: // ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63. const int kMaxCallers = 62; HANDLE hProcess = GetCurrentProcess(); SymInitialize(hProcess, NULL, TRUE); PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)malloc(sizeof(SYMBOL_INFO) + 256); pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = 255; void* callers[kMaxCallers]; int count = (func)(0, kMaxCallers, callers, NULL); // To skip the pDebugPrintStack function frame, we start from 1 instead of 0. for(int i = skip; i < count; i++) { //PLOG_INFO("*** %d called from %016I64LX\n", i, callers[i]); DWORD addr = (DWORD)(callers[i]); DWORD64 symDisplacement = 0; if (SymFromAddr(hProcess, addr, 0, pSymbol)) { IMAGEHLP_LINE lineInfo = {sizeof(IMAGEHLP_LINE)}; DWORD dwLineDisplacement; if (SymGetLineFromAddr(hProcess, addr, &dwLineDisplacement, &lineInfo)) { PLOG_INFO("%s:%s(),Line %u", lineInfo.FileName, pSymbol->Name, lineInfo.LineNumber); } // Stop the walk at main function. if (pstrcmp(pSymbol->Name, "main") == 0) { break; } } } SymCleanup(GetCurrentProcess()); }
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; }
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 }
const std::string PXL_stack_trace(int num_traces) { #if defined(_DEBUG) uint32 i; DWORD* stacks = new DWORD[num_traces]; uint16 frames_captured; SYMBOL_INFO* symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames_captured = CaptureStackBackTrace(0, num_traces, (PVOID*)stacks, NULL); //needs to be allocated on heap symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 192; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); IMAGEHLP_LINE line; DWORD disp; std::string output = ""; char* char_output = new char[255]; for (i = 0; i < frames_captured; i++) { SymFromAddr(process, stacks[i], NULL, symbol); SymGetLineFromAddr(process, stacks[i], &disp, &line); //convert file name to string and remove everything in the string before src or include std::string file_name = line.FileName; int id; if ((id = file_name.rfind("src")) != -1) { file_name = file_name.substr(id + 4, file_name.length()); } else if ((id = file_name.rfind("include")) != -1) { file_name = file_name.substr(id, file_name.length()); } if (id != -1) { sprintf(char_output, "%i: %s (%s, line %i)\n", frames_captured - i - 1, symbol->Name, file_name.c_str(), line.LineNumber); output += char_output; } } delete symbol; delete[] stacks; return output; #endif return ""; }
/*********************************************************************** * symbol_get_function_line_status * * Find the symbol nearest to a given address. */ enum dbg_line_status symbol_get_function_line_status(const ADDRESS64* addr) { IMAGEHLP_LINE il; DWORD disp; ULONG64 disp64, start; DWORD lin = (DWORD)memory_to_linear_addr(addr); char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* sym = (SYMBOL_INFO*)buffer; struct dbg_type func; il.SizeOfStruct = sizeof(il); sym->SizeOfStruct = sizeof(SYMBOL_INFO); sym->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO); /* do we have some info for lin address ? */ if (!SymFromAddr(dbg_curr_process->handle, lin, &disp64, sym)) return dbg_no_line_info; switch (sym->Tag) { case SymTagThunk: /* FIXME: so far dbghelp doesn't return the 16 <=> 32 thunks * and furthermore, we no longer take care of them !!! */ return dbg_in_a_thunk; case SymTagFunction: case SymTagPublicSymbol: break; default: WINE_FIXME("Unexpected sym-tag 0x%08x\n", sym->Tag); case SymTagData: return dbg_no_line_info; } /* we should have a function now */ if (!SymGetLineFromAddr(dbg_curr_process->handle, lin, &disp, &il)) return dbg_no_line_info; func.module = sym->ModBase; func.id = sym->info; if (symbol_get_debug_start(&func, &start) && lin < start) return dbg_not_on_a_line_number; if (!sym->Size) sym->Size = 0x100000; if (il.FileName && il.FileName[0] && disp < sym->Size) return (disp == 0) ? dbg_on_a_line_number : dbg_not_on_a_line_number; return dbg_no_line_info; }
/* static */ BOOL wxDbgHelpDLL::CallSymGetLineFromAddr(HANDLE hProcess, DWORD64 dwAddr, wxString* fileName, size_t* line) { DWORD dwDisplacement; #ifdef UNICODE if ( SymGetLineFromAddrW64 ) { SizedStruct<IMAGEHLP_LINEW64> lineW64; if ( SymGetLineFromAddrW64(hProcess, dwAddr, &dwDisplacement, &lineW64) ) { *fileName = lineW64.FileName; *line = lineW64.LineNumber; return TRUE; } } #endif // UNICODE if ( SymGetLineFromAddr64 ) { SizedStruct<IMAGEHLP_LINE64> line64; if ( SymGetLineFromAddr64(hProcess, dwAddr, &dwDisplacement, &line64) ) { *fileName = line64.FileName; *line = line64.LineNumber; return TRUE; } } if ( SymGetLineFromAddr ) { SizedStruct<IMAGEHLP_LINE> line32; if ( SymGetLineFromAddr(hProcess, dwAddr, &dwDisplacement, &line32) ) { *fileName = line32.FileName; *line = line32.LineNumber; return TRUE; } } return FALSE; }
void source_list_from_addr(const ADDRESS64* addr, int nlines) { IMAGEHLP_LINE il; ADDRESS64 la; DWORD disp; if (!addr) { memory_get_current_pc(&la); addr = &la; } il.SizeOfStruct = sizeof(il); if (SymGetLineFromAddr(dbg_curr_process->handle, (unsigned long)memory_to_linear_addr(addr), &disp, &il)) source_list(&il, NULL, nlines); }
BOOL CallStack::symSourceInfoFromAddress(UINT address, TCHAR* lpszSourceInfo, UINT BufSizeTCHARs) { BOOL ret = FALSE; IMAGEHLP_LINE lineInfo; DWORD dwDisp; TCHAR lpModuleInfo[MLD_MAX_NAME_LENGTH] = MLD_TRACEINFO_EMPTY; _tcscpy_s(lpszSourceInfo, BufSizeTCHARs, MLD_TRACEINFO_NOSYMBOL); memset( &lineInfo, NULL, sizeof( IMAGEHLP_LINE ) ); lineInfo.SizeOfStruct = sizeof( IMAGEHLP_LINE ); if ( SymGetLineFromAddr( m_hProcess, address, &dwDisp, &lineInfo ) ) { // Using the "sourcefile(linenumber)" format #ifdef UNICODE wchar_t dest[1024] ; int len = strlen((char *)lineInfo.FileName) + 1 ; MultiByteToWideChar(CP_ACP, 0, (char *)lineInfo.FileName, len, dest, len) ; _stprintf_s(lpszSourceInfo, BufSizeTCHARs, _T("%s(%d): 0x%08X"), dest, lineInfo.LineNumber, address );// <--- Size of the char thing. #else _stprintf_s(lpszSourceInfo, BufSizeTCHARs, _T("%s(%d): 0x%08X"), lineInfo.FileName, lineInfo.LineNumber, address );// <--- Size of the char thing. #endif ret = TRUE; } else { // Using the "modulename!address" format symModuleNameFromAddress( address, lpModuleInfo, MLD_MAX_NAME_LENGTH); if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) { // Using the "address" format _stprintf_s(lpszSourceInfo, BufSizeTCHARs, _T("0x%08X"), lpModuleInfo, address ); } else { _stprintf_s(lpszSourceInfo, BufSizeTCHARs, _T("%sdll! 0x%08X"), lpModuleInfo, address ); } ret = FALSE; } // return ret; }
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); }
xgc_void DumpStackFrame() { StackFrameSequence FrameSequence; GetStackTrace( FrameSequence ); xgc_char szSymbol[sizeof( SYMBOL_INFO ) + 1024]; SYS_TIP( "---------------stack frame begin--------------" ); for( UINT nCur = 0; nCur < FrameSequence.Count && FrameSequence.Frame[nCur]; ++nCur ) { ZeroMemory( szSymbol, sizeof( szSymbol ) ); PSYMBOL_INFO pSymInfo = (PSYMBOL_INFO) &szSymbol; pSymInfo->SizeOfStruct = sizeof( SYMBOL_INFO ); pSymInfo->MaxNameLen = sizeof( szSymbol ) - sizeof( SYMBOL_INFO ); // Get the function. DWORD64 dwDisp = 0; if( SymFromAddr( hProcess, (UINT_PTR)FrameSequence.Frame[nCur], &dwDisp, pSymInfo ) ) { // If I got a symbol, give the source and line a whirl. IMAGEHLP_LINE lineInfo; lineInfo.SizeOfStruct = sizeof( lineInfo ); DWORD dwDisplacement = 0; if( SymGetLineFromAddr( hProcess, (UINT_PTR)FrameSequence.Frame[nCur], &dwDisplacement, &lineInfo ) ) { // Put this on the next line and indented a bit. LOG_EXT_FORMAT( SYS, lineInfo.FileName, pSymInfo->Name, lineInfo.LineNumber, "stack", "stack frame %p : %s", FrameSequence.Frame[nCur], pSymInfo->Name ); } else { LOG_TAG_FORMAT( SYS, "stack", "LastError:[%u], stack frame %p", GetLastError(), FrameSequence.Frame[nCur], pSymInfo->Name ); } } else { LOG_TAG_FORMAT( SYS, "stack", "stack frame %p", FrameSequence.Frame[nCur] ); } } SYS_TIP( "---------------stack frame end--------------" ); }
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); } }
// Get source file name and line number from IP address // The output format is: "sourcefile(linenumber)" or // "modulename!address" or // "address" static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) { BOOL ret = FALSE; IMAGEHLP_LINE lineInfo; DWORD dwDisp; TCHAR lpszFileName[BUFFERSIZE] = _T(""); TCHAR lpModuleInfo[BUFFERSIZE] = _T(""); _tcscpy( lpszSourceInfo, _T("?(?)") ); ::ZeroMemory( &lineInfo, sizeof( lineInfo ) ); lineInfo.SizeOfStruct = sizeof( lineInfo ); if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) ) { // Got it. Let's use "sourcefile(linenumber)" format PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT]; _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext); _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); ret = TRUE; } else { // There is no source file information. :( // Let's use the "modulename!address" format GetModuleNameFromAddress( address, lpModuleInfo ); if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) // There is no modulename information. :(( // Let's use the "address" format _stprintf( lpszSourceInfo, _T("0x%08X"), address ); else _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address ); ret = FALSE; } return ret; }
void StackTree::printCallstack(StackNode* node) { while (node) { HANDLE process = GetCurrentProcess(); uint8 symbol_mem[sizeof(SYMBOL_INFO) + 256 * sizeof(char)]; SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(symbol_mem); memset(symbol_mem, 0, sizeof(symbol_mem)); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); BOOL success = SymFromAddr(process, (DWORD64)(node->m_instruction), 0, symbol); if (success) { IMAGEHLP_LINE line; DWORD offset; if (SymGetLineFromAddr(process, (DWORD64)(node->m_instruction), &offset, &line)) { OutputDebugString("\t"); OutputDebugString(line.FileName); OutputDebugString("("); char tmp[20]; toCString((uint32)line.LineNumber, tmp, sizeof(tmp)); OutputDebugString(tmp); OutputDebugString("):"); } OutputDebugString("\t"); OutputDebugString(symbol->Name); OutputDebugString("\n"); } else { OutputDebugString("\tN/A\n"); } node = node->m_parent; } }
/* ================ 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 }
/*********************************************************************** * symbol_get_lvalue * * Get the address of a named symbol. * Return values: * sglv_found: if the symbol is found * sglv_unknown: if the symbol isn't found * sglv_aborted: some error occurred (likely, many symbols of same name exist, * and user didn't pick one of them) */ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* rtn, BOOL bp_disp) { struct sgv_data sgv; int i; char buffer[512]; DWORD opt; IMAGEHLP_STACK_FRAME ihsf; if (strlen(name) + 4 > sizeof(buffer)) { WINE_WARN("Too long symbol (%s)\n", name); return sglv_unknown; } sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = DBG_IVAR(AlwaysShowThunks); if (strchr(name, '!')) { strcpy(buffer, name); } else { buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); } /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); if (!sgv.num) { const char* ptr = strchr(name, '!'); if ((ptr && ptr[1] != '_') || (!ptr && *name != '_')) { if (ptr) { int offset = ptr - name; memcpy(buffer, name, offset + 1); buffer[offset + 1] = '_'; strcpy(&buffer[offset + 2], ptr + 1); } else { buffer[0] = '*'; buffer[1] = '!'; buffer[2] = '_'; strcpy(&buffer[3], name); } SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv); } } SymSetOptions(opt); /* now grab local symbols */ if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV) { sgv.frame_offset = ihsf.FrameOffset; SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv); } if (!sgv.num) { dbg_printf("No symbols found for %s\n", name); return sglv_unknown; } /* recompute potential offsets for functions (linenumber, skip prolog) */ for (i = 0; i < sgv.num; i++) { if (sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL|SYMFLAG_LOCAL|SYMFLAG_THUNK)) continue; if (lineno == -1) { struct dbg_type type; ULONG64 addr; type.module = sgv.syms[i].lvalue.type.module; type.id = sgv.syms[i].sym_info; if (bp_disp && symbol_get_debug_start(&type, &addr)) sgv.syms[i].lvalue.addr.Offset = addr; } else { DWORD disp; IMAGEHLP_LINE il; BOOL found = FALSE; il.SizeOfStruct = sizeof(il); SymGetLineFromAddr(dbg_curr_process->handle, (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr), &disp, &il); do { if (lineno == il.LineNumber) { sgv.syms[i].lvalue.addr.Offset = il.Address; found = TRUE; break; } } while (SymGetLineNext(dbg_curr_process->handle, &il)); if (!found) WINE_FIXME("No line (%d) found for %s (setting to symbol start)\n", lineno, name); } } i = 0; if (dbg_interactiveP) { if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) { dbg_printf("Many symbols with name '%s', " "choose the one you want (<cr> to abort):\n", name); for (i = 0; i < sgv.num; i++) { if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) continue; dbg_printf("[%d]: ", i + 1); if (sgv.syms[i].flags & SYMFLAG_LOCAL) { dbg_printf("%s %sof %s\n", sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", name); } else if (sgv.syms[i].flags & SYMFLAG_THUNK) { print_address(&sgv.syms[i].lvalue.addr, TRUE); /* FIXME: should display where the thunks points to */ dbg_printf(" thunk %s\n", name); } else { print_address(&sgv.syms[i].lvalue.addr, TRUE); dbg_printf("\n"); } } do { i = 0; if (input_read_line("=> ", buffer, sizeof(buffer))) { if (buffer[0] == '\0') return sglv_aborted; i = atoi(buffer); if (i < 1 || i > sgv.num) dbg_printf("Invalid choice %d\n", i); } else return sglv_aborted; } while (i < 1 || i > sgv.num); /* The array is 0-based, but the choices are 1..n, * so we have to subtract one before returning. */ i--; } } else { /* FIXME: could display the list of non-picked up symbols */ if (sgv.num > 1) dbg_printf("More than one symbol named %s, picking the first one\n", name); } *rtn = sgv.syms[i].lvalue; return sglv_found; }
void printTrace() { SymInitialize(GetCurrentProcess(), NULL, TRUE); UINT32 maxframes = 62; UINT_PTR myFrames[62]; ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes); ULONG BackTraceHash; maxframes = CaptureStackBackTrace(0, maxframes, reinterpret_cast<PVOID*>(myFrames), &BackTraceHash); const UINT_PTR* pFrame = myFrames; const size_t frameSize = maxframes; UINT32 startIndex = 0; int unresolvedFunctionsCount = 0; IMAGEHLP_LINE sourceInfo = { 0 }; sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE); // Use static here to increase performance, and avoid heap allocs. // It's thread safe because of g_heapMapLock lock. static char stack_line[1024] = ""; bool isPrevFrameInternal = false; DWORD NumChars = 0; const size_t max_line_length = 512; const int resolvedCapacity = 62 * max_line_length; const size_t allocedBytes = resolvedCapacity * sizeof(char); char resolved[resolvedCapacity]; if (resolved) { ZeroMemory(resolved, allocedBytes); } HANDLE hProcess = GetCurrentProcess(); int resolvedLength = 0; // Iterate through each frame in the call stack. for (UINT32 frame = 0; frame < frameSize; frame++) { if (pFrame[frame] == 0) break; // Try to get the source file and line number associated with // this program counter address. SIZE_T programCounter = pFrame[frame]; DWORD64 displacement64; BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 256 * sizeof(char)]; LPCSTR functionName = getFunctionName(programCounter, displacement64, (SYMBOL_INFO*)&symbolBuffer); // It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here // in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns. // When that happens there is nothing we can do except crash. DWORD displacement = 0; BOOL foundline = SymGetLineFromAddr(hProcess, programCounter, &displacement, &sourceInfo); bool isFrameInternal = false; // show one allocation function for context if (NumChars > 0 && !isFrameInternal && isPrevFrameInternal) { resolvedLength += NumChars; if (resolved) { strncat_s(resolved, resolvedCapacity, stack_line, NumChars); } } isPrevFrameInternal = isFrameInternal; if (!foundline) displacement = (DWORD)displacement64; NumChars = resolveFunction(programCounter, foundline ? &sourceInfo : NULL, displacement, functionName, stack_line, _countof(stack_line)); if (NumChars > 0 && !isFrameInternal) { resolvedLength += NumChars; if (resolved) { strncat_s(resolved, resolvedCapacity, stack_line, NumChars); } } } // end for loop printLog(resolved); SymCleanup(GetCurrentProcess()); return; }
void DumpStackStak(HANDLE hLogFile, PEXCEPTION_POINTERS lpExcetion) { STACKFRAME stackFrame; #ifdef _X86_ stackFrame.AddrPC.Offset = lpExcetion->ContextRecord->Eip; stackFrame.AddrPC.Mode = AddrModeFlat; stackFrame.AddrStack.Offset = lpExcetion->ContextRecord->Esp; stackFrame.AddrStack.Mode = AddrModeFlat; stackFrame.AddrFrame.Offset = lpExcetion->ContextRecord->Ebp; stackFrame.AddrFrame.Mode = AddrModeFlat; #else stackFrame.AddrPC.Offset = (DWORD)lpExcetion->ContextRecord->Fir ; stackFrame.AddrPC.Mode = AddrModeFlat ; stackFrame.AddrReturn.Offset = (DWORD)lpExcetion->ContextRecord->IntRa; stackFrame.AddrReturn.Mode = AddrModeFlat ; stackFrame.AddrStack.Offset = (DWORD)lpExcetion->ContextRecord->IntSp; stackFrame.AddrStack.Mode = AddrModeFlat ; stackFrame.AddrFrame.Offset = (DWORD)lpExcetion->ContextRecord->IntFp; stackFrame.AddrFrame.Mode = AddrModeFlat ; #endif //set up symbol engine DWORD dwOpts = SymGetOptions(); SymSetOptions(dwOpts|SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); SymInitialize(GetCurrentProcess(), NULL, TRUE); #ifdef _WIN64 #define CH_MACHINE IMAGE_FILE_MACHINE_IA64 #else #define CH_MACHINE IMAGE_FILE_MACHINE_I386 #endif WriteLogFile(hLogFile, "\r\n\r\nStack trace list:\r\n"); do { BOOL bRet = StackWalk(CH_MACHINE, GetCurrentProcess(), GetCurrentThread(), &stackFrame, lpExcetion->ContextRecord, (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory, SymFunctionTableAccess, SymGetModuleBase, NULL); if (bRet == FALSE || stackFrame.AddrFrame.Offset == 0) break; DWORD dwModuleBase = SymGetModuleBase(GetCurrentProcess(), stackFrame.AddrPC.Offset); if (dwModuleBase == 0) break; //module name of call TCHAR szModuleName[MAX_PATH] = {0}; GetModuleFileName((HMODULE)dwModuleBase, szModuleName, MAX_PATH); //funtion name DWORD dwDisp = 0; TCHAR szFuntionName[MAX_PATH+sizeof(IMAGEHLP_SYMBOL)] = {0}; PIMAGEHLP_SYMBOL lpSymb = (PIMAGEHLP_SYMBOL)szFuntionName; lpSymb->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); lpSymb->MaxNameLength = MAX_PATH; SymGetSymFromAddr(GetCurrentProcess(), stackFrame.AddrPC.Offset, &dwDisp, lpSymb); //line number and filename IMAGEHLP_LINE hlpLine; SymGetLineFromAddr(GetCurrentProcess(), (DWORD)stackFrame.AddrPC.Offset, &dwDisp, &hlpLine); WriteLogFile(hLogFile, "%s-%s %s::%d\r\n", lpSymb->Name, GetFilePart(szModuleName), hlpLine.FileName, hlpLine.LineNumber); } while (1); }
void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream) { HANDLE m_hProcess = GetCurrentProcess(); DWORD dwMachineType = 0; CONTEXT context = *pContext; // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) ) { return; } STACKFRAME sf; memset( &sf, 0, sizeof(sf) ); #ifdef _M_IX86 // Initialize the STACKFRAME structure for the first call. This is only // necessary for Intel CPUs, and isn't mentioned in the documentation. sf.AddrPC.Offset = context.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = context.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = context.Ebp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_I386; #endif while ( 1 ) { // Get the next stack frame if ( ! StackWalk( dwMachineType, m_hProcess, GetCurrentThread(), &sf, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0 ) ) break; if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure break; // the frame is OK. Bail if not. // Get the name of the function for this stack frame entry BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + MAX_SYM_NAME ]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; DWORD64 symDisplacement = 0; // Displacement of the input address, // relative to the start of the symbol IMAGEHLP_MODULE module = { sizeof(IMAGEHLP_MODULE) }; if(SymGetModuleInfo(m_hProcess, sf.AddrPC.Offset, &module)) { outputStream << module.ModuleName << "!"; if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol)) { char undecoratedName[MAX_SYM_NAME]; UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE); outputStream << undecoratedName; outputStream << "("; // Use SymSetContext to get just the locals/params for this frame IMAGEHLP_STACK_FRAME imagehlpStackFrame; imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; SymSetContext( m_hProcess, &imagehlpStackFrame, 0 ); // Enumerate the locals/parameters EnumerateSymbolsContext context(sf, outputStream); SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context ); outputStream << ")"; outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement)); // Get the source line for this stack frame entry IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) }; DWORD dwLineDisplacement; if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo ) ) { outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber); } } else { outputStream << Address(reinterpret_cast<void*>(sf.AddrPC.Offset)); } } outputStream << "\n"; } SymCleanup(m_hProcess); return; }
static void dumpBacktrace( unsigned int depth ) { if ( depth == 0 ) depth = 20; #if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__) int stderr_fd = -1; if ( access( "/usr/bin/c++filt", X_OK ) < 0 ) { myPrint( "Stacktrace (c++filt NOT FOUND):\n" ); } else { int fd[2]; if ( pipe( fd ) == 0 && fork() == 0 ) { close( STDIN_FILENO ); // close stdin // stdin from pipe if ( dup( fd[0] ) != STDIN_FILENO ) { QgsDebugMsg( "dup to stdin failed" ); } close( fd[1] ); // close writing end execl( "/usr/bin/c++filt", "c++filt", static_cast< char * >( nullptr ) ); perror( "could not start c++filt" ); exit( 1 ); } myPrint( "Stacktrace (piped through c++filt):\n" ); stderr_fd = dup( STDERR_FILENO ); close( fd[0] ); // close reading end close( STDERR_FILENO ); // close stderr // stderr to pipe int stderr_new = dup( fd[1] ); if ( stderr_new != STDERR_FILENO ) { if ( stderr_new >= 0 ) close( stderr_new ); QgsDebugMsg( "dup to stderr failed" ); } close( fd[1] ); // close duped pipe } void **buffer = new void *[ depth ]; int nptrs = backtrace( buffer, depth ); backtrace_symbols_fd( buffer, nptrs, STDERR_FILENO ); delete [] buffer; if ( stderr_fd >= 0 ) { int status; close( STDERR_FILENO ); int dup_stderr = dup( stderr_fd ); if ( dup_stderr != STDERR_FILENO ) { close( dup_stderr ); QgsDebugMsg( "dup to stderr failed" ); } close( stderr_fd ); wait( &status ); } #elif defined(Q_OS_WIN) void **buffer = new void *[ depth ]; SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME ); SymInitialize( GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols;http://download.osgeo.org/osgeo4w/symstore", TRUE ); unsigned short nFrames = CaptureStackBackTrace( 1, depth, buffer, nullptr ); SYMBOL_INFO *symbol = ( SYMBOL_INFO * ) qgsMalloc( sizeof( SYMBOL_INFO ) + 256 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); IMAGEHLP_LINE *line = ( IMAGEHLP_LINE * ) qgsMalloc( sizeof( IMAGEHLP_LINE ) ); line->SizeOfStruct = sizeof( IMAGEHLP_LINE ); for ( int i = 0; i < nFrames; i++ ) { DWORD dwDisplacement; SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol ); symbol->Name[ 255 ] = 0; if ( SymGetLineFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[i] ), &dwDisplacement, line ) ) { myPrint( "%s(%d) : (%s) frame %d, address %x\n", line->FileName, line->LineNumber, symbol->Name, i, symbol->Address ); } else { myPrint( "%s(%d) : (%s) unknown source location, frame %d, address %x [GetLastError()=%d]\n", __FILE__, __LINE__, symbol->Name, i, symbol->Address, GetLastError() ); } } qgsFree( symbol ); qgsFree( line ); #else Q_UNUSED( depth ); #endif }
/* Runs a stack trace * Parameters: * e - The exception information * Returns: * The stack trace with function and line number information */ __inline char *StackTrace(EXCEPTION_POINTERS *e) { static char buffer[5000]; char curmodule[32]; DWORD symOptions, dwDisp, frame; HANDLE hProcess = GetCurrentProcess(); IMAGEHLP_SYMBOL *pSym = MyMallocEx(sizeof(IMAGEHLP_SYMBOL)+500); IMAGEHLP_LINE pLine; IMAGEHLP_MODULE pMod; STACKFRAME Stack; /* Load the stack information */ memset(&Stack, 0, sizeof(Stack)); Stack.AddrPC.Offset = e->ContextRecord->Eip; Stack.AddrPC.Mode = AddrModeFlat; Stack.AddrFrame.Offset = e->ContextRecord->Ebp; Stack.AddrFrame.Mode = AddrModeFlat; Stack.AddrStack.Offset = e->ContextRecord->Esp; Stack.AddrStack.Mode = AddrModeFlat; if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) hProcess = (HANDLE)GetCurrentProcessId(); else hProcess = GetCurrentProcess(); /* Initialize symbol retrieval system */ SymInitialize(hProcess, NULL, TRUE); SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_UNDNAME); bzero(pSym, sizeof(IMAGEHLP_SYMBOL)+500); pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); pSym->MaxNameLength = 500; bzero(&pLine, sizeof(IMAGEHLP_LINE)); pLine.SizeOfStruct = sizeof(IMAGEHLP_LINE); bzero(&pMod, sizeof(IMAGEHLP_MODULE)); pMod.SizeOfStruct = sizeof(IMAGEHLP_MODULE); /* Retrieve the first module name */ SymGetModuleInfo(hProcess, Stack.AddrPC.Offset, &pMod); strcpy(curmodule, pMod.ModuleName); sprintf(buffer, "\tModule: %s\n", pMod.ModuleName); /* Walk through the stack */ for (frame = 0; ; frame++) { char buf[500]; if (!StackWalk(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &Stack, NULL, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) break; SymGetModuleInfo(hProcess, Stack.AddrPC.Offset, &pMod); if (strcmp(curmodule, pMod.ModuleName)) { strcpy(curmodule, pMod.ModuleName); sprintf(buf, "\tModule: %s\n", pMod.ModuleName); strcat(buffer, buf); } SymGetLineFromAddr(hProcess, Stack.AddrPC.Offset, &dwDisp, &pLine); SymGetSymFromAddr(hProcess, Stack.AddrPC.Offset, &dwDisp, pSym); sprintf(buf, "\t\t#%d %s:%d: %s\n", frame, pLine.FileName, pLine.LineNumber, pSym->Name); strcat(buffer, buf); } return buffer; }
/*********************************************************************** * dbg_exception_prolog * * Examine exception and decide if interactive mode is entered(return TRUE) * or exception is silently continued(return FALSE) * is_debug means the exception is a breakpoint or single step exception */ static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec) { ADDRESS64 addr; BOOL is_break; char hexbuf[MAX_OFFSET_TO_STR_LEN]; memory_get_current_pc(&addr); break_suspend_execution(); dbg_curr_thread->excpt_record = *rec; dbg_curr_thread->in_exception = TRUE; if (!is_debug) { switch (addr.Mode) { case AddrModeFlat: dbg_printf(" in 32-bit code (%s)", memory_offset_to_string(hexbuf, addr.Offset, 0)); break; case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset); break; default: dbg_printf(" bad address"); } dbg_printf(".\n"); } /* this will resynchronize builtin dbghelp's internal ELF module list */ SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0); if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break); /* * Do a quiet backtrace so that we have an idea of what the situation * is WRT the source files. */ stack_fetch_frames(); if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode)) return FALSE; if (addr.Mode != dbg_curr_thread->addr_mode) { const char* name = NULL; switch (addr.Mode) { case AddrMode1616: name = "16 bit"; break; case AddrMode1632: name = "32 bit"; break; case AddrModeReal: name = "vm86"; break; case AddrModeFlat: name = "32 bit"; break; } dbg_printf("In %s mode.\n", name); dbg_curr_thread->addr_mode = addr.Mode; } display_print(); if (!is_debug) { /* This is a real crash, dump some info */ be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); stack_backtrace(dbg_curr_tid); } else { static char* last_name; static char* last_file; char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; void* lin = memory_to_linear_addr(&addr); DWORD64 disp64; IMAGEHLP_LINE il; DWORD disp; si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; il.SizeOfStruct = sizeof(il); if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) && SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il)) { if ((!last_name || strcmp(last_name, si->Name)) || (!last_file || strcmp(last_file, il.FileName))) { HeapFree(GetProcessHeap(), 0, last_name); HeapFree(GetProcessHeap(), 0, last_file); last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name); last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName); dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber); } } } if (!is_debug || is_break || dbg_curr_thread->exec_mode == dbg_exec_step_over_insn || dbg_curr_thread->exec_mode == dbg_exec_step_into_insn) { ADDRESS64 tmp = addr; /* Show where we crashed */ memory_disasm_one_insn(&tmp); } source_list_from_addr(&addr, 0); return TRUE; }
static void JKG_WriteStackCrawl( fileHandle_t *f, DWORD *stackCrawl ) { int i, dmod, gotsource, sourcedisp; HANDLE proc, thread; IMAGEHLP_LINE line; DWORD disp; char ModName[260]; static char SymPath[4096]; static char basepath[260]; static char fspath[260]; PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL)malloc(1024); proc = GetCurrentProcess(); thread = GetCurrentThread(); SymPath[0] = 0; basepath[0] = 0; fspath[0] = 0; InitSymbolPath(SymPath, NULL); SymInitialize(proc, SymPath, TRUE); memset(sym, 0, 1024); sym->MaxNameLength = 800; sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); for(i = 0; i < MAX_JKG_ASSERT_STACK_CRAWL; i++) { if(stackCrawl[i] == 0) continue; // Grab the base address of the module that's the problem atm dmod = SymGetModuleBase(proc, stackCrawl[i]); if (!dmod) { strcpy(ModName,"Unknown"); } else { GetModuleBaseName(proc,(HMODULE)dmod, ModName, 260); } if (SymGetLineFromAddr(proc, stackCrawl[i], (PDWORD)&sourcedisp, &line)) { gotsource = 1; } else { gotsource = 0; } if (SymGetSymFromAddr(proc, stackCrawl[i], &disp, sym)) { if (gotsource) { JKG_WriteToAssertLogEasy(va("%s::%s(+0x%X) [0x%08X] - (%s:%i)\r\n", ModName, sym->Name, disp, stackCrawl[i], line.FileName, line.LineNumber), f); } else { JKG_WriteToAssertLogEasy(va("%s::%s(+0x%X) [0x%08X]\r\n", ModName, sym->Name, disp, stackCrawl[i]), f); } } else { if (gotsource) { // Not likely... JKG_WriteToAssertLogEasy(va("%s [0x%08X] - (%s:%i)\r\n", ModName, stackCrawl[i], line.FileName, line.LineNumber), f); } else { JKG_WriteToAssertLogEasy(va("%s [0x%08X]\r\n", ModName, stackCrawl[i]), f); } } } free(sym); JKG_WriteToAssertLogEasy("\r\n", f); }
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; }
/*********************************************************************** * symbol_get_line * * Find the symbol nearest to a given address. * Returns sourcefile name and line number in a format that the listing * handler can deal with. */ BOOL symbol_get_line(const char* filename, const char* name, IMAGEHLP_LINE* line) { struct sgv_data sgv; char buffer[512]; DWORD opt, disp, linear; unsigned i, found = FALSE; IMAGEHLP_LINE il; sgv.num = 0; sgv.num_thunks = 0; sgv.name = &buffer[2]; sgv.do_thunks = FALSE; buffer[0] = '*'; buffer[1] = '!'; strcpy(&buffer[2], name); /* this is a wine specific options to return also ELF modules in the * enumeration */ SymSetOptions((opt = SymGetOptions()) | 0x40000000); if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv)) { SymSetOptions(opt); return FALSE; } if (!sgv.num && (name[0] != '_')) { buffer[2] = '_'; strcpy(&buffer[3], name); if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv)) { SymSetOptions(opt); return FALSE; } } SymSetOptions(opt); for (i = 0; i < sgv.num; i++) { linear = (DWORD)memory_to_linear_addr(&sgv.syms[i].lvalue.addr); il.SizeOfStruct = sizeof(il); if (!SymGetLineFromAddr(dbg_curr_process->handle, linear, &disp, &il)) continue; if (filename && strcmp(line->FileName, filename)) continue; if (found) { WINE_FIXME("Several found, returning first (may not be what you want)...\n"); break; } found = TRUE; *line = il; } if (!found) { if (filename) dbg_printf("No such function %s in %s\n", name, filename); else dbg_printf("No such function %s\n", name); return FALSE; } return TRUE; }