mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Use backtrace on windows. Updated backtrace API
This commit is contained in:
committed by
Christoffer Lerno
parent
587d5578ab
commit
81c93e3488
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@@ -41,6 +41,7 @@ jobs:
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile-run examples\load_world.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile-run examples\process.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile --test -g -O0 --threads 1 --target macos-x64 examples\constants.c3
|
||||
..\build\${{ matrix.build_type }}\c3c.exe compile-run msvc_stack.c3
|
||||
|
||||
- name: Build testproject
|
||||
run: |
|
||||
|
||||
@@ -91,7 +91,10 @@ fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIV
|
||||
{
|
||||
@pool()
|
||||
{
|
||||
BacktraceList! backtrace = backtrace::backtrace_load(mem::temp());
|
||||
void*[256] buffer;
|
||||
void*[] backtraces = backtrace::capture_current(&buffer);
|
||||
backtraces_to_ignore++;
|
||||
BacktraceList! backtrace = backtrace::symbolize_backtrace(backtraces, mem::temp());
|
||||
if (catch backtrace) return false;
|
||||
if (backtrace.len() <= backtraces_to_ignore) return false;
|
||||
io::eprint("\nERROR: '");
|
||||
|
||||
@@ -132,7 +132,7 @@ const MemoryEnvironment MEMORY_ENV = (MemoryEnvironment)$$MEMORY_ENVIRONMENT;
|
||||
const bool TRACK_MEMORY = DEBUG_SYMBOLS && (COMPILER_SAFE_MODE || TESTING);
|
||||
const bool X86_64 = ARCH_TYPE == X86_64;
|
||||
const bool AARCH64 = ARCH_TYPE == AARCH64;
|
||||
const bool NATIVE_STACKTRACE = LINUX || DARWIN;
|
||||
const bool NATIVE_STACKTRACE = LINUX || DARWIN || WIN32;
|
||||
const bool LINUX = LIBC && OS_TYPE == LINUX;
|
||||
const bool DARWIN = LIBC && os_is_darwin();
|
||||
const bool WIN32 = LIBC && OS_TYPE == WIN32;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
module std::os::backtrace;
|
||||
import std::collections::list;
|
||||
|
||||
fault BacktraceFault
|
||||
{
|
||||
@@ -6,6 +7,7 @@ fault BacktraceFault
|
||||
EXECUTABLE_PATH_NOT_FOUND,
|
||||
IMAGE_NOT_FOUND,
|
||||
NO_BACKTRACE_SYMBOLS,
|
||||
RESOLUTION_FAILED,
|
||||
}
|
||||
|
||||
const Backtrace BACKTRACE_UNKNOWN = { 0, "", "", "", 0, null };
|
||||
@@ -20,6 +22,7 @@ struct Backtrace (Printable)
|
||||
Allocator* allocator;
|
||||
}
|
||||
|
||||
|
||||
fn bool Backtrace.has_file(&self)
|
||||
{
|
||||
return self.file.len > 0;
|
||||
@@ -50,12 +53,9 @@ fn void Backtrace.free(&self)
|
||||
self.allocator.free(self.file);
|
||||
}
|
||||
|
||||
def backtrace_load = darwin::backtrace_load @if(env::DARWIN);
|
||||
def backtrace_load = linux::backtrace_load @if(env::LINUX);
|
||||
|
||||
fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_file, String file = "", uint line = 0, Allocator* using = mem::heap())
|
||||
fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_file, String file = "", uint line = 0, Allocator* allocator)
|
||||
{
|
||||
if (!using)
|
||||
if (!allocator)
|
||||
{
|
||||
self.offset = offset;
|
||||
self.function = function;
|
||||
@@ -66,11 +66,31 @@ fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_
|
||||
return self;
|
||||
}
|
||||
self.offset = offset;
|
||||
self.function = function.copy(using);
|
||||
self.object_file = object_file.copy(using);
|
||||
self.file = file.copy(using);
|
||||
self.allocator = using;
|
||||
self.function = function.copy(allocator);
|
||||
self.object_file = object_file.copy(allocator);
|
||||
self.file = file.copy(allocator);
|
||||
self.allocator = allocator;
|
||||
self.line = line;
|
||||
return self;
|
||||
}
|
||||
|
||||
fn void*[] capture_current(void*[] buffer) @if(env::POSIX || env::WIN32)
|
||||
{
|
||||
if (!buffer.len) return buffer[:0];
|
||||
$switch
|
||||
$case env::POSIX:
|
||||
CInt len = posix::backtrace(buffer.ptr, buffer.len);
|
||||
return buffer[:len];
|
||||
$case env::WIN32:
|
||||
Win32_WORD len = win32::rtlCaptureStackBackTrace(0, buffer.len, buffer.ptr, null);
|
||||
return buffer[:len];
|
||||
$default:
|
||||
return buffer[:0];
|
||||
$endswitch
|
||||
}
|
||||
|
||||
def BacktraceList = List(<Backtrace>);
|
||||
|
||||
def symbolize_backtrace = linux::symbolize_backtrace @if(env::LINUX);
|
||||
def symbolize_backtrace = win32::symbolize_backtrace @if(env::WIN32);
|
||||
def symbolize_backtrace = darwin::symbolize_backtrace @if(env::DARWIN);
|
||||
|
||||
@@ -28,7 +28,7 @@ import std::os::win32;
|
||||
|
||||
fn uint num_cpu()
|
||||
{
|
||||
SystemInfo info;
|
||||
win32::get_system_info(&info);
|
||||
Win32_SYSTEM_INFO info;
|
||||
win32::getSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import std::collections::list;
|
||||
|
||||
extern fn isz readlink(ZString path, char* buf, usz bufsize);
|
||||
|
||||
def BacktraceList = List(<Backtrace>);
|
||||
|
||||
const PT_PHDR = 6;
|
||||
const EI_NIDENT = 16;
|
||||
def Elf32_Half = ushort;
|
||||
@@ -153,7 +151,8 @@ fn Backtrace! backtrace_load_element(void* addr, Allocator* allocator = mem::hea
|
||||
.object_file = info.dli_fname.copy(allocator),
|
||||
.offset = (uptr)addr,
|
||||
.file = "".copy(allocator),
|
||||
.line = 0
|
||||
.line = 0,
|
||||
.allocator = allocator
|
||||
};
|
||||
}
|
||||
uint line = 0;
|
||||
@@ -174,13 +173,10 @@ fn Backtrace! backtrace_load_element(void* addr, Allocator* allocator = mem::hea
|
||||
};
|
||||
}
|
||||
|
||||
fn BacktraceList! backtrace_load(Allocator* allocator)
|
||||
fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator* allocator)
|
||||
{
|
||||
void*[256] bt_buffer;
|
||||
CInt size = posix::backtrace(&bt_buffer, 256);
|
||||
io::printfn("Backtrace list %s", size);
|
||||
BacktraceList list;
|
||||
list.init_new(size, allocator);
|
||||
list.init_new(backtrace.len, allocator);
|
||||
defer catch
|
||||
{
|
||||
foreach (trace : list)
|
||||
@@ -191,9 +187,9 @@ fn BacktraceList! backtrace_load(Allocator* allocator)
|
||||
}
|
||||
@pool(allocator)
|
||||
{
|
||||
for (usz i = 0; i < size; i++)
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
Backtrace trace = backtrace_load_element(bt_buffer[i], allocator)!;
|
||||
Backtrace trace = backtrace_load_element(addr, allocator)!;
|
||||
list.append(trace);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,8 +76,6 @@ fn String! executable_path(Allocator *allocator)
|
||||
return ((ZString)&path).copy(allocator);
|
||||
}
|
||||
|
||||
def BacktraceList = List(<Backtrace>);
|
||||
|
||||
fn uptr! load_address() @local
|
||||
{
|
||||
Darwin_segment_command_64* cmd = darwin::getsegbyname("__TEXT");
|
||||
@@ -128,18 +126,17 @@ fn Backtrace! backtrace_load_element(String execpath, void* buffer, void* load_a
|
||||
.function = info.dli_sname ? info.dli_sname.copy(allocator) : "???".copy(allocator),
|
||||
.object_file = info.dli_fname.copy(allocator),
|
||||
.file = "".copy(allocator),
|
||||
.line = 0
|
||||
.line = 0,
|
||||
.allocator = allocator
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
fn BacktraceList! backtrace_load(Allocator* allocator)
|
||||
fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator* allocator)
|
||||
{
|
||||
void*[256] bt_buffer;
|
||||
CInt size = posix::backtrace(&bt_buffer, 256);
|
||||
void *load_addr = (void *)load_address()!;
|
||||
BacktraceList list;
|
||||
list.init_new(size, allocator);
|
||||
list.init_new(backtrace.len, allocator);
|
||||
defer catch
|
||||
{
|
||||
foreach (trace : list)
|
||||
@@ -151,11 +148,9 @@ fn BacktraceList! backtrace_load(Allocator* allocator)
|
||||
@pool(allocator)
|
||||
{
|
||||
String execpath = executable_path(mem::temp())!;
|
||||
for (usz i = 1; i < size; i++)
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
void* buffer = bt_buffer[i];
|
||||
Backtrace trace = backtrace_load_element(execpath, buffer, load_addr, allocator)!;
|
||||
list.append(trace);
|
||||
list.append(backtrace_load_element(execpath, addr, load_addr, allocator) ?? backtrace::BACKTRACE_UNKNOWN);
|
||||
}
|
||||
};
|
||||
return list;
|
||||
|
||||
@@ -28,7 +28,22 @@ const Win32_DWORD PIPE_WAIT = 0;
|
||||
const Win32_DWORD PIPE_NOWAIT = 1;
|
||||
const Win32_DWORD PIPE_ACCEPT_REMOTE_CLIENTS = 0;
|
||||
const Win32_DWORD PIPE_REJECT_REMOTE_CLIENTS = 8;
|
||||
const SYMOPT_CASE_INSENSITIVE = 0x01;
|
||||
const SYMOPT_UNDNAME = 0x02;
|
||||
const SYMOPT_DEFERRED_LOADS = 0x04;
|
||||
const SYMOPT_NO_CPP = 0x08;
|
||||
const SYMOPT_LOAD_LINES = 0x10;
|
||||
const SYMOPT_OMAP_FIND_NEAREST = 0x20;
|
||||
const SYMOPT_LOAD_ANYTHING = 0x40;
|
||||
const SYMOPT_IGNORE_CVREC = 0x80;
|
||||
|
||||
const IMAGE_FILE_MACHINE_UNKNOWN = 0;
|
||||
const IMAGE_FILE_MACHINE_TARGET_HOST = 1;
|
||||
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");
|
||||
@@ -47,70 +62,136 @@ extern fn Win32_DWORD sleepEx(Win32_DWORD ms, Win32_BOOL alertable) @extern("Sle
|
||||
extern fn Win32_HANDLE createThread(void* attributes, usz stack, ThreadFn func, void* arg, uint flags, uint* thread_id) @extern("CreateThread");
|
||||
extern fn Win32_BOOL getExitCodeThread(Win32_HANDLE handle, uint* exit_code) @extern("GetExitCodeThread");
|
||||
extern fn Win32_BOOL getExitCodeProcess(Win32_HANDLE hProcess, Win32_LPDWORD lpExitCode) @extern("GetExitCodeProcess");
|
||||
extern fn uint getThreadId(Win32_HANDLE) @extern("GetThreadId");
|
||||
extern fn void exitThread(uint res) @noreturn @extern("ExitThread");
|
||||
extern fn Win32_DWORD getThreadId(Win32_HANDLE) @extern("GetThreadId");
|
||||
extern fn void exitThread(Win32_DWORD dwExitCode) @noreturn @extern("ExitThread");
|
||||
extern fn Win32_HANDLE getCurrentThread() @extern("GetCurrentThread");
|
||||
extern fn Win32_BOOL terminateProcess(Win32_HANDLE hProcess, Win32_UINT uExitCode) @extern("TerminateProcess");
|
||||
extern fn Win32_DWORD getCurrentProcessId() @extern("GetCurrentProcessId");
|
||||
extern fn Win32_HANDLE getCurrentProcess() @extern("GetCurrentProcess");
|
||||
extern fn Win32_DWORD getCurrentThreadId() @extern("GetCurrentThreadId");
|
||||
extern fn Win32_BOOL setHandleInformation(Win32_HANDLE hObject, Win32_DWORD dwMask, Win32_DWORD dwFlags) @extern("SetHandleInformation");
|
||||
extern fn Win32_HANDLE createEventA(
|
||||
Win32_LPSECURITY_ATTRIBUTES lpEventAttributes,
|
||||
Win32_BOOL bManualReset,
|
||||
Win32_BOOL bInitialState,
|
||||
Win32_LPCSTR lpName
|
||||
) @extern("CreateEventA");
|
||||
extern fn Win32_BOOL createProcessW(
|
||||
Win32_LPCWSTR lpApplicationName,
|
||||
Win32_LPWSTR lpCommandLine,
|
||||
Win32_LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
Win32_LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
Win32_BOOL bInheritHandles,
|
||||
Win32_DWORD dwCreationFlags,
|
||||
Win32_LPVOID lpEnvironment,
|
||||
Win32_LPCWSTR lpCurrentDirectory,
|
||||
Win32_LPSTARTUPINFOW lpStartupInfo,
|
||||
Win32_LPPROCESS_INFORMATION lpProcessInformation
|
||||
) @extern("CreateProcessW");
|
||||
extern fn Win32_HANDLE createNamedPipeA(
|
||||
Win32_LPCSTR lpName, Win32_DWORD dwOpenMode, Win32_DWORD dwPipeMode,
|
||||
Win32_DWORD nMaxInstances, Win32_DWORD nOutBufferSize, Win32_DWORD nInBufferSize,
|
||||
Win32_DWORD nDefaultTimeOut, Win32_LPSECURITY_ATTRIBUTES lpSecurityAttributes
|
||||
) @extern("CreateNamedPipeA");
|
||||
extern fn Win32_BOOL getOverlappedResult(
|
||||
Win32_HANDLE hFile,
|
||||
Win32_LPOVERLAPPED lpOverlapped,
|
||||
Win32_LPDWORD lpNumberOfBytesTransferred,
|
||||
Win32_BOOL bWait
|
||||
) @extern("GetOverlappedResult");
|
||||
extern fn Win32_DWORD getEnvironmentVariableW(
|
||||
Win32_LPCWSTR lpName,
|
||||
Win32_LPWSTR lpBuffer,
|
||||
Win32_DWORD nSize
|
||||
) @extern("GetEnvironmentVariableW");
|
||||
extern fn Win32_BOOL setEnvironmentVariableW(
|
||||
Win32_LPCWSTR lpName,
|
||||
Win32_LPCWSTR lpValue
|
||||
) @extern("SetEnvironmentVariableW");
|
||||
extern fn Win32_HANDLE createEventA(Win32_LPSECURITY_ATTRIBUTES lpEventAttributes, Win32_BOOL bManualReset, Win32_BOOL bInitialState, Win32_LPCSTR lpName) @extern("CreateEventA");
|
||||
extern fn Win32_BOOL createProcessW(Win32_LPCWSTR lpApplicationName, Win32_LPWSTR lpCommandLine, Win32_LPSECURITY_ATTRIBUTES lpProcessAttributes, Win32_LPSECURITY_ATTRIBUTES lpThreadAttributes, Win32_BOOL bInheritHandles, Win32_DWORD dwCreationFlags, Win32_LPVOID lpEnvironment, Win32_LPCWSTR lpCurrentDirectory, Win32_LPSTARTUPINFOW lpStartupInfo, Win32_LPPROCESS_INFORMATION lpProcessInformation) @extern("CreateProcessW");
|
||||
extern fn Win32_HANDLE createNamedPipeA(Win32_LPCSTR lpName, Win32_DWORD dwOpenMode, Win32_DWORD dwPipeMode, Win32_DWORD nMaxInstances, Win32_DWORD nOutBufferSize, Win32_DWORD nInBufferSize, Win32_DWORD nDefaultTimeOut, Win32_LPSECURITY_ATTRIBUTES lpSecurityAttributes) @extern("CreateNamedPipeA");
|
||||
extern fn Win32_BOOL getOverlappedResult(Win32_HANDLE hFile, Win32_LPOVERLAPPED lpOverlapped, Win32_LPDWORD lpNumberOfBytesTransferred, Win32_BOOL bWait) @extern("GetOverlappedResult");
|
||||
extern fn Win32_DWORD getEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPWSTR lpBuffer, Win32_DWORD nSize) @extern("GetEnvironmentVariableW");
|
||||
extern fn Win32_BOOL setEnvironmentVariableW(Win32_LPCWSTR lpName, Win32_LPCWSTR lpValue) @extern("SetEnvironmentVariableW");
|
||||
extern fn void getSystemInfo(Win32_LPSYSTEM_INFO lpSystemInfo) @extern("GetSystemInfo");
|
||||
extern fn Win32_BOOL enumProcessModules(Win32_HANDLE hProcess, Win32_HMODULE* lphModule, Win32_DWORD cb, Win32_LPDWORD lpcbNeeded) @extern("K32EnumProcessModules");
|
||||
extern fn Win32_BOOL getModuleInformation(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPMODULEINFO lpmodinfo, Win32_DWORD cb) @extern("K32GetModuleInformation");
|
||||
extern fn Win32_DWORD symAddrIncludeInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 address) @extern("SymAddrIncludeInlineTrace");
|
||||
extern fn Win32_BOOL symQueryInlineTrace(Win32_HANDLE hProcess, Win32_DWORD64 startAddress, Win32_DWORD startContext, Win32_DWORD64 startRetAddress, Win32_DWORD64 curAddress, Win32_LPDWORD curContext, Win32_LPDWORD curFrameIndex) @extern("SymQueryInlineTrace");
|
||||
extern fn Win32_BOOL symFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 address, Win32_ULONG inlineContext, Win32_PDWORD64 displacement, Win32_PSYMBOL_INFO symbol) @extern("SymFromInlineContext");
|
||||
extern fn Win32_BOOL symGetLineFromInlineContext(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_ULONG inlineContext, Win32_DWORD64 qwModuleBaseAddress, Win32_PDWORD pdwDisplacement, Win32_PIMAGEHLP_LINE64 line64) @extern("SymGetLineFromInlineContext");
|
||||
extern fn Win32_ULONG rtlWalkFrameChain(Win32_PVOID*, Win32_ULONG, Win32_ULONG) @extern("RtlWalkFrameChain");
|
||||
extern fn Win32_BOOL symInitialize(Win32_HANDLE hProcess, Win32_PCSTR userSearchPath, Win32_BOOL fInvadeProcess) @extern("SymInitialize");
|
||||
extern fn Win32_BOOL symCleanup(Win32_HANDLE hProcess) @extern("SymCleanup");
|
||||
extern fn Win32_DWORD getModuleFileNameA(Win32_HMODULE hModule, Win32_LPSTR lpFilename, Win32_DWORD nSize) @extern("GetModuleFileNameA");
|
||||
extern fn Win32_DWORD getModuleFileNameExA(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPSTR lpFilename, Win32_DWORD nSize) @extern("GetModuleFileNameExA");
|
||||
extern fn Win32_DWORD64 symLoadModuleEx(Win32_HANDLE hProcess, Win32_HANDLE hFile, Win32_PCSTR imageName, Win32_PCSTR moduleName, Win32_DWORD64 baseOfDll, Win32_DWORD dllSize, Win32_PMODLOAD_DATA data, Win32_DWORD flags) @extern("SymLoadModule");
|
||||
extern fn Win32_BOOL stackWalk64(Win32_DWORD machineType, Win32_HANDLE hProcess, Win32_HANDLE hThread, Win32_LPSTACKFRAME64 stackFrame, Win32_PVOID contextRecord, Win32_PREAD_PROCESS_MEMORY_ROUTINE64 readMemoryRoutine, Win32_PFUNCTION_TABLE_ACCESS_ROUTINE64 functionTableAccessRoutine, Win32_PGET_MODULE_BASE_ROUTINE64 getModuleBaseRoutine, Win32_PTRANSLATE_ADDRESS_ROUTINE64 translateAddress) @extern("StackWalk64");
|
||||
extern fn void rtlCaptureContext(Win32_PCONTEXT contextRecord) @extern("RtlCaptureContext");
|
||||
extern fn void* symFunctionTableAccess64(Win32_HANDLE hProcess, Win32_DWORD64 addrBase) @extern("SymFunctionTableAccess64");
|
||||
extern fn Win32_DWORD64 symGetModuleBase64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr) @extern("SymGetModuleBase64");
|
||||
extern fn Win32_DWORD getModuleBaseNameA(Win32_HANDLE hProcess, Win32_HMODULE hModule, Win32_LPSTR lpBaseName, Win32_DWORD nSize) @extern("K32GetModuleBaseNameA");
|
||||
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");
|
||||
extern fn Win32_WORD rtlCaptureStackBackTrace(Win32_DWORD framesToSkip, Win32_DWORD framesToCapture, Win32_PVOID *backTrace, Win32_PDWORD backTraceHash) @extern("RtlCaptureStackBackTrace");
|
||||
extern fn Win32_BOOL symGetModuleInfo64(Win32_HANDLE hProcess, Win32_DWORD64 qwAddr, Win32_PIMAGEHLP_MODULE64 moduleInfo) @extern("SymGetModuleInfo64");
|
||||
|
||||
struct SystemInfo
|
||||
fn Win32_DWORD! load_modules()
|
||||
{
|
||||
union {
|
||||
uint dwOemId;
|
||||
struct {
|
||||
ushort wProcessorArchitecture;
|
||||
ushort wReserved;
|
||||
Win32_HANDLE process = getCurrentProcess();
|
||||
Win32_DWORD needed;
|
||||
symInitialize(getCurrentProcess(), null, 1);
|
||||
Win32_DWORD symOptions = symGetOptions();
|
||||
symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME;
|
||||
symSetOptions(symOptions);
|
||||
Win32_HMODULE[1024] mod_buffer;
|
||||
if (!enumProcessModules(process, &mod_buffer, mod_buffer.len, &needed))
|
||||
{
|
||||
return BacktraceFault.RESOLUTION_FAILED?;
|
||||
}
|
||||
if (needed > mod_buffer.len) return BacktraceFault.RESOLUTION_FAILED?;
|
||||
Win32_HMODULE[] modules = mod_buffer[:needed];
|
||||
void* base = null;
|
||||
foreach (mod : modules)
|
||||
{
|
||||
Win32_MODULEINFO info;
|
||||
if (!getModuleInformation(process, mod, &info, $sizeof(info)))
|
||||
{
|
||||
return BacktraceFault.RESOLUTION_FAILED?;
|
||||
}
|
||||
uint dwPageSize;
|
||||
void* lpMinimumApplicationAddress;
|
||||
void* lpMaximumApplicationAddress;
|
||||
usz dwActiveProcessorMask;
|
||||
uint dwNumberOfProcessors;
|
||||
uint dwProcessorType;
|
||||
uint dwAllocationGranularity;
|
||||
ushort wProcessorLevel;
|
||||
ushort wProcessorRevision;
|
||||
if (!base) base = info.lpBaseOfDll;
|
||||
Win32_DWORD load_size = info.sizeOfImage;
|
||||
char[1024] char_buf;
|
||||
Win32_DWORD len = getModuleFileNameA(mod, (Win32_LPSTR)&char_buf, char_buf.len - 1);
|
||||
if (len < 1) continue;
|
||||
char[1024] module_name;
|
||||
Win32_DWORD len2 = getModuleBaseNameA(process, mod, (Win32_LPSTR)&module_name, 1021);
|
||||
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);
|
||||
}
|
||||
if (!base) return BacktraceFault.IMAGE_NOT_FOUND?;
|
||||
Win32_IMAGE_NT_HEADERS* h = imageNtHeader(base);
|
||||
return h.fileHeader.machine;
|
||||
}
|
||||
|
||||
extern fn CInt get_system_info(SystemInfo*) @extern("GetSystemInfo");
|
||||
struct Symbol
|
||||
{
|
||||
inline Win32_SYMBOL_INFO sym;
|
||||
char[256] buffer;
|
||||
}
|
||||
|
||||
Win32_DWORD64 displacement;
|
||||
|
||||
fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator* allocator)
|
||||
{
|
||||
BacktraceList list;
|
||||
list.init_new(backtrace.len, allocator);
|
||||
Win32_HANDLE process = getCurrentProcess();
|
||||
symInitialize(process, null, 1);
|
||||
defer symCleanup(process);
|
||||
foreach (addr : backtrace)
|
||||
{
|
||||
list.append(resolve_backtrace(addr, process, allocator) ?? backtrace::BACKTRACE_UNKNOWN);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
fn Backtrace! resolve_backtrace(void* addr, Win32_HANDLE process, Allocator* allocator)
|
||||
{
|
||||
Symbol symbol;
|
||||
//Win32_DWORD image_type = load_modules()!;
|
||||
symbol.sizeOfStruct = Win32_SYMBOL_INFO.sizeof;
|
||||
symbol.maxNameLen = 255;
|
||||
if (!symFromAddr(process, (Win32_DWORD64)addr - 1, &displacement, &symbol))
|
||||
{
|
||||
return BacktraceFault.NO_BACKTRACE_SYMBOLS?;
|
||||
}
|
||||
Win32_IMAGEHLP_MODULE64 module_info;
|
||||
module_info.sizeOfStruct = Win32_IMAGEHLP_MODULE64.sizeof;
|
||||
if (!symGetModuleInfo64(process, (Win32_DWORD64)addr - 1, &module_info))
|
||||
{
|
||||
return BacktraceFault.NO_BACKTRACE_SYMBOLS?;
|
||||
}
|
||||
ZString module_name = (ZString)&module_info.imageName;
|
||||
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 - 1, &offset, &line))
|
||||
{
|
||||
backtrace.init((uptr)addr, .function = zname.str_view(), .object_file = module_name.str_view(), .allocator = allocator);
|
||||
return backtrace;
|
||||
}
|
||||
String filename = ((ZString)line.fileName).str_view();
|
||||
backtrace.init((uptr)addr, .function = zname.str_view(), .object_file = module_name.str_view(), .file = filename, .line = line.lineNumber, .allocator = allocator);
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
@@ -266,3 +266,431 @@ struct Win32_PROCESS_INFORMATION
|
||||
|
||||
def Win32_PPROCESS_INFORMATION = Win32_PROCESS_INFORMATION*;
|
||||
def Win32_LPPROCESS_INFORMATION = Win32_PROCESS_INFORMATION*;
|
||||
|
||||
struct Win32_SYSTEM_INFO
|
||||
{
|
||||
union
|
||||
{
|
||||
Win32_DWORD dwOemId;
|
||||
struct
|
||||
{
|
||||
Win32_WORD wProcessorArchitecture;
|
||||
Win32_WORD wReserved;
|
||||
}
|
||||
}
|
||||
Win32_DWORD dwPageSize;
|
||||
Win32_LPVOID lpMinimumApplicationAddress;
|
||||
Win32_LPVOID lpMaximumApplicationAddress;
|
||||
Win32_DWORD_PTR dwActiveProcessorMask;
|
||||
Win32_DWORD dwNumberOfProcessors;
|
||||
Win32_DWORD dwProcessorType;
|
||||
Win32_DWORD dwAllocationGranularity;
|
||||
Win32_WORD wProcessorLevel;
|
||||
Win32_WORD wProcessorRevision;
|
||||
}
|
||||
|
||||
def Win32_LPSYSTEM_INFO = Win32_SYSTEM_INFO*;
|
||||
|
||||
struct Win32_MODULEINFO
|
||||
{
|
||||
Win32_LPVOID lpBaseOfDll;
|
||||
Win32_DWORD sizeOfImage;
|
||||
Win32_LPVOID entryPoint;
|
||||
}
|
||||
|
||||
struct Win32_IMAGEHLP_LINE64
|
||||
{
|
||||
Win32_DWORD sizeOfStruct;
|
||||
Win32_PVOID key;
|
||||
Win32_DWORD lineNumber;
|
||||
Win32_PCHAR fileName;
|
||||
Win32_DWORD64 address;
|
||||
}
|
||||
|
||||
enum Win32_SYM_TYPE
|
||||
{
|
||||
SYM_NONE,
|
||||
SYM_COFF,
|
||||
SYM_CV,
|
||||
SYM_PDB,
|
||||
SYM_EXPORT,
|
||||
SYM_DEFERRED,
|
||||
SYM_SYM,
|
||||
SYM_DIA,
|
||||
SYM_VIRTUAL
|
||||
}
|
||||
|
||||
struct Win32_GUID
|
||||
{
|
||||
CULong data1;
|
||||
CUShort data2;
|
||||
CUShort data3;
|
||||
char[8] data4;
|
||||
}
|
||||
|
||||
struct Win32_IMAGEHLP_MODULE64
|
||||
{
|
||||
Win32_DWORD sizeOfStruct;
|
||||
Win32_DWORD64 baseOfImage;
|
||||
Win32_DWORD imageSize;
|
||||
Win32_DWORD timeDateStamp;
|
||||
Win32_DWORD checkSum;
|
||||
Win32_DWORD numSyms;
|
||||
Win32_SYM_TYPE symType;
|
||||
Win32_CHAR[32] moduleName;
|
||||
Win32_CHAR[256] imageName;
|
||||
Win32_CHAR[256] loadedImageName;
|
||||
Win32_CHAR[256] loadedPdbName;
|
||||
Win32_DWORD cVSig;
|
||||
Win32_CHAR** cVData;
|
||||
Win32_DWORD pdbSig;
|
||||
Win32_GUID pdbSig70;
|
||||
Win32_DWORD pdbAge;
|
||||
Win32_BOOL pdbUnmatched;
|
||||
Win32_BOOL dbgUnmatched;
|
||||
Win32_BOOL lineNumbers;
|
||||
Win32_BOOL globalSymbols;
|
||||
Win32_BOOL typeInfo;
|
||||
Win32_BOOL sourceIndexed;
|
||||
Win32_BOOL publics;
|
||||
Win32_DWORD machineType;
|
||||
Win32_DWORD reserved;
|
||||
}
|
||||
|
||||
def Win32_PIMAGEHLP_MODULE64 = Win32_IMAGEHLP_MODULE64*;
|
||||
|
||||
struct Win32_ARM64_NT_CONTEXT @align(16)
|
||||
{
|
||||
Win32_DWORD contextFlags;
|
||||
Win32_DWORD cpsr;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
Win32_DWORD64 x0;
|
||||
Win32_DWORD64 x1;
|
||||
Win32_DWORD64 x2;
|
||||
Win32_DWORD64 x3;
|
||||
Win32_DWORD64 x4;
|
||||
Win32_DWORD64 x5;
|
||||
Win32_DWORD64 x6;
|
||||
Win32_DWORD64 x7;
|
||||
Win32_DWORD64 x8;
|
||||
Win32_DWORD64 x9;
|
||||
Win32_DWORD64 x10;
|
||||
Win32_DWORD64 x11;
|
||||
Win32_DWORD64 x12;
|
||||
Win32_DWORD64 x13;
|
||||
Win32_DWORD64 x14;
|
||||
Win32_DWORD64 x15;
|
||||
Win32_DWORD64 x16;
|
||||
Win32_DWORD64 x17;
|
||||
Win32_DWORD64 x18;
|
||||
Win32_DWORD64 x19;
|
||||
Win32_DWORD64 x20;
|
||||
Win32_DWORD64 x21;
|
||||
Win32_DWORD64 x22;
|
||||
Win32_DWORD64 x23;
|
||||
Win32_DWORD64 x24;
|
||||
Win32_DWORD64 x25;
|
||||
Win32_DWORD64 x26;
|
||||
Win32_DWORD64 x27;
|
||||
Win32_DWORD64 x28;
|
||||
Win32_DWORD64 fp;
|
||||
Win32_DWORD64 lr;
|
||||
}
|
||||
Win32_DWORD64[31] x;
|
||||
}
|
||||
Win32_DWORD64 sp;
|
||||
Win32_DWORD64 pc;
|
||||
Win32_ARM64_NT_NEON128[32] v;
|
||||
Win32_DWORD fpcr;
|
||||
Win32_DWORD fpsr;
|
||||
Win32_DWORD[ARM64_MAX_BREAKPOINTS] bcr;
|
||||
Win32_DWORD64[ARM64_MAX_BREAKPOINTS] bvr;
|
||||
Win32_DWORD[ARM64_MAX_WATCHPOINTS] wcr;
|
||||
Win32_DWORD64[ARM64_MAX_WATCHPOINTS] wvr;
|
||||
}
|
||||
const ARM64_MAX_BREAKPOINTS = 8;
|
||||
const ARM64_MAX_WATCHPOINTS = 2;
|
||||
|
||||
struct Win32_ARM64_NT_NEON128
|
||||
{
|
||||
Win32_ULONGLONG low;
|
||||
Win32_LONGLONG high;
|
||||
}
|
||||
|
||||
struct Win32_XMM_SAVE_AREA32
|
||||
{
|
||||
Win32_USHORT controlWord;
|
||||
Win32_USHORT statusWord;
|
||||
Win32_UCHAR tagWord;
|
||||
Win32_UCHAR reserved1;
|
||||
Win32_USHORT errorOpcode;
|
||||
Win32_ULONG errrorOffset;
|
||||
Win32_USHORT errorSelector;
|
||||
Win32_USHORT reserved2;
|
||||
Win32_ULONG dataOffset;
|
||||
Win32_USHORT dataSelector;
|
||||
Win32_USHORT reserved3;
|
||||
Win32_ULONG mxCsr;
|
||||
Win32_ULONG mxCsr_Mask;
|
||||
Win32_M128A[8] floatRegisters;
|
||||
Win32_M128A[16] xmmRegisters;
|
||||
Win32_UCHAR[96] reserved4;
|
||||
}
|
||||
|
||||
struct Win32_AMD64_CONTEXT @align(16)
|
||||
{
|
||||
Win32_DWORD64 p1Home;
|
||||
Win32_DWORD64 p2Home;
|
||||
Win32_DWORD64 p3Home;
|
||||
Win32_DWORD64 p4Home;
|
||||
Win32_DWORD64 p5Home;
|
||||
Win32_DWORD64 p6Home;
|
||||
Win32_DWORD contextFlags;
|
||||
Win32_DWORD mxCsr;
|
||||
Win32_WORD segCs;
|
||||
Win32_WORD segDs;
|
||||
Win32_WORD segEs;
|
||||
Win32_WORD segFs;
|
||||
Win32_WORD segGs;
|
||||
Win32_WORD segSs;
|
||||
Win32_DWORD eFlags;
|
||||
Win32_DWORD64 dr0;
|
||||
Win32_DWORD64 dr1;
|
||||
Win32_DWORD64 dr2;
|
||||
Win32_DWORD64 dr3;
|
||||
Win32_DWORD64 dr6;
|
||||
Win32_DWORD64 dr7;
|
||||
Win32_DWORD64 rax;
|
||||
Win32_DWORD64 rcx;
|
||||
Win32_DWORD64 rdx;
|
||||
Win32_DWORD64 rbx;
|
||||
Win32_DWORD64 rsp;
|
||||
Win32_DWORD64 rbp;
|
||||
Win32_DWORD64 rsi;
|
||||
Win32_DWORD64 rdi;
|
||||
Win32_DWORD64 r8;
|
||||
Win32_DWORD64 r9;
|
||||
Win32_DWORD64 r10;
|
||||
Win32_DWORD64 r11;
|
||||
Win32_DWORD64 r12;
|
||||
Win32_DWORD64 r13;
|
||||
Win32_DWORD64 r14;
|
||||
Win32_DWORD64 r15;
|
||||
Win32_DWORD64 rip;
|
||||
union
|
||||
{
|
||||
Win32_XMM_SAVE_AREA32 fltSave;
|
||||
//Win32_NEON128[16] q;
|
||||
Win32_ULONGLONG[32] d;
|
||||
struct
|
||||
{
|
||||
Win32_M128A[2] header;
|
||||
Win32_M128A[8] legacy;
|
||||
Win32_M128A xmm0;
|
||||
Win32_M128A xmm1;
|
||||
Win32_M128A xmm2;
|
||||
Win32_M128A xmm3;
|
||||
Win32_M128A xmm4;
|
||||
Win32_M128A xmm5;
|
||||
Win32_M128A xmm6;
|
||||
Win32_M128A xmm7;
|
||||
Win32_M128A xmm8;
|
||||
Win32_M128A xmm9;
|
||||
Win32_M128A xmm10;
|
||||
Win32_M128A xmm11;
|
||||
Win32_M128A xmm12;
|
||||
Win32_M128A xmm13;
|
||||
Win32_M128A xmm14;
|
||||
Win32_M128A xmm15;
|
||||
}
|
||||
Win32_DWORD[32] s;
|
||||
}
|
||||
Win32_M128A[26] vectorRegister;
|
||||
Win32_DWORD64 vectorControl;
|
||||
Win32_DWORD64 debugControl;
|
||||
Win32_DWORD64 lastBranchToRip;
|
||||
Win32_DWORD64 lastBranchFromRip;
|
||||
Win32_DWORD64 lastExceptionToRip;
|
||||
Win32_DWORD64 lastExceptionFromRip;
|
||||
}
|
||||
|
||||
const CONTEXT_AMD64 = 0x00100000;
|
||||
const CONTEXT_AMD64_CONTROL = CONTEXT_AMD64 | 0x0001;
|
||||
const CONTEXT_AMD64_INTEGER = CONTEXT_AMD64 | 0x0002;
|
||||
const CONTEXT_AMD64_SEGMENTS = CONTEXT_AMD64 | 0x0004;
|
||||
const CONTEXT_AMD64_FLOATING_POINT = CONTEXT_AMD64 | 0x0008;
|
||||
const CONTEXT_AMD64_DEBUG_REGISTERS = CONTEXT_AMD64 | 0x0010;
|
||||
const CONTEXT_AMD64_FULL = CONTEXT_AMD64_CONTROL | CONTEXT_AMD64_INTEGER | CONTEXT_AMD64_FLOATING_POINT;
|
||||
const CONTEXT_AMD64_ALL = CONTEXT_AMD64_CONTROL | CONTEXT_AMD64_INTEGER | CONTEXT_AMD64_SEGMENTS | CONTEXT_AMD64_FLOATING_POINT | CONTEXT_AMD64_DEBUG_REGISTERS;
|
||||
|
||||
def CONTEXT_CONTROL = CONTEXT_AMD64_CONTROL;
|
||||
def CONTEXT_FULL = CONTEXT_AMD64_FULL;
|
||||
def CONTEXT_ALL = CONTEXT_AMD64_ALL;
|
||||
|
||||
def Win32_CONTEXT = Win32_AMD64_CONTEXT;
|
||||
def Win32_PCONTEXT = Win32_CONTEXT*;
|
||||
|
||||
struct Win32_M128A @align(16)
|
||||
{
|
||||
Win32_ULONGLONG low;
|
||||
Win32_LONGLONG high;
|
||||
}
|
||||
|
||||
struct Win32_IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
Win32_ULONG virtualAddress;
|
||||
Win32_ULONG size;
|
||||
}
|
||||
|
||||
struct Win32_IMAGE_OPTIONAL_HEADER64
|
||||
{
|
||||
Win32_WORD magic;
|
||||
Win32_BYTE majorLinkerVersion;
|
||||
Win32_BYTE minorLinkerVersion;
|
||||
Win32_DWORD sizeOfCode;
|
||||
Win32_DWORD sizeOfInitializedData;
|
||||
Win32_DWORD sizeOfUninitializedData;
|
||||
Win32_DWORD addressOfEntryPoint;
|
||||
Win32_DWORD baseOfCode;
|
||||
Win32_ULONGLONG imageBase;
|
||||
Win32_DWORD sectionAlignment;
|
||||
Win32_DWORD fileAlignment;
|
||||
Win32_WORD majorOperatingSystemVersion;
|
||||
Win32_WORD minorOperatingSystemVersion;
|
||||
Win32_WORD majorImageVersion;
|
||||
Win32_WORD minorImageVersion;
|
||||
Win32_WORD majorSubsystemVersion;
|
||||
Win32_WORD minorSubsystemVersion;
|
||||
Win32_DWORD win32VersionValue;
|
||||
Win32_DWORD sizeOfImage;
|
||||
Win32_DWORD sizeOfHeaders;
|
||||
Win32_DWORD checkSum;
|
||||
Win32_WORD subsystem;
|
||||
Win32_WORD dllCharacteristics;
|
||||
Win32_ULONGLONG sizeOfStackReserve;
|
||||
Win32_ULONGLONG sizeOfStackCommit;
|
||||
Win32_ULONGLONG sizeOfHeapReserve;
|
||||
Win32_ULONGLONG sizeOfHeapCommit;
|
||||
Win32_DWORD loaderFlags;
|
||||
Win32_DWORD numberOfRvaAndSizes;
|
||||
Win32_IMAGE_DATA_DIRECTORY[16] dataDirectory;
|
||||
}
|
||||
|
||||
def Win32_PIMAGE_OPTIONAL_HEADER64 = Win32_IMAGE_OPTIONAL_HEADER64*;
|
||||
struct Win32_IMAGE_FILE_HEADER
|
||||
{
|
||||
Win32_WORD machine;
|
||||
Win32_WORD numberOfSections;
|
||||
Win32_DWORD timeDateStamp;
|
||||
Win32_DWORD pointerToSymbolTable;
|
||||
Win32_DWORD numberOfSymbols;
|
||||
Win32_WORD sizeOfOptionalHeader;
|
||||
Win32_WORD characteristics;
|
||||
}
|
||||
|
||||
def Win32_PIMAGE_FILE_HEADER = Win32_IMAGE_FILE_HEADER*;
|
||||
|
||||
struct Win32_IMAGE_NT_HEADERS
|
||||
{
|
||||
Win32_DWORD signature;
|
||||
Win32_IMAGE_FILE_HEADER fileHeader;
|
||||
Win32_IMAGE_OPTIONAL_HEADER64 optionalHeader;
|
||||
}
|
||||
|
||||
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[1] name;
|
||||
}
|
||||
|
||||
def Win32_PSYMBOL_INFO = Win32_SYMBOL_INFO*;
|
||||
|
||||
struct Win32_MODLOAD_DATA
|
||||
{
|
||||
Win32_DWORD ssize;
|
||||
Win32_DWORD ssig;
|
||||
Win32_PVOID data;
|
||||
Win32_DWORD size;
|
||||
Win32_DWORD flags;
|
||||
}
|
||||
|
||||
enum Win32_ADDRESS_MODE
|
||||
{
|
||||
ADDR_MODE_1616,
|
||||
ADDR_MODE_1632,
|
||||
ADDR_MODE_REAL,
|
||||
ADDR_MODE_FLAT,
|
||||
}
|
||||
|
||||
struct Win32_ADDRESS64
|
||||
{
|
||||
Win32_DWORD64 offset;
|
||||
Win32_WORD segment;
|
||||
Win32_ADDRESS_MODE mode;
|
||||
}
|
||||
|
||||
struct Win32_KDHELP64
|
||||
{
|
||||
Win32_DWORD64 thread;
|
||||
Win32_DWORD thCallbackStack;
|
||||
Win32_DWORD thCallbackBStore;
|
||||
Win32_DWORD nextCallback;
|
||||
Win32_DWORD framePointer;
|
||||
Win32_DWORD64 kiCallUserMode;
|
||||
Win32_DWORD64 keUserCallbackDispatcher;
|
||||
Win32_DWORD64 systemRangeStart;
|
||||
Win32_DWORD64 kiUserExceptionDispatcher;
|
||||
Win32_DWORD64 stackBase;
|
||||
Win32_DWORD64 stackLimit;
|
||||
Win32_DWORD buildVersion;
|
||||
Win32_DWORD retpolineStubFunctionTableSize;
|
||||
Win32_DWORD64 retpolineStubFunctionTable;
|
||||
Win32_DWORD retpolineStubOffset;
|
||||
Win32_DWORD retpolineStubSize;
|
||||
Win32_DWORD64[2] reserved0;
|
||||
}
|
||||
|
||||
struct Win32_STACKFRAME64
|
||||
{
|
||||
Win32_ADDRESS64 addrPC;
|
||||
Win32_ADDRESS64 addrReturn;
|
||||
Win32_ADDRESS64 addrFrame;
|
||||
Win32_ADDRESS64 addrStack;
|
||||
Win32_ADDRESS64 addrBStore;
|
||||
Win32_PVOID funcTableEntry;
|
||||
Win32_DWORD64[4] params;
|
||||
Win32_BOOL far;
|
||||
Win32_BOOL virtual;
|
||||
Win32_DWORD64[3] reserved;
|
||||
Win32_KDHELP64 kdHelp;
|
||||
}
|
||||
|
||||
def Win32_PREAD_PROCESS_MEMORY_ROUTINE64 = fn Win32_BOOL(Win32_HANDLE hProcess, Win32_DWORD64 qwBaseAddress, Win32_PVOID lpBuffer, Win32_DWORD nSize, Win32_LPDWORD lpNumberOfBytesRead);
|
||||
def Win32_PFUNCTION_TABLE_ACCESS_ROUTINE64 = fn Win32_PVOID(Win32_HANDLE ahProcess, Win32_DWORD64 addrBase);
|
||||
def Win32_PGET_MODULE_BASE_ROUTINE64 = fn Win32_DWORD64(Win32_HANDLE hProcess, Win32_DWORD64 address);
|
||||
def Win32_PTRANSLATE_ADDRESS_ROUTINE64 = fn Win32_DWORD64(Win32_HANDLE hProcess, Win32_HANDLE hThread, Win32_LPADDRESS64 lpaddr);
|
||||
def Win32_PKDHELP64 = Win32_KDHELP64*;
|
||||
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_LPMODULEINFO = Win32_MODULEINFO*;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
- New generic syntax.
|
||||
- Slice initialization.
|
||||
- `$feature` for feature flags.
|
||||
- Improved stack trace.
|
||||
- Native stacktrace for Linux, MacOS and Windows.
|
||||
- Macro ref parameters are now of pointer type and ref parameters are not assignable.
|
||||
- Added `nextcase default`.
|
||||
- Added `$embed` to embed binary data.
|
||||
|
||||
@@ -5,11 +5,7 @@ import std::os;
|
||||
|
||||
fn void! test2()
|
||||
{
|
||||
BacktraceList list = linux::backtrace_load(mem::heap())!;
|
||||
foreach (Backtrace trace : list)
|
||||
{
|
||||
io::printfn("%s", trace);
|
||||
}
|
||||
builtin::print_backtrace("hello", 1);
|
||||
}
|
||||
|
||||
fn void test1()
|
||||
|
||||
18
resources/msvc_stack.c3
Normal file
18
resources/msvc_stack.c3
Normal file
@@ -0,0 +1,18 @@
|
||||
module test;
|
||||
import std::io;
|
||||
import std::collections::map;
|
||||
import std::os;
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
builtin::print_backtrace("hello", 1);
|
||||
|
||||
|
||||
int x = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
test1();
|
||||
}
|
||||
@@ -78,6 +78,7 @@ static const char *string_esc(const char *str)
|
||||
static void linker_setup_windows(const char ***args_ref, LinkerType linker_type, const char ***additional_linked_ref)
|
||||
{
|
||||
add_arg(active_target.win.use_win_subsystem ? "/SUBSYSTEM:WINDOWS" : "/SUBSYSTEM:CONSOLE");
|
||||
vec_add(*additional_linked_ref, "dbghelp");
|
||||
if (linker_type == LINKER_CC) return;
|
||||
//add_arg("/MACHINE:X64");
|
||||
bool is_debug = false;
|
||||
@@ -382,8 +383,9 @@ static const char *find_linux_crt_begin(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
static void linker_setup_linux(const char ***args_ref, LinkerType linker_type, const char ***additional_linked_ref)
|
||||
{
|
||||
vec_add(*additional_linked_ref, "dl");
|
||||
if (linker_type == LINKER_CC)
|
||||
{
|
||||
if (!link_libc())
|
||||
@@ -391,7 +393,6 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg("-nostdlib");
|
||||
return;
|
||||
}
|
||||
vec_add(active_target.linker_libs, "dl");
|
||||
if (active_target.debug_info == DEBUG_INFO_FULL)
|
||||
{
|
||||
add_arg("-rdynamic");
|
||||
@@ -438,7 +439,6 @@ static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg2("-L", crt_dir);
|
||||
add_arg("-L");
|
||||
add_arg("/usr/lib/x86_64-linux-gnu/libdl.so");
|
||||
add_arg("-ldl");
|
||||
add_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2");
|
||||
add_arg("-lm");
|
||||
add_arg("-lpthread");
|
||||
@@ -583,7 +583,7 @@ static bool linker_setup(const char ***args_ref, const char **files_to_link, uns
|
||||
linker_setup_freebsd(args_ref, linker_type);
|
||||
break;
|
||||
case OS_TYPE_LINUX:
|
||||
linker_setup_linux(args_ref, linker_type);
|
||||
linker_setup_linux(args_ref, linker_type, &additional_linked);
|
||||
break;
|
||||
case OS_TYPE_UNKNOWN:
|
||||
if (link_libc())
|
||||
|
||||
@@ -34,7 +34,7 @@ int target_alloca_addr_space()
|
||||
|
||||
bool os_supports_stacktrace(OsType os_type)
|
||||
{
|
||||
return os_type == OS_TYPE_LINUX || os_is_apple(os_type);
|
||||
return os_type == OS_TYPE_LINUX || os_is_apple(os_type) || os_type == OS_TYPE_WIN32;
|
||||
}
|
||||
bool os_is_apple(OsType os_type)
|
||||
{
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.703"
|
||||
#define COMPILER_VERSION "0.4.704"
|
||||
|
||||
Reference in New Issue
Block a user