| 30 | |
| 31 | namespace das { |
| 32 | static void print_stack_trace(CONTEXT *ctx) { |
| 33 | HANDLE process = GetCurrentProcess(); |
| 34 | HANDLE thread = GetCurrentThread(); |
| 35 | SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); |
| 36 | if (!SymInitialize(process, NULL, TRUE)) { |
| 37 | fprintf(stderr, "SymInitialize failed: %lu\n", GetLastError()); |
| 38 | return; |
| 39 | } |
| 40 | STACKFRAME64 frame = {}; |
| 41 | #if defined(_M_X64) |
| 42 | frame.AddrPC.Offset = ctx->Rip; |
| 43 | frame.AddrFrame.Offset = ctx->Rbp; |
| 44 | frame.AddrStack.Offset = ctx->Rsp; |
| 45 | DWORD machineType = IMAGE_FILE_MACHINE_AMD64; |
| 46 | #elif defined(_M_ARM64) |
| 47 | frame.AddrPC.Offset = ctx->Pc; |
| 48 | frame.AddrFrame.Offset = ctx->Fp; |
| 49 | frame.AddrStack.Offset = ctx->Sp; |
| 50 | DWORD machineType = IMAGE_FILE_MACHINE_ARM64; |
| 51 | #else |
| 52 | frame.AddrPC.Offset = ctx->Eip; |
| 53 | frame.AddrFrame.Offset = ctx->Ebp; |
| 54 | frame.AddrStack.Offset = ctx->Esp; |
| 55 | DWORD machineType = IMAGE_FILE_MACHINE_I386; |
| 56 | #endif |
| 57 | frame.AddrPC.Mode = AddrModeFlat; |
| 58 | frame.AddrFrame.Mode = AddrModeFlat; |
| 59 | frame.AddrStack.Mode = AddrModeFlat; |
| 60 | |
| 61 | alignas(SYMBOL_INFO) char symbolBuf[sizeof(SYMBOL_INFO) + 256]; |
| 62 | SYMBOL_INFO *symbol = (SYMBOL_INFO *)symbolBuf; |
| 63 | symbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
| 64 | symbol->MaxNameLen = 255; |
| 65 | |
| 66 | IMAGEHLP_LINE64 line = {}; |
| 67 | line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); |
| 68 | |
| 69 | CrashFrame collectedFrames[DAS_CRASH_HANDLER_MAX_STACK_FRAMES]; |
| 70 | int frameCount = 0; |
| 71 | |
| 72 | fprintf(stderr, "Stack trace:\n"); |
| 73 | for (int i = 0; i < DAS_CRASH_HANDLER_MAX_STACK_FRAMES; i++) { |
| 74 | if (!StackWalk64(machineType, process, thread, &frame, ctx, NULL, |
| 75 | SymFunctionTableAccess64, SymGetModuleBase64, NULL)) |
| 76 | break; |
| 77 | if (frame.AddrPC.Offset == 0) |
| 78 | break; |
| 79 | DWORD64 displacement64 = 0; |
| 80 | DWORD displacement32 = 0; |
| 81 | const char * symName = nullptr; |
| 82 | if (SymFromAddr(process, frame.AddrPC.Offset, &displacement64, symbol)) { |
| 83 | symName = symbol->Name; |
| 84 | if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &displacement32, &line)) { |
| 85 | fprintf(stderr, " [%2d] %s + 0x%llx (%s:%lu)\n", i, symName, |
| 86 | (unsigned long long)displacement64, line.FileName, line.LineNumber); |
| 87 | } else { |
| 88 | fprintf(stderr, " [%2d] %s + 0x%llx\n", i, symName, |
| 89 | (unsigned long long)displacement64); |
no test coverage detected