aboutsummaryrefslogtreecommitdiff
path: root/lib/std/debug/Dwarf.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2024-08-28 05:58:10 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2024-08-28 06:45:17 -0400
commit12275cf4b9a1e02e08aef8e1b29e5accb16268f1 (patch)
treed9503440a86820f10be7415140ba3bfff53cc87b /lib/std/debug/Dwarf.zig
parent4cc16fd6f7ac22e32ff4e42b61ad1bb7157d282f (diff)
downloadzig-12275cf4b9a1e02e08aef8e1b29e5accb16268f1.tar.gz
zig-12275cf4b9a1e02e08aef8e1b29e5accb16268f1.zip
Dwarf: fix parsing self-hosted debug info for stack traces
Diffstat (limited to 'lib/std/debug/Dwarf.zig')
-rw-r--r--lib/std/debug/Dwarf.zig27
1 files changed, 13 insertions, 14 deletions
diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig
index 7cce30df38..21d60214dd 100644
--- a/lib/std/debug/Dwarf.zig
+++ b/lib/std/debug/Dwarf.zig
@@ -279,10 +279,11 @@ pub const Die = struct {
};
}
- fn getAttrRef(self: *const Die, id: u64) !u64 {
+ fn getAttrRef(self: *const Die, id: u64, unit_offset: u64, unit_len: u64) !u64 {
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
return switch (form_value.*) {
- .ref => |value| value,
+ .ref => |offset| if (offset < unit_len) unit_offset + offset else bad(),
+ .ref_addr => |addr| addr,
else => bad(),
};
}
@@ -428,14 +429,14 @@ pub const ExceptionFrameHeader = struct {
};
const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame);
- if (!self.isValidPtr(u8, @intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
+ if (fde_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
if (fde_entry_header.type != .fde) return bad();
// CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable
const cie_offset = fde_entry_header.type.fde;
try eh_frame_fbr.seekTo(cie_offset);
const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame);
- if (!self.isValidPtr(u8, @intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
+ if (cie_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
if (cie_entry_header.type != .cie) return bad();
cie.* = try CommonInformationEntry.parse(
@@ -942,13 +943,12 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
defer fbr.pos = after_die_offset;
// Follow the DIE it points to and repeat
- const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin);
- if (ref_offset > next_offset) return bad();
- try fbr.seekTo(this_unit_offset + ref_offset);
+ const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin, this_unit_offset, next_offset);
+ try fbr.seekTo(ref_offset);
this_die_obj = (try parseDie(
&fbr,
attrs_bufs[2],
- abbrev_table,
+ abbrev_table, // wrong abbrev table for different cu
unit_header.format,
)) orelse return bad();
} else if (this_die_obj.getAttr(AT.specification)) |_| {
@@ -956,13 +956,12 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
defer fbr.pos = after_die_offset;
// Follow the DIE it points to and repeat
- const ref_offset = try this_die_obj.getAttrRef(AT.specification);
- if (ref_offset > next_offset) return bad();
- try fbr.seekTo(this_unit_offset + ref_offset);
+ const ref_offset = try this_die_obj.getAttrRef(AT.specification, this_unit_offset, next_offset);
+ try fbr.seekTo(ref_offset);
this_die_obj = (try parseDie(
&fbr,
attrs_bufs[2],
- abbrev_table,
+ abbrev_table, // wrong abbrev table for different cu
unit_header.format,
)) orelse return bad();
} else {
@@ -1494,7 +1493,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
}
} else {
const FileEntFmt = struct {
- content_type_code: u8,
+ content_type_code: u16,
form_code: u16,
};
{
@@ -1539,7 +1538,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad();
for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {
ent_fmt.* = .{
- .content_type_code = try fbr.readUleb128(u8),
+ .content_type_code = try fbr.readUleb128(u16),
.form_code = try fbr.readUleb128(u16),
};
}