dqn: Start mocking up stack trace lib

This commit is contained in:
doyle 2023-08-30 00:14:31 +10:00
parent 76cc1f278c
commit 0028e9ca62
2 changed files with 101 additions and 1 deletions

View File

@ -1847,10 +1847,110 @@ static void Dqn_Test_RunSuite()
dqn_library->log_callback = prev_log_callback; dqn_library->log_callback = prev_log_callback;
} }
#define WIN32_LEAN_AND_MEAN
#include <TlHelp32.h>
#include <DbgHelp.h> // STACKFRAME64, ...
#include <winnt.h> // CONTEXT
#pragma comment(lib, "DbgHelp.lib")
// extern "C"
// {
// /*HANDLE*/ void * __stdcall GetCurrentProcess(void);
// /*HANDLE*/ void * __stdcall GetCurrentThread(void);
// }
void DumpStackTrace()
{
#if !defined(_M_X64)
#error "Platform is not implemented"
#endif
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 frame = {};
frame.AddrPC.Offset = context.Rip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Rbp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Rsp;
frame.AddrStack.Mode = AddrModeFlat;
void *thread = GetCurrentThread();
static Dqn_TicketMutex mutex = {};
Dqn_TicketMutex_Begin(&mutex);
void *process = GetCurrentProcess();
static bool init = false;
if (!init) {
SymInitialize(process, nullptr /*UserSearchPath*/, true /*fInvadeProcess*/);
SymSetOptions(SYMOPT_LOAD_LINES);
init = 1;
}
for (;;) {
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64,
process,
thread,
&frame,
&context,
nullptr /*ReadMemoryRoutine*/,
SymFunctionTableAccess64,
SymGetModuleBase64,
nullptr /*TrnaslateAddress*/)) {
break;
}
if (frame.AddrPC.Offset == frame.AddrReturn.Offset) {
// TODO(doyle): Recursion
}
if (frame.AddrPC.Offset == 0) {
break;
// TODO(doyle): Invalid program counter
} else {
// NOTE: Get file+line =================================================================
IMAGEHLP_LINE64 line = {};
line.SizeOfStruct = sizeof(line);
DWORD line_displacement = 0;
if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &line_displacement, &line)) {
printf("%s(%lu): ", line.FileName, line.LineNumber);
} else {
DWORD error = GetLastError();
printf("SymFromAddr returned error : %lu\n", error);
}
// NOTE: Get function name ============================================================
char buffer[sizeof(SYMBOL_INFO) + 1024] = {};
SYMBOL_INFO *symbol = new (buffer) SYMBOL_INFO;
symbol->SizeOfStruct = sizeof(*symbol);
symbol->MaxNameLen = 1024;
uint64_t symbol_displacement = 0; // Offset to the beginning of the symbol to the address
if (SymFromAddr(process, frame.AddrPC.Offset, &symbol_displacement, symbol)) {
printf("%.*s\n", DQN_CAST(int)symbol->NameLen, symbol->Name);
} else {
DWORD error = GetLastError();
printf("SymFromAddr returned error : %lu\n", error);
}
}
}
Dqn_TicketMutex_End(&mutex);
}
#if defined(DQN_TEST_WITH_MAIN) #if defined(DQN_TEST_WITH_MAIN)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
(void)argv; (void)argc; (void)argv; (void)argc;
printf("%s\n\n", b_stacktrace_get_string());
DumpStackTrace();
return 1;
Dqn_Test_RunSuite(); Dqn_Test_RunSuite();
return 0; return 0;
} }

View File

@ -15,7 +15,7 @@ pushd Build
REM Z7 Combine multi-debug files to one debug file REM Z7 Combine multi-debug files to one debug file
set common_flags=-D DQN_TEST_WITH_MAIN -I %script_dir% %script_dir%\Misc\dqn_unit_tests.cpp set common_flags=-D DQN_TEST_WITH_MAIN -I %script_dir% %script_dir%\Misc\dqn_unit_tests.cpp
set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -WX -nologo set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo
REM Optionally pass `-analyze` to `msvc_compile_flags` for more checks, but, REM Optionally pass `-analyze` to `msvc_compile_flags` for more checks, but,
REM it slows down compilation by around 5s on my old laptop. REM it slows down compilation by around 5s on my old laptop.