authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-23 21:09:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-23 21:11:02-07:00
log60722261fa465ecff559c9903e0855d538826ed4
tree682e4e4fac54183af02fb8286da2cb13c5d6f91a
parent0f01e812ff054ea83661272bf0a96af228f2ffe3

std.debug: DWARFv5 fixes

handle str_offsets_base and addr_base correctly. handle data16 fix compilation on 32-bit hosts remove stray debug print statement closes #12120

3 files changed, 126 insertions(+), 120 deletions(-)

lib/std/debug.zig+12-11
...@@ -837,12 +837,12 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo...@@ -837,12 +837,12 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
837 // This coff file has embedded DWARF debug info837 // This coff file has embedded DWARF debug info
838 _ = sec;838 _ = sec;
839 // TODO: free the section data slices839 // TODO: free the section data slices
840 const debug_info_data = di.coff.getSectionDataAlloc(".debug_info", allocator) catch null;840 const debug_info = di.coff.getSectionDataAlloc(".debug_info", allocator) catch null;
841 const debug_abbrev_data = di.coff.getSectionDataAlloc(".debug_abbrev", allocator) catch null;841 const debug_abbrev = di.coff.getSectionDataAlloc(".debug_abbrev", allocator) catch null;
842 const debug_str_data = di.coff.getSectionDataAlloc(".debug_str", allocator) catch null;842 const debug_str = di.coff.getSectionDataAlloc(".debug_str", allocator) catch null;
843 const debug_str_offsets = di.coff.getSectionDataAlloc(".debug_str_offsets", allocator) catch null;843 const debug_str_offsets = di.coff.getSectionDataAlloc(".debug_str_offsets", allocator) catch null;
844 const debug_line_data = di.coff.getSectionDataAlloc(".debug_line", allocator) catch null;844 const debug_line = di.coff.getSectionDataAlloc(".debug_line", allocator) catch null;
845 const debug_line_str_data = di.coff.getSectionDataAlloc(".debug_line_str", allocator) catch null;845 const debug_line_str = di.coff.getSectionDataAlloc(".debug_line_str", allocator) catch null;
846 const debug_ranges = di.coff.getSectionDataAlloc(".debug_ranges", allocator) catch null;846 const debug_ranges = di.coff.getSectionDataAlloc(".debug_ranges", allocator) catch null;
847 const debug_loclists = di.coff.getSectionDataAlloc(".debug_loclists", allocator) catch null;847 const debug_loclists = di.coff.getSectionDataAlloc(".debug_loclists", allocator) catch null;
848 const debug_rnglists = di.coff.getSectionDataAlloc(".debug_rnglists", allocator) catch null;848 const debug_rnglists = di.coff.getSectionDataAlloc(".debug_rnglists", allocator) catch null;
...@@ -852,12 +852,12 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo...@@ -852,12 +852,12 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
852852
853 var dwarf = DW.DwarfInfo{853 var dwarf = DW.DwarfInfo{
854 .endian = native_endian,854 .endian = native_endian,
855 .debug_info = debug_info_data orelse return error.MissingDebugInfo,855 .debug_info = debug_info orelse return error.MissingDebugInfo,
856 .debug_abbrev = debug_abbrev_data orelse return error.MissingDebugInfo,856 .debug_abbrev = debug_abbrev orelse return error.MissingDebugInfo,
857 .debug_str = debug_str_data orelse return error.MissingDebugInfo,857 .debug_str = debug_str orelse return error.MissingDebugInfo,
858 .debug_str_offsets = debug_str_offsets,858 .debug_str_offsets = debug_str_offsets,
859 .debug_line = debug_line_data orelse return error.MissingDebugInfo,859 .debug_line = debug_line orelse return error.MissingDebugInfo,
860 .debug_line_str = debug_line_str_data,860 .debug_line_str = debug_line_str,
861 .debug_ranges = debug_ranges,861 .debug_ranges = debug_ranges,
862 .debug_loclists = debug_loclists,862 .debug_loclists = debug_loclists,
863 .debug_rnglists = debug_rnglists,863 .debug_rnglists = debug_rnglists,
...@@ -1663,6 +1663,7 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -1663,6 +1663,7 @@ pub const ModuleDebugInfo = switch (native_os) {
1663 o_file_di,1663 o_file_di,
1664 DW.AT.name,1664 DW.AT.name,
1665 o_file_di.debug_str,1665 o_file_di.debug_str,
1666 compile_unit.*,
1666 ) catch |err| switch (err) {1667 ) catch |err| switch (err) {
1667 error.MissingDebugInfo, error.InvalidDebugInfo => "???",1668 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
1668 },1669 },
...@@ -1784,7 +1785,7 @@ fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo)...@@ -1784,7 +1785,7 @@ fn getSymbolFromDwarf(allocator: mem.Allocator, address: u64, di: *DW.DwarfInfo)
1784 if (nosuspend di.findCompileUnit(address)) |compile_unit| {1785 if (nosuspend di.findCompileUnit(address)) |compile_unit| {
1785 return SymbolInfo{1786 return SymbolInfo{
1786 .symbol_name = nosuspend di.getSymbolName(address) orelse "???",1787 .symbol_name = nosuspend di.getSymbolName(address) orelse "???",
1787 .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name, di.debug_str) catch |err| switch (err) {1788 .compile_unit_name = compile_unit.die.getAttrString(di, DW.AT.name, di.debug_str, compile_unit.*) catch |err| switch (err) {
1788 error.MissingDebugInfo, error.InvalidDebugInfo => "???",1789 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
1789 },1790 },
1790 .line_info = nosuspend di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) {1791 .line_info = nosuspend di.getLineNumberInfo(allocator, compile_unit.*, address) catch |err| switch (err) {
lib/std/dwarf.zig+112-107
...@@ -168,6 +168,11 @@ const CompileUnit = struct {...@@ -168,6 +168,11 @@ const CompileUnit = struct {
168 is_64: bool,168 is_64: bool,
169 die: *Die,169 die: *Die,
170 pc_range: ?PcRange,170 pc_range: ?PcRange,
171
172 str_offsets_base: usize,
173 addr_base: usize,
174 rnglists_base: usize,
175 loclists_base: usize,
171};176};
172177
173const AbbrevTable = std.ArrayList(AbbrevTableEntry);178const AbbrevTable = std.ArrayList(AbbrevTableEntry);
...@@ -205,7 +210,7 @@ const AbbrevAttr = struct {...@@ -205,7 +210,7 @@ const AbbrevAttr = struct {
205210
206const FormValue = union(enum) {211const FormValue = union(enum) {
207 Address: u64,212 Address: u64,
208 AddrOffset: u64,213 AddrOffset: usize,
209 Block: []u8,214 Block: []u8,
210 Const: Constant,215 Const: Constant,
211 ExprLoc: []u8,216 ExprLoc: []u8,
...@@ -215,10 +220,11 @@ const FormValue = union(enum) {...@@ -215,10 +220,11 @@ const FormValue = union(enum) {
215 RefAddr: u64,220 RefAddr: u64,
216 String: []const u8,221 String: []const u8,
217 StrPtr: u64,222 StrPtr: u64,
218 StrOffset: u64,223 StrOffset: usize,
219 LineStrPtr: u64,224 LineStrPtr: u64,
220 LocListOffset: u64,225 LocListOffset: u64,
221 RangeListOffset: u64,226 RangeListOffset: u64,
227 data16: [16]u8,
222228
223 fn getString(fv: FormValue, di: DwarfInfo) ![]const u8 {229 fn getString(fv: FormValue, di: DwarfInfo) ![]const u8 {
224 switch (fv) {230 switch (fv) {
...@@ -235,6 +241,14 @@ const FormValue = union(enum) {...@@ -235,6 +241,14 @@ const FormValue = union(enum) {
235 const int = try c.asUnsignedLe();241 const int = try c.asUnsignedLe();
236 return math.cast(U, int) orelse return badDwarf();242 return math.cast(U, int) orelse return badDwarf();
237 },243 },
244 .SecOffset => |x| return math.cast(U, x) orelse return badDwarf(),
245 else => return badDwarf(),
246 }
247 }
248
249 fn getData16(fv: FormValue) ![16]u8 {
250 switch (fv) {
251 .data16 => |d| return d,
238 else => return badDwarf(),252 else => return badDwarf(),
239 }253 }
240 }254 }
...@@ -274,42 +288,30 @@ const Die = struct {...@@ -274,42 +288,30 @@ const Die = struct {
274 return null;288 return null;
275 }289 }
276290
277 fn getAttrAddr(self: *const Die, di: *DwarfInfo, id: u64) error{ InvalidDebugInfo, MissingDebugInfo }!u64 {291 fn getAttrAddr(
278 const form_value = self.getAttr(id) orelse return missingDwarf();292 self: *const Die,
293 di: *DwarfInfo,
294 id: u64,
295 compile_unit: CompileUnit,
296 ) error{ InvalidDebugInfo, MissingDebugInfo }!u64 {
297 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
279 return switch (form_value.*) {298 return switch (form_value.*) {
280 FormValue.Address => |value| value,299 FormValue.Address => |value| value,
281 FormValue.AddrOffset => |index| {300 FormValue.AddrOffset => |index| {
282 const debug_addr = di.debug_addr orelse return badDwarf();301 const debug_addr = di.debug_addr orelse return badDwarf();
283 if (debug_addr.len < 8) return badDwarf();302 // addr_base points to the first item after the header, however we
284 const first_32_bits = mem.readInt(u32, debug_addr[0..4], di.endian);303 // need to read the header to know the size of each item. Empirically,
285 const is_64 = first_32_bits == 0xffffffff;304 // it may disagree with is_64 on the compile unit.
286 var off: usize = undefined;305 // The header is 8 or 12 bytes depending on is_64.
287 const length: u64 = l: {306 if (compile_unit.addr_base < 8) return badDwarf();
288 if (is_64) {
289 if (debug_addr.len < 16) return badDwarf();
290 off = 12;
291 break :l mem.readInt(u64, debug_addr[4..12], di.endian);
292 } else {
293 if (debug_addr.len < 8) return badDwarf();
294 if (first_32_bits >= 0xfffffff0) return badDwarf();
295 off = 4;
296 break :l first_32_bits;
297 }
298 };
299 if (index > length) return badDwarf();
300
301 const version = mem.readInt(u16, debug_addr[off..][0..2], di.endian);
302 off += 2;
303 if (version < 5) return badDwarf();
304307
305 const addr_size = debug_addr[off];308 const version = mem.readInt(u16, debug_addr[compile_unit.addr_base - 4 ..][0..2], di.endian);
306 off += 1;309 if (version != 5) return badDwarf();
307310
308 const seg_size = debug_addr[off];311 const addr_size = debug_addr[compile_unit.addr_base - 2];
309 off += 1;312 const seg_size = debug_addr[compile_unit.addr_base - 1];
310313
311 const base_offset = self.getAttrSecOffset(AT.addr_base) catch off;314 const byte_offset = compile_unit.addr_base + (addr_size + seg_size) * index;
312 const byte_offset = base_offset + (addr_size + seg_size) * index;
313 if (byte_offset + addr_size > debug_addr.len) return badDwarf();315 if (byte_offset + addr_size > debug_addr.len) return badDwarf();
314 switch (addr_size) {316 switch (addr_size) {
315 1 => return debug_addr[byte_offset],317 1 => return debug_addr[byte_offset],
...@@ -324,16 +326,12 @@ const Die = struct {...@@ -324,16 +326,12 @@ const Die = struct {
324 }326 }
325327
326 fn getAttrSecOffset(self: *const Die, id: u64) !u64 {328 fn getAttrSecOffset(self: *const Die, id: u64) !u64 {
327 const form_value = self.getAttr(id) orelse return missingDwarf();329 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
328 return switch (form_value.*) {330 return form_value.getUInt(u64);
329 FormValue.Const => |value| value.asUnsignedLe(),
330 FormValue.SecOffset => |value| value,
331 else => error.InvalidDebugInfo,
332 };
333 }331 }
334332
335 fn getAttrUnsignedLe(self: *const Die, id: u64) !u64 {333 fn getAttrUnsignedLe(self: *const Die, id: u64) !u64 {
336 const form_value = self.getAttr(id) orelse return missingDwarf();334 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
337 return switch (form_value.*) {335 return switch (form_value.*) {
338 FormValue.Const => |value| value.asUnsignedLe(),336 FormValue.Const => |value| value.asUnsignedLe(),
339 else => error.InvalidDebugInfo,337 else => error.InvalidDebugInfo,
...@@ -341,51 +339,35 @@ const Die = struct {...@@ -341,51 +339,35 @@ const Die = struct {
341 }339 }
342340
343 fn getAttrRef(self: *const Die, id: u64) !u64 {341 fn getAttrRef(self: *const Die, id: u64) !u64 {
344 const form_value = self.getAttr(id) orelse return missingDwarf();342 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
345 return switch (form_value.*) {343 return switch (form_value.*) {
346 FormValue.Ref => |value| value,344 FormValue.Ref => |value| value,
347 else => error.InvalidDebugInfo,345 else => error.InvalidDebugInfo,
348 };346 };
349 }347 }
350348
351 pub fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64, opt_str: ?[]const u8) error{ InvalidDebugInfo, MissingDebugInfo }![]const u8 {349 pub fn getAttrString(
352 const form_value = self.getAttr(id) orelse return missingDwarf();350 self: *const Die,
351 di: *DwarfInfo,
352 id: u64,
353 opt_str: ?[]const u8,
354 compile_unit: CompileUnit,
355 ) error{ InvalidDebugInfo, MissingDebugInfo }![]const u8 {
356 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
353 switch (form_value.*) {357 switch (form_value.*) {
354 FormValue.String => |value| return value,358 FormValue.String => |value| return value,
355 FormValue.StrPtr => |offset| return di.getString(offset),359 FormValue.StrPtr => |offset| return di.getString(offset),
356 FormValue.StrOffset => |index| {360 FormValue.StrOffset => |index| {
357 const debug_str_offsets = di.debug_str_offsets orelse return badDwarf();361 const debug_str_offsets = di.debug_str_offsets orelse return badDwarf();
358 if (debug_str_offsets.len < 8) return badDwarf();362 if (compile_unit.str_offsets_base == 0) return badDwarf();
359 const first_32_bits = mem.readInt(u32, debug_str_offsets[0..4], di.endian);363 if (compile_unit.is_64) {
360 const is_64 = first_32_bits == 0xffffffff;364 const byte_offset = compile_unit.str_offsets_base + 8 * index;
361 var off: usize = undefined;365 if (byte_offset + 8 > debug_str_offsets.len) return badDwarf();
362 const length: u64 = l: {
363 if (is_64) {
364 if (debug_str_offsets.len < 16) return badDwarf();
365 off = 12;
366 break :l mem.readInt(u64, debug_str_offsets[4..12], di.endian);
367 } else {
368 if (debug_str_offsets.len < 8) return badDwarf();
369 if (first_32_bits >= 0xfffffff0) return badDwarf();
370 off = 4;
371 break :l first_32_bits;
372 }
373 };
374 if (index > length) return badDwarf();
375
376 const version = mem.readInt(u16, debug_str_offsets[off..][0..2], di.endian);
377 off += 2;
378 if (version < 5) return badDwarf();
379
380 off += 2; // reserved
381
382 const base_offset = self.getAttrSecOffset(AT.str_offsets_base) catch off;
383 if (is_64) {
384 const byte_offset = base_offset + 8 * index;
385 const offset = mem.readInt(u64, debug_str_offsets[byte_offset..][0..8], di.endian);366 const offset = mem.readInt(u64, debug_str_offsets[byte_offset..][0..8], di.endian);
386 return getStringGeneric(opt_str, offset);367 return getStringGeneric(opt_str, offset);
387 } else {368 } else {
388 const byte_offset = base_offset + 4 * index;369 const byte_offset = compile_unit.str_offsets_base + 4 * index;
370 if (byte_offset + 4 > debug_str_offsets.len) return badDwarf();
389 const offset = mem.readInt(u32, debug_str_offsets[byte_offset..][0..4], di.endian);371 const offset = mem.readInt(u32, debug_str_offsets[byte_offset..][0..4], di.endian);
390 return getStringGeneric(opt_str, offset);372 return getStringGeneric(opt_str, offset);
391 }373 }
...@@ -401,7 +383,7 @@ const FileEntry = struct {...@@ -401,7 +383,7 @@ const FileEntry = struct {
401 dir_index: u32 = 0,383 dir_index: u32 = 0,
402 mtime: u64 = 0,384 mtime: u64 = 0,
403 size: u64 = 0,385 size: u64 = 0,
404 md5: u128 = 0,386 md5: [16]u8 = [1]u8{0} ** 16,
405};387};
406388
407const LineNumberProgram = struct {389const LineNumberProgram = struct {
...@@ -606,7 +588,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en...@@ -606,7 +588,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en
606 FORM.addrx2 => return FormValue{ .AddrOffset = try in_stream.readInt(u16, endian) },588 FORM.addrx2 => return FormValue{ .AddrOffset = try in_stream.readInt(u16, endian) },
607 FORM.addrx3 => return FormValue{ .AddrOffset = try in_stream.readInt(u24, endian) },589 FORM.addrx3 => return FormValue{ .AddrOffset = try in_stream.readInt(u24, endian) },
608 FORM.addrx4 => return FormValue{ .AddrOffset = try in_stream.readInt(u32, endian) },590 FORM.addrx4 => return FormValue{ .AddrOffset = try in_stream.readInt(u32, endian) },
609 FORM.addrx => return FormValue{ .AddrOffset = try nosuspend leb.readULEB128(u64, in_stream) },591 FORM.addrx => return FormValue{ .AddrOffset = try nosuspend leb.readULEB128(usize, in_stream) },
610592
611 FORM.block1 => parseFormValueBlock(allocator, in_stream, endian, 1),593 FORM.block1 => parseFormValueBlock(allocator, in_stream, endian, 1),
612 FORM.block2 => parseFormValueBlock(allocator, in_stream, endian, 2),594 FORM.block2 => parseFormValueBlock(allocator, in_stream, endian, 2),
...@@ -619,6 +601,11 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en...@@ -619,6 +601,11 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en
619 FORM.data2 => parseFormValueConstant(in_stream, false, endian, 2),601 FORM.data2 => parseFormValueConstant(in_stream, false, endian, 2),
620 FORM.data4 => parseFormValueConstant(in_stream, false, endian, 4),602 FORM.data4 => parseFormValueConstant(in_stream, false, endian, 4),
621 FORM.data8 => parseFormValueConstant(in_stream, false, endian, 8),603 FORM.data8 => parseFormValueConstant(in_stream, false, endian, 8),
604 FORM.data16 => {
605 var buf: [16]u8 = undefined;
606 if ((try nosuspend in_stream.readAll(&buf)) < 16) return error.EndOfFile;
607 return FormValue{ .data16 = buf };
608 },
622 FORM.udata, FORM.sdata => {609 FORM.udata, FORM.sdata => {
623 const signed = form_id == FORM.sdata;610 const signed = form_id == FORM.sdata;
624 return parseFormValueConstant(in_stream, signed, endian, -1);611 return parseFormValueConstant(in_stream, signed, endian, -1);
...@@ -647,7 +634,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en...@@ -647,7 +634,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en
647 FORM.strx2 => return FormValue{ .StrOffset = try in_stream.readInt(u16, endian) },634 FORM.strx2 => return FormValue{ .StrOffset = try in_stream.readInt(u16, endian) },
648 FORM.strx3 => return FormValue{ .StrOffset = try in_stream.readInt(u24, endian) },635 FORM.strx3 => return FormValue{ .StrOffset = try in_stream.readInt(u24, endian) },
649 FORM.strx4 => return FormValue{ .StrOffset = try in_stream.readInt(u32, endian) },636 FORM.strx4 => return FormValue{ .StrOffset = try in_stream.readInt(u32, endian) },
650 FORM.strx => return FormValue{ .StrOffset = try nosuspend leb.readULEB128(u64, in_stream) },637 FORM.strx => return FormValue{ .StrOffset = try nosuspend leb.readULEB128(usize, in_stream) },
651 FORM.line_strp => FormValue{ .LineStrPtr = try readAddress(in_stream, endian, is_64) },638 FORM.line_strp => FormValue{ .LineStrPtr = try readAddress(in_stream, endian, is_64) },
652 FORM.indirect => {639 FORM.indirect => {
653 const child_form_id = try nosuspend leb.readULEB128(u64, in_stream);640 const child_form_id = try nosuspend leb.readULEB128(u64, in_stream);
...@@ -663,7 +650,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en...@@ -663,7 +650,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en
663 FORM.loclistx => return FormValue{ .LocListOffset = try nosuspend leb.readULEB128(u64, in_stream) },650 FORM.loclistx => return FormValue{ .LocListOffset = try nosuspend leb.readULEB128(u64, in_stream) },
664 FORM.rnglistx => return FormValue{ .RangeListOffset = try nosuspend leb.readULEB128(u64, in_stream) },651 FORM.rnglistx => return FormValue{ .RangeListOffset = try nosuspend leb.readULEB128(u64, in_stream) },
665 else => {652 else => {
666 std.debug.print("unrecognized form id: {x}\n", .{form_id});653 //std.debug.print("unrecognized form id: {x}\n", .{form_id});
667 return badDwarf();654 return badDwarf();
668 },655 },
669 };656 };
...@@ -771,11 +758,26 @@ pub const DwarfInfo = struct {...@@ -771,11 +758,26 @@ pub const DwarfInfo = struct {
771758
772 const next_unit_pos = this_unit_offset + next_offset;759 const next_unit_pos = this_unit_offset + next_offset;
773760
761 var compile_unit: CompileUnit = undefined;
762
774 while ((try seekable.getPos()) < next_unit_pos) {763 while ((try seekable.getPos()) < next_unit_pos) {
775 const die_obj = (try di.parseDie(arena, in, abbrev_table, is_64)) orelse continue;764 var die_obj = (try di.parseDie(arena, in, abbrev_table, is_64)) orelse continue;
776 const after_die_offset = try seekable.getPos();765 const after_die_offset = try seekable.getPos();
777766
778 switch (die_obj.tag_id) {767 switch (die_obj.tag_id) {
768 TAG.compile_unit => {
769 compile_unit = .{
770 .version = version,
771 .is_64 = is_64,
772 .die = &die_obj,
773 .pc_range = null,
774
775 .str_offsets_base = if (die_obj.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,
776 .addr_base = if (die_obj.getAttr(AT.addr_base)) |fv| try fv.getUInt(usize) else 0,
777 .rnglists_base = if (die_obj.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0,
778 .loclists_base = if (die_obj.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0,
779 };
780 },
779 TAG.subprogram, TAG.inlined_subroutine, TAG.subroutine, TAG.entry_point => {781 TAG.subprogram, TAG.inlined_subroutine, TAG.subroutine, TAG.entry_point => {
780 const fn_name = x: {782 const fn_name = x: {
781 var depth: i32 = 3;783 var depth: i32 = 3;
...@@ -783,7 +785,7 @@ pub const DwarfInfo = struct {...@@ -783,7 +785,7 @@ pub const DwarfInfo = struct {
783 // Prevent endless loops785 // Prevent endless loops
784 while (depth > 0) : (depth -= 1) {786 while (depth > 0) : (depth -= 1) {
785 if (this_die_obj.getAttr(AT.name)) |_| {787 if (this_die_obj.getAttr(AT.name)) |_| {
786 const name = try this_die_obj.getAttrString(di, AT.name, di.debug_str);788 const name = try this_die_obj.getAttrString(di, AT.name, di.debug_str, compile_unit);
787 break :x try allocator.dupe(u8, name);789 break :x try allocator.dupe(u8, name);
788 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {790 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {
789 // Follow the DIE it points to and repeat791 // Follow the DIE it points to and repeat
...@@ -816,7 +818,7 @@ pub const DwarfInfo = struct {...@@ -816,7 +818,7 @@ pub const DwarfInfo = struct {
816 };818 };
817819
818 const pc_range = x: {820 const pc_range = x: {
819 if (die_obj.getAttrAddr(di, AT.low_pc)) |low_pc| {821 if (die_obj.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| {
820 if (die_obj.getAttr(AT.high_pc)) |high_pc_value| {822 if (die_obj.getAttr(AT.high_pc)) |high_pc_value| {
821 const pc_end = switch (high_pc_value.*) {823 const pc_end = switch (high_pc_value.*) {
822 FormValue.Address => |value| value,824 FormValue.Address => |value| value,
...@@ -873,23 +875,20 @@ pub const DwarfInfo = struct {...@@ -873,23 +875,20 @@ pub const DwarfInfo = struct {
873875
874 var address_size: u8 = undefined;876 var address_size: u8 = undefined;
875 var debug_abbrev_offset: u64 = undefined;877 var debug_abbrev_offset: u64 = undefined;
876 switch (version) {878 if (version >= 5) {
877 5 => {879 const unit_type = try in.readInt(u8, di.endian);
878 const unit_type = try in.readInt(u8, di.endian);880 if (unit_type != UT.compile) return badDwarf();
879 if (unit_type != UT.compile) return badDwarf();881 address_size = try in.readByte();
880 address_size = try in.readByte();882 debug_abbrev_offset = if (is_64)
881 debug_abbrev_offset = if (is_64)883 try in.readInt(u64, di.endian)
882 try in.readInt(u64, di.endian)884 else
883 else885 try in.readInt(u32, di.endian);
884 try in.readInt(u32, di.endian);886 } else {
885 },887 debug_abbrev_offset = if (is_64)
886 else => {888 try in.readInt(u64, di.endian)
887 debug_abbrev_offset = if (is_64)889 else
888 try in.readInt(u64, di.endian)890 try in.readInt(u32, di.endian);
889 else891 address_size = try in.readByte();
890 try in.readInt(u32, di.endian);
891 address_size = try in.readByte();
892 },
893 }892 }
894 if (address_size != @sizeOf(usize)) return badDwarf();893 if (address_size != @sizeOf(usize)) return badDwarf();
895894
...@@ -905,8 +904,19 @@ pub const DwarfInfo = struct {...@@ -905,8 +904,19 @@ pub const DwarfInfo = struct {
905904
906 if (compile_unit_die.tag_id != TAG.compile_unit) return badDwarf();905 if (compile_unit_die.tag_id != TAG.compile_unit) return badDwarf();
907906
908 const pc_range = x: {907 var compile_unit: CompileUnit = .{
909 if (compile_unit_die.getAttrAddr(di, AT.low_pc)) |low_pc| {908 .version = version,
909 .is_64 = is_64,
910 .pc_range = null,
911 .die = compile_unit_die,
912 .str_offsets_base = if (compile_unit_die.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,
913 .addr_base = if (compile_unit_die.getAttr(AT.addr_base)) |fv| try fv.getUInt(usize) else 0,
914 .rnglists_base = if (compile_unit_die.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0,
915 .loclists_base = if (compile_unit_die.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0,
916 };
917
918 compile_unit.pc_range = x: {
919 if (compile_unit_die.getAttrAddr(di, AT.low_pc, compile_unit)) |low_pc| {
910 if (compile_unit_die.getAttr(AT.high_pc)) |high_pc_value| {920 if (compile_unit_die.getAttr(AT.high_pc)) |high_pc_value| {
911 const pc_end = switch (high_pc_value.*) {921 const pc_end = switch (high_pc_value.*) {
912 FormValue.Address => |value| value,922 FormValue.Address => |value| value,
...@@ -929,12 +939,7 @@ pub const DwarfInfo = struct {...@@ -929,12 +939,7 @@ pub const DwarfInfo = struct {
929 }939 }
930 };940 };
931941
932 try di.compile_unit_list.append(allocator, CompileUnit{942 try di.compile_unit_list.append(allocator, compile_unit);
933 .version = version,
934 .is_64 = is_64,
935 .pc_range = pc_range,
936 .die = compile_unit_die,
937 });
938943
939 this_unit_offset += next_offset;944 this_unit_offset += next_offset;
940 }945 }
...@@ -955,7 +960,7 @@ pub const DwarfInfo = struct {...@@ -955,7 +960,7 @@ pub const DwarfInfo = struct {
955 // specified by DW_AT.low_pc or to some other value encoded960 // specified by DW_AT.low_pc or to some other value encoded
956 // in the list itself.961 // in the list itself.
957 // If no starting value is specified use zero.962 // If no starting value is specified use zero.
958 var base_address = compile_unit.die.getAttrAddr(di, AT.low_pc) catch |err| switch (err) {963 var base_address = compile_unit.die.getAttrAddr(di, AT.low_pc, compile_unit.*) catch |err| switch (err) {
959 error.MissingDebugInfo => @as(u64, 0), // TODO https://github.com/ziglang/zig/issues/11135964 error.MissingDebugInfo => @as(u64, 0), // TODO https://github.com/ziglang/zig/issues/11135
960 else => return err,965 else => return err,
961 };966 };
...@@ -1087,7 +1092,7 @@ pub const DwarfInfo = struct {...@@ -1087,7 +1092,7 @@ pub const DwarfInfo = struct {
1087 const in = &stream.reader();1092 const in = &stream.reader();
1088 const seekable = &stream.seekableStream();1093 const seekable = &stream.seekableStream();
10891094
1090 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.debug_line_str);1095 const compile_unit_cwd = try compile_unit.die.getAttrString(di, AT.comp_dir, di.debug_line_str, compile_unit);
1091 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);1096 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);
10921097
1093 try seekable.seekTo(line_info_offset);1098 try seekable.seekTo(line_info_offset);
...@@ -1202,7 +1207,7 @@ pub const DwarfInfo = struct {...@@ -1202,7 +1207,7 @@ pub const DwarfInfo = struct {
1202 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1207 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
1203 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),1208 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),
1204 LNCT.size => e.size = try form_value.getUInt(u64),1209 LNCT.size => e.size = try form_value.getUInt(u64),
1205 LNCT.MD5 => e.md5 = try form_value.getUInt(u128),1210 LNCT.MD5 => e.md5 = try form_value.getData16(),
1206 else => continue,1211 else => continue,
1207 }1212 }
1208 }1213 }
...@@ -1240,7 +1245,7 @@ pub const DwarfInfo = struct {...@@ -1240,7 +1245,7 @@ pub const DwarfInfo = struct {
1240 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1245 LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
1241 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),1246 LNCT.timestamp => e.mtime = try form_value.getUInt(u64),
1242 LNCT.size => e.size = try form_value.getUInt(u64),1247 LNCT.size => e.size = try form_value.getUInt(u64),
1243 LNCT.MD5 => e.md5 = try form_value.getUInt(u128),1248 LNCT.MD5 => e.md5 = try form_value.getData16(),
1244 else => continue,1249 else => continue,
1245 }1250 }
1246 }1251 }
...@@ -1370,12 +1375,12 @@ pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: mem.Allocator) !void {...@@ -1370,12 +1375,12 @@ pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: mem.Allocator) !void {
13701375
1371/// This function is to make it handy to comment out the return and make it1376/// This function is to make it handy to comment out the return and make it
1372/// into a crash when working on this file.1377/// into a crash when working on this file.
1373inline fn badDwarf() error{InvalidDebugInfo} {1378fn badDwarf() error{InvalidDebugInfo} {
1374 //std.os.abort(); // can be handy to uncomment when working on this file1379 //std.os.abort(); // can be handy to uncomment when working on this file
1375 return error.InvalidDebugInfo;1380 return error.InvalidDebugInfo;
1376}1381}
13771382
1378inline fn missingDwarf() error{MissingDebugInfo} {1383fn missingDwarf() error{MissingDebugInfo} {
1379 //std.os.abort(); // can be handy to uncomment when working on this file1384 //std.os.abort(); // can be handy to uncomment when working on this file
1380 return error.MissingDebugInfo;1385 return error.MissingDebugInfo;
1381}1386}
src/link/MachO.zig+2-2
...@@ -5862,8 +5862,8 @@ pub fn generateSymbolStabs(...@@ -5862,8 +5862,8 @@ pub fn generateSymbolStabs(
5862 else => |e| return e,5862 else => |e| return e,
5863 };5863 };
58645864
5865 const tu_name = try compile_unit.die.getAttrString(&debug_info, dwarf.AT.name, debug_info.debug_str);5865 const tu_name = try compile_unit.die.getAttrString(&debug_info, dwarf.AT.name, debug_info.debug_str, compile_unit.*);
5866 const tu_comp_dir = try compile_unit.die.getAttrString(&debug_info, dwarf.AT.comp_dir, debug_info.debug_str);5866 const tu_comp_dir = try compile_unit.die.getAttrString(&debug_info, dwarf.AT.comp_dir, debug_info.debug_str, compile_unit.*);
58675867
5868 // Open scope5868 // Open scope
5869 try locals.ensureUnusedCapacity(3);5869 try locals.ensureUnusedCapacity(3);