walkStackWindows
Function parameters
Parameters
- addresses:[]usize
- existing_context:?*const windows.CONTEXT
Type definitions in this namespace
Types
- SourceLocation
- Unresolved source locations can be represented with a single `usize` that
A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`.
Functions
- FullPanic
- A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`.
- lockStdErr
- Allows the caller to freely write to stderr until `unlockStdErr` is called.
- lockStderrWriter
- Allows the caller to freely write to stderr until `unlockStdErr` is called.
- Print to stderr, silently returning on failure.
- dumpHex
- Tries to print a hexadecimal view of the bytes, unbuffered, and ignores any error returned.
- dumpHexFallible
- Prints a hexadecimal view of the bytes, returning any error that occurs.
- dumpCurrentStackTrace
- Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
- dumpCurrentStackTraceToWriter
- Prints the current stack trace to the provided writer.
- copyContext
- Copies one context to another, updating any internal pointers
- relocateContext
- Updates any internal pointers in the context to reflect its current location
- getContext
- Capture the current context.
- dumpStackTraceFromBase
- Tries to print the stack trace starting from the supplied base pointer to stderr,
- captureStackTrace
- Returns a slice with the same pointer as addresses, with a potentially smaller len.
- dumpStackTrace
- Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
- assert
- Invokes detectable illegal behavior when `ok` is `false`.
- assertReadable
- Invokes detectable illegal behavior when the provided slice is not mapped
- assertAligned
- Invokes detectable illegal behavior when the provided array is not aligned
- panic
- Equivalent to `@panic` but with a formatted message.
- panicExtra
- Equivalent to `@panic` but with a formatted message, and with an explicitly
- defaultPanic
- Dumps a stack trace to standard error, then aborts.
- attachSegfaultHandler
- Attaches a global SIGSEGV handler which calls `@panic("segmentation fault");`
- inValgrind
- Detect whether the program is being executed in the Valgrind virtual machine.
Deprecated because it returns the optimization mode of the standard
Values
- runtime_safety
- Deprecated because it returns the optimization mode of the standard
- sys_can_stack_trace
- = switch (builtin.cpu.arch) { // Observed to go into an infinite loop. // TODO: Make this work. .mips, .mipsel, .mips64, .mips64el, .s390x, => false, // `@returnAddress()` in LLVM 10 gives // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address". // On Emscripten, Zig only supports `@returnAddress()` in debug builds // because Emscripten's implementation is very slow. .wasm32, .wasm64, => native_os == .emscripten and builtin.mode == .Debug, // `@returnAddress()` is unsupported in LLVM 13. .bpfel, .bpfeb, => false, else => true, }
- have_ucontext
- = posix.ucontext_t != void
- ThreadContext
- Platform-specific thread state.
- have_getcontext
- = @TypeOf(posix.system.getcontext) != void
- have_segfault_handling_support
- Whether or not the current target can print useful debug information when a segfault occurs.
- default_enable_segfault_handler
- = runtime_safety and have_segfault_handling_support
Source
Implementation
pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const windows.CONTEXT) usize {
if (builtin.cpu.arch == .x86) {
// RtlVirtualUnwind doesn't exist on x86
return windows.ntdll.RtlCaptureStackBackTrace(0, addresses.len, @as(**anyopaque, @ptrCast(addresses.ptr)), null);
}
const tib = &windows.teb().NtTib;
var context: windows.CONTEXT = undefined;
if (existing_context) |context_ptr| {
context = context_ptr.*;
} else {
context = std.mem.zeroes(windows.CONTEXT);
windows.ntdll.RtlCaptureContext(&context);
}
var i: usize = 0;
var image_base: windows.DWORD64 = undefined;
var history_table: windows.UNWIND_HISTORY_TABLE = std.mem.zeroes(windows.UNWIND_HISTORY_TABLE);
while (i < addresses.len) : (i += 1) {
const current_regs = context.getRegs();
if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &history_table)) |runtime_function| {
var handler_data: ?*anyopaque = null;
var establisher_frame: u64 = undefined;
_ = windows.ntdll.RtlVirtualUnwind(
windows.UNW_FLAG_NHANDLER,
image_base,
current_regs.ip,
runtime_function,
&context,
&handler_data,
&establisher_frame,
null,
);
} else {
// leaf function
context.setIp(@as(*usize, @ptrFromInt(current_regs.sp)).*);
context.setSp(current_regs.sp + @sizeOf(usize));
}
const next_regs = context.getRegs();
if (next_regs.sp < @intFromPtr(tib.StackLimit) or next_regs.sp > @intFromPtr(tib.StackBase)) {
break;
}
if (next_regs.ip == 0) {
break;
}
addresses[i] = next_regs.ip;
}
return i;
}