dumpStackTraceFromBase
Tries to print the stack trace starting from the supplied base pointer to stderr, unbuffered, and ignores any error returned. TODO multithreaded awareness
Function parameters
Parameters
- context:*ThreadContext
- stderr:*Writer
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 fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
nosuspend {
if (builtin.target.cpu.arch.isWasm()) {
if (native_os == .wasi) {
stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
}
return;
}
if (builtin.strip_debug_info) {
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
return;
}
const debug_info = getSelfDebugInfo() catch |err| {
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
return;
};
const tty_config = io.tty.detectConfig(.stderr());
if (native_os == .windows) {
// On x86_64 and aarch64, the stack will be unwound using RtlVirtualUnwind using the context
// provided by the exception handler. On x86, RtlVirtualUnwind doesn't exist. Instead, a new backtrace
// will be captured and frames prior to the exception will be filtered.
// The caveat is that RtlCaptureStackBackTrace does not include the KiUserExceptionDispatcher frame,
// which is where the IP in `context` points to, so it can't be used as start_addr.
// Instead, start_addr is recovered from the stack.
const start_addr = if (builtin.cpu.arch == .x86) @as(*const usize, @ptrFromInt(context.getRegs().bp + 4)).* else null;
writeStackTraceWindows(stderr, debug_info, tty_config, context, start_addr) catch return;
return;
}
var it = StackIterator.initWithContext(null, debug_info, context) catch return;
defer it.deinit();
// DWARF unwinding on aarch64-macos is not complete so we need to get pc address from mcontext
const pc_addr = if (builtin.target.os.tag.isDarwin() and native_arch == .aarch64)
context.mcontext.ss.pc
else
it.unwind_state.?.dwarf_context.pc;
printSourceAtAddress(debug_info, stderr, pc_addr, tty_config) catch return;
while (it.next()) |return_address| {
printLastUnwindError(&it, debug_info, stderr, tty_config);
// On arm64 macOS, the address of the last frame is 0x0 rather than 0x1 as on x86_64 macOS,
// therefore, we do a check for `return_address == 0` before subtracting 1 from it to avoid
// an overflow. We do not need to signal `StackIterator` as it will correctly detect this
// condition on the subsequent iteration and return `null` thus terminating the loop.
// same behaviour for x86-windows-msvc
const address = if (return_address == 0) return_address else return_address - 1;
printSourceAtAddress(debug_info, stderr, address, tty_config) catch return;
} else printLastUnwindError(&it, debug_info, stderr, tty_config);
}
}