authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-02 12:00:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-02 14:14:59-07:00
log975c185b92a7d470ea705b28f46a8004bdda3c60
treecb0d037c9a2f38b348ae10b621db417e2f941fa1
parent48d584e3a33a76ef4ea643905a11d311e9ed8bbf

fix compilation on powerpc GNU systems

...which have a ucontext_t but not a PC register. The current stack unwinding implementation does not yet support this architecture. Also fix name of `std.debug.SelfInfo.openSelf` to remove redundancy. Also removed this hook into root providing an "openSelfDebugInfo" function. Sorry, this debugging code is not of sufficient quality to offer a plugin API right now.

6 files changed, 51 insertions(+), 41 deletions(-)

lib/std/debug.zig+15-7
...@@ -88,7 +88,7 @@ pub fn getSelfDebugInfo() !*SelfInfo {...@@ -88,7 +88,7 @@ pub fn getSelfDebugInfo() !*SelfInfo {
88 if (self_debug_info) |*info| {88 if (self_debug_info) |*info| {
89 return info;89 return info;
90 } else {90 } else {
91 self_debug_info = try SelfInfo.openSelf(getDebugInfoAllocator());91 self_debug_info = try SelfInfo.open(getDebugInfoAllocator());
92 return &self_debug_info.?;92 return &self_debug_info.?;
93 }93 }
94}94}
...@@ -573,17 +573,19 @@ pub const StackIterator = struct {...@@ -573,17 +573,19 @@ pub const StackIterator = struct {
573 pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t) !StackIterator {573 pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t) !StackIterator {
574 // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that574 // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that
575 // the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder.575 // the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder.
576 if (builtin.target.isDarwin() and native_arch == .aarch64) {576 if (builtin.target.isDarwin() and native_arch == .aarch64)
577 return init(first_address, context.mcontext.ss.fp);577 return init(first_address, context.mcontext.ss.fp);
578 } else {578
579 if (SelfInfo.supports_unwinding) {
579 var iterator = init(first_address, null);580 var iterator = init(first_address, null);
580 iterator.unwind_state = .{581 iterator.unwind_state = .{
581 .debug_info = debug_info,582 .debug_info = debug_info,
582 .dwarf_context = try SelfInfo.UnwindContext.init(debug_info.allocator, context),583 .dwarf_context = try SelfInfo.UnwindContext.init(debug_info.allocator, context),
583 };584 };
584
585 return iterator;585 return iterator;
586 }586 }
587
588 return init(first_address, null);
587 }589 }
588590
589 pub fn deinit(it: *StackIterator) void {591 pub fn deinit(it: *StackIterator) void {
...@@ -725,11 +727,13 @@ pub fn writeCurrentStackTrace(...@@ -725,11 +727,13 @@ pub fn writeCurrentStackTrace(
725 tty_config: io.tty.Config,727 tty_config: io.tty.Config,
726 start_addr: ?usize,728 start_addr: ?usize,
727) !void {729) !void {
728 var context: ThreadContext = undefined;
729 const has_context = getContext(&context);
730 if (native_os == .windows) {730 if (native_os == .windows) {
731 var context: ThreadContext = undefined;
732 assert(getContext(&context));
731 return writeStackTraceWindows(out_stream, debug_info, tty_config, &context, start_addr);733 return writeStackTraceWindows(out_stream, debug_info, tty_config, &context, start_addr);
732 }734 }
735 var context: ThreadContext = undefined;
736 const has_context = getContext(&context);
733737
734 var it = (if (has_context) blk: {738 var it = (if (has_context) blk: {
735 break :blk StackIterator.initWithContext(start_addr, debug_info, &context) catch null;739 break :blk StackIterator.initWithContext(start_addr, debug_info, &context) catch null;
...@@ -1340,7 +1344,7 @@ test "manage resources correctly" {...@@ -1340,7 +1344,7 @@ test "manage resources correctly" {
1340 }1344 }
13411345
1342 const writer = std.io.null_writer;1346 const writer = std.io.null_writer;
1343 var di = try SelfInfo.openSelf(testing.allocator);1347 var di = try SelfInfo.open(testing.allocator);
1344 defer di.deinit();1348 defer di.deinit();
1345 try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.io.getStdErr()));1349 try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.io.getStdErr()));
1346}1350}
...@@ -1581,5 +1585,9 @@ pub inline fn inValgrind() bool {...@@ -1581,5 +1585,9 @@ pub inline fn inValgrind() bool {
1581}1585}
15821586
1583test {1587test {
1588 _ = &Dwarf;
1589 _ = &MemoryAccessor;
1590 _ = &Pdb;
1591 _ = &SelfInfo;
1584 _ = &dumpHex;1592 _ = &dumpHex;
1585}1593}
lib/std/debug/Dwarf.zig+24
...@@ -2023,3 +2023,27 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize {...@@ -2023,3 +2023,27 @@ fn pcRelBase(field_ptr: usize, pc_rel_offset: i64) !usize {
2023 return std.math.add(usize, field_ptr, @as(usize, @intCast(pc_rel_offset)));2023 return std.math.add(usize, field_ptr, @as(usize, @intCast(pc_rel_offset)));
2024 }2024 }
2025}2025}
2026
2027pub fn supportsUnwinding(target: std.Target) bool {
2028 return switch (target.cpu.arch) {
2029 .x86 => switch (target.os.tag) {
2030 .linux, .netbsd, .solaris, .illumos => true,
2031 else => false,
2032 },
2033 .x86_64 => switch (target.os.tag) {
2034 .linux, .netbsd, .freebsd, .openbsd, .macos, .ios, .solaris, .illumos => true,
2035 else => false,
2036 },
2037 .arm => switch (target.os.tag) {
2038 .linux => true,
2039 else => false,
2040 },
2041 .aarch64 => switch (target.os.tag) {
2042 .linux, .netbsd, .freebsd, .macos, .ios => true,
2043 else => false,
2044 },
2045 // Unwinding is possible on other targets but this implementation does
2046 // not support them...yet!
2047 else => false,
2048 };
2049}
lib/std/debug/Dwarf/abi.zig+3-24
...@@ -5,35 +5,14 @@ const mem = std.mem;...@@ -5,35 +5,14 @@ const mem = std.mem;
5const posix = std.posix;5const posix = std.posix;
6const Arch = std.Target.Cpu.Arch;6const Arch = std.Target.Cpu.Arch;
77
8pub fn supportsUnwinding(target: std.Target) bool {8/// Returns `null` for CPU architectures without an instruction pointer register.
9 return switch (target.cpu.arch) {9pub fn ipRegNum(arch: Arch) ?u8 {
10 .x86 => switch (target.os.tag) {
11 .linux, .netbsd, .solaris, .illumos => true,
12 else => false,
13 },
14 .x86_64 => switch (target.os.tag) {
15 .linux, .netbsd, .freebsd, .openbsd, .macos, .ios, .solaris, .illumos => true,
16 else => false,
17 },
18 .arm => switch (target.os.tag) {
19 .linux => true,
20 else => false,
21 },
22 .aarch64 => switch (target.os.tag) {
23 .linux, .netbsd, .freebsd, .macos, .ios => true,
24 else => false,
25 },
26 else => false,
27 };
28}
29
30pub fn ipRegNum(arch: Arch) u8 {
31 return switch (arch) {10 return switch (arch) {
32 .x86 => 8,11 .x86 => 8,
33 .x86_64 => 16,12 .x86_64 => 16,
34 .arm => 15,13 .arm => 15,
35 .aarch64 => 32,14 .aarch64 => 32,
36 else => unreachable,15 else => null,
37 };16 };
38}17}
3918
lib/std/debug/Dwarf/expression.zig+2-2
...@@ -1190,11 +1190,11 @@ test "DWARF expressions" {...@@ -1190,11 +1190,11 @@ test "DWARF expressions" {
1190 mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);1190 mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);
1191 (try abi.regValueNative(&thread_context, abi.fpRegNum(native_arch, reg_context), reg_context)).* = 1;1191 (try abi.regValueNative(&thread_context, abi.fpRegNum(native_arch, reg_context), reg_context)).* = 1;
1192 (try abi.regValueNative(&thread_context, abi.spRegNum(native_arch, reg_context), reg_context)).* = 2;1192 (try abi.regValueNative(&thread_context, abi.spRegNum(native_arch, reg_context), reg_context)).* = 2;
1193 (try abi.regValueNative(&thread_context, abi.ipRegNum(native_arch), reg_context)).* = 3;1193 (try abi.regValueNative(&thread_context, abi.ipRegNum(native_arch).?, reg_context)).* = 3;
11941194
1195 try b.writeBreg(writer, abi.fpRegNum(native_arch, reg_context), @as(usize, 100));1195 try b.writeBreg(writer, abi.fpRegNum(native_arch, reg_context), @as(usize, 100));
1196 try b.writeBreg(writer, abi.spRegNum(native_arch, reg_context), @as(usize, 200));1196 try b.writeBreg(writer, abi.spRegNum(native_arch, reg_context), @as(usize, 200));
1197 try b.writeBregx(writer, abi.ipRegNum(native_arch), @as(usize, 300));1197 try b.writeBregx(writer, abi.ipRegNum(native_arch).?, @as(usize, 300));
1198 try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400));1198 try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400));
11991199
1200 _ = try stack_machine.run(program.items, allocator, context, 0);1200 _ = try stack_machine.run(program.items, allocator, context, 0);
lib/std/debug/SelfInfo.zig+6-7
...@@ -34,18 +34,15 @@ allocator: Allocator,...@@ -34,18 +34,15 @@ allocator: Allocator,
34address_map: std.AutoHashMap(usize, *Module),34address_map: std.AutoHashMap(usize, *Module),
35modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModule) else void,35modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModule) else void,
3636
37pub const OpenSelfError = error{37pub const OpenError = error{
38 MissingDebugInfo,38 MissingDebugInfo,
39 UnsupportedOperatingSystem,39 UnsupportedOperatingSystem,
40} || @typeInfo(@typeInfo(@TypeOf(SelfInfo.init)).Fn.return_type.?).ErrorUnion.error_set;40} || @typeInfo(@typeInfo(@TypeOf(SelfInfo.init)).Fn.return_type.?).ErrorUnion.error_set;
4141
42pub fn openSelf(allocator: Allocator) OpenSelfError!SelfInfo {42pub fn open(allocator: Allocator) OpenError!SelfInfo {
43 nosuspend {43 nosuspend {
44 if (builtin.strip_debug_info)44 if (builtin.strip_debug_info)
45 return error.MissingDebugInfo;45 return error.MissingDebugInfo;
46 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
47 return root.os.debug.openSelfDebugInfo(allocator);
48 }
49 switch (native_os) {46 switch (native_os) {
50 .linux,47 .linux,
51 .freebsd,48 .freebsd,
...@@ -1721,6 +1718,8 @@ pub const UnwindContext = struct {...@@ -1721,6 +1718,8 @@ pub const UnwindContext = struct {
1721 allocator: Allocator,1718 allocator: Allocator,
1722 thread_context: *std.debug.ThreadContext,1719 thread_context: *std.debug.ThreadContext,
1723 ) !UnwindContext {1720 ) !UnwindContext {
1721 comptime assert(supports_unwinding);
1722
1724 const pc = stripInstructionPtrAuthCode(1723 const pc = stripInstructionPtrAuthCode(
1725 (try regValueNative(thread_context, ip_reg_num, null)).*,1724 (try regValueNative(thread_context, ip_reg_num, null)).*,
1726 );1725 );
...@@ -1982,8 +1981,8 @@ fn spRegNum(reg_context: Dwarf.abi.RegisterContext) u8 {...@@ -1982,8 +1981,8 @@ fn spRegNum(reg_context: Dwarf.abi.RegisterContext) u8 {
1982 return Dwarf.abi.spRegNum(native_arch, reg_context);1981 return Dwarf.abi.spRegNum(native_arch, reg_context);
1983}1982}
19841983
1985const ip_reg_num = Dwarf.abi.ipRegNum(native_arch);1984const ip_reg_num = Dwarf.abi.ipRegNum(native_arch).?;
1986const supports_unwinding = Dwarf.abi.supportsUnwinding(builtin.target);1985pub const supports_unwinding = Dwarf.supportsUnwinding(builtin.target);
19871986
1988fn unwindFrameMachODwarf(1987fn unwindFrameMachODwarf(
1989 context: *UnwindContext,1988 context: *UnwindContext,
test/standalone/coff_dwarf/main.zig+1-1
...@@ -9,7 +9,7 @@ pub fn main() !void {...@@ -9,7 +9,7 @@ pub fn main() !void {
9 defer assert(gpa.deinit() == .ok);9 defer assert(gpa.deinit() == .ok);
10 const allocator = gpa.allocator();10 const allocator = gpa.allocator();
1111
12 var debug_info = try std.debug.openSelfDebugInfo(allocator);12 var debug_info = try std.debug.SelfInfo.open(allocator);
13 defer debug_info.deinit();13 defer debug_info.deinit();
1414
15 var add_addr: usize = undefined;15 var add_addr: usize = undefined;