Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Windows.h>
- #include <DbgHelp.h> // need DbgHelp32.lib
- #include <string>
- #define TRACE_MAX_STACK_FRAMES 1024
- #define TRACE_MAX_FUNCTION_NAME_LENGTH 1024
- template <typename I>
- std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1)
- {
- std::string rc(hex_len,'0');
- for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
- rc[i] = ((w>>j) & 0x0f)["0123456789ABCDEF"];
- return rc;
- }
- // Outputs current frames without (skip_frames+1) frames from top of stack stack.
- // not usable for exceptions and uses CaptureStackBackTrace из Windows Vista SDK (default VS2010)
- // might need StackWalk64 fore more details about stack.
- static bool GetStackWalk( std::string &outWalk, USHORT skip_frames = 0)
- {
- // RTTI for .pdb symbols. Might want this in global scope
- static struct SymServer {
- bool good;
- SymServer() : good(false) {
- // deferred load, allow 32bit, undecorate names.
- ::SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME );
- // Microsoft symbol servers.
- good = ::SymInitialize( ::GetCurrentProcess(),
- NULL, // user path to .pdb
- TRUE ) == TRUE;
- }
- ~SymServer() { ::SymCleanup( ::GetCurrentProcess() ); }
- } SymServerGuard;
- if(!SymServerGuard.good) return false;
- auto hProcess = ::GetCurrentProcess();
- // up to TRACE_MAX_STACK_FRAMES
- PVOID addrs[ TRACE_MAX_STACK_FRAMES ] = { };
- // 1st frame is GetStackWalk.
- USHORT usFrames = CaptureStackBackTrace( 1 + skip_frames, TRACE_MAX_STACK_FRAMES - skip_frames, addrs, NULL );
- outWalk.append("=== Stack backtrace:\n");
- for (long long i = 0; i < usFrames; i++) {
- // buffer for SYMBOL_INFO with string of 1024 bytes.
- ULONG64 buffer[ (sizeof( SYMBOL_INFO ) + TRACE_MAX_FUNCTION_NAME_LENGTH + sizeof( ULONG64 ) - 1) / sizeof( ULONG64 ) ] = { 0 };
- SYMBOL_INFO *info = new (buffer) SYMBOL_INFO;
- info->SizeOfStruct = sizeof( SYMBOL_INFO );
- info->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
- DWORD64 displacement = 0;
- IMAGEHLP_LINE64 line = { sizeof(IMAGEHLP_LINE64) };
- // frame number
- outWalk.append(std::to_string(i)).append( ". " );
- DWORD disp = 0;
- // Attempt to get information about the symbol and add it to our output parameter.
- if(::SymFromAddr( hProcess, DWORD64(addrs[ i ]), &displacement, info ))
- {
- // attempt to get line info, if it present
- if (::SymGetLineFromAddr64(hProcess, DWORD(addrs[ i ]), &disp, &line))
- {
- outWalk.append( info->Name, info->NameLen ).append(" : 0x").append(n2hexstr(line.Address))
- .append("\n\t\"").append(line.FileName).append("\" line: ").append(std::to_string((long long)line.LineNumber))
- .append(" + ").append(std::to_string((long long)disp));
- }
- else
- {
- outWalk.append( info->Name, info->NameLen );
- }
- }
- outWalk.append( "\n" );
- }
- return true;
- }
- // Test thing
- struct S {
- S() {
- std::string s;
- GetStackWalk(s);
- std::cout << s << std::endl;
- }
- } s;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement