Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DWARF unwinding, and an external debug info loader for ELF #15823

Merged
merged 81 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
ea9917d
debug: support loading elf debug info from external files
kcbanner May 1, 2023
f6148f1
add CommonInformationEntry parser
kcbanner May 4, 2023
6c1d1aa
begin working on parsing unwind info
kcbanner May 7, 2023
8b8d627
- add call frame instruction parser
kcbanner May 8, 2023
38303d7
add VirtualMachine to run CFA instructions
kcbanner May 8, 2023
f3f3c87
- add DWARF expression parser
kcbanner May 9, 2023
338df86
- fix remember_state
kcbanner May 9, 2023
7b4611c
- move writing code to zig-dwarfdump
kcbanner May 10, 2023
a0a40c2
- implement more opcodes
kcbanner May 10, 2023
69399fb
- add default register rule
kcbanner May 11, 2023
b449d98
- rework StackIterator to optionally use debug_info to unwind the stack
kcbanner May 15, 2023
9145ff7
dwarf: implement more register number mappings
kcbanner May 22, 2023
e72e762
dwarf: implement more register mappings, fix up macos compile
kcbanner May 22, 2023
c98e03f
- rework CFI instruction parsing to not use std.meta
kcbanner May 22, 2023
a325d7f
fmt and cleanup
kcbanner May 22, 2023
d1a9bb1
debug: fixup context detection for wasi
kcbanner May 25, 2023
d74c8ac
dwarf: fixup for sort changes
kcbanner May 25, 2023
2f75d20
debug: use an explicit context type instead of anytype for dumpStackT…
kcbanner May 25, 2023
551f153
dwarf: fixes for non-64 bit systems
kcbanner May 26, 2023
5ebca43
debug: fixing more compile errors on arches that I hadn't tested on yet
kcbanner May 27, 2023
865d4d2
debug: more fixups for mips linux not having ucontext_t
kcbanner May 27, 2023
dd20357
debug: fix memory leak when an error occurs opening a pdb file
kcbanner May 27, 2023
5781016
dwarf: add support for .eh_frame_hdr when unwinding
kcbanner May 29, 2023
adbc5bb
dwarf: fixup pointer cast
kcbanner Jun 2, 2023
a47212c
- rebase and update to lastest master
kcbanner Jun 23, 2023
5219882
add more safety checks when searching for eh_frame entries using find…
kcbanner Jun 23, 2023
84a1244
dwarf: use eh_frame length if it's available
kcbanner Jun 25, 2023
6abf1fb
update to new builtin syntax
kcbanner Jun 25, 2023
41832aa
linux: add getcontext for x86_64
kcbanner Jun 26, 2023
a9b6f2d
dwarf: add support for .debug_frame and CIE version 4
kcbanner Jun 26, 2023
5cd8ab2
debug: enhance writeCurrentStackTrace to use context-based unwinding …
kcbanner Jun 26, 2023
89ef004
debug: x86 unwinding support, more unwinding fixes
kcbanner Jun 27, 2023
caa3347
linux: rework getcontext to closer match the specification (saved IP/…
kcbanner Jun 28, 2023
f991b9d
debug: fix reading -gdwarf generated debug sections in COFF files
kcbanner Jun 29, 2023
23d9b59
c: add getcontext
kcbanner Jul 1, 2023
9c908ea
test: add standalone test for DWARF unwinding with -fomit-frame-pointer
kcbanner Jul 1, 2023
7bc1695
c: musl doesn't implement getcontext, so defer to our implementation …
kcbanner Jul 1, 2023
ccc9f82
c: fixup getcontext
kcbanner Jul 1, 2023
6a5e2b7
debug: de-duplicate some code in macos ModuleDebugInfo
kcbanner Jul 2, 2023
395ab47
dwarf: fix logic error in eh_frame_hdry binary search
kcbanner Jul 2, 2023
f04f970
dwarf: add support for DWARF5 DW_AT_ranges in subprograms, add DebugR…
kcbanner Jul 2, 2023
62598c2
debug: rework how unwind errors are printed, and add module name look…
kcbanner Jul 2, 2023
b85f840
dwarf: don't dupe function names, as they are backed by the memory ma…
kcbanner Jul 3, 2023
412cd78
debug: fixup base address calculations for macho
kcbanner Jul 3, 2023
576ffaa
darwin: update mcontext_t definition for aarch64 to add neon state
kcbanner Jul 4, 2023
ad5f74c
dwarf: introduce ExpressionContext, add more expression opcodes
kcbanner Jul 5, 2023
424b129
dwarf: add expression writer
kcbanner Jul 5, 2023
8547c42
dwarf: expression fixups for non-64bit arches, check call_frame_conte…
kcbanner Jul 7, 2023
5f72c65
debug: rename StackTraceContext to ThreadContext
kcbanner Jul 7, 2023
463bbe7
dwarf: implement constx,addrx, begin adding DWARF expression tests
kcbanner Jul 7, 2023
5c0d4ce
debug: add dupeContext, store a pointer to a copy of ThreadContext on…
kcbanner Jul 7, 2023
54ca62f
dwarf: fixup regBytes for the case where there is no context support
kcbanner Jul 7, 2023
021f537
dwarf: fixup default endianness in ExpressionOptions, add control flo…
kcbanner Jul 8, 2023
21d0154
dwarf: skip register tests on unimplemented arch / os, add tests for …
kcbanner Jul 8, 2023
d226b74
dwarf: add ExpressionError to work around the compiler not being able…
kcbanner Jul 8, 2023
94354aa
macho: add unwindFrame which can unwind stack frames using the __unwi…
kcbanner Jul 8, 2023
203d96a
debug: add relocateContext
kcbanner Jul 9, 2023
5dfb159
macho: add aarch64 implementation to unwindFrame
kcbanner Jul 9, 2023
891fa3b
debug: fix initialization of the optional fields on StackIterator
kcbanner Jul 10, 2023
e5aa2bb
debug: fixup last_error being printed too many times
kcbanner Jul 11, 2023
9b25bee
debug: fixup have_getcontext
kcbanner Jul 11, 2023
b180313
dwarf: use cie.return_address_register instead of assuming it's in th…
kcbanner Jul 12, 2023
06bf2e0
tests: use a more portable way of determining the return address in t…
kcbanner Jul 12, 2023
9549b4a
debug: fixup an inconsistency in the getcontext implementation on aa…
kcbanner Jul 13, 2023
7d8b423
macho: remove unnecessary checks
kcbanner Jul 13, 2023
ec96095
compilation: pass omit_frame_pointer through to builtin.zig
kcbanner Jul 13, 2023
ba813d0
dwarf: add abi.stripInstructionPtrAuthCode
kcbanner Jul 14, 2023
5e399d9
use eh_frame from the mapped binary if available
kcbanner Jul 15, 2023
618b0eb
dwarf: fixup integer overflow in readEhPointer
kcbanner Jul 16, 2023
2c76020
debug: load the macho unwind sections from the already-mapped image
kcbanner Jul 16, 2023
bdb0a6f
test: add a test for dwarf embedded in coff
kcbanner Jul 16, 2023
774dc2f
dwarf: add explicit_fde_offset to support more optimal __unwind_info …
kcbanner Jul 17, 2023
97bda56
macho: don't scan all eh_frame entries, instead follow the offset fro…
kcbanner Jul 17, 2023
1a2bb70
dwarf: write the CFA as SP before the register update, in case the SP…
kcbanner Jul 18, 2023
d99b40d
dwarf: fix the unwinder using the incorrect row from the FDE in certa…
kcbanner Jul 18, 2023
2bc2b01
dwarf: update the pc register
kcbanner Jul 18, 2023
4421b14
dwarf: fixup rules for setting ip
kcbanner Jul 18, 2023
253e697
dwarf: implement aarch64 default register rules
kcbanner Jul 19, 2023
6d87bb3
debug: disable the new unwinder on aarch64-macos
kcbanner Jul 19, 2023
8e6a62b
test: disable omit_frame_pointer unwinding tests on aarch64-macos
kcbanner Jul 19, 2023
b1d86db
dwarf: move macho unwind code from macho -> dwarf
kcbanner Jul 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,13 @@ pub extern "c" fn timer_delete(timerid: c.timer_t) c_int;
pub extern "c" fn timer_settime(timerid: c.timer_t, flags: c_int, new_value: *const c.itimerspec, old_value: *c.itimerspec) c_int;
pub extern "c" fn timer_gettime(timerid: c.timer_t, flags: c_int, curr_value: *c.itimerspec) c_int;

pub usingnamespace if (builtin.os.tag == .linux and builtin.target.isMusl()) struct {
// musl does not implement getcontext
pub const getcontext = std.os.linux.getcontext;
} else struct {
pub extern "c" fn getcontext(ucp: *std.os.ucontext_t) c_int;
};

Comment on lines +416 to +422
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this usingnamespace. Just put the definition here and let the linker tell the user that the symbol does not exist. The user should do this logic themselves if they want to reach into Linux directly.

This is the std.c namespace after all, it should not pretend to be libc and then do something else.

pub const max_align_t = if (builtin.abi == .msvc)
f64
else if (builtin.target.isDarwin())
Expand Down
6 changes: 2 additions & 4 deletions lib/std/c/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,10 @@ pub const ucontext_t = extern struct {
link: ?*ucontext_t,
mcsize: u64,
mcontext: *mcontext_t,
__mcontext_data: mcontext_t,
};

pub const mcontext_t = extern struct {
es: arch_bits.exception_state,
ss: arch_bits.thread_state,
};
pub const mcontext_t = arch_bits.mcontext_t;

extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
Expand Down
13 changes: 13 additions & 0 deletions lib/std/c/darwin/aarch64.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// See C headers in
// lib/libc/include/aarch64-macos.12-gnu/mach/arm/_structs.h
// lib/libc/include/aarch64-macos.13-none/arm/_mcontext.h

pub const mcontext_t = extern struct {
es: exception_state,
ss: thread_state,
ns: neon_state,
};

pub const exception_state = extern struct {
far: u64, // Virtual Fault Address
Expand All @@ -17,6 +24,12 @@ pub const thread_state = extern struct {
__pad: u32,
};

pub const neon_state = extern struct {
q: [32]u128,
fpsr: u32,
fpcr: u32,
};

pub const EXC_TYPES_COUNT = 14;
pub const EXC_MASK_MACHINE = 0;

Expand Down
29 changes: 29 additions & 0 deletions lib/std/c/darwin/x86_64.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
const c = @import("../darwin.zig");

pub const mcontext_t = extern struct {
es: exception_state,
ss: thread_state,
fs: float_state,
};

pub const exception_state = extern struct {
trapno: u16,
cpu: u16,
Expand Down Expand Up @@ -31,6 +37,29 @@ pub const thread_state = extern struct {
gs: u64,
};

const stmm_reg = [16]u8;
const xmm_reg = [16]u8;
pub const float_state = extern struct {
reserved: [2]c_int,
fcw: u16,
fsw: u16,
ftw: u8,
rsrv1: u8,
fop: u16,
ip: u32,
cs: u16,
rsrv2: u16,
dp: u32,
ds: u16,
rsrv3: u16,
mxcsr: u32,
mxcsrmask: u32,
stmm: [8]stmm_reg,
xmm: [16]xmm_reg,
rsrv4: [96]u8,
reserved1: c_int,
};

pub const THREAD_STATE = 4;
pub const THREAD_STATE_COUNT: c.mach_msg_type_number_t = @sizeOf(thread_state) / @sizeOf(c_int);

Expand Down
13 changes: 8 additions & 5 deletions lib/std/coff.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,11 @@ pub const Coff = struct {
return Strtab{ .buffer = self.data[offset..][0..size] };
}

pub fn strtabRequired(self: *const Coff) bool {
kubkon marked this conversation as resolved.
Show resolved Hide resolved
for (self.getSectionHeaders()) |*sect_hdr| if (sect_hdr.getName() == null) return true;
return false;
}

pub fn getSectionHeaders(self: *const Coff) []align(1) const SectionHeader {
const coff_header = self.getCoffHeader();
const offset = self.coff_header_offset + @sizeOf(CoffHeader) + coff_header.size_of_optional_header;
Expand Down Expand Up @@ -1248,14 +1253,12 @@ pub const Coff = struct {
return null;
}

pub fn getSectionData(self: *const Coff, comptime name: []const u8) ![]const u8 {
const sec = self.getSectionByName(name) orelse return error.MissingCoffSection;
pub fn getSectionData(self: *const Coff, sec: *align(1) const SectionHeader) []const u8 {
return self.data[sec.pointer_to_raw_data..][0..sec.virtual_size];
}

// Return an owned slice full of the section data
pub fn getSectionDataAlloc(self: *const Coff, comptime name: []const u8, allocator: mem.Allocator) ![]u8 {
const section_data = try self.getSectionData(name);
pub fn getSectionDataAlloc(self: *const Coff, sec: *align(1) const SectionHeader, allocator: mem.Allocator) ![]u8 {
const section_data = self.getSectionData(sec);
return allocator.dupe(u8, section_data);
}
};
Expand Down