1 #include "backtrace/tan_backtrace.h"
11 #pragma comment(lib, "dbghelp.lib")
19 bool init_back_trace(
const char *) {
return true; }
21 inline std::vector<StackFrame> stack_trace() {
24 DWORD machine = IMAGE_FILE_MACHINE_AMD64;
26 DWORD machine = IMAGE_FILE_MACHINE_I386;
28 HANDLE process = GetCurrentProcess();
29 HANDLE thread = GetCurrentThread();
31 if (SymInitialize(process,
nullptr, TRUE) == FALSE) {
32 cerr <<
"Failed to call SymInitialize\n";
33 return std::vector<StackFrame>();
36 SymSetOptions(SYMOPT_LOAD_LINES);
39 context.ContextFlags = CONTEXT_FULL;
40 RtlCaptureContext(&context);
43 STACKFRAME frame = {};
44 frame.AddrPC.Offset = context.Rip;
45 frame.AddrPC.Mode = AddrModeFlat;
46 frame.AddrFrame.Offset = context.Rbp;
47 frame.AddrFrame.Mode = AddrModeFlat;
48 frame.AddrStack.Offset = context.Rsp;
49 frame.AddrStack.Mode = AddrModeFlat;
51 STACKFRAME frame = {};
52 frame.AddrPC.Offset = context.Eip;
53 frame.AddrPC.Mode = AddrModeFlat;
54 frame.AddrFrame.Offset = context.Ebp;
55 frame.AddrFrame.Mode = AddrModeFlat;
56 frame.AddrStack.Offset = context.Esp;
57 frame.AddrStack.Mode = AddrModeFlat;
62 std::vector<StackFrame> frames;
64 machine, process, thread, &frame, &context,
nullptr, SymFunctionTableAccess, SymGetModuleBase,
nullptr)) {
68 DWORD64 moduleBase = 0;
73 moduleBase = SymGetModuleBase(process, frame.AddrPC.Offset);
80 char symbolBuffer[
sizeof(IMAGEHLP_SYMBOL) + 255]{0};
81 auto symbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
82 symbol->SizeOfStruct =
sizeof(IMAGEHLP_SYMBOL) + 255;
83 symbol->MaxNameLength = 254;
85 if (SymGetSymFromAddr(process, frame.AddrPC.Offset, &offset, symbol)) {
86 f.name = symbol->Name;
88 DWORD error = GetLastError();
89 printf(
"Failed to resolve address 0x%llX: %lu\n", frame.AddrPC.Offset, error);
90 f.name =
"Unknown Function";
94 line.SizeOfStruct =
sizeof(IMAGEHLP_LINE);
97 if (SymGetLineFromAddr(process, frame.AddrPC.Offset, &offset_ln, &line)) {
98 f.file = line.FileName;
99 f.line = line.LineNumber;
101 DWORD error = GetLastError();
102 printf(
"Failed to resolve line for 0x%llX%lu\n", frame.AddrPC.Offset, error);
116 void print_back_trace() {
117 std::vector<StackFrame> stack = stack_trace();
118 for (
auto &i : stack) {
119 printf(
"%s:%u in function %s\n", i.file.c_str(), i.line, i.name.c_str());
123 #include <backtrace.h>
126 void *__bt_state =
nullptr;
128 int bt_callback(
void *, uintptr_t,
const char *filename,
int lineno,
const char *
function) {
130 const char *func_name =
function;
132 char *demangled = abi::__cxa_demangle(
function,
nullptr,
nullptr, &status);
134 func_name = demangled;
137 if (filename && func_name) {
138 printf(
"%s:%d in function %s\n", filename, lineno, func_name);
143 void bt_error_callback(
void *,
const char *msg,
int errnum) {
144 printf(
"Error %d occurred when getting the stacktrace: %s", errnum, msg);
147 void bt_error_callback_create(
void *data,
const char *msg,
int errnum) {
148 printf(
"Error %d occurred when initializing the stacktrace: %s", errnum, msg);
149 bool *status = (
bool *)data;
153 bool init_back_trace(
const char *filename) {
155 __bt_state = backtrace_create_state(filename, 0, bt_error_callback_create, (
void *)status);
159 void print_back_trace() {
161 printf(
"Make sure init_back_trace() is called before calling print_stack_trace()\n");
164 backtrace_full((backtrace_state *)__bt_state, 0, bt_callback, bt_error_callback,
nullptr);