//static void MemoryManager::DumpMemory() { static int dumpCount = 0; MemoryManager* instance = GetInstance(); DWORD64 dwDisplacement = 0; DWORD64 dwAddress; IMAGEHLP_LINE64 line; DWORD dwLineDisplacement; DWORD error; HANDLE hProcess; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); hProcess = GetCurrentProcess(); if (!SymInitialize(hProcess, NULL, TRUE)) { error = GetLastError(); LogError("SymInitialize returned error : %d\n", error); } std::stringstream filename; filename << "MemDump" << dumpCount++ << ".txt"; FILE *myFile = nullptr; errno_t openResult = fopen_s(&myFile, filename.str().c_str(), "w"); XTVERIFY(openResult == 0); if (myFile) { fprintf(myFile, "Total Memory Used:%u\n\n", (uint32)instance->m_totalAlloc); Alloc* currentAlloc = instance->m_head; while(currentAlloc != NULL) { dwAddress = (DWORD64)currentAlloc->m_stack[2]; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); fprintf(myFile, "Size: %u\n", (uint32)currentAlloc->m_size); if (currentAlloc->m_stackDepth >= 3 && SymGetLineFromAddr64(hProcess, dwAddress, &dwLineDisplacement, &line)) { fprintf(myFile, "%s:%u\n", line.FileName, line.LineNumber); } else { fprintf(myFile, "Unknown File\n"); } fprintf(myFile, "Callstack:\n"); for(int i = 0; i < currentAlloc->m_stackDepth; i++) { dwAddress = (DWORD64)currentAlloc->m_stack[i]; pSymbol->SizeOfStruct = 88; //sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol)) { const char* name = pSymbol->Name; fprintf(myFile, "\t%i: %s\n", i, name); } else { fprintf(myFile, "\t%i: Unknown\n", i); } } fprintf(myFile, "\n"); currentAlloc = currentAlloc->m_next; } _flushall(); CONTEXT Context; memset(&Context, 0, sizeof(Context)); RtlCaptureContext(&Context); fclose(myFile); } SymCleanup(hProcess); }
FunctionResolver::FunctionResolver(HANDLE processHandle) : m_hProcess(processHandle) { SymSetOptions(SYMOPT_DEBUG | SYMOPT_LOAD_ANYTHING); }
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], "-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 : %d\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 : %d\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 : %d\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 : %d 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 addr = _strtoui64(buf, NULL, 16); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; IMAGEHLP_LINE64 line; DWORD dummy; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; if (print_function_name) { if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) { printf("%s\n", pSymbol->Name); } else { printf("??\n"); } } line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) { printf("%s:%d\n", line.FileName, (int)line.LineNumber); } else { printf("??:0\n"); } } SymUnloadModule64(process, module_base); SymCleanup(process); return rv; }
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c) { if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack { InitializeCriticalSection(&_DbgHelpLock); _bLockInit = true; } DWORD imageType = IMAGE_FILE_MACHINE_I386; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); int frameNum = 0; // counts walked frames int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000. Arbitrary limit to guarantee no condition of infinate walking in corrupted memory. DWORD offsetFromLine; // tells us line number in the source file #if defined(_LINUX64) || defined(_WIN64) || defined(_IOS) unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were #else DWORD offsetFromSymbol; // tells us how far from the symbol we were #endif DWORD symOptions; // symbol handler settings IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN ); GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number IMAGEHLP_MODULE Module; IMAGEHLP_LINE Line; STACKFRAME64 s; // in/out stackframe memset( &s, '\0', sizeof s ); // note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014 GString symSearchPath; #ifdef _UNICODE wchar_t *tt = 0, *p; tt = new wchar_t[TTBUFLEN]; #else char *tt = 0, *p; tt = new char[TTBUFLEN]; #endif // build symbol search path from: symSearchPath = ""; // current directory if (GetCurrentDirectory(TTBUFLEN, tt)) symSearchPath << tt << "; "; // dir with executable if ( GetModuleFileName( 0, tt, TTBUFLEN ) ) { #ifdef _UNICODE for (p = tt + wcslen(tt) - 1; p >= tt; --p) #else for (p = tt + strlen(tt) - 1; p >= tt; --p) // VC6 does not have a _tcsclen() and we still support VC6 #endif { // locate the rightmost path separator if ( *p == '\\' || *p == '/' || *p == ':' ) break; } // if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte if ( p != tt ) // path sep found? { if ( *p == ':' ) // we leave colons in place ++ p; *p = '\0'; // eliminate the exe name and last path sep symSearchPath << tt << "; "; } } // environment variable _NT_SYMBOL_PATH GString g("_NT_SYMBOL_PATH"); if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable _NT_ALTERNATE_SYMBOL_PATH g = "_NT_ALTERNATE_SYMBOL_PATH"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable SYSTEMROOT g = "SYSTEMROOT"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 ); // 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" // Although "const" was not defined, the API call is "const" in behavior. In newer versions of the Windows API this has been fixed. // In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the // GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not) // know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" #if defined(_MSC_VER) && _MSC_VER <= 1200 if (!SymInitialize(hProcess, symSearchPath.Buf(), false)) // symSearchPath == (char *) #else if (!SymInitialize(hProcess, symSearchPath, true)) // symSearchPath == (const char *) --OR-- (const wchar_t *) depending on the _UNICODE preprocessor definition #endif { goto tagCleanUp; } symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES; symOptions &= ~SYMOPT_UNDNAME; SymSetOptions( symOptions ); enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() ); // init STACKFRAME for first call, definitions found in ImageHlp.h #ifdef _M_IX86 imageType = IMAGE_FILE_MACHINE_I386; s.AddrPC.Offset = c.Eip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Ebp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Esp; s.AddrStack.Mode = AddrModeFlat; #elif _M_X64 imageType = IMAGE_FILE_MACHINE_AMD64; s.AddrPC.Offset = c.Rip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Rsp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Rsp; s.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 imageType = IMAGE_FILE_MACHINE_IA64; s.AddrPC.Offset = c.StIIP; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.IntSp; s.AddrFrame.Mode = AddrModeFlat; s.AddrBStore.Offset = c.RsBSP; s.AddrBStore.Mode = AddrModeFlat; s.AddrStack.Offset = c.IntSp; s.AddrStack.Mode = AddrModeFlat; #endif 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; // DbgHelp is single threaded, so acquire a lock. EnterCriticalSection(&_DbgHelpLock); while ( frameNum < MAX_STACK_FRAMES ) { // get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase()) // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can // assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found. #ifdef _WIN64 if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) #else if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) #endif break; // Maybe it failed, maybe we have finished walking the stack if ( s.AddrPC.Offset != 0 ) { // Most likely a valid stack rame // show procedure info if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) ) { break; } else { // UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack strStackName.Empty(); UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE); strStackName.SetLength(strlen(strStackName._str)); // SymGetLineFromAddr() to get the source.cpp and the line number IMAGEHLP_LINE64 Line; if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE) { GString g(Line.FileName); // Line.FileName conains the "c:\Full\Path\TO\Source.cpp" // Builds string "Foo::Bar[Source.cpp]@777" strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; } // add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0 if (frameNum > 0) _stk += strStackName; } } else { // base reached SetLastError(0); break; } ++frameNum; } LeaveCriticalSection(&_DbgHelpLock); // de-init symbol handler etc. (SymCleanup()) SymCleanup( hProcess ); free( pSym ); tagCleanUp:; delete [] tt; CloseHandle(hProcess); }
void printStackTrace( std::ostream &os ) { HANDLE process = GetCurrentProcess(); BOOL ret = SymInitialize( process, NULL, TRUE ); if ( ret == FALSE ) { DWORD dosError = GetLastError(); os << "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 ); CONTEXT context; memset( &context, 0, sizeof(context) ); context.ContextFlags = CONTEXT_CONTROL; RtlCaptureContext( &context ); 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 symbolRecordSize = sizeof(SYMBOL_INFO) + nameSize; boost::scoped_array<char> symbolBuffer( new char[symbolRecordSize] ); memset( symbolBuffer.get(), 0, symbolRecordSize ); SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>( symbolBuffer.get() ); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = nameSize; std::vector<TraceItem> traceList; TraceItem traceItem; size_t moduleWidth = 0; size_t fileWidth = 0; size_t frameCount = 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 ) { frameCount = i; break; } // module (executable) name IMAGEHLP_MODULE64 module; memset ( &module, 0, sizeof(module) ); module.SizeOfStruct = sizeof(module); ret = SymGetModuleInfo64( process, frame64.AddrPC.Offset, &module ); char* moduleName = module.LoadedImageName; char* backslash = strrchr( moduleName, '\\' ); if ( backslash ) { moduleName = backslash + 1; } traceItem.module = moduleName; size_t len = traceItem.module.length(); if ( len > moduleWidth ) { moduleWidth = len; } // source code filename and line number IMAGEHLP_LINE64 line; memset( &line, 0, sizeof(line) ); line.SizeOfStruct = sizeof(line); DWORD displacement32; ret = SymGetLineFromAddr64( process, frame64.AddrPC.Offset, &displacement32, &line ); if ( ret ) { std::string filename( line.FileName ); std::string::size_type start = filename.find( "\\src\\mongo\\" ); if ( start == std::string::npos ) { start = filename.find( "\\src\\third_party\\" ); } if ( start != std::string::npos ) { std::string shorter( "..." ); shorter += filename.substr( start ); traceItem.sourceFile.swap( shorter ); } else { traceItem.sourceFile.swap( filename ); } len = traceItem.sourceFile.length() + 3; traceItem.lineNumber = line.LineNumber; if ( traceItem.lineNumber < 10 ) { len += 1; } else if ( traceItem.lineNumber < 100 ) { len += 2; } else if ( traceItem.lineNumber < 1000 ) { len += 3; } else if ( traceItem.lineNumber < 10000 ) { len += 4; } else { len += 5; } traceItem.sourceLength = len; if ( len > fileWidth ) { fileWidth = len; } } else { traceItem.sourceFile.clear(); traceItem.sourceLength = 0; } // symbol name and offset from symbol DWORD64 displacement; ret = SymFromAddr( process, frame64.AddrPC.Offset, &displacement, symbol ); if ( ret ) { traceItem.symbol = symbol->Name; traceItem.instructionOffset = displacement; } else { traceItem.symbol = "???"; traceItem.instructionOffset = 0; } // add to list traceList.push_back( traceItem ); } SymCleanup( process ); // print list ++moduleWidth; ++fileWidth; for ( size_t i = 0; i < frameCount; ++i ) { os << traceList[i].module << " "; size_t width = traceList[i].module.length(); while ( width < moduleWidth ) { os << " "; ++width; } if ( traceList[i].sourceFile.length() ) { os << traceList[i].sourceFile << "(" << std::dec << traceList[i].lineNumber << ") "; } width = traceList[i].sourceLength; while ( width < fileWidth ) { os << " "; ++width; } os << traceList[i].symbol << "+0x" << std::hex << traceList[i].instructionOffset; os << std::endl; } }
std::ostream& backtrace( std::ostream& os ) { #ifdef _WIN32 // Sym* functions from DbgHelp are not thread-safe... static Lock lock; ScopedMutex<> mutex( lock ); typedef USHORT (WINAPI *CaptureStackBackTraceType)( __in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG ); CaptureStackBackTraceType backtraceFunc = (CaptureStackBackTraceType) GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace"); if( !backtraceFunc ) return os; SymSetOptions( SYMOPT_UNDNAME | SYMOPT_LOAD_LINES ); HANDLE hProcess = GetCurrentProcess(); if( !SymInitialize( hProcess, 0, TRUE )) return os; void* stack[ LB_BACKTRACE_DEPTH ]; unsigned short frames = (backtraceFunc)( 0, LB_BACKTRACE_DEPTH, stack, 0 ); SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc( sizeof(SYMBOL_INFO) + (LB_SYMBOL_LENGTH+-1)*sizeof(char), 1 ); symbol->MaxNameLen = LB_SYMBOL_LENGTH; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); os << disableFlush << disableHeader << indent << std::endl; for( unsigned short i = 0; i < frames; ++i ) { os << frames-i-1 << ": "; if ( !SymFromAddr( hProcess, (DWORD64)stack[i], 0, symbol )) os << "Unknown symbol"; else { os << symbol->Name << " - "; IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) }; if( !SymGetLineFromAddr64( hProcess, (DWORD64)stack[i], 0, &line )) os << std::hex << "0x" << symbol->Address << std::dec; else os << line.FileName << ":" << line.LineNumber; } os << std::endl; } os << exdent << enableHeader << enableFlush; free( symbol ); SymCleanup( hProcess ); #else void* callstack[ LB_BACKTRACE_DEPTH ]; const int frames = ::backtrace( callstack, LB_BACKTRACE_DEPTH ); char** names = ::backtrace_symbols( callstack, frames ); os << disableFlush << disableHeader << indent << std::endl; for( int i = 1; i < frames; ++i ) { std::string name = names[ i ]; # ifdef __linux__ const size_t symbolPos = name.find( "(_" ); # else const size_t symbolPos = name.find( " _" ); # endif if( symbolPos != std::string::npos ) name = name.substr( symbolPos+1, name.length( )); # ifdef __linux__ const size_t spacePos = name.find( '+' ); # else const size_t spacePos = name.find( ' ' ); # endif if( spacePos != std::string::npos ) name = name.substr( 0, spacePos ); int status; char* demangled = abi::__cxa_demangle( name.c_str(), 0, 0, &status); if( symbolPos == std::string::npos || spacePos == std::string::npos ) os << names[ i ] << std::endl; else { if( demangled ) { os << demangled << std::endl; free( demangled ); } else os << name << std::endl; } } os << exdent << enableHeader << enableFlush; ::free( names ); #endif return os; }
int main(int argc, char** argv) { int retv = 0; HANDLE hFile = INVALID_HANDLE_VALUE; enum dbg_start ds; #ifdef __i386__ be_cpu = &be_i386; #elif defined(__powerpc__) be_cpu = &be_ppc; #elif defined(__ALPHA__) be_cpu = &be_alpha; #elif defined(__x86_64__) be_cpu = &be_x86_64; #elif defined(__sparc__) be_cpu = &be_sparc; #elif defined(__arm__) be_cpu = &be_arm; #else # error CPU unknown #endif /* Initialize the output */ dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE); /* Initialize internal vars */ if (!dbg_load_internal_vars()) return -1; /* as we don't care about exec name */ argc--; argv++; if (argc && !strcmp(argv[0], "--help")) return dbg_winedbg_usage(TRUE); if (argc && !strcmp(argv[0], "--gdb")) { retv = gdb_main(argc, argv); if (retv == -1) dbg_winedbg_usage(FALSE); return retv; } dbg_init_console(); SymSetOptions((SymGetOptions() & ~(SYMOPT_UNDNAME)) | SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS); if (argc && (!strcmp(argv[0], "--auto") || !strcmp(argv[0], "--minidump"))) { /* force some internal variables */ DBG_IVAR(BreakOnDllLoad) = 0; dbg_houtput = GetStdHandle(STD_ERROR_HANDLE); switch (dbg_active_auto(argc, argv)) { case start_ok: return 0; case start_error_parse: return dbg_winedbg_usage(FALSE); case start_error_init: return -1; } } /* parse options */ while (argc > 0 && argv[0][0] == '-') { if (!strcmp(argv[0], "--command")) { argc--; argv++; hFile = parser_generate_command_file(argv[0], NULL); if (hFile == INVALID_HANDLE_VALUE) { dbg_printf("Couldn't open temp file (%u)\n", GetLastError()); return 1; } argc--; argv++; continue; } if (!strcmp(argv[0], "--file")) { argc--; argv++; hFile = CreateFileA(argv[0], GENERIC_READ|DELETE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { dbg_printf("Couldn't open file %s (%u)\n", argv[0], GetLastError()); return 1; } argc--; argv++; continue; } if (!strcmp(argv[0], "--")) { argc--; argv++; break; } return dbg_winedbg_usage(FALSE); } if (!argc) ds = start_ok; else if ((ds = dbg_active_attach(argc, argv)) == start_error_parse && (ds = minidump_reload(argc, argv)) == start_error_parse) ds = dbg_active_launch(argc, argv); switch (ds) { case start_ok: break; case start_error_parse: return dbg_winedbg_usage(FALSE); case start_error_init: return -1; } dbg_start_interactive(hFile); return 0; }
/*********************************************************************** * 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; }
/*********************************************************************** * 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; }
static void stack_trace( PEXCEPTION_POINTERS pInfo ) { char message[1024]; int len = 0; size_t i; HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); IMAGEHLP_LINE64 line; DWORD dline = 0; DWORD options; CONTEXT context; STACKFRAME64 stackframe; DWORD image; memcpy( &context, pInfo->ContextRecord, sizeof(CONTEXT) ); options = SymGetOptions(); options |= SYMOPT_DEBUG; options |= SYMOPT_LOAD_LINES; SymSetOptions( options ); SymInitialize( process, NULL, TRUE ); ZeroMemory( &stackframe, sizeof(STACKFRAME64) ); #ifdef _M_IX86 image = IMAGE_FILE_MACHINE_I386; 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; #elif _M_X64 image = IMAGE_FILE_MACHINE_AMD64; stackframe.AddrPC.Offset = context.Rip; stackframe.AddrPC.Mode = AddrModeFlat; stackframe.AddrFrame.Offset = context.Rsp; stackframe.AddrFrame.Mode = AddrModeFlat; stackframe.AddrStack.Offset = context.Rsp; stackframe.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 image = IMAGE_FILE_MACHINE_IA64; stackframe.AddrPC.Offset = context.StIIP; stackframe.AddrPC.Mode = AddrModeFlat; stackframe.AddrFrame.Offset = context.IntSp; stackframe.AddrFrame.Mode = AddrModeFlat; stackframe.AddrBStore.Offset = context.RsBSP; stackframe.AddrBStore.Mode = AddrModeFlat; stackframe.AddrStack.Offset = context.IntSp; stackframe.AddrStack.Mode = AddrModeFlat; #endif len += snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) ) { len += snprintf(message + len, 1024 - len,"Exception: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); } if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) { len += snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); } if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) ) { len += snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline); } for( i = 0; i < 25; i++ ) { char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; BOOL result = StackWalk64( image, process, thread, &stackframe, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); DWORD64 displacement = 0; if( !result ) break; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = MAX_SYM_NAME; len += snprintf( message + len, 1024 - len, "% 2d %p", i, (void*)stackframe.AddrPC.Offset ); if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) ) { len += snprintf( message + len, 1024 - len, " %s ", symbol->Name ); } if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) { len += snprintf(message + len, 1024 - len,"(%s:%d:%d) ", (char*)line.FileName, (int)line.LineNumber, (int)dline); } len += snprintf( message + len, 1024 - len, "("); len += ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len ); len += snprintf( message + len, 1024 - len, ")\n"); } #ifdef XASH_SDL if( host.type != HOST_DEDICATED ) // let system to restart server automaticly SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR,"Sys_Crash", message, host.hWnd ); #endif Sys_PrintLog(message); SymCleanup(process); }
int CMiniDumpReader::Open(CString sFileName, CString sSymSearchPath) { static DWORD dwProcessID = 0; if(m_bLoaded) { return 1; } m_sFileName = sFileName; m_sSymSearchPath = sSymSearchPath; m_hFileMiniDump = CreateFile( sFileName, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, NULL, NULL); if(m_hFileMiniDump==INVALID_HANDLE_VALUE) { Close(); return 1; } m_hFileMapping = CreateFileMapping( m_hFileMiniDump, NULL, PAGE_READONLY, 0, 0, 0); if(m_hFileMapping==NULL) { Close(); return 2; } m_pMiniDumpStartPtr = MapViewOfFile( m_hFileMapping, FILE_MAP_READ, 0, 0, 0); if(m_pMiniDumpStartPtr==NULL) { Close(); return 3; } m_DumpData.m_hProcess = (HANDLE)(++dwProcessID); DWORD dwOptions = 0; //dwOptions |= SYMOPT_DEFERRED_LOADS; // Symbols are not loaded until a reference is made requiring the symbols be loaded. dwOptions |= SYMOPT_EXACT_SYMBOLS; // Do not load an unmatched .pdb file. dwOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; // Do not display system dialog boxes when there is a media failure such as no media in a drive. dwOptions |= SYMOPT_UNDNAME; // All symbols are presented in undecorated form. SymSetOptions(dwOptions); strconv_t strconv; BOOL bSymInit = SymInitializeW( m_DumpData.m_hProcess, strconv.t2w(sSymSearchPath), FALSE); if(!bSymInit) { m_DumpData.m_hProcess = NULL; Close(); return 5; } /*SymRegisterCallbackW64( m_DumpData.m_hProcess, SymRegisterCallbackProc64, (ULONG64)this);*/ m_bReadSysInfoStream = !ReadSysInfoStream(); m_bReadModuleListStream = !ReadModuleListStream(); m_bReadThreadListStream = !ReadThreadListStream(); m_bReadMemoryListStream = !ReadMemoryListStream(); m_bReadExceptionStream = !ReadExceptionStream(); m_bLoaded = true; return 0; }
void julia_init(char *imageFile) { jl_page_size = jl_getpagesize(); jl_find_stack_bottom(); jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT); #ifdef _OS_WINDOWS_ uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls uv_dlopen("Kernel32.dll",jl_kernel32_handle); uv_dlopen("msvcrt.dll",jl_crtdll_handle); uv_dlopen("Ws2_32.dll",jl_winsock_handle); _jl_exe_handle.handle = GetModuleHandleA(NULL); #if defined(_CPU_X86_64_) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); SymInitialize(GetCurrentProcess(), NULL, 1); needsSymRefreshModuleList = 0; #endif #endif jl_io_loop = uv_default_loop(); //this loop will internal events (spawining process etc.) init_stdio(); #if defined(__linux__) int ncores = jl_cpu_cores(); if (ncores > 1) { cpu_set_t cpumask; CPU_ZERO(&cpumask); for(int i=0; i < ncores; i++) { CPU_SET(i, &cpumask); } sched_setaffinity(0, sizeof(cpu_set_t), &cpumask); } #endif #ifdef JL_GC_MARKSWEEP jl_gc_init(); jl_gc_disable(); #endif jl_init_frontend(); jl_init_types(); jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo); jl_init_codegen(); jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0); jl_init_serializer(); if (!imageFile) { jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; jl_core_module = jl_new_module(jl_symbol("Core")); jl_core_module->parent = jl_main_module; jl_set_const(jl_main_module, jl_symbol("Core"), (jl_value_t*)jl_core_module); jl_module_using(jl_main_module, jl_core_module); jl_current_module = jl_core_module; jl_init_intrinsic_functions(); jl_init_primitives(); jl_load("boot.jl"); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); } if (imageFile) { JL_TRY { jl_restore_system_image(imageFile); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); jl_show(jl_stderr_obj(), jl_exception_in_transit); JL_PRINTF(JL_STDERR, "\n"); jl_exit(1); } } // set module field of primitive types int i; void **table = jl_core_module->bindings.table; for(i=1; i < jl_core_module->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; if (b->value && jl_is_datatype(b->value)) { jl_datatype_t *tt = (jl_datatype_t*)b->value; tt->name->module = jl_core_module; } } } // the Main module is the one which is always open, and set as the // current module for bare (non-module-wrapped) toplevel expressions. // it does "using Base" if Base is available. if (jl_base_module != NULL) { jl_add_standard_imports(jl_main_module); } // eval() uses Main by default, so Main.eval === Core.eval jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval")); jl_current_module = jl_main_module; #ifndef _OS_WINDOWS_ struct sigaction actf; memset(&actf, 0, sizeof(struct sigaction)); sigemptyset(&actf.sa_mask); actf.sa_handler = fpe_handler; actf.sa_flags = 0; if (sigaction(SIGFPE, &actf, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } stack_t ss; ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; ss.ss_sp = malloc(ss.ss_size); if (sigaltstack(&ss, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno)); jl_exit(1); } struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); sigemptyset(&act.sa_mask); act.sa_sigaction = segv_handler; act.sa_flags = SA_ONSTACK | SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) { JL_PRINTF(JL_STDERR, "Couldn't set SIGPIPE\n"); jl_exit(1); } #else if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) { JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n"); jl_exit(1); } #endif #ifdef JL_GC_MARKSWEEP jl_gc_enable(); #endif }
//https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633(v=vs.85).aspx void Util::getStackTrace(std::string& stream) { #ifdef _WIN32 stream = "===========Call stack===========\n"; typedef USHORT(WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG); CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibraryA("kernel32.dll"), "RtlCaptureStackBackTrace")); if (func == NULL) { stream += "[Error] Failed to resolve Call Stack print function\n"; return; } //Set to get the full decorated function name DWORD options = SymGetOptions(); DWORD newOptions = options & ~SYMOPT_UNDNAME; newOptions = newOptions | SYMOPT_PUBLICS_ONLY; SymSetOptions(newOptions); // 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; void * callers_stack[kMaxCallers]; unsigned short frames; SYMBOL_INFO * symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames = (func)(0, kMaxCallers, callers_stack, NULL); symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); //printf("(%016I64LX):\n", sample_address); //out << "(" << sample_address << "): " << std::endl; const unsigned short MAX_CALLERS_SHOWN = 6; frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN; for (unsigned int i = 0; i < frames; i++) { SymFromAddr(process, (DWORD64)(callers_stack[i]), 0, symbol); //printf("*** %d: %016I64LX %s - 0x%0X\n", i, callers_stack[i], symbol->Name, symbol->Address); char undecoratedName[MAX_SYM_NAME]; //UnDecorateSymbolName(symbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE); stream += std::string(symbol->Name, symbol->NameLen) + "\n"; //stream += std::string(undecoratedName) + "\n"; } free(symbol); stream += "=======End of Call stack========\n"; #else stream = "===========Call stack===========\n"; void *array[10]; size_t size = 0; size = backtrace(array, 10); char** symbols = backtrace_symbols(array, size); if(symbols == nullptr) { printLog(LogMessageType::Error, __FILE__, __LINE__, "Failed to get symbols."); return; } for(size_t i = 0; i < size; i++) { int status = 0; //char* name = abi::__cxa_demangle(symbols[i], tmp, &dms, &status); //We have to create the subsequence first std::string tmp(symbols[i]); size_t tmp_i = tmp.find_first_of('+'); size_t end_index = tmp_i != std::string::npos ? tmp_i : tmp.length() - 1; std::string symbol(tmp.begin() + tmp.find_first_of('(') + 1, tmp.begin() + end_index); char* name = abi::__cxa_demangle(symbol.c_str(), nullptr, nullptr, &status); if(status != 0) { //printLog(LogMessageType::Error, __FILE__, __LINE__, "Failed to demangle name \"%s\" with code %d", symbol.c_str(), status); } if(name == nullptr) { stream += std::string(symbols[i]) + "\n"; } else { stream += std::string(name) + "\n"; free(name); } } stream += "=======End of Call stack========\n"; #endif }
void julia_init(char *imageFile) { jl_page_size = jl_getpagesize(); jl_find_stack_bottom(); jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT); #ifdef _OS_WINDOWS_ uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls uv_dlopen("Kernel32.dll",jl_kernel32_handle); uv_dlopen("msvcrt.dll",jl_crtdll_handle); uv_dlopen("Ws2_32.dll",jl_winsock_handle); _jl_exe_handle.handle = GetModuleHandleA(NULL); if (!DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), (PHANDLE)&hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS )) { JL_PRINTF(JL_STDERR, "Couldn't access handle to main thread\n"); } #if defined(_CPU_X86_64_) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); SymInitialize(GetCurrentProcess(), NULL, 1); needsSymRefreshModuleList = 0; #endif #endif jl_io_loop = uv_default_loop(); //this loop will internal events (spawining process etc.) init_stdio(); #if defined(__linux__) int ncores = jl_cpu_cores(); if (ncores > 1) { cpu_set_t cpumask; CPU_ZERO(&cpumask); for(int i=0; i < ncores; i++) { CPU_SET(i, &cpumask); } sched_setaffinity(0, sizeof(cpu_set_t), &cpumask); } #endif #ifdef JL_GC_MARKSWEEP jl_gc_init(); jl_gc_disable(); #endif jl_init_frontend(); jl_init_types(); jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo); jl_init_codegen(); jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0); jl_init_serializer(); if (!imageFile) { jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; jl_core_module = jl_new_module(jl_symbol("Core")); jl_core_module->parent = jl_main_module; jl_set_const(jl_main_module, jl_symbol("Core"), (jl_value_t*)jl_core_module); jl_module_using(jl_main_module, jl_core_module); jl_current_module = jl_core_module; jl_init_intrinsic_functions(); jl_init_primitives(); jl_load("boot.jl"); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); } if (imageFile) { JL_TRY { jl_restore_system_image(imageFile); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); jl_show(jl_stderr_obj(), jl_exception_in_transit); JL_PRINTF(JL_STDERR, "\n"); jl_exit(1); } } // set module field of primitive types int i; void **table = jl_core_module->bindings.table; for(i=1; i < jl_core_module->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; if (b->value && jl_is_datatype(b->value)) { jl_datatype_t *tt = (jl_datatype_t*)b->value; tt->name->module = jl_core_module; } } } // the Main module is the one which is always open, and set as the // current module for bare (non-module-wrapped) toplevel expressions. // it does "using Base" if Base is available. if (jl_base_module != NULL) { jl_add_standard_imports(jl_main_module); } // eval() uses Main by default, so Main.eval === Core.eval jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval")); jl_current_module = jl_main_module; #ifndef _OS_WINDOWS_ signal_stack = malloc(SIGSTKSZ); struct sigaction actf; memset(&actf, 0, sizeof(struct sigaction)); sigemptyset(&actf.sa_mask); actf.sa_handler = fpe_handler; actf.sa_flags = 0; if (sigaction(SIGFPE, &actf, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } #if defined(_OS_LINUX_) stack_t ss; ss.ss_flags = 0; ss.ss_size = SIGSTKSZ; ss.ss_sp = signal_stack; if (sigaltstack(&ss, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaltstack: %s\n", strerror(errno)); jl_exit(1); } struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); sigemptyset(&act.sa_mask); act.sa_sigaction = segv_handler; act.sa_flags = SA_ONSTACK | SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) { JL_PRINTF(JL_STDERR, "sigaction: %s\n", strerror(errno)); jl_exit(1); } if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) { JL_PRINTF(JL_STDERR, "Couldn't set SIGPIPE\n"); jl_exit(1); } #elif defined (_OS_DARWIN_) kern_return_t ret; mach_port_t self = mach_task_self(); ret = mach_port_allocate(self,MACH_PORT_RIGHT_RECEIVE,&segv_port); HANDLE_MACH_ERROR("mach_port_allocate",ret); ret = mach_port_insert_right(self,segv_port,segv_port,MACH_MSG_TYPE_MAKE_SEND); HANDLE_MACH_ERROR("mach_port_insert_right",ret); // Alright, create a thread to serve as the listener for exceptions pthread_t thread; pthread_attr_t attr; if (pthread_attr_init(&attr) != 0) { JL_PRINTF(JL_STDERR, "pthread_attr_init failed"); jl_exit(1); } pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); if (pthread_create(&thread,&attr,mach_segv_listener,NULL) != 0) { JL_PRINTF(JL_STDERR, "pthread_create failed"); jl_exit(1); } pthread_attr_destroy(&attr); ret = task_set_exception_ports(self,EXC_MASK_BAD_ACCESS,segv_port,EXCEPTION_DEFAULT,MACHINE_THREAD_STATE); HANDLE_MACH_ERROR("task_set_exception_ports",ret); #endif #else if (signal(SIGFPE, (void (__cdecl *)(int))fpe_handler) == SIG_ERR) { JL_PRINTF(JL_STDERR, "Couldn't set SIGFPE\n"); jl_exit(1); } #endif #ifdef JL_GC_MARKSWEEP jl_gc_enable(); #endif }
int exceptionHandler(unsigned int code, struct _EXCEPTION_POINTERS *e) { char strCode[128]; bool canContinue; int numException = 0; char szTemp[1024]; PEXCEPTION_POINTERS eNext = e; PEXCEPTION_RECORD excRec; static DWORD numCall = 0; if (numCall++ >= 4) ExitProcess(0); _snprintf(szTemp, sizeof(szTemp), "!!! exceptionHandler(0x%08p)->0x%08p [ %03d ] *************************** !!!", e, e->ExceptionRecord, numCall); // OutputDebugString(szTemp); deb(szTemp); _snprintf(szTemp, sizeof(szTemp), "eax=0x%08X ebx=0x%08X ecx=0x%08X edx=0x%08X\r\nesi=0x%08X edi=0x%08X esp=0x%08X ebp=0x%08X", eNext->ContextRecord->Eax, eNext->ContextRecord->Ebx, eNext->ContextRecord->Ecx, eNext->ContextRecord->Edx, eNext->ContextRecord->Esi, eNext->ContextRecord->Edi, eNext->ContextRecord->Esp, eNext->ContextRecord->Ebp); // OutputDebugString(szTemp); deb(szTemp); do { excRec = eNext->ExceptionRecord; numException++; // deb(" -> # %-4d 0x%08p", numException, excRec); // deb("code: %x", excRec->ExceptionCode); canContinue = excRec->ExceptionFlags == EXCEPTION_NONCONTINUABLE ? true:false; // deb("canContinue: %d", canContinue); if (excRec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { _snprintf(strCode, sizeof(strCode), "Access violation (%s @ 0x%08p)", excRec->ExceptionInformation[0] ? "WRITE":"READ", excRec->ExceptionInformation[1]); } else if (excRec->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { _snprintf(strCode, sizeof(strCode), "Access in-page violation (%s @ 0x%08p) ntcode: %d", excRec->ExceptionInformation[0] ? "READ":"WRITE", excRec->ExceptionInformation[1], excRec->ExceptionInformation[2]); } else { _snprintf(strCode, sizeof(strCode), "<unkcode=%X> d0: 0x%08x d1: 0x%08x d2: 0x%08x", excRec->ExceptionCode, excRec->ExceptionInformation[0], excRec->ExceptionInformation[1], excRec->ExceptionInformation[2]); } _snprintf(szTemp, sizeof(szTemp), "Exception 0x%08X %s Address=0x%08X canContinue=%s", excRec->ExceptionCode, strCode, excRec->ExceptionAddress, canContinue ? "yes":"no"); deb(szTemp); if (!eNext->ExceptionRecord->ExceptionRecord) break; excRec = eNext->ExceptionRecord->ExceptionRecord; eNext->ExceptionRecord = eNext->ExceptionRecord->ExceptionRecord; } while (excRec->ExceptionRecord); // find symbols LPAPI_VERSION av = ImagehlpApiVersion(); // deb("dbghelp.dll: %d.%d rev:%d", av->MajorVersion, av->MinorVersion, av->Revision); int ret = SymInitialize(GetCurrentProcess(), "c:\\symbols", TRUE); SymSetOptions(SYMOPT_UNDNAME | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_DEFERRED_LOADS | 0x01000000 | SYMOPT_CASE_INSENSITIVE | SYMOPT_LOAD_ANYTHING | SYMOPT_LOAD_LINES); if (!ret) deb("syminit failed: code=%d, %s", ret, fmterr()); PSYMBOL_INFO si; unsigned long stackPtr = e->ContextRecord->Esp; DWORD dwDisp = false; unsigned __int64 dwDisp64 = false; LPVOID addr; si = (PSYMBOL_INFO)malloc(4096); for (int i = 0;i<100;i++) { memset(si, 0, 4096); // si.Name = (char*) a(128); si->MaxNameLen = 3000; si->SizeOfStruct = sizeof(SYMBOL_INFO) + 3000; memcpy((void*) &addr, (void*)stackPtr, 4); char szTemp[128]; memset(szTemp, 0, sizeof(szTemp)); si->Address = (unsigned __int64)addr; // get sym module name ret = SymFromAddr(GetCurrentProcess(), (unsigned __int64)addr, &dwDisp64, si); // if(ret) snprintf(szTemp, sizeof(szTemp), " %03d 0x%08X :%-25s", i, addr, si->Name); // get sym module line number IMAGEHLP_LINE64 il; memset(&il, 0, sizeof(il)); il.SizeOfStruct = sizeof(IMAGEHLP_LINE64); il.Address = (unsigned __int64)addr; ret = SymGetLineFromAddr64(GetCurrentProcess(), (unsigned __int64)addr, &dwDisp, &il); char szTemp2[128]; memset(szTemp2, 0, sizeof(szTemp2)); if (il.LineNumber) snprintf(szTemp2, sizeof(szTemp2), " %s:%d (0x%08X)", il.FileName, il.LineNumber, il.Address); // show line info if (addr && (strlen(szTemp) || strlen(szTemp2))) deb(" %s %s", szTemp, szTemp2[0] ? szTemp2:""); stackPtr -= 4; } // ret=SymEnumSymbols(GetCurrentProcess(), 0, "!", EnumSymProc, NULL); // if(!ret) // deb("enum err: %s", fmterr()); deb("!!! exceptionHandler out\r\n"); // EXCEPTION_CONTINUE_EXECUTION // EXCEPTION_EXECUTE_HANDLER return EXCEPTION_EXECUTE_HANDLER; }
DbgHelp::DbgHelp(HANDLE process) : mProcess(process) , mDbgHelp(0) , mMutex() , mSymGetModuleInfo64(0) , mSymLoadModule64(0) , mSymInitialize(0) , mSymUnloadModule64(0) , mSymEnumerateModules64(0) , mSymCleanup(0) , mSymFunctionTableAccess64(0) , mSymGetModuleBase64(0) , mSymGetSymFromAddr64(0) , mSymSetOptions(0) , mSymGetOptions(0) , mUnDecorateSymbolName(0) , mSymUnDName64(0) , mStackWalk64(0) , mMiniDumpWriteDump(0) //, mSymRegisterCallback64(0) // currently not used: //, mSymEnumSymbols(0) //, mSymEnumTypes(0) //, mSymSetContext(0) //, mSymGetTypeInfo(0) //, mImagehlpApiVersion(0) { if(!mProcess) { throw StackDumpException(__FILE__, __LINE__, "DbgHelp: invalid process handle passed"); } // // Load dbgHelp.dll and map the functions we need // if((mDbgHelp = ::LoadLibraryW(cDbgHelpDllPath)) == 0) { throw StackDumpException(__FILE__, __LINE__, "DbgHelp: Failed to load dbgHelp.dll"); } // Map function pointers if(0 == (mSymGetModuleInfo64 = reinterpret_cast<SymGetModuleInfo64Fnc> (GetProcAddress(mDbgHelp, "SymGetModuleInfo64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetModuleInfo64"); if(0 == (mSymLoadModule64 = reinterpret_cast<SymLoadModule64Fnc> (GetProcAddress(mDbgHelp, "SymLoadModule64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymLoadModule64"); if(0 == (mSymInitialize = reinterpret_cast<SymInitializeFnc> (GetProcAddress(mDbgHelp, "SymInitialize")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymInitialize"); if(0 == (mSymUnloadModule64 = reinterpret_cast<SymUnloadModule64Fnc> (GetProcAddress(mDbgHelp, "SymUnloadModule64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymUnloadModule64"); if(0 == (mSymEnumerateModules64 = reinterpret_cast<SymEnumerateModules64Fnc> (GetProcAddress(mDbgHelp, "SymEnumerateModules64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumerateModules64"); if(0 == (mSymCleanup = reinterpret_cast<SymCleanupFnc> (GetProcAddress(mDbgHelp, "SymCleanup")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymCleanup"); if(0 == (mSymFunctionTableAccess64 = reinterpret_cast<SymFunctionTableAccess64Fnc> (GetProcAddress(mDbgHelp, "SymFunctionTableAccess64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymFunctionTableAccess64"); if(0 == (mSymGetModuleBase64 = reinterpret_cast<SymGetModuleBase64Fnc> (GetProcAddress(mDbgHelp, "SymGetModuleBase64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetModuleBase64"); if(0 == (mSymGetSymFromAddr64 = reinterpret_cast<SymGetSymFromAddr64Fnc> (GetProcAddress(mDbgHelp, "SymGetSymFromAddr64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetSymFromAddr64"); if(0 == (mSymSetOptions = reinterpret_cast<SymSetOptionsFnc> (GetProcAddress(mDbgHelp, "SymSetOptions")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymSetOptions"); if(0 == (mSymGetOptions = reinterpret_cast<SymGetOptionsFnc> (GetProcAddress(mDbgHelp, "SymGetOptions")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetOptions"); if(0 == (mUnDecorateSymbolName = reinterpret_cast<UnDecorateSymbolNameFnc> (GetProcAddress(mDbgHelp, "UnDecorateSymbolName")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: UnDecorateSymbolName"); if(0 == (mSymUnDName64 = reinterpret_cast<SymUnDName64Fnc> (GetProcAddress(mDbgHelp, "SymUnDName64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymUnDName64"); if(0 == (mStackWalk64 = reinterpret_cast<StackWalk64Fnc> (GetProcAddress(mDbgHelp, "StackWalk64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: StackWalk64"); if(0 == (mMiniDumpWriteDump = reinterpret_cast<MiniDumpWriteDumpFnc> (GetProcAddress(mDbgHelp, "MiniDumpWriteDump")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: MiniDumpWriteDump"); //if(0 == (mSymRegisterCallback64 = reinterpret_cast<SymRegisterCallback64Fnc> (GetProcAddress(mDbgHelp, "SymRegisterCallback64")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymRegisterCallback64"); // currently not used: // if(0 == (mSymEnumSymbols = reinterpret_cast<SymEnumTypesFnc> (GetProcAddress(mDbgHelp, "SymEnumSymbols")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumSymbols"); // if(0 == (mSymEnumTypes = reinterpret_cast<SymEnumSymbolsFnc> (GetProcAddress(mDbgHelp, "SymEnumTypes")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymEnumTypes"); // if(0 == (mSymSetContext = reinterpret_cast<SymSetContextFnc> (GetProcAddress(mDbgHelp, "SymSetContext")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymSetContext"); // if(0 == (mSymGetTypeInfo = reinterpret_cast<SymGetTypeInfoFnc> (GetProcAddress(mDbgHelp, "SymGetTypeInfo")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: SymGetTypeInfo"); // if(0 == (mImagehlpApiVersion = reinterpret_cast<ImagehlpApiVersionFnc> (GetProcAddress(mDbgHelp, "ImagehlpApiVersion")))) throw StackDumpException(__FILE__, __LINE__, "Function not found in dbghelp.dll: ImagehlpApiVersion"); // // Initialize dbgHelp lib // if(!SymInitialize(0, false)) // set no user path since we're manually loading all modules { ::FreeLibrary(mDbgHelp); // don't use NcErrorFacade to throw, since it would try to log a callstack throw StackDumpException(__FILE__, __LINE__, "DbgHelp: Failed to initialize"); } // Set options DWORD symOptions = SymGetOptions(); symOptions &= ~SYMOPT_UNDNAME; // We undecorate names manually since that enable us to get more info symOptions |= SYMOPT_PUBLICS_ONLY; // Needed to get types of function parameters, sacrificing access to private and local info // symOptions |= SYMOPT_DEBUG; SymSetOptions(symOptions); // SymRegisterCallback64(traceEvents, 0); }
/** * Initializes the symbol engine if needed. */ bool FWindowsPlatformStackWalk::InitStackWalking() { // DbgHelp functions are not thread safe, but this function can potentially be called from different // threads in our engine, so we take a critical section static FCriticalSection CriticalSection; FScopeLock Lock( &CriticalSection ); // Only initialize once. if( !GStackWalkingInitialized ) { void* DllHandle = FPlatformProcess::GetDllHandle( TEXT("PSAPI.DLL") ); if( DllHandle == NULL ) { return false; } // Load dynamically linked PSAPI routines. FEnumProcesses = (TFEnumProcesses) FPlatformProcess::GetDllExport( DllHandle,TEXT("EnumProcesses")); FEnumProcessModules = (TFEnumProcessModules) FPlatformProcess::GetDllExport( DllHandle,TEXT("EnumProcessModules")); #if WINVER > 0x502 FGetModuleFileNameEx = (TFGetModuleFileNameEx) FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleFileNameExW")); FGetModuleBaseName = (TFGetModuleBaseName) FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleBaseNameW")); #else FGetModuleFileNameEx = (TFGetModuleFileNameEx) FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleFileNameExA")); FGetModuleBaseName = (TFGetModuleBaseName) FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleBaseNameA")); #endif FGetModuleInformation = (TFGetModuleInformation) FPlatformProcess::GetDllExport( DllHandle,TEXT("GetModuleInformation")); // Abort if we can't look up the functions. if( !FEnumProcesses || !FEnumProcessModules || !FGetModuleFileNameEx || !FGetModuleBaseName || !FGetModuleInformation ) { return false; } // Set up the symbol engine. uint32 SymOpts = SymGetOptions(); SymOpts |= SYMOPT_LOAD_LINES; SymOpts |= SYMOPT_FAIL_CRITICAL_ERRORS; SymOpts |= SYMOPT_DEFERRED_LOADS; SymOpts |= SYMOPT_EXACT_SYMBOLS; // This option allows for undecorated names to be handled by the symbol engine. SymOpts |= SYMOPT_UNDNAME; // Disable by default as it can be very spammy/slow. Turn it on if you are debugging symbol look-up! // SymOpts |= SYMOPT_DEBUG; // Not sure these are important or desirable // SymOpts |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS; // SymOpts |= SYMOPT_CASE_INSENSITIVE; SymSetOptions( SymOpts ); // Initialize the symbol engine. const FString RemoteStorage = GetRemoteStorage(GetDownstreamStorage()); #if WINVER > 0x502 SymInitializeW( GetCurrentProcess(), RemoteStorage.IsEmpty() ? nullptr : *RemoteStorage, true ); #else SymInitialize( GetCurrentProcess(), nullptr, true ); #endif GNeedToRefreshSymbols = false; GStackWalkingInitialized = true; if (!FPlatformProperties::IsMonolithicBuild() && FPlatformStackWalk::WantsDetailedCallstacksInNonMonolithicBuilds()) { LoadProcessModules( RemoteStorage ); } } #if WINVER > 0x502 else if (GNeedToRefreshSymbols) { // Refresh and reload symbols SymRefreshModuleList( GetCurrentProcess() ); if (!FPlatformProperties::IsMonolithicBuild() && FPlatformStackWalk::WantsDetailedCallstacksInNonMonolithicBuilds()) { const FString RemoteStorage = GetRemoteStorage( GetDownstreamStorage() ); LoadProcessModules( RemoteStorage ); } GNeedToRefreshSymbols = false; } #endif return GStackWalkingInitialized; }
void printCallStack() { SymInitialize(GetCurrentProcess(), NULL, TRUE); SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); DWORD mtype; CONTEXT ctx; ZeroMemory(&ctx, sizeof(CONTEXT)); ctx.ContextFlags = CONTEXT_CONTROL; RtlCaptureContext(&ctx); STACKFRAME64 stack; ZeroMemory(&stack, sizeof(STACKFRAME64)); #ifdef _M_IX86 mtype = IMAGE_FILE_MACHINE_I386; stack.AddrPC.Offset = ctx.Eip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrFrame.Offset = ctx.Ebp; stack.AddrFrame.Mode = AddrModeFlat; stack.AddrStack.Offset = ctx.Esp; stack.AddrStack.Mode = AddrModeFlat; #elif _M_X64 mtype = IMAGE_FILE_MACHINE_AMD64; stack.AddrPC.Offset = ctx.Rip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrFrame.Offset = ctx.Rsp; stack.AddrFrame.Mode = AddrModeFlat; stack.AddrStack.Offset = ctx.Rsp; stack.AddrStack.Mode = AddrModeFlat; #endif DWORD ldsp = 0; IMAGEHLP_LINE64 line; ZeroMemory(&line, sizeof(IMAGEHLP_LINE64)); line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO sym = (PSYMBOL_INFO)buf; sym->SizeOfStruct = sizeof(SYMBOL_INFO); sym->MaxNameLen = MAX_SYM_NAME; UINT num = 0; while (StackWalk64(mtype, GetCurrentProcess(), GetCurrentThread(), &stack, &ctx, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { if (stack.AddrPC.Offset == 0) { break; } ++num; BOOL res = SymGetLineFromAddr64(GetCurrentProcess(), stack.AddrPC.Offset, &ldsp, &line); res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym); if (res == TRUE) { // TODO replace with inner printf("\t[%i] %s (%s:%d)\n", num, sym->Name, line.FileName, line.LineNumber); } else { // TODO replace with inner printf("\t[%i] 0x%p\n", num, stack.AddrPC.Offset); } } SymCleanup(GetCurrentProcess()); }
//----------------------------------------------------------------------------// static void dumpBacktrace(size_t frames) { #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", 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); #endif #endif }
LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* ptrs) { EXCEPTION_RECORD* rec = ptrs->ExceptionRecord; CONTEXT* ctx = ptrs->ContextRecord; DWORD base = Vars.pModule ? Vars.pModule->dwBaseAddress : (DWORD)Vars.hModule; char path[MAX_PATH+_MAX_FNAME] = ""; sprintf_s(path, sizeof(path), "%s\\D2BS.bin", Vars.szPath); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId()); HANDLE hThread = GetCurrentThread(); CONTEXT context = *ctx; SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS); SymInitialize(hProcess, Vars.szPath, TRUE); SymLoadModule64(hProcess, NULL, path, NULL, base, 0); STACKFRAME64 stack; stack.AddrPC.Offset = context.Eip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrStack.Offset = context.Esp; stack.AddrStack.Mode = AddrModeFlat; stack.AddrFrame.Offset = context.Ebp; stack.AddrFrame.Mode = AddrModeFlat; std::string trace; for(int i = 0; i < 64; i++) { if(!StackWalk64(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stack, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) break; // infinite loop if(stack.AddrReturn.Offset == stack.AddrPC.Offset) break; // jump to 0 if(stack.AddrPC.Offset == 0) break; SYMBOL_INFO* sym = GetSymFromAddr(hProcess, stack.AddrPC.Offset); if(sym) { char msg[1024]; ULONG64 base = (sym->Address - sym->ModBase); IMAGEHLP_LINE64* line = GetLineFromAddr(hProcess, stack.AddrPC.Offset); if(line) sprintf_s(msg, 1024, "\t%s+0x%08x, File: %s line %d\n", sym->Name, base, strrchr(line->FileName, '\\')+1, line->LineNumber); else sprintf_s(msg, 1024, "\t%s+0x%08x\n", sym->Name, base); trace.append(msg); delete line; } else { char addr[100]; sprintf_s(addr, sizeof(addr), "\t0x%08x\n", stack.AddrFrame.Offset); trace.append(addr); } delete[] (char*)sym; } SYMBOL_INFO* sym = GetSymFromAddr(hProcess, (DWORD64)rec->ExceptionAddress); IMAGEHLP_LINE64* line = GetLineFromAddr(hProcess, (DWORD64)rec->ExceptionAddress); Log("EXCEPTION!\n*** 0x%08x at 0x%08x (%s in %s line %d)\n" "D2BS loaded at: 0x%08x\n" "Registers:\n" "\tEIP: 0x%08x, ESP: 0x%08x\n" "\tCS: 0x%04x, DS: 0x%04x, ES: 0x%04x, SS: 0x%04x, FS: 0x%04x, GS: 0x%04x\n" "\tEAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x, ESI: 0x%08x, EDI: 0x%08x, EBP: 0x%08x, FLG: 0x%08x\n" "Stack Trace:\n%s\nEnd of stack trace.", rec->ExceptionCode, rec->ExceptionAddress, sym != NULL ? sym->Name : "Unknown", line != NULL ? strrchr(line->FileName, '\\')+1 : "Unknown", line != NULL ? line->LineNumber : 0, base, ctx->Eip, ctx->Esp, ctx->SegCs, ctx->SegDs, ctx->SegEs, ctx->SegSs, ctx->SegFs, ctx->SegGs, ctx->Eax, ctx->Ebx, ctx->Ecx, ctx->Edx, ctx->Esi, ctx->Edi, ctx->Ebp, ctx->EFlags, trace.c_str()); delete[] (char*)sym; delete line; SymCleanup(hProcess); return EXCEPTION_EXECUTE_HANDLER; }
static void print_backtrace(CONTEXT *pctx) { SymGetLineFromAddrW64_func_t zbx_SymGetLineFromAddrW64 = NULL; SymFromAddr_func_t zbx_SymFromAddr = NULL; CONTEXT ctx, ctxcount; STACKFRAME64 s, scount; PSYMBOL_INFO pSym = NULL; HMODULE hModule; HANDLE hProcess, hThread; DWORD64 offset; wchar_t szProcessName[MAX_PATH]; char *process_name = NULL, *process_path = NULL, *frame = NULL; size_t frame_alloc = 0, frame_offset; int nframes = 0; ctx = *pctx; zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ==="); memset(&s, 0, sizeof(s)); s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Mode = AddrModeFlat; #ifdef _M_X64 s.AddrPC.Offset = ctx.Rip; s.AddrFrame.Offset = ctx.Rbp; s.AddrStack.Offset = ctx.Rsp; #else s.AddrPC.Offset = ctx.Eip; s.AddrFrame.Offset = ctx.Ebp; s.AddrStack.Offset = ctx.Esp; #endif hProcess = GetCurrentProcess(); hThread = GetCurrentThread(); if (0 != GetModuleFileNameEx(hProcess, NULL, szProcessName, ARRSIZE(szProcessName))) { char *ptr; int path_alloc = 0, path_offset = 0; process_name = zbx_unicode_to_utf8(szProcessName); if (NULL != (ptr = strstr(process_name, progname))) zbx_strncpy_alloc(&process_path, &path_alloc, &path_offset, process_name, ptr - process_name); } if (NULL != (hModule = GetModuleHandle(TEXT("DbgHelp.DLL")))) { zbx_SymGetLineFromAddrW64 = (SymGetLineFromAddrW64_func_t)GetProcAddress(hModule, "SymGetLineFromAddr64"); zbx_SymFromAddr = (SymFromAddr_func_t)GetProcAddress(hModule, "SymFromAddr"); } if (NULL != zbx_SymFromAddr || NULL != zbx_SymGetLineFromAddrW64) { SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES); if (FALSE != SymInitialize(hProcess, process_path, TRUE)) { pSym = (PSYMBOL_INFO) zbx_malloc(NULL, sizeof(SYMBOL_INFO) + MAX_SYM_NAME); memset(pSym, 0, sizeof(SYMBOL_INFO) + MAX_SYM_NAME); pSym->SizeOfStruct = sizeof(SYMBOL_INFO); pSym->MaxNameLen = MAX_SYM_NAME; } } scount = s; ctxcount = ctx; /* get number of frames, ctxcount may be modified during StackWalk64() calls */ while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &scount, &ctxcount, NULL, NULL, NULL, NULL)) { if (0 == scount.AddrReturn.Offset) break; nframes++; } while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &s, &ctx, NULL, NULL, NULL, NULL)) { frame_offset = 0; zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%d: %s", nframes--, NULL == process_name ? "(unknown)" : process_name); if (NULL != pSym) { DWORD dwDisplacement; IMAGEHLP_LINE64 line = {sizeof(IMAGEHLP_LINE64)}; zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, '('); if (NULL != zbx_SymFromAddr && TRUE == zbx_SymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym)) { zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%s+0x%lx", pSym->Name, offset); } if (NULL != zbx_SymGetLineFromAddrW64 && TRUE == zbx_SymGetLineFromAddrW64(hProcess, s.AddrPC.Offset, &dwDisplacement, &line)) { zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, " %s:%d", line.FileName, line.LineNumber); } zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, ')'); } zabbix_log(LOG_LEVEL_CRIT, "%s [0x%lx]", frame, s.AddrPC.Offset); if (0 == s.AddrReturn.Offset) break; } SymCleanup(hProcess); zbx_free(frame); zbx_free(process_path); zbx_free(process_name); zbx_free(pSym); }
int dbg_help_client_t::init(char* path) { DWORD64 dwBaseAddr=0; int chars; char exe_path[MAX_PATH]; chars = GetModuleFileName(NULL, exe_path, MAX_PATH); if (chars == 0) { fprintf(stderr,"Could not find base path for XED executable\n"); fflush(stderr); exit(1); } //fprintf(stderr,"EXE PATH %s\n", exe_path); char* dir = find_base_path(exe_path); //fprintf(stderr,"DIR %s\n", dir); char* dbghelp = append3(dir,"\\","dbghelp.dll"); //fprintf(stderr,"DBGHLP %s\n", dbghelp); if (_access_s(dbghelp,4) != 0) { //fprintf(stderr, // "WARNING: Could not find dbghelp.dll in xed.exe directory\n"); //fflush(stderr); return 0; } //fprintf(stderr,"FOUND DBGHELP\n"); if (validate_version(dbghelp)) { fprintf(stderr, "WARNING: dbghelp.dll version is too old\n"); fflush(stderr); return 0; } //FIXME: Add a version check for the dll ( ImagehlpApiVersion is NOT //the right thing) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); hProcess = GetCurrentProcess(); if (SymInitialize(hProcess, NULL, FALSE)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymInitialize returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } actual_base = SymLoadModuleEx(hProcess, NULL, path, NULL, dwBaseAddr, 0, NULL, 0); if (actual_base) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymLoadModuleEx returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumerateModules64(hProcess, (PSYM_ENUMMODULES_CALLBACK64)enum_modules, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumerateModules64 returned error : %d 0x%x\n", error, error); fflush(stderr); return 0; } if (SymEnumSymbols(hProcess, actual_base, 0, enum_sym, this)) { // nothing } else { error = GetLastError(); fprintf(stderr,"SymEnumSymbols failed: %d 0x%x\n", error, error); fflush(stderr); return 0; } make_symbol_vector(&sym_tab); initialized = true; return 1; }
static void sym_init(void) { proc = GetCurrentProcess(); SymInitialize(proc, NULL, TRUE); SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_FAIL_CRITICAL_ERRORS| SYMOPT_NO_PROMPTS|SYMOPT_UNDNAME); }
int main(int argc, char **argv) { BOOL bRet; DWORD dwRet; bool debug = false; char *szModule = nullptr; bool functions = false; bool demangle = false; bool pretty = false; while (1) { int opt = getopt(argc, argv, "?CDe:fHp"); switch (opt) { case 'C': demangle = true; break; case 'D': debug = true; break; case 'e': szModule = optarg; break; case 'f': functions = true; break; case 'H': usage(argv[0]); return EXIT_SUCCESS; case 'p': pretty = true; break; case '?': fprintf(stderr, "error: invalid option `%c`\n", optopt); /* pass-through */ default: usage(argv[0]); return EXIT_FAILURE; case -1: break; } if (opt == -1) { break; } } if (szModule == nullptr) { usage(argv[0]); return EXIT_FAILURE; } // Load the module HMODULE hModule = nullptr; #ifdef _WIN64 hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE); #endif if (!hModule) { hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES); } if (!hModule) { fprintf(stderr, "error: failed to load %s\n", szModule); return EXIT_FAILURE; } DWORD dwSymOptions = SymGetOptions(); dwSymOptions |= SYMOPT_LOAD_LINES; #ifndef NDEBUG dwSymOptions |= SYMOPT_DEBUG; #endif // We can get more information by calling UnDecorateSymbolName() ourselves. dwSymOptions &= ~SYMOPT_UNDNAME; SymSetOptions(dwSymOptions); HANDLE hProcess = GetCurrentProcess(); bRet = InitializeSym(hProcess, FALSE); assert(bRet); if (debug) { SymRegisterCallback64(hProcess, &callback, 0); } dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, (DWORD64)(UINT_PTR)hModule, 0, NULL, 0); if (!dwRet) { fprintf(stderr, "warning: failed to load module symbols\n"); } if (!GetModuleHandleA("symsrv.dll")) { fprintf(stderr, "warning: symbol server not loaded\n"); } while (optind < argc) { const char *arg = argv[optind++]; DWORD64 dwRelAddr; if (arg[0] == '0' && arg[1] == 'x') { sscanf(&arg[2], "%08" PRIX64, &dwRelAddr); } else { dwRelAddr = atol(arg); } UINT_PTR dwAddr = (UINT_PTR)hModule + dwRelAddr; if (functions) { struct { SYMBOL_INFO Symbol; CHAR Name[512]; } sym; char UnDecoratedName[512]; const char *function = "??"; ZeroMemory(&sym, sizeof sym); sym.Symbol.SizeOfStruct = sizeof sym.Symbol; sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name; DWORD64 dwSymDisplacement = 0; bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol); if (bRet) { function = sym.Symbol.Name; if (demangle) { if (UnDecorateSymbolName( sym.Symbol.Name, UnDecoratedName, sizeof UnDecoratedName, UNDNAME_COMPLETE)) { function = UnDecoratedName; } } } fputs(function, stdout); fputs(pretty ? " at " : "\n", stdout); } IMAGEHLP_LINE64 line; ZeroMemory(&line, sizeof line); line.SizeOfStruct = sizeof line; DWORD dwLineDisplacement = 0; bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line); if (bRet) { fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber); } else { fputs("??:?\n", stdout); } fflush(stdout); } SymCleanup(hProcess); FreeLibrary(hModule); return 0; }
static void dump_thread(void *arg) { HANDLE dbghelp; BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL); BOOL (WINAPI *pSymCleanup)(HANDLE); BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64); DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64); BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *); BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *); HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD); DWORD tid = *(DWORD *)arg; HANDLE ph; HANDLE th; dbghelp = LoadLibrary("dbghelp.dll"); if (!dbghelp) return; pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize"); pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup"); pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64"); pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64"); pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr"); pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64"); pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread"); if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 && pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) { SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); ph = GetCurrentProcess(); pSymInitialize(ph, NULL, TRUE); th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid); if (th) { if (SuspendThread(th) != (DWORD)-1) { CONTEXT context; memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_FULL; if (GetThreadContext(th, &context)) { char libpath[MAX_PATH]; char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; SYMBOL_INFO *info = (SYMBOL_INFO *)buf; DWORD mac; STACKFRAME64 frame; memset(&frame, 0, sizeof(frame)); #if defined(_M_AMD64) || defined(__x86_64__) mac = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Rip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Rbp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Rsp; #elif defined(_M_IA64) || defined(__ia64__) mac = IMAGE_FILE_MACHINE_IA64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.StIIP; frame.AddrBStore.Mode = AddrModeFlat; frame.AddrBStore.Offset = context.RsBSP; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.IntSp; #else /* i386 */ mac = IMAGE_FILE_MACHINE_I386; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Eip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Ebp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Esp; #endif while (pStackWalk64(mac, ph, th, &frame, &context, NULL, NULL, NULL, NULL)) { DWORD64 addr = frame.AddrPC.Offset; IMAGEHLP_LINE64 line; DWORD64 displacement; DWORD tmp; if (addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0) break; memset(buf, 0, sizeof(buf)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (pSymFromAddr(ph, addr, &displacement, info)) { if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) fprintf(stderr, "%s", libpath); fprintf(stderr, "(%s+0x%I64x)", info->Name, displacement); } fprintf(stderr, " [0x%p]", (void *)(VALUE)addr); memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); if (pSymGetLineFromAddr64(ph, addr, &tmp, &line)) fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber); fprintf(stderr, "\n"); } } ResumeThread(th); } CloseHandle(th); } pSymCleanup(ph); } FreeLibrary(dbghelp); }
void AFXAPI AfxDumpStack(DWORD dwTarget /* = AFX_STACK_DUMP_TARGET_DEFAULT */) { CTraceClipboardData clipboardData(dwTarget); clipboardData.SendOut("=== begin AfxDumpStack output ===\r\n"); CDWordArray adwAddress; HANDLE hProcess = ::GetCurrentProcess(); if (SymInitialize(hProcess, NULL, FALSE)) { // force undecorated names to get params DWORD dw = SymGetOptions(); dw &= ~SYMOPT_UNDNAME; SymSetOptions(dw); HANDLE hThread = ::GetCurrentThread(); CONTEXT threadContext; threadContext.ContextFlags = CONTEXT_FULL; if (::GetThreadContext(hThread, &threadContext)) { STACKFRAME stackFrame; memset(&stackFrame, 0, sizeof(stackFrame)); stackFrame.AddrPC.Mode = AddrModeFlat; DWORD dwMachType; #if defined(_M_IX86) dwMachType = IMAGE_FILE_MACHINE_I386; // program counter, stack pointer, and frame pointer stackFrame.AddrPC.Offset = threadContext.Eip; stackFrame.AddrStack.Offset = threadContext.Esp; stackFrame.AddrStack.Mode = AddrModeFlat; stackFrame.AddrFrame.Offset = threadContext.Ebp; stackFrame.AddrFrame.Mode = AddrModeFlat; #elif defined(_M_MRX000) // only program counter dwMachType = IMAGE_FILE_MACHINE_R4000; stackFrame.AddrPC. Offset = treadContext.Fir; #elif defined(_M_ALPHA) // only program counter dwMachType = IMAGE_FILE_MACHINE_ALPHA; stackFrame.AddrPC.Offset = (unsigned long) threadContext.Fir; #elif defined(_M_PPC) // only program counter dwMachType = IMAGE_FILE_MACHINE_POWERPC; stackFrame.AddrPC.Offset = threadContext.Iar; #elif #error("Unknown Target Machine"); #endif adwAddress.SetSize(0, 16); int nFrame; for (nFrame = 0; nFrame < 1024; nFrame++) { if (!StackWalk(dwMachType, hProcess, hProcess, &stackFrame, &threadContext, NULL, FunctionTableAccess, GetModuleBase, NULL)) { break; } adwAddress.SetAtGrow(nFrame, stackFrame.AddrPC.Offset); } } } else { DWORD dw = GetLastError(); char sz[100]; wsprintfA(sz, "AfxDumpStack Error: IMAGEHLP.DLL wasn't found. " "GetLastError() returned 0x%8.8X\r\n", dw); clipboardData.SendOut(sz); } // dump it out now int nAddress; int cAddresses = adwAddress.GetSize(); for (nAddress = 0; nAddress < cAddresses; nAddress++) { SYMBOL_INFO info; DWORD dwAddress = adwAddress[nAddress]; char sz[20]; wsprintfA(sz, "%8.8X: ", dwAddress); clipboardData.SendOut(sz); if (ResolveSymbol(hProcess, dwAddress, info)) { clipboardData.SendOut(info.szModule); clipboardData.SendOut(info.szSymbol); } else clipboardData.SendOut("symbol not found"); clipboardData.SendOut("\r\n"); } clipboardData.SendOut("=== end AfxDumpStack() output ===\r\n"); }
/** * 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; boost::scoped_array<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; } }
void CSymbolEngine::SetOptions( DWORD Options ) { SymSetOptions( Options ); }
static void dumpBacktrace( unsigned int depth ) { if ( depth == 0 ) depth = 20; #if (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", ( char * ) 0 ); 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 if ( dup( fd[1] ) != STDERR_FILENO ) { 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 ); if ( dup( stderr_fd ) != STDERR_FILENO ) { 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", TRUE ); unsigned short nFrames = CaptureStackBackTrace( 1, depth, buffer, NULL ); SYMBOL_INFO *symbol = ( SYMBOL_INFO * ) qgsMalloc( sizeof( SYMBOL_INFO ) + 256 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); for ( int i = 0; i < nFrames; i++ ) { SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol ); symbol->Name[ 255 ] = 0; myPrint( "%d: %s [%x]\n", i, symbol->Name, symbol->Address ); } qgsFree( symbol ); #endif }
void mrpt::system::getCallStackBackTrace(TCallStackBackTrace& out_bt) { out_bt.backtrace_levels.clear(); const unsigned int framesToSkip = 1; // skip *this* function from the backtrace const unsigned int framesToCapture = 64; #ifdef _WIN32 void* backTrace[framesToCapture]{}; SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); const HANDLE hProcess = GetCurrentProcess(); if (!SymInitialize( hProcess, nullptr /* UserSearchPath */, TRUE /*fInvadeProcess*/)) { std::cerr << "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!" << std::endl; return; } char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; const USHORT nFrames = CaptureStackBackTrace( framesToSkip, framesToCapture, backTrace, nullptr); for (unsigned int i = 0; i < nFrames; i++) { TCallStackEntry cse; cse.address = backTrace[i]; if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol)) { cse.symbolName = "???"; cse.symbolNameOriginal = "???"; out_bt.backtrace_levels.emplace_back(cse); continue; } SYMBOL_INFO& si = *pSymbol; cse.symbolNameOriginal = si.Name; char undecorated_name[1024]; if (!UnDecorateSymbolName( si.Name, undecorated_name, sizeof(undecorated_name), UNDNAME_COMPLETE)) { cse.symbolName = cse.symbolNameOriginal; } else { cse.symbolName = std::string(undecorated_name); } out_bt.backtrace_levels.emplace_back(cse); } #else // Based on: https://gist.github.com/fmela/591333 void* callstack[framesToCapture]; const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]); int nFrames = ::backtrace(callstack, nMaxFrames); char** symbols = ::backtrace_symbols(callstack, nFrames); for (int i = (int)framesToSkip; i < nFrames; i++) { TCallStackEntry cse; cse.address = callstack[i]; Dl_info info; if (dladdr(callstack[i], &info) && info.dli_sname) { char* demangled = nullptr; int status = -1; if (info.dli_sname[0] == '_') { demangled = abi::__cxa_demangle( info.dli_sname, nullptr, nullptr, &status); } cse.symbolNameOriginal = info.dli_sname == nullptr ? symbols[i] : info.dli_sname; cse.symbolName = status == 0 ? std::string(demangled) : cse.symbolNameOriginal; free(demangled); } out_bt.backtrace_levels.emplace_back(cse); } free(symbols); #endif }