diff --git a/lib/std/os/win32/process.c3 b/lib/std/os/win32/process.c3 index 50e5ae4d2..8a2798146 100644 --- a/lib/std/os/win32/process.c3 +++ b/lib/std/os/win32/process.c3 @@ -43,6 +43,7 @@ const IMAGE_FILE_MACHINE_I386 = 0x014c; const IMAGE_FILE_MACHINE_IA64 = 0x0200; const IMAGE_FILE_MACHINE_ARM64 = 0xAA64; const IMAGE_FILE_MACHINE_AMD64 = 0x8664; +const UNDNAME_COMPLETE = 0x0000; extern fn void initializeCriticalSection(Win32_CRITICAL_SECTION* section) @extern("InitializeCriticalSection"); extern fn void deleteCriticalSection(Win32_CRITICAL_SECTION* section) @extern("DeleteCriticalSection"); @@ -95,6 +96,9 @@ extern fn Win32_DWORD getModuleBaseNameA(Win32_HANDLE hProcess, Win32_HMODULE h extern fn Win32_DWORD symGetOptions() @extern("SymGetOptions"); extern fn Win32_DWORD symSetOptions(Win32_DWORD symOptions) @extern("SymSetOptions"); extern fn Win32_PIMAGE_NT_HEADERS imageNtHeader(Win32_PVOID base) @extern("ImageNtHeader"); +extern fn Win32_DWORD unDecorateSymbolName(Win32_PCSTR name, Win32_PSTR outputString, Win32_DWORD maxStringLength, Win32_DWORD flags) @extern("UnDecorateSymbolName"); +extern fn Win32_BOOL symFromAddr(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @extern("SymFromAddr"); +extern fn Win32_BOOL symGetLineFromAddr64(Win32_HANDLE hProcess, Win32_DWORD64 dwAddr, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line) @extern("SymGetLineFromAddr64"); import std::io; fn void*[] load_callstack(void*[] locations) @@ -115,25 +119,22 @@ fn void*[] load_callstack(void*[] locations) usz total = 0; while (total < locations.len) { - if (!stackWalk64(machine_type, process, thread, &s, &context, null, - &symFunctionTableAccess64, &symGetModuleBase64, null)) break; + if (!stackWalk64(machine_type, process, thread, &s, &context, null, + &symFunctionTableAccess64, &symGetModuleBase64, null)) break; if (s.addrReturn.offset == 0) break; locations[total++] = (void*)(uptr)s.addrPC.offset; } return locations[:total]; } -fn Backtrace! resolve(void* addr) +fn Win32_DWORD! load_modules() { - io::printn("a"); Win32_HANDLE process = getCurrentProcess(); Win32_DWORD needed; symInitialize(getCurrentProcess(), null, 1); - io::printn("b"); Win32_DWORD symOptions = symGetOptions(); symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME; symSetOptions(symOptions); - io::printn("c"); Win32_HMODULE[1024] mod_buffer; if (!enumProcessModules(process, &mod_buffer, mod_buffer.len, &needed)) { @@ -142,10 +143,8 @@ fn Backtrace! resolve(void* addr) if (needed > mod_buffer.len) return BacktraceFault.RESOLUTION_FAILED?; Win32_HMODULE[] modules = mod_buffer[:needed]; void* base = null; - io::printn("d"); foreach (mod : modules) { - io::printn("e"); Win32_MODULEINFO info; if (!getModuleInformation(process, mod, &info, $sizeof(info))) { @@ -161,15 +160,48 @@ fn Backtrace! resolve(void* addr) Win32_DWORD len2 = getModuleBaseNameA(process, mod, (Win32_LPSTR)&module_name, 1021); io::printn((String)module_name[:len2]); if (len2 < 1) continue; - Win32_DWORD64 base_addr = symLoadModuleEx(process, null, (Win32_PCSTR)&char_buf, (Win32_PCSTR)&module_name, (Win32_DWORD64)info.lpBaseOfDll, load_size, null, 0); + Win32_DWORD64 base_addr = symLoadModuleEx(process, null, (Win32_PCSTR)&char_buf, (Win32_PCSTR)&module_name, (Win32_DWORD64)info.lpBaseOfDll, load_size, null, 0); } - io::printn("f"); if (!base) return BacktraceFault.IMAGE_NOT_FOUND?; - io::printn("g"); Win32_IMAGE_NT_HEADERS* h = imageNtHeader(base); - io::printn("g"); - Win32_DWORD image_type = h.fileHeader.machine; - return backtrace::BACKTRACE_UNKNOWN; + return h.fileHeader.machine; +} + +struct Symbol +{ + inline Win32_SYMBOL_INFO sym; + char[256] buffer; +} + +Win32_DWORD64 displacement; + +fn Backtrace! resolve(void* addr) +{ + Win32_HANDLE process = getCurrentProcess(); + Symbol symbol; + Win32_DWORD image_type = load_modules()!; + symbol.sizeOfStruct = Symbol.sizeof; + symbol.maxNameLen = 255; + if (!symFromAddr(process, (Win32_ULONG64)addr, &displacement, &symbol)) + { + io::printfn("Last error: %d", getLastError()); + return BacktraceFault.NO_BACKTRACE_SYMBOLS?; + } + char[256] name; + unDecorateSymbolName(symbol.name, (Win32_PSTR)&name, 256, UNDNAME_COMPLETE); + Win32_DWORD offset = 0; + Win32_IMAGEHLP_LINE64 line; + Backtrace backtrace; + ZString zname = (ZString)&name; + if (!symGetLineFromAddr64(process, (Win32_ULONG64)addr, &offset, &line)) + { + + backtrace.init((uptr)addr, .function = zname.str_view(), .object_file = ""); + return backtrace; + } + String filename = ((ZString)line.fileName).str_view(); + backtrace.init((uptr)addr, .function = zname.str_view(), .object_file = filename, .file = filename, .line = line.lineNumber); + return backtrace; } fn String get_module_name_and_prepare_symbols(uptr addr) diff --git a/lib/std/os/win32/types.c3 b/lib/std/os/win32/types.c3 index ca8ef58af..f7aec5729 100644 --- a/lib/std/os/win32/types.c3 +++ b/lib/std/os/win32/types.c3 @@ -307,26 +307,6 @@ struct Win32_IMAGEHLP_LINE64 Win32_DWORD64 address; } -struct Win32_SYMBOL_INFO -{ - Win32_ULONG sizeOfStruct; - Win32_ULONG typeIndex; - Win32_ULONG64[2] reserved; - Win32_ULONG index; - Win32_ULONG size; - Win32_ULONG64 modBase; - Win32_ULONG flags; - Win32_ULONG64 value; - Win32_ULONG64 address; - Win32_ULONG register; - Win32_ULONG scope; - Win32_ULONG tag; - Win32_ULONG nameLen; - Win32_ULONG maxNameLen; - Win32_CHAR[1] name; -} - - struct Win32_ARM64_NT_CONTEXT @align(16) { Win32_DWORD contextFlags; @@ -570,6 +550,27 @@ struct Win32_IMAGE_NT_HEADERS def Win32_PIMAGE_NT_HEADERS = Win32_IMAGE_NT_HEADERS*; +struct Win32_SYMBOL_INFO +{ + Win32_ULONG sizeOfStruct; + Win32_ULONG typeIndex; + Win32_ULONG64[2] reserved; + Win32_ULONG index; + Win32_ULONG size; + Win32_ULONG64 modBase; + Win32_ULONG flags; + Win32_ULONG64 value; + Win32_ULONG64 address; + Win32_ULONG register; + Win32_ULONG scope; + Win32_ULONG tag; + Win32_ULONG nameLen; + Win32_ULONG maxNameLen; + Win32_CHAR[] name; +} + +def Win32_PSYMBOL_INFO = Win32_SYMBOL_INFO*; + struct Win32_MODLOAD_DATA { Win32_DWORD ssize; @@ -639,6 +640,5 @@ def Win32_LPADDRESS64 = Win32_ADDRESS64*; def Win32_LPSTACKFRAME64 = Win32_STACKFRAME64*; def Win32_PMODLOAD_DATA = Win32_MODLOAD_DATA*; def Win32_PIMAGEHLP_LINE64 = Win32_IMAGEHLP_LINE64*; -def Win32_PSYMBOL_INFO = Win32_SYMBOL_INFO*; def Win32_LPMODULEINFO = Win32_MODULEINFO*; diff --git a/resources/msvc_stack.c3 b/resources/msvc_stack.c3 index ae65b6ce6..404c895a6 100644 --- a/resources/msvc_stack.c3 +++ b/resources/msvc_stack.c3 @@ -8,8 +8,12 @@ fn void test1() void*[200] buf; void*[] addrs = win32::load_callstack(&buf); io::printfn("Hello2 %s", addrs); - (void)win32::resolve(addrs[0]); - io::printn("--"); + Backtrace! trace = win32::resolve(addrs[0]); + if (catch err = trace) + { + io::printfn("Failed: %s", err); + } + (void)io::printn(trace); } fn void main() {