authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-03 21:19:38+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-04 03:22:40+02:00
log9dbfa5b2946193e71a80805ed490d64b66994f1c
tree4e77afa38b48f2cfca03356e5400a2bcac705bbe
parentd8268fac9829965ac0ffff72fb2f96a36d04d996

std.debug: consider FP-based unwinding on hexagon and powerpc safe

The ABIs make this safe and reliable due to their backchain requirements.

1 files changed, 16 insertions(+), 4 deletions(-)

lib/std/debug.zig+16-4
......@@ -697,7 +697,7 @@ pub fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_
697697 var printed_any_frame = false;
698698 while (true) switch (it.next()) {
699699 .switch_to_fp => |unwind_error| {
700 if (StackIterator.fp_unwind_is_safe) continue; // no need to even warn
700 if (StackIterator.abi_requires_backchain or StackIterator.fp_unwind_is_safe) continue; // no need to even warn
701701 const module_name = di.getModuleName(di_gpa, unwind_error.address) catch "???";
702702 const caption: []const u8 = switch (unwind_error.err) {
703703 error.MissingDebugInfo => "unwind info unavailable",
......@@ -855,10 +855,22 @@ const StackIterator = union(enum) {
855855 }
856856 }
857857
858 /// On aarch64-macos, Apple mandate that the frame pointer is always used.
859 /// TODO: are there any other architectures with guarantees like this?
858 /// <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers>
860859 const fp_unwind_is_safe = builtin.cpu.arch == .aarch64 and builtin.os.tag.isDarwin();
861860
861 /// On some architectures, we can do FP unwinding even with `-fomit-frame-pointer` due to ABI
862 /// requirements. Typically this is because the ABI requires a backchain regardless of whether
863 /// codegen actually uses a frame pointer for stack frame access.
864 const abi_requires_backchain = switch (builtin.cpu.arch) {
865 .hexagon,
866 .powerpc,
867 .powerpcle,
868 .powerpc64,
869 .powerpc64le,
870 => true,
871 else => false,
872 };
873
862874 /// Whether the current unwind strategy is allowed given `allow_unsafe`.
863875 fn stratOk(it: *const StackIterator, allow_unsafe: bool) bool {
864876 return switch (it.*) {
......@@ -867,7 +879,7 @@ const StackIterator = union(enum) {
867879 // immediately regardless of anything. But FPs could also be omitted from a different
868880 // linked object, so it's not guaranteed to be safe, unless the target specifically
869881 // requires it.
870 .fp => !builtin.omit_frame_pointer and (fp_unwind_is_safe or allow_unsafe),
882 .fp => abi_requires_backchain or (!builtin.omit_frame_pointer and (fp_unwind_is_safe or allow_unsafe)),
871883 };
872884 }
873885