DoxigAlpha

dumpSegfaultInfoPosix

Function parameters

Parameters

#
sig:i32
code:i32
addr:usize
ctx_ptr:?*anyopaque

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
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

#
fn dumpSegfaultInfoPosix(sig: i32, code: i32, addr: usize, ctx_ptr: ?*anyopaque) void {
    const stderr = lockStderrWriter(&.{});
    defer unlockStderrWriter();
    _ = switch (sig) {
        posix.SIG.SEGV => if (native_arch == .x86_64 and native_os == .linux and code == 128) // SI_KERNEL
            // x86_64 doesn't have a full 64-bit virtual address space.
            // Addresses outside of that address space are non-canonical
            // and the CPU won't provide the faulting address to us.
            // This happens when accessing memory addresses such as 0xaaaaaaaaaaaaaaaa
            // but can also happen when no addressable memory is involved;
            // for example when reading/writing model-specific registers
            // by executing `rdmsr` or `wrmsr` in user-space (unprivileged mode).
            stderr.writeAll("General protection exception (no address available)\n")
        else
            stderr.print("Segmentation fault at address 0x{x}\n", .{addr}),
        posix.SIG.ILL => stderr.print("Illegal instruction at address 0x{x}\n", .{addr}),
        posix.SIG.BUS => stderr.print("Bus error at address 0x{x}\n", .{addr}),
        posix.SIG.FPE => stderr.print("Arithmetic exception at address 0x{x}\n", .{addr}),
        else => unreachable,
    } catch posix.abort();

    switch (native_arch) {
        .x86,
        .x86_64,
        .arm,
        .armeb,
        .thumb,
        .thumbeb,
        .aarch64,
        .aarch64_be,
        => {
            // Some kernels don't align `ctx_ptr` properly. Handle this defensively.
            const ctx: *align(1) posix.ucontext_t = @ptrCast(ctx_ptr);
            var new_ctx: posix.ucontext_t = ctx.*;
            if (builtin.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) {
                // The kernel incorrectly writes the contents of `__mcontext_data` right after `mcontext`,
                // rather than after the 8 bytes of padding that are supposed to sit between the two. Copy the
                // contents to the right place so that the `mcontext` pointer will be correct after the
                // `relocateContext` call below.
                new_ctx.__mcontext_data = @as(*align(1) extern struct {
                    onstack: c_int,
                    sigmask: std.c.sigset_t,
                    stack: std.c.stack_t,
                    link: ?*std.c.ucontext_t,
                    mcsize: u64,
                    mcontext: *std.c.mcontext_t,
                    __mcontext_data: std.c.mcontext_t align(@sizeOf(usize)), // Disable padding after `mcontext`.
                }, @ptrCast(ctx)).__mcontext_data;
            }
            relocateContext(&new_ctx);
            dumpStackTraceFromBase(&new_ctx, stderr);
        },
        else => {},
    }
}