521 Commits

Author SHA1 Message Date
Jacob Young
2e31077fe0 Coff: implement threadlocal variables 2025-10-10 22:47:47 -07:00
Alex Rønne Petersen
f33d3a5166
std.debug: greatly expand target support for segfault handling/unwinding
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-10 04:43:15 +02:00
Alex Rønne Petersen
3f5e782357
std.debug: fix FP unwinding for LoongArch 2025-10-09 20:43:32 +02:00
Alex Rønne Petersen
98f0bf9b67
std.debug: fix SelfInfo default for freestanding ELF targets 2025-10-09 20:43:32 +02:00
mlugg
80f6b8c4b3 std.debug: fix incorrect FP unwinding on RISC-V and SPARC
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-09 19:31:44 +01:00
Alex Rønne Petersen
fdd109420d
std.debug: add noinline to functions that capture the current stack trace
Fixes stack traces missing a frame depending on inlining decisions.

ref https://github.com/ziglang/zig/issues/25418
2025-10-07 16:47:57 +02:00
Alex Rønne Petersen
9760068826 std.debug: prefer FP unwinding on targets where it is ideal
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-07 16:44:25 +02:00
Alex Rønne Petersen
e6e4792a58 std.debug: completely disable FP-based unwinding on mips 2025-10-05 07:18:50 +02:00
Alex Rønne Petersen
b54bdace75
Merge pull request #25457 from linusg/more-serenity
std.debug: Add unwind support for serenity
2025-10-04 07:09:59 +02:00
Alex Rønne Petersen
9dbfa5b294 std.debug: consider FP-based unwinding on hexagon and powerpc safe
The ABIs make this safe and reliable due to their backchain requirements.
2025-10-04 03:22:40 +02:00
Alex Rønne Petersen
d8268fac98 std.debug: fix FP-based unwinding on powerpc64
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-04 03:03:54 +02:00
Linus Groh
b0f280f4a4 std.debug: Add unwind support for serenity 2025-10-03 22:59:40 +01:00
Alex Rønne Petersen
0f56d7afe2
std.debug: use correct return address offset for s390x
Makes FP-based unwinding work.
2025-10-03 03:29:20 +02:00
Alex Rønne Petersen
771410cbf2
std.debug.SelfInfo: rename Darwin to MachO 2025-10-01 23:47:47 +02:00
Alex Rønne Petersen
e1fb662f60
std.debug: don't use SelfInfo.Windows for UEFI
It is, in fact, Windows-only.
2025-10-01 23:47:47 +02:00
Alex Rønne Petersen
59633e54a2
std.debug: select SelfInfo using ObjectFormat.default() 2025-10-01 23:47:47 +02:00
mlugg
1120546f72
std.debug.SelfInfo: remove shared logic
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-30 14:18:26 +01:00
mlugg
156cd8f678
std.debug: significantly speed up capturing stack traces
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-30 13:44:56 +01:00
mlugg
b0f222777c
std.debug: cap total stack trace frames
...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-30 13:44:56 +01:00
mlugg
099a950410
std.debug.SelfInfo: thread safety
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-30 13:44:55 +01:00
mlugg
084e92879a
std: don't get CPU context when using CBE targeting MSVC
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-30 13:44:55 +01:00
mlugg
2ab650b481
std.debug: go back to storing return addresses instead of call addresses
...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-30 13:44:55 +01:00
mlugg
3a9c680ad7
std: allow disabling stack tracing
This option disables both capturing and printing stack traces. The
default is to disable if debug info is stripped.
2025-09-30 13:44:55 +01:00
mlugg
abb2b1e2da
std.debug: update support checks 2025-09-30 13:44:55 +01:00
mlugg
dd8d59686a
std.debug: miscellaneous fixes
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-30 13:44:54 +01:00
mlugg
a18fd41064
std: rework/remove ucontext_t
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-30 13:44:54 +01:00
mlugg
51d08f4b9b
fix compile errors and minor bugs 2025-09-30 13:44:54 +01:00
mlugg
344ab62b3f
std.debug: don't attempt SelfInfo unwinding when unsupported 2025-09-30 13:44:53 +01:00
mlugg
02a0ade138
std.debug: never attempt FP unwind under fomit-frame-pointer 2025-09-30 13:44:53 +01:00
mlugg
bfbbda7751
compiler: fix new panic handler in release builds 2025-09-30 13:44:52 +01:00
mlugg
c1a30bd0d8
std: replace debug.Dwarf.ElfModule with debug.ElfFile
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-30 13:44:52 +01:00
mlugg
f798048739
std.debug: don't include dumpCurrentStackTrace frame
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-30 13:44:52 +01:00
mlugg
2743fdb7ce
std.debug: try removing a probably-redundant condition 2025-09-30 13:44:52 +01:00
mlugg
229f0a01b8
std.debug: handle ThreadContext slightly better
It's now user-overrideable, and uses `noreturn` types to neatly stop
analysis.
2025-09-30 13:44:52 +01:00
mlugg
1392a7af17
std.debug: unwinding on Windows
...using `RtlVirtualUnwind` on x86_64 and aarch64, and
`RtaCaptureStackBackTrace` on x86.
2025-09-30 13:44:52 +01:00
mlugg
3a561da38d
std: doc comments and tweaks 2025-09-30 13:44:51 +01:00
mlugg
202aeacc05
std: fixes 2025-09-30 13:44:51 +01:00
mlugg
253fdfce70
SelfInfo: be honest about how general unwinding is
...in that it isn't: it's currently very specialized to DWARF unwinding.

Also, make a type unmanaged.
2025-09-30 13:44:51 +01:00
mlugg
9859440d83
add freestanding support IN THEORY
untested because this branch has errors rn
2025-09-30 13:44:51 +01:00
mlugg
5709369d05
std.debug: improve the APIs and stuff 2025-09-30 13:44:51 +01:00
mlugg
c895aa7a35
std.debug.SelfInfo: concrete error sets
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-30 13:44:50 +01:00
mlugg
84b65860cf
the world if ElfModule didn't suck: 2025-09-30 13:44:49 +01:00
mlugg
b750e7cf9e
change one million things 2025-09-30 13:44:49 +01:00
Jacob Young
b706949736
debug: refactor stack frame capturing 2025-09-30 13:44:48 +01:00
Andrew Kelley
04bd30f021 std.debug.assertAligned: support const pointers 2025-09-07 20:22:38 -07:00
Alex Rønne Petersen
d8d0a3e5c7
std.debug: disable stack traces on loongarch
Observed to ~randomly crash during FP-based unwinding.

The path forward here will be DWARF-based unwinding.
2025-09-03 11:27:42 +02:00
Andrew Kelley
ec36e0609f delete behavior test that depends on std.fmt
behavior tests should have minimal dependency on std
2025-08-31 12:49:18 -07:00
Andrew Kelley
79f267f6b9 std.Io: delete GenericReader
and delete deprecated alias std.io
2025-08-29 17:14:26 -07:00
mlugg
a31950aa57 std.debug: remove @frameAddress() "UAF"
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-28 10:56:11 +01:00
Andrew Kelley
12686d9b7d delete std.debug.FixedBufferReader
now that std.Io.Reader has sufficient debug performance
2025-08-25 04:05:37 -07:00