The old logic advanced in the wrong direction and also overwrote one register in
consecutive pairs. I'm not aware of any case where this matters in practice
since macOS mandates the use of an FP register on AArch64, but we should still
get it right.
SelfUnwinder already unconditionally strips pointer authentication codes, so for
the self-unwinding case, we just need to make sure that these opcodes don't
cause unwinding to fail due to error.UnimplementedUserOpcode.
This makes stack traces with `-fincremental`, um, sort of work:
```
thread 29999 panic: this is the RIGHT panic
/home/mlugg/panic.zig:15:25: 0x7a1907 in bar (panic.zig)
1, 2, 3, 123 => @panic("this is the RIGHT panic"),
^
/home/mlugg/panic.zig:7:12: 0x7a138c in foo (panic.zig)
bar(123);
^
/home/mlugg/panic.zig:2:8: 0x7a12fe in main (panic.zig)
foo(true);
^
/home/mlugg/zig/master/lib/std/start.zig:779:64: 0x7a0e3b in callMain (std.zig)
^
/home/mlugg/zig/master/lib/std/Target.zig:1651:5: 0x7a0861 in _start (std.zig)
pub inline fn isSparc(arch: Arch) bool {
^
Aborted ./panic
```
The last two frames are clearly incorrect. However, we actually agree
with lldb-zig about those source locations, so it seems like that's a
bug in the compiler's `link.Dwarf2` implementation.
Fixes#31797
I finally had time to work on this.
I've implemented it so that, when an adjacent dSYM exist and its uuid match that of the current binary, we load its DWARF and use that for all getDwarfForAddress requests.
All of this is done eagerly at `MachOFile.load` for simplicity rather than later and lazier. Happy to change that to whatever you think is best.
This implementation is quite minimal and makes dSYM support "best-effort" as in, it treats dSYM parsing error as non-fatal and fallbacks using the current stabs/ofiles mechanism.
You can test it that way on macOS:
```
zig build-exe panic.zig
dsymutil panic -o panic.dSYM
strip -S panic
./panic
```
with panic.zig:
```
pub fn main() void {
@panic("panic");
}
```
Before:
```
thread 57569166 panic: panic
???:?:?: 0x103071c2b in _panic.main (/private/tmp/panic)
???:?:?: 0x103071bb3 in _main (/private/tmp/panic)
???:?:?: 0x180d5ab97 in start (/usr/lib/dyld)
fish: Job 1, './panic' terminated by signal SIGABRT (Abort)
```
After:
```
thread 57569653 panic: panic
/private/tmp/panic.zig:2:5: 0x1029d771b in main (panic)
@panic("panic");
^
/Users/cerisier/code/codeberg.org/ziglang/zig/lib/std/start.zig:698:59: 0x1029d76a3 in callMain (panic)
if (fn_info.params.len == 0) return wrapMain(root.main());
^
???:?:?: 0x180d5ab97 in start (/usr/lib/dyld)
fish: Job 1, './panic' terminated by signal SIGABRT (Abort)
```
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35582
Reviewed-by: mlugg <mlugg@noreply.codeberg.org>
For generic code, it is far more useful to consider this equivalent to
`unreachable`. Meanwhile, it is difficult to accidentally write concrete
code which performs this operation, so very little is actually lost from
not having a compile error.
If we accept that this operation does not trigger a compile error, then
it already has the potential to invoke Illegal Behavior today, because
uninstantiable types have an unspecified size in memory, so the
dereference always potentially exceeds the pointer's provenance. (That
said, this only means it is *possible* for the operation to invoke IB,
so the langspec should nonetheless explicitly specify that dereferencing
a pointer to an uninstantiable type is itself Illegal Behavior.)
Storing uninstantiable types into memory does not require any specific
language rules, because that operation can never be reached anyway due
to it requiring an operand (the RHS of `a = b`) whose type is the store
type, which is (by definition) impossible for uninstantiable types.
Resolves: https://codeberg.org/ziglang/zig/issues/36247
Some dwarf section names like __debug_str_offsets don't fit in a Mach-O
sectname buffer, so their actual name in Mach-O binaries is truncated.
When searching for sections to load an object file's debug info, we now
compare the section name with the truncated name. Before, the full name
was checked, so we would unconditionally skip __debug_str_offsets dwarf
sections.
DW_FORM_ref_addr encoding specification is different in dwarf version 2.
parseFormValue() now accepts a `version` argument so that it can parse
such attributes correctly based on the version.
* `tools/generate_c_size_and_align_checks.zig`: superceded by any cbe
output artifact
* `cTypePreferredAlignment`: no uses, if brought back, cbe should be
updated to verify `__alignof`
Closes#19991Closes#20881Closes#35523
Symtab search is always a reasonable fallback if debug information is
absent, invalid, or unsupported. Therefore, by changing the error
handling here to get symbols from the symtab even if `std.debug.Dwarf`
returns an error, we make stack traces slightly better in some cases.
This affects the self-hosted `Elf2` linker: that linker does not yet
understand DWARF sections, so it ends up emitting incomplete (or
sometimes invalid) DWARF. However, it still has a valid symtab, so we
should at least be able to see function symbol names in the stack trace!
Before this patch, we just saw "???" for everything, but after this
patch, we do indeed get the symbol names.
It seems like whatever bug was causing this to be unreliable is no longer
present; all module tests work for me with DWARF unwinding enabled. So let's
enable this for now, and if any breakage does pop up later, we can deal with it
then.
65922a2d4 started using some (deprecated but still available) dyld
functions for stack unwinding and debug information on Darwin targets,
because they are significantly faster than `dladdr` (which is the
"correct" thing to use). However, these functions are unavailable on
Darwin targets other than macOS, for instance on iOS. Therefore, on
those targets, we must fall back to the slow `dladdr` path.
The DWARF spec has CFI instructions that take signed offsets, but at least LLVM
always emits the unsigned variants, even for e.g. `.cfi_def_cfa_offset -4`.