| author | |
| committer | |
| log | 975c185b92a7d470ea705b28f46a8004bdda3c60 |
| tree | cb0d037c9a2f38b348ae10b621db417e2f941fa1 |
| parent | 48d584e3a33a76ef4ea643905a11d311e9ed8bbf |
...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 | 88 | if (self_debug_info) |*info| { |
| 89 | 89 | return info; |
| 90 | 90 | } else { |
| 91 | self_debug_info = try SelfInfo.openSelf(getDebugInfoAllocator()); | |
| 91 | self_debug_info = try SelfInfo.open(getDebugInfoAllocator()); | |
| 92 | 92 | return &self_debug_info.?; |
| 93 | 93 | } |
| 94 | 94 | } |
| ... | ... | @@ -573,17 +573,19 @@ pub const StackIterator = struct { |
| 573 | 573 | pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t) !StackIterator { |
| 574 | 574 | // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that |
| 575 | 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 | 577 | return init(first_address, context.mcontext.ss.fp); |
| 578 | } else { | |
| 578 | ||
| 579 | if (SelfInfo.supports_unwinding) { | |
| 579 | 580 | var iterator = init(first_address, null); |
| 580 | 581 | iterator.unwind_state = .{ |
| 581 | 582 | .debug_info = debug_info, |
| 582 | 583 | .dwarf_context = try SelfInfo.UnwindContext.init(debug_info.allocator, context), |
| 583 | 584 | }; |
| 584 | ||
| 585 | 585 | return iterator; |
| 586 | 586 | } |
| 587 | ||
| 588 | return init(first_address, null); | |
| 587 | 589 | } |
| 588 | 590 | |
| 589 | 591 | pub fn deinit(it: *StackIterator) void { |
| ... | ... | @@ -725,11 +727,13 @@ pub fn writeCurrentStackTrace( |
| 725 | 727 | tty_config: io.tty.Config, |
| 726 | 728 | start_addr: ?usize, |
| 727 | 729 | ) !void { |
| 728 | var context: ThreadContext = undefined; | |
| 729 | const has_context = getContext(&context); | |
| 730 | 730 | if (native_os == .windows) { |
| 731 | var context: ThreadContext = undefined; | |
| 732 | assert(getContext(&context)); | |
| 731 | 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); | |
| 733 | 737 | |
| 734 | 738 | var it = (if (has_context) blk: { |
| 735 | 739 | break :blk StackIterator.initWithContext(start_addr, debug_info, &context) catch null; |
| ... | ... | @@ -1340,7 +1344,7 @@ test "manage resources correctly" { |
| 1340 | 1344 | } |
| 1341 | 1345 | |
| 1342 | 1346 | const writer = std.io.null_writer; |
| 1343 | var di = try SelfInfo.openSelf(testing.allocator); | |
| 1347 | var di = try SelfInfo.open(testing.allocator); | |
| 1344 | 1348 | defer di.deinit(); |
| 1345 | 1349 | try printSourceAtAddress(&di, writer, showMyTrace(), io.tty.detectConfig(std.io.getStdErr())); |
| 1346 | 1350 | } |
| ... | ... | @@ -1581,5 +1585,9 @@ pub inline fn inValgrind() bool { |
| 1581 | 1585 | } |
| 1582 | 1586 | |
| 1583 | 1587 | test { |
| 1588 | _ = &Dwarf; | |
| 1589 | _ = &MemoryAccessor; | |
| 1590 | _ = &Pdb; | |
| 1591 | _ = &SelfInfo; | |
| 1584 | 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 | 2023 | return std.math.add(usize, field_ptr, @as(usize, @intCast(pc_rel_offset))); |
| 2024 | 2024 | } |
| 2025 | 2025 | } |
| 2026 | ||
| 2027 | pub 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 | 5 | const posix = std.posix; |
| 6 | 6 | const Arch = std.Target.Cpu.Arch; |
| 7 | 7 | |
| 8 | pub fn supportsUnwinding(target: std.Target) bool { | |
| 9 | return switch (target.cpu.arch) { | |
| 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 | ||
| 30 | pub fn ipRegNum(arch: Arch) u8 { | |
| 8 | /// Returns `null` for CPU architectures without an instruction pointer register. | |
| 9 | pub fn ipRegNum(arch: Arch) ?u8 { | |
| 31 | 10 | return switch (arch) { |
| 32 | 11 | .x86 => 8, |
| 33 | 12 | .x86_64 => 16, |
| 34 | 13 | .arm => 15, |
| 35 | 14 | .aarch64 => 32, |
| 36 | else => unreachable, | |
| 15 | else => null, | |
| 37 | 16 | }; |
| 38 | 17 | } |
| 39 | 18 |
lib/std/debug/Dwarf/expression.zig+2-2| ... | ... | @@ -1190,11 +1190,11 @@ test "DWARF expressions" { |
| 1190 | 1190 | mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian); |
| 1191 | 1191 | (try abi.regValueNative(&thread_context, abi.fpRegNum(native_arch, reg_context), reg_context)).* = 1; |
| 1192 | 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; | |
| 1194 | 1194 | |
| 1195 | 1195 | try b.writeBreg(writer, abi.fpRegNum(native_arch, reg_context), @as(usize, 100)); |
| 1196 | 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 | 1198 | try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400)); |
| 1199 | 1199 | |
| 1200 | 1200 | _ = try stack_machine.run(program.items, allocator, context, 0); |
lib/std/debug/SelfInfo.zig+6-7| ... | ... | @@ -34,18 +34,15 @@ allocator: Allocator, |
| 34 | 34 | address_map: std.AutoHashMap(usize, *Module), |
| 35 | 35 | modules: if (native_os == .windows) std.ArrayListUnmanaged(WindowsModule) else void, |
| 36 | 36 | |
| 37 | pub const OpenSelfError = error{ | |
| 37 | pub const OpenError = error{ | |
| 38 | 38 | MissingDebugInfo, |
| 39 | 39 | UnsupportedOperatingSystem, |
| 40 | 40 | } || @typeInfo(@typeInfo(@TypeOf(SelfInfo.init)).Fn.return_type.?).ErrorUnion.error_set; |
| 41 | 41 | |
| 42 | pub fn openSelf(allocator: Allocator) OpenSelfError!SelfInfo { | |
| 42 | pub fn open(allocator: Allocator) OpenError!SelfInfo { | |
| 43 | 43 | nosuspend { |
| 44 | 44 | if (builtin.strip_debug_info) |
| 45 | 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 | 46 | switch (native_os) { |
| 50 | 47 | .linux, |
| 51 | 48 | .freebsd, |
| ... | ... | @@ -1721,6 +1718,8 @@ pub const UnwindContext = struct { |
| 1721 | 1718 | allocator: Allocator, |
| 1722 | 1719 | thread_context: *std.debug.ThreadContext, |
| 1723 | 1720 | ) !UnwindContext { |
| 1721 | comptime assert(supports_unwinding); | |
| 1722 | ||
| 1724 | 1723 | const pc = stripInstructionPtrAuthCode( |
| 1725 | 1724 | (try regValueNative(thread_context, ip_reg_num, null)).*, |
| 1726 | 1725 | ); |
| ... | ... | @@ -1982,8 +1981,8 @@ fn spRegNum(reg_context: Dwarf.abi.RegisterContext) u8 { |
| 1982 | 1981 | return Dwarf.abi.spRegNum(native_arch, reg_context); |
| 1983 | 1982 | } |
| 1984 | 1983 | |
| 1985 | const ip_reg_num = Dwarf.abi.ipRegNum(native_arch); | |
| 1986 | const supports_unwinding = Dwarf.abi.supportsUnwinding(builtin.target); | |
| 1984 | const ip_reg_num = Dwarf.abi.ipRegNum(native_arch).?; | |
| 1985 | pub const supports_unwinding = Dwarf.supportsUnwinding(builtin.target); | |
| 1987 | 1986 | |
| 1988 | 1987 | fn unwindFrameMachODwarf( |
| 1989 | 1988 | context: *UnwindContext, |
test/standalone/coff_dwarf/main.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ pub fn main() !void { |
| 9 | 9 | defer assert(gpa.deinit() == .ok); |
| 10 | 10 | const allocator = gpa.allocator(); |
| 11 | 11 | |
| 12 | var debug_info = try std.debug.openSelfDebugInfo(allocator); | |
| 12 | var debug_info = try std.debug.SelfInfo.open(allocator); | |
| 13 | 13 | defer debug_info.deinit(); |
| 14 | 14 | |
| 15 | 15 | var add_addr: usize = undefined; |