| ... | ... | @@ -697,7 +697,10 @@ pub fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Writer, tty_ |
| 697 | 697 | var printed_any_frame = false; |
| 698 | 698 | while (true) switch (it.next()) { |
| 699 | 699 | .switch_to_fp => |unwind_error| { |
| 700 | | if (StackIterator.abi_requires_backchain or StackIterator.fp_unwind_is_safe) continue; // no need to even warn |
| 700 | switch (StackIterator.fp_usability) { |
| 701 | .useless, .unsafe => {}, |
| 702 | .safe, .ideal => continue, // no need to even warn |
| 703 | } |
| 701 | 704 | const module_name = di.getModuleName(di_gpa, unwind_error.address) catch "???"; |
| 702 | 705 | const caption: []const u8 = switch (unwind_error.err) { |
| 703 | 706 | error.MissingDebugInfo => "unwind info unavailable", |
| ... | ... | @@ -840,7 +843,8 @@ const StackIterator = union(enum) { |
| 840 | 843 | if (!(builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) and |
| 841 | 844 | SelfInfo != void and |
| 842 | 845 | SelfInfo.can_unwind and |
| 843 | | cpu_context.Native != noreturn) |
| 846 | cpu_context.Native != noreturn and |
| 847 | fp_usability != .ideal) |
| 844 | 848 | { |
| 845 | 849 | // We don't need `di_first` here, because our PC is in `std.debug`; we're only interested |
| 846 | 850 | // in our caller's frame and above. |
| ... | ... | @@ -855,32 +859,41 @@ const StackIterator = union(enum) { |
| 855 | 859 | } |
| 856 | 860 | } |
| 857 | 861 | |
| 858 | | /// Some architectures make FP unwinding too impractical. For example, due to its very silly ABI |
| 859 | | /// design decisions, it's not possible to do generic FP unwinding on MIPS; we would need to do |
| 860 | | /// a complicated code scanning algorithm instead. At that point, we may as well just use DWARF. |
| 861 | | const fp_unwind_is_impossible = switch (builtin.cpu.arch) { |
| 862 | const FpUsability = enum { |
| 863 | /// FP unwinding is impractical on this target. For example, due to its very silly ABI |
| 864 | /// design decisions, it's not possible to do generic FP unwinding on MIPS without a |
| 865 | /// complicated code scanning algorithm. |
| 866 | useless, |
| 867 | /// FP unwinding is unsafe on this target; we may crash when doing so. We will only perform |
| 868 | /// FP unwinding in the case of crashes/panics, or if the user opts in. |
| 869 | unsafe, |
| 870 | /// FP unwinding is guaranteed to be safe on this target. We will do so if unwinding with |
| 871 | /// debug info does not work, and if this compilation has frame pointers enabled. |
| 872 | safe, |
| 873 | /// FP unwinding is the best option on this target. This is usually because the ABI requires |
| 874 | /// a backchain pointer, thus making it always available, safe, and fast. |
| 875 | ideal, |
| 876 | }; |
| 877 | |
| 878 | const fp_usability: FpUsability = switch (builtin.target.cpu.arch) { |
| 862 | 879 | .mips, |
| 863 | 880 | .mipsel, |
| 864 | 881 | .mips64, |
| 865 | 882 | .mips64el, |
| 866 | | => true, |
| 867 | | else => false, |
| 868 | | }; |
| 869 | | |
| 870 | | /// <https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers> |
| 871 | | const fp_unwind_is_safe = builtin.cpu.arch == .aarch64 and builtin.os.tag.isDarwin(); |
| 872 | | |
| 873 | | /// On some architectures, we can do FP unwinding even with `-fomit-frame-pointer` due to ABI |
| 874 | | /// requirements. Typically this is because the ABI requires a backchain regardless of whether |
| 875 | | /// codegen actually uses a frame pointer for stack frame access. |
| 876 | | const abi_requires_backchain = switch (builtin.cpu.arch) { |
| 883 | => .useless, |
| 877 | 884 | .hexagon, |
| 885 | // The PowerPC ABIs don't actually strictly require a backchain pointer; they allow omitting |
| 886 | // it when full unwind info is present. Despite this, both GCC and Clang always enforce the |
| 887 | // presence of the backchain pointer no matter what options they are given. This seems to be |
| 888 | // a case of "the spec is only a polite suggestion", except it works in our favor this time! |
| 878 | 889 | .powerpc, |
| 879 | 890 | .powerpcle, |
| 880 | 891 | .powerpc64, |
| 881 | 892 | .powerpc64le, |
| 882 | | => true, |
| 883 | | else => false, |
| 893 | => .ideal, |
| 894 | // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers |
| 895 | .aarch64 => if (builtin.target.os.tag.isDarwin()) .safe else .unsafe, |
| 896 | else => .unsafe, |
| 884 | 897 | }; |
| 885 | 898 | |
| 886 | 899 | /// Whether the current unwind strategy is allowed given `allow_unsafe`. |
| ... | ... | @@ -891,13 +904,11 @@ const StackIterator = union(enum) { |
| 891 | 904 | // immediately regardless of anything. But FPs could also be omitted from a different |
| 892 | 905 | // linked object, so it's not guaranteed to be safe, unless the target specifically |
| 893 | 906 | // requires it. |
| 894 | | .fp => s: { |
| 895 | | if (fp_unwind_is_impossible) break :s false; |
| 896 | | if (abi_requires_backchain) break :s true; |
| 897 | | if (builtin.omit_frame_pointer) break :s false; |
| 898 | | if (fp_unwind_is_safe) break :s true; |
| 899 | | if (allow_unsafe) break :s true; |
| 900 | | break :s false; |
| 907 | .fp => switch (fp_usability) { |
| 908 | .useless => false, |
| 909 | .unsafe => allow_unsafe and !builtin.omit_frame_pointer, |
| 910 | .safe => !builtin.omit_frame_pointer, |
| 911 | .ideal => true, |
| 901 | 912 | }, |
| 902 | 913 | }; |
| 903 | 914 | } |