aboutsummaryrefslogtreecommitdiff
path: root/lib/std/debug.zig
AgeCommit message (Collapse)Author
2025-10-10Coff: implement threadlocal variablesJacob Young
2025-10-10std.debug: greatly expand target support for segfault handling/unwindingAlex Rønne Petersen
I made a couple of decisions for this based on the fact that we don't expose the signal_ucontext_t type outside of the file: * Adding all the floating point and vector state to every ucontext_t and mcontext_t variant was way, way too much work, especially when we don't even use the stuff. So I deleted all that and kept only the bare minimum needed to reach into general-purpose registers. * There is no particularly compelling reason to stick to the naming and struct nesting used in the system headers. So we can actually unify the access patterns for almost all of these variants by taking some liberties here; as a result, fromPosixSignalContext() is now much nicer to read and extend.
2025-10-09std.debug: fix FP unwinding for LoongArchAlex Rønne Petersen
2025-10-09std.debug: fix SelfInfo default for freestanding ELF targetsAlex Rønne Petersen
2025-10-09std.debug: fix incorrect FP unwinding on RISC-V and SPARCmlugg
I broke this when porting this logic for the `std.debug` rework in https://github.com/ziglang/zig/pull/25227. The offset that I copied was actually being treated as relative to the address of the *saved* base pointer. I think it makes more sense to do what I did and just treat all offsets as relative to this frame's base.
2025-10-07std.debug: add noinline to functions that capture the current stack traceAlex Rønne Petersen
Fixes stack traces missing a frame depending on inlining decisions. ref https://github.com/ziglang/zig/issues/25418
2025-10-07std.debug: prefer FP unwinding on targets where it is idealAlex Rønne Petersen
If the ABI requires a backchain pointer, FP unwinding is always possible, safe, and fast, so there's really no reason not to use it.
2025-10-05std.debug: completely disable FP-based unwinding on mipsAlex Rønne Petersen
2025-10-04Merge pull request #25457 from linusg/more-serenityAlex Rønne Petersen
std.debug: Add unwind support for serenity
2025-10-04std.debug: consider FP-based unwinding on hexagon and powerpc safeAlex Rønne Petersen
The ABIs make this safe and reliable due to their backchain requirements.
2025-10-04std.debug: fix FP-based unwinding on powerpc64Alex Rønne Petersen
This just needs to do the same thing as powerpc64le. Note that the saved LR is at the same position in both ELF v1 and v2.
2025-10-03std.debug: Add unwind support for serenityLinus Groh
2025-10-03std.debug: use correct return address offset for s390xAlex Rønne Petersen
Makes FP-based unwinding work.
2025-10-01std.debug.SelfInfo: rename Darwin to MachOAlex Rønne Petersen
2025-10-01std.debug: don't use SelfInfo.Windows for UEFIAlex Rønne Petersen
It is, in fact, Windows-only.
2025-10-01std.debug: select SelfInfo using ObjectFormat.default()Alex Rønne Petersen
2025-09-30std.debug.SelfInfo: remove shared logicmlugg
There were only a few dozen lines of common logic, and they frankly introduced more complexity than they eliminated. Instead, let's accept that the implementations of `SelfInfo` are all pretty different and want to track different state. This probably fixes some synchronization and memory bugs by simplifying a bunch of stuff. It also improves the DWARF unwind cache, making it around twice as fast in a debug build with the self-hosted x86_64 backend, because we no longer have to redundantly go through the hashmap lookup logic to find the module. Unwinding on Windows will also see a slight performance boost from this change, because `RtlVirtualUnwind` does not need to know the module whatsoever, so the old `SelfInfo` implementation was doing redundant work. Lastly, this makes it even easier to implement `SelfInfo` on freestanding targets; there is no longer a need to emulate a real module system, since the user controls the whole implementation! There are various other small refactors here in the `SelfInfo` implementations as well as in the DWARF unwinding logic. This change turned out to make a lot of stuff simpler!
2025-09-30std.debug: significantly speed up capturing stack tracesmlugg
By my estimation, these changes speed up DWARF unwinding when using the self-hosted x86_64 backend by around 7x. There are two very significant enhancements: we no longer iterate frames which don't fit in the stack trace buffer, and we cache register rules (in a fixed buffer) to avoid re-parsing and evaluating CFI instructions in most cases. Alongside this are a bunch of smaller enhancements, such as pre-caching the result of evaluating the CIE's initial instructions, avoiding re-parsing of CIEs, and big simplifications to the `Dwarf.Unwind.VirtualMachine` logic.
2025-09-30std.debug: cap total stack trace framesmlugg
...just in case there is broken debug info and/or bad values on the stack, either of which could cause stack unwinding to potentially loop forever.
2025-09-30std.debug.SelfInfo: thread safetymlugg
This has been a TODO for ages, but in the past it didn't really matter because stack traces are typically printed to stderr for which a mutex is held so in practice there was a mutex guarding usage of `SelfInfo`. However, now that `SelfInfo` is also used for simply capturing traces, thread safety is needed. Instead of just a single mutex, though, there are a couple of different mutexes involved; this helps make critical sections smaller, particularly when unwinding the stack as `unwindFrame` doesn't typically need to hold any lock at all.
2025-09-30std: don't get CPU context when using CBE targeting MSVCmlugg
Calling `current` here causes compilation failures as the C backend currently does not emit valid MSVC inline assembly. This change means that when building for MSVC with the self-hosted C backend, only FP unwinding can be used.
2025-09-30std.debug: go back to storing return addresses instead of call addressesmlugg
...and just deal with signal handlers by adding 1 to create a fake "return address". The system I tried out where the addresses returned by `StackIterator` were pre-subtracted didn't play nicely with error traces, which in hindsight, makes perfect sense. This definition also removes some ugly off-by-one issues in matching `first_address`, so I do think this is a better approach.
2025-09-30std: allow disabling stack tracingmlugg
This option disables both capturing and printing stack traces. The default is to disable if debug info is stripped.
2025-09-30std.debug: update support checksmlugg
2025-09-30std.debug: miscellaneous fixesmlugg
Mostly on macOS, since Loris showed me a not-great stack trace, and I spent 8 hours trying to make it better. The dyld shared cache is designed in a way which makes this really hard to do right, and documentation is non-existent, but this *seems* to work pretty well. I'll leave the ruling on whether I did a good job to CI and our users.
2025-09-30std: rework/remove ucontext_tmlugg
Our usage of `ucontext_t` in the standard library was kind of problematic. We unnecessarily mimiced libc-specific structures, and our `getcontext` implementation was overkill for our use case of stack tracing. This commit introduces a new namespace, `std.debug.cpu_context`, which contains "context" types for various architectures (currently x86, x86_64, ARM, and AARCH64) containing the general-purpose CPU registers; the ones needed in practice for stack unwinding. Each implementation has a function `current` which populates the structure using inline assembly. The structure is user-overrideable, though that should only be necessary if the standard library does not have an implementation for the *architecture*: that is to say, none of this is OS-dependent. Of course, in POSIX signal handlers, we get a `ucontext_t` from the kernel. The function `std.debug.cpu_context.fromPosixSignalContext` converts this to a `std.debug.cpu_context.Native` with a big ol' target switch. This functionality is not exposed from `std.c` or `std.posix`, and neither are `ucontext_t`, `mcontext_t`, or `getcontext`. The rationale is that these types and functions do not conform to a specific ABI, and in fact tend to get updated over time based on CPU features and extensions; in addition, different libcs use different structures which are "partially compatible" with the kernel structure. Overall, it's a mess, but all we need is the kernel context, so we can just define a kernel-compatible structure as long as we don't claim C compatibility by putting it in `std.c` or `std.posix`. This change resulted in a few nice `std.debug` simplifications, but nothing too noteworthy. However, the main benefit of this change is that DWARF unwinding---sometimes necessary for collecting stack traces reliably---now requires far less target-specific integration. Also fix a bug I noticed in `PageAllocator` (I found this due to a bug in my distro's QEMU distribution; thanks, broken QEMU patch!) and I think a couple of minor bugs in `std.debug`. Resolves: #23801 Resolves: #23802
2025-09-30fix compile errors and minor bugsmlugg
2025-09-30std.debug: don't attempt SelfInfo unwinding when unsupportedmlugg
2025-09-30std.debug: never attempt FP unwind under fomit-frame-pointermlugg
2025-09-30compiler: fix new panic handler in release buildsmlugg
2025-09-30std: replace debug.Dwarf.ElfModule with debug.ElfFilemlugg
This abstraction isn't really tied to DWARF at all! Really, we're just loading some information from an ELF file which is useful for debugging. That *includes* DWARF, but it also includes other information. For instance, the other change here: Now, if DWARF information is missing, `debug.SelfInfo.ElfModule` will name symbols by finding a matching symtab entry. We actually already do this on Mach-O, so it makes obvious sense to do the same on ELF! This change is what motivated the restructuring to begin with. The symtab work is derived from #22077. Co-authored-by: geemili <opensource@geemili.xyz>
2025-09-30std.debug: don't include dumpCurrentStackTrace framemlugg
If it's not given, we should set `first_address` to the return address of `dumpCurrentStackTrace` to avoid the call to `writeCurrentStackTrace` appearing in the trace. However, we must only do that if no `context` is given; if there's a context then we're starting the stack unwind elsewhere.
2025-09-30std.debug: try removing a probably-redundant conditionmlugg
2025-09-30std.debug: handle ThreadContext slightly bettermlugg
It's now user-overrideable, and uses `noreturn` types to neatly stop analysis.
2025-09-30std.debug: unwinding on Windowsmlugg
...using `RtlVirtualUnwind` on x86_64 and aarch64, and `RtaCaptureStackBackTrace` on x86.
2025-09-30std: doc comments and tweaksmlugg
2025-09-30std: fixesmlugg
2025-09-30SelfInfo: be honest about how general unwinding ismlugg
...in that it isn't: it's currently very specialized to DWARF unwinding. Also, make a type unmanaged.
2025-09-30add freestanding support IN THEORYmlugg
untested because this branch has errors rn
2025-09-30std.debug: improve the APIs and stuffmlugg
2025-09-30std.debug.SelfInfo: concrete error setsmlugg
The downside of this commit is that more precise errors are no longer propagated up. However, these errors were pretty useless in isolation due to them having no context; and regardless, we intentionally swallow most of them in `std.debug` anyway. Therefore, this is better in practice, because it allows `std.debug` to give slightly more useful warnings when handling errors. This commit does that for unwind errors, for instance, which differentiate between the unwind info being corrupt vs missing vs inaccessible vs unsupported. A better solution would be to also include more detailed information via the diagnostics pattern, but this commit is an incremental improvement.
2025-09-30the world if ElfModule didn't suck:mlugg
2025-09-30change one million thingsmlugg
2025-09-30debug: refactor stack frame capturingJacob Young
2025-09-07std.debug.assertAligned: support const pointersAndrew Kelley
2025-09-03std.debug: disable stack traces on loongarchAlex Rønne Petersen
Observed to ~randomly crash during FP-based unwinding. The path forward here will be DWARF-based unwinding.
2025-08-31delete behavior test that depends on std.fmtAndrew Kelley
behavior tests should have minimal dependency on std
2025-08-29std.Io: delete GenericReaderAndrew Kelley
and delete deprecated alias std.io
2025-08-28std.debug: remove `@frameAddress()` "UAF"mlugg
We can't call `@frameAddress()` and then immediately `return`! That invalidates the frame. This *usually* isn't a problem, because the stack walk `next` call will *probably* have a stack frame and it will *probably* be at the exact same address, but neither of those is a guarantee. On powerpc, presumably some unfortunate inlining was going on, so this frame was indeed invalidated when we started walking frames. We need to explicitly pass `@frameAddress` into any function which will return before we actually walk the stack. Pretty simple patch. Resolves: #24970
2025-08-25delete std.debug.FixedBufferReaderAndrew Kelley
now that std.Io.Reader has sufficient debug performance