//----------------------------------------------------------------------------// static void dumpBacktrace(size_t frames) { #if defined(__ANDROID__) // Not implemented yet. CEGUI_UNUSED(frames); #else #if defined(_DEBUG) || defined(DEBUG) #if defined(_MSC_VER) SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES); if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) return; HANDLE thread = GetCurrentThread(); CONTEXT context; RtlCaptureContext(&context); STACKFRAME64 stackframe; ZeroMemory(&stackframe, sizeof(stackframe)); stackframe.AddrPC.Mode = AddrModeFlat; stackframe.AddrStack.Mode = AddrModeFlat; stackframe.AddrFrame.Mode = AddrModeFlat; #if _M_IX86 stackframe.AddrPC.Offset = context.Eip; stackframe.AddrStack.Offset = context.Esp; stackframe.AddrFrame.Offset = context.Ebp; DWORD machine_arch = IMAGE_FILE_MACHINE_I386; #elif _M_X64 stackframe.AddrPC.Offset = context.Rip; stackframe.AddrStack.Offset = context.Rsp; stackframe.AddrFrame.Offset = context.Rbp; DWORD machine_arch = IMAGE_FILE_MACHINE_AMD64; #endif char symbol_buffer[1024]; ZeroMemory(symbol_buffer, sizeof(symbol_buffer)); PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(symbol_buffer); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = sizeof(symbol_buffer) - sizeof(SYMBOL_INFO); Logger& logger(Logger::getSingleton()); logger.logEvent("========== Start of Backtrace ==========", Errors); size_t frame_no = 0; while (StackWalk64(machine_arch, GetCurrentProcess(), thread, &stackframe, &context, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0) && stackframe.AddrPC.Offset) { symbol->Address = stackframe.AddrPC.Offset; DWORD64 displacement = 0; char signature[256]; if (SymFromAddr(GetCurrentProcess(), symbol->Address, &displacement, symbol)) UnDecorateSymbolName(symbol->Name, signature, sizeof(signature), UNDNAME_COMPLETE); else sprintf_s(signature, sizeof(signature), "%p", ULongToPtr(symbol->Address)); IMAGEHLP_MODULE64 modinfo; modinfo.SizeOfStruct = sizeof(modinfo); const BOOL have_image_name = SymGetModuleInfo64(GetCurrentProcess(), symbol->Address, &modinfo); char outstr[512]; sprintf_s(outstr, sizeof(outstr), "#%d %s +%#llx (%s)", frame_no, signature, displacement, (have_image_name ? modinfo.LoadedImageName : "????")); logger.logEvent(outstr, Errors); if (++frame_no >= frames) break; if (!stackframe.AddrReturn.Offset) break; } logger.logEvent("========== End of Backtrace ==========", Errors); SymCleanup(GetCurrentProcess()); #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__HAIKU__) void* buffer[frames]; const int received = backtrace(&buffer[0], frames); Logger& logger(Logger::getSingleton()); logger.logEvent("========== Start of Backtrace ==========", Errors); for (int i = 0; i < received; ++i) { char outstr[512]; Dl_info info; if (dladdr(buffer[i], &info)) { if (!info.dli_sname) snprintf(outstr, 512, "#%d %p (%s)", i, buffer[i], info.dli_fname); else { ptrdiff_t offset = static_cast<char*>(buffer[i]) - static_cast<char*>(info.dli_saddr); int demangle_result = 0; char* demangle_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &demangle_result); snprintf(outstr, 512, "#%d %s +%#tx (%s)", i, demangle_name ? demangle_name : info.dli_sname, offset, info.dli_fname); std::free(demangle_name); } } else snprintf(outstr, 512, "#%d --- error ---", i); logger.logEvent(outstr, Errors); } logger.logEvent("========== End of Backtrace ==========", Errors); #else CEGUI_UNUSED(frames); #endif #else CEGUI_UNUSED(frames); #endif #endif }
static void dumpBacktrace( unsigned int depth ) { if ( depth == 0 ) depth = 20; #if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__) // Below there is a bunch of operations that are not safe in multi-threaded // environment (dup()+close() combo, wait(), juggling with file descriptors). // Maybe some problems could be resolved with dup2() and waitpid(), but it seems // that if the operations on descriptors are not serialized, things will get nasty. // That's why there's this lovely mutex here... static QMutex mutex; QMutexLocker locker( &mutex ); 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 }
//============================================================================== std::vector <std::string> getStackBacktrace() { std::vector <std::string> result; #if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD assert(false); // sorry, not implemented yet! #elif BEAST_WINDOWS HANDLE process = GetCurrentProcess(); SymInitialize (process, nullptr, TRUE); void* stack[128]; int frames = (int) CaptureStackBackTrace (0, std::distance(std::begin(stack), std::end(stack)), stack, nullptr); // Allow symbols that are up to 1024 characters long. std::size_t constexpr nameLength = 1024; alignas(SYMBOL_INFO) unsigned char symbuf[ sizeof(SYMBOL_INFO) + nameLength * sizeof(SYMBOL_INFO::Name)]; auto symbol = reinterpret_cast<SYMBOL_INFO*>(symbuf); for (int i = 0; i < frames; ++i) { DWORD64 displacement = 0; std::memset (symbol, 0, sizeof(symbuf)); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = nameLength; if (SymFromAddr (process, (DWORD64)stack[i], &displacement, symbol)) { std::string frame; frame.append (std::to_string (i) + ": "); IMAGEHLP_MODULE64 moduleInfo { sizeof(moduleInfo) }; if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo)) { frame.append (moduleInfo.ModuleName); frame.append (": "); } frame.append (symbol->Name); if (displacement) { frame.append ("+"); frame.append (std::to_string (displacement)); } result.push_back (frame); } } #else void* stack[128]; int frames = backtrace (stack, std::distance(std::begin(stack), std::end(stack))); std::unique_ptr<char*[], decltype(std::free)*> frame { backtrace_symbols (stack, frames), std::free }; for (int i = 0; i < frames; ++i) result.push_back (frame[i]); #endif return result; }
void AbstractBTGenerator::Run(HANDLE hThread, bool bFaultingThread) { assert(m_process.IsValid()); assert(hThread); if (!Init()) { assert(false); return; } if (bFaultingThread) { const QString threadInfo = QString("Faulting thread (%1)").arg( reinterpret_cast<quintptr>(hThread) ); emit DebugLine(threadInfo); } else { const QString threadInfo = QString("Thread %1").arg( reinterpret_cast<quintptr>(hThread) ); emit DebugLine(threadInfo); } //HANDLE hFile = CreateFile(L"C:\\test\\test.dmp", FILE_ALL_ACCESS, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); //if (!MiniDumpWriteDump(m_process.GetHandle(), m_process.GetId(), hFile, // MiniDumpNormal, NULL, NULL, NULL)) //{ // HRESULT hres = (HRESULT) GetLastError(); // printf("%08X\n\n", hres); //} //SafeCloseHandle(hFile); DWORD dw = SuspendThread(hThread); assert(dw != DWORD(-1)); if (dw == DWORD(-1)) { qCritical() << "SuspendThread() failed: " << GetLastError(); return; } CONTEXT context; ZeroMemory(&context, sizeof(context)); if (!bFaultingThread) { // if it's not the faulting thread, get its context context.ContextFlags = CONTEXT_FULL; if (!GetThreadContext(hThread, &context)) { ResumeThread(hThread); assert(false); qCritical() << "GetThreadContext() failed: " << GetLastError(); return; } } else { // if it is, get it from KCrash HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, sharedMemoryName); if (hMapFile == NULL) { qCritical() << "OpenFileMapping() failed: " << GetLastError(); return; } CONTEXT *othercontext = (CONTEXT*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CONTEXT)); if (othercontext == NULL) { qCritical() << "MapViewOfFile() failed: " << GetLastError(); SafeCloseHandle(hMapFile); return; } CopyMemory(&context, othercontext, sizeof(CONTEXT)); UnmapViewOfFile(othercontext); // continue even if it fails SafeCloseHandle(hMapFile); } // some of this stuff is taken from StackWalker ZeroMemory(&m_currentFrame, sizeof(m_currentFrame)); DWORD machineType = IMAGE_FILE_MACHINE_UNKNOWN; #if defined(_M_IX86) machineType = IMAGE_FILE_MACHINE_I386; m_currentFrame.AddrPC.Offset = context.Eip; m_currentFrame.AddrFrame.Offset = context.Ebp; m_currentFrame.AddrStack.Offset = context.Esp; #elif defined(_M_X64) machineType = IMAGE_FILE_MACHINE_AMD64; m_currentFrame.AddrPC.Offset = context.Rip; m_currentFrame.AddrFrame.Offset = context.Rbp; m_currentFrame.AddrStack.Offset = context.Rsp; #else # error This architecture is not supported. #endif m_currentFrame.AddrPC.Mode = AddrModeFlat; m_currentFrame.AddrFrame.Mode = AddrModeFlat; m_currentFrame.AddrStack.Mode = AddrModeFlat; SymSetOptions(SymGetOptions() | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES); SymInitialize(m_process.GetHandle(), NULL, FALSE); LoadSymbols(); for (int i = 0; /*nothing*/; i++) { SetLastError(0); if (!StackWalk64( machineType, m_process.GetHandle(), hThread, &m_currentFrame, &context, &Callbacks::ReadProcessMemory, &Callbacks::SymFunctionTableAccess64, &Callbacks::SymGetModuleBase64, NULL)) { emit Finished(); qDebug() << "Stackwalk finished; GetLastError=" << GetLastError(); break; } FrameChanged(); QString modulename = GetModuleName(); QString functionname = GetFunctionName(); QString file = GetFile(); int line = GetLine(); QString address = QString::number(m_currentFrame.AddrPC.Offset, 16); QString debugLine = QString::fromLatin1(BACKTRACE_FORMAT). arg(modulename).arg(functionname).arg(file).arg(line).arg(address); emit DebugLine(debugLine); } // Resume the target thread now, or else the crashing process will not // be terminated ResumeThread(hThread); SymCleanup(m_process.GetHandle()); emit DebugLine(QString()); }
int main(int argc, char *argv[]) { DWORD error; HANDLE process; ULONG64 module_base; int i; char* search; char buf[256]; /* Enough to hold one hex address, I trust! */ int rv = 0; /* We may add SYMOPT_UNDNAME if --demangle is specified: */ DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; char* filename = "a.out"; /* The default if -e isn't specified */ int print_function_name = 0; /* Set to 1 if -f is specified */ for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { print_function_name = 1; } else if (strcmp(argv[i], "--demangle") == 0 || strcmp(argv[i], "-C") == 0) { symopts |= SYMOPT_UNDNAME; } else if (strcmp(argv[i], "--exe") == 0 || strcmp(argv[i], "-e") == 0) { if (i + 1 >= argc) { fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); return 1; } filename = argv[i+1]; i++; /* to skip over filename too */ } else if (strcmp(argv[i], "--help") == 0) { usage(); exit(0); } else { usage(); exit(1); } } process = GetCurrentProcess(); if (!SymInitialize(process, NULL, FALSE)) { error = GetLastError(); fprintf(stderr, "SymInitialize returned error : %lu\n", error); return 1; } search = malloc(SEARCH_CAP); if (SymGetSearchPath(process, search, SEARCH_CAP)) { if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { fprintf(stderr, "Search path too long\n"); SymCleanup(process); return 1; } strcat(search, ";" WEBSYM); } else { error = GetLastError(); fprintf(stderr, "SymGetSearchPath returned error : %lu\n", error); rv = 1; /* An error, but not a fatal one */ strcpy(search, WEBSYM); /* Use a default value */ } if (!SymSetSearchPath(process, search)) { error = GetLastError(); fprintf(stderr, "SymSetSearchPath returned error : %lu\n", error); rv = 1; /* An error, but not a fatal one */ } SymSetOptions(symopts); module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); if (!module_base) { /* SymLoadModuleEx failed */ error = GetLastError(); fprintf(stderr, "SymLoadModuleEx returned error : %lu for %s\n", error, filename); SymCleanup(process); return 1; } buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ while (fgets(buf, sizeof(buf)-1, stdin)) { /* GNU addr2line seems to just do a strtol and ignore any * weird characters it gets, so we will too. */ unsigned __int64 reladdr = _strtoui64(buf, NULL, 16); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; memset(buffer, 0, sizeof(buffer)); PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; IMAGEHLP_LINE64 line; DWORD dummy; // Just ignore overflow. In an overflow scenario, the resulting address // will be lower than module_base which hasn't been mapped by any prior // SymLoadModuleEx() command. This will cause SymFromAddr() and // SymGetLineFromAddr64() both to return failures and print the correct // ?? and ??:0 message variant. ULONG64 absaddr = reladdr + module_base; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); // The length of the name is not including the null-terminating character. pSymbol->MaxNameLen = MAX_SYM_NAME - 1; if (print_function_name) { if (SymFromAddr(process, (DWORD64)absaddr, NULL, pSymbol)) { printf("%s\n", pSymbol->Name); } else { printf("??\n"); } } line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); if (SymGetLineFromAddr64(process, (DWORD64)absaddr, &dummy, &line)) { printf("%s:%d\n", line.FileName, (int)line.LineNumber); } else { printf("??:0\n"); } } SymUnloadModule64(process, module_base); SymCleanup(process); return rv; }
ULONG getSymbols() { CString FilePathName; PCSTR path; DWORD error; DWORD64 dw64Base; DWORD dwFileSize; g_CountOfFunFound = 0; dw64Base = getNtBase(); if (dw64Base==0) { ::MessageBox(NULL,"Get base 0",NULL,NULL); return 0 ; } char szSystemDir[1024]={0}; GetSystemDirectory(szSystemDir, sizeof(szSystemDir)); FilePathName = szSystemDir; FilePathName = FilePathName+"\\"+PathFindFileName(osname); path=FilePathName; //记得要带上symsrv.dll和dbghelp.dll char *pSymPath = "srv*C:\\winddk\\symbolsl*http://msdl.microsoft.com/download/symbols"; myprint("retriving symbols for %s,symbols store in %s\r\n",path, pSymPath); SymCleanup(GetCurrentProcess()); if (SymInitialize(GetCurrentProcess(), pSymPath, TRUE)) { // SymInitialize returned success } else { // SymInitialize failed error = GetLastError(); myprint("SymInitialize returned error : %d\n", error); return 0; } DWORD err=0; // get the file size HANDLE hFile = CreateFile( FilePathName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if( INVALID_HANDLE_VALUE == hFile ) { err = GetLastError(); ::MessageBox(NULL,"out",NULL,NULL); return false; } if( INVALID_FILE_SIZE == ( dwFileSize = GetFileSize(hFile, NULL)) ) { } CloseHandle(hFile); DWORD64 dw64ModAddress=SymLoadModule64( GetCurrentProcess(),NULL, (char*)path,NULL,dw64Base,dwFileSize); if(dw64ModAddress==0) { error = GetLastError(); myprint("SymLoadModule64 returned error : %d\n", error); return 0; } if(!SymEnumSymbols( GetCurrentProcess(), dw64ModAddress, NULL, // Null point out that list all symbols SymEnumSymbolsProc, NULL)) { //_tprintf( _T("Failed when SymEnumSymbols(): %d \n"), GetLastError() ); return 0; } myprint("g_CountOfFunFound %d\r\n", g_CountOfFunFound); bool bRetSym = (g_CountOfFunFound>sizeof(dync_funs)/sizeof(dync_funs[0])); return bRetSym?dw64Base:0; }
void ConfigDlg::LoadSymbols() { g_StackDepth = GetDlgItemInt( IDC_EDIT1, NULL, FALSE ); if( m_bChanged ) { CString csExeName; GetModuleFileName( 0, csExeName.GetBuffer( MAX_PATH), MAX_PATH ); csExeName.ReleaseBuffer(); csExeName = csExeName.MakeLower(); csExeName.Replace( _T(".exe"), _T("Mem.ini")); CStdioFile File; if( !File.Open( csExeName, CFile::modeCreate|CFile::modeWrite )) { goto LoadDll; } int nCount = m_List.GetItemCount(); m_csPath.Empty(); for( int nId = 0;nId < nCount; nId++ ) { CString csItem = m_List.GetItemText( nId ,0 ); m_csPath += csItem + _T(";"); csItem += _T("\r\n"); File.WriteString( csItem ); } File.Close(); } LoadDll: HMODULE hModule = GetModuleHandle( _T("dbghelp.dll")); SymRefreshModuleListDef pSymRefreshModuleList; if( hModule ) { pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList")); CString csLoadedDll; GetModuleFileName( hModule, csLoadedDll.GetBuffer(MAX_PATH), MAX_PATH ); csLoadedDll.ReleaseBuffer(); if( !pSymRefreshModuleList ) { // old version of dbghelp :( MessageBox( "Your application has already loaded dbghelp.dll from " + csLoadedDll + "\n\nFor acqurate results, replace this dll with the latest version of dbghelp.dll" "coming with \"Debugging tools for windows\" or with the dll the application folder of this utility", "Error", MB_OK ); } else { MessageBox( "Your application has already loaded dbghelp.dll from " + csLoadedDll + " Please confirm that the symsrv.dll exists in th same folder.\n" "Otherwise symbol server will not work", "Warning", MB_OK ); } } else { // static int nTempvariable; // MEMORY_BASIC_INFORMATION MemInfo; // CString csDllPath; // if( !VirtualQuery( &nTempvariable, &MemInfo, sizeof(MemInfo))) // { // goto LoadDll; // } CString csDllPath; HMODULE hHookDll = GetModuleHandle( _T("HookDll.dll")); if( !GetModuleFileName( hHookDll, csDllPath.GetBuffer( MAX_PATH), MAX_PATH )) { goto LoadDll; } csDllPath.ReleaseBuffer(); int nPos = csDllPath.ReverseFind( _T('\\')); if( 0 >= nPos ) { goto LoadDll; } csDllPath = csDllPath.Left( nPos + 1 ); //csDllPath = "C:\\Program Files\\Debugging Tools for Windows (x86)\\"; csDllPath += _T("dbghelp.dll"); hModule = LoadLibrary( csDllPath ); if( !hModule) { hModule = LoadLibrary( _T("dbghelp.dll")); pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList")); if( !pSymRefreshModuleList ) { MessageBox( "Failed to load the dbghelp.dll from the local directory\n\n" "The application will continue with the default dbghelp.dll. But some feature may" "be unavailable", "Error", MB_OK ); } } else { pSymRefreshModuleList = (SymRefreshModuleListDef)GetProcAddress( hModule, _T("SymRefreshModuleList")); } } SymCleanup(GetCurrentProcess()); CString csWholePath = m_csPath; csWholePath.TrimRight( ';' ); DWORD dwOption = 0;//SymGetOptions(); dwOption |= SYMOPT_CASE_INSENSITIVE|SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS| SYMOPT_LOAD_ANYTHING|SYMOPT_UNDNAME; SymSetOptions( dwOption ); CWinThread* pThread = AfxBeginThread( ThreadEntry, this ); HANDLE hThread = pThread->m_hThread; BOOL fInvadeProcess = (0 == pSymRefreshModuleList)?TRUE:FALSE; BOOL bRet = SymInitialize(GetCurrentProcess(), (LPTSTR)csWholePath.operator LPCTSTR() , fInvadeProcess ); SymRegisterCallback64( GetCurrentProcess(),SymRegisterCallbackProc64,(ULONG64 )this ); while( !m_ProgressDlg.m_hWnd )// wait untill the dialog is created { Sleep( 50 ); } if( pSymRefreshModuleList ) { pSymRefreshModuleList( GetCurrentProcess()); } //SymRefreshModuleList( GetCurrentProcess()); m_ProgressDlg.SendMessage( WM_CLOSE ); WaitForSingleObject( hThread, 10000 ); }
/** * Print stack trace (using a specified stack context) to "os" * * @param context CONTEXT record for stack trace * @param os ostream& to receive printed stack backtrace */ void printWindowsStackTrace( CONTEXT& context, std::ostream& os ) { SimpleMutex::scoped_lock lk(_stackTraceMutex); HANDLE process = GetCurrentProcess(); BOOL ret = SymInitialize(process, getSymbolSearchPath(process), TRUE); if ( ret == FALSE ) { DWORD dosError = GetLastError(); log() << "Stack trace failed, SymInitialize failed with error " << std::dec << dosError << std::endl; return; } DWORD options = SymGetOptions(); options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS; SymSetOptions( options ); STACKFRAME64 frame64; memset( &frame64, 0, sizeof(frame64) ); #if defined(_M_AMD64) DWORD imageType = IMAGE_FILE_MACHINE_AMD64; frame64.AddrPC.Offset = context.Rip; frame64.AddrFrame.Offset = context.Rbp; frame64.AddrStack.Offset = context.Rsp; #elif defined(_M_IX86) DWORD imageType = IMAGE_FILE_MACHINE_I386; frame64.AddrPC.Offset = context.Eip; frame64.AddrFrame.Offset = context.Ebp; frame64.AddrStack.Offset = context.Esp; #else #error Neither _M_IX86 nor _M_AMD64 were defined #endif frame64.AddrPC.Mode = AddrModeFlat; frame64.AddrFrame.Mode = AddrModeFlat; frame64.AddrStack.Mode = AddrModeFlat; const size_t nameSize = 1024; const size_t symbolBufferSize = sizeof(SYMBOL_INFO) + nameSize; std::unique_ptr<char[]> symbolCharBuffer( new char[symbolBufferSize] ); memset( symbolCharBuffer.get(), 0, symbolBufferSize ); SYMBOL_INFO* symbolBuffer = reinterpret_cast<SYMBOL_INFO*>( symbolCharBuffer.get() ); symbolBuffer->SizeOfStruct = sizeof(SYMBOL_INFO); symbolBuffer->MaxNameLen = nameSize; // build list std::vector<TraceItem> traceList; TraceItem traceItem; size_t moduleWidth = 0; size_t sourceWidth = 0; for ( size_t i = 0; i < maxBackTraceFrames; ++i ) { ret = StackWalk64( imageType, process, GetCurrentThread(), &frame64, &context, NULL, NULL, NULL, NULL ); if ( ret == FALSE || frame64.AddrReturn.Offset == 0 ) { break; } DWORD64 address = frame64.AddrPC.Offset; getModuleName( process, address, &traceItem.moduleName ); size_t width = traceItem.moduleName.length(); if ( width > moduleWidth ) { moduleWidth = width; } getSourceFileAndLineNumber( process, address, &traceItem.sourceAndLine ); width = traceItem.sourceAndLine.length(); if ( width > sourceWidth ) { sourceWidth = width; } getsymbolAndOffset( process, address, symbolBuffer, &traceItem.symbolAndOffset ); traceList.push_back( traceItem ); } SymCleanup( process ); // print list ++moduleWidth; ++sourceWidth; size_t frameCount = traceList.size(); for ( size_t i = 0; i < frameCount; ++i ) { std::stringstream ss; ss << traceList[i].moduleName << " "; size_t width = traceList[i].moduleName.length(); while ( width < moduleWidth ) { ss << " "; ++width; } ss << traceList[i].sourceAndLine << " "; width = traceList[i].sourceAndLine.length(); while ( width < sourceWidth ) { ss << " "; ++width; } ss << traceList[i].symbolAndOffset; log() << ss.str() << std::endl; } }