Skip to content

Commit

Permalink
Backtrace msvc
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Nov 14, 2023
1 parent 03b103b commit 3f140f2
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 37 deletions.
60 changes: 46 additions & 14 deletions lib/std/os/win32/process.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand All @@ -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))
{
Expand All @@ -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)))
{
Expand All @@ -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)
Expand Down
42 changes: 21 additions & 21 deletions lib/std/os/win32/types.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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*;

8 changes: 6 additions & 2 deletions resources/msvc_stack.c3
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down

0 comments on commit 3f140f2

Please sign in to comment.