authorgravatar for fabi.theo@gmail.comTheo Fabi <fabi.theo@gmail.com> 2026-07-23 11:54:00-04:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-02 12:03:06+02:00
log833105128485bf84a22f26506eb5e7b9bfa146a0
tree37eee896082b17553e613dbe08b6c8c71d93e984
parent8523ee09ae1f03d93d8029263c7bb7fe0ec282e7

debug.Dwarf: FORM_ref_addr is host address sized in DWARFv2

DW_FORM_ref_addr encoding specification is different in dwarf version 2. parseFormValue() now accepts a `version` argument so that it can parse such attributes correctly based on the version.

1 files changed, 16 insertions(+), 5 deletions(-)

lib/std/debug/Dwarf.zig+16-5
...@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -450,6 +450,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
450 unit_header.format,450 unit_header.format,
451 endian,451 endian,
452 address_size,452 address_size,
453 version,
453 )) orelse continue;454 )) orelse continue;
454455
455 switch (die_obj.tag_id) {456 switch (die_obj.tag_id) {
...@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
485 unit_header.format,486 unit_header.format,
486 endian,487 endian,
487 address_size,488 address_size,
489 version,
488 )) orelse return bad();490 )) orelse return bad();
489 } else if (this_die_obj.getAttr(AT.specification)) |_| {491 } else if (this_die_obj.getAttr(AT.specification)) |_| {
490 const after_die_offset = fr.seek;492 const after_die_offset = fr.seek;
...@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {...@@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
500 unit_header.format,502 unit_header.format,
501 endian,503 endian,
502 address_size,504 address_size,
505 version,
503 )) orelse return bad();506 )) orelse return bad();
504 } else {507 } else {
505 break :x null;508 break :x null;
...@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi...@@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi
611 unit_header.format,614 unit_header.format,
612 endian,615 endian,
613 address_size,616 address_size,
617 version,
614 )) orelse return bad();618 )) orelse return bad();
615619
616 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();620 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
...@@ -931,6 +935,7 @@ fn parseDie(...@@ -931,6 +935,7 @@ fn parseDie(
931 format: Format,935 format: Format,
932 endian: Endian,936 endian: Endian,
933 addr_size_bytes: u8,937 addr_size_bytes: u8,
938 version: u16,
934) ScanError!?Die {939) ScanError!?Die {
935 const abbrev_code = try fr.takeLeb128(u64);940 const abbrev_code = try fr.takeLeb128(u64);
936 if (abbrev_code == 0) return null;941 if (abbrev_code == 0) return null;
...@@ -939,7 +944,7 @@ fn parseDie(...@@ -939,7 +944,7 @@ fn parseDie(
939 const attrs = attrs_buf[0..table_entry.attrs.len];944 const attrs = attrs_buf[0..table_entry.attrs.len];
940 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{945 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{
941 .id = attr.id,946 .id = attr.id,
942 .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload),947 .value = try parseFormValue(fr, attr.form_id, format, endian, addr_size_bytes, attr.payload, version),
943 };948 };
944 return .{949 return .{
945 .tag_id = table_entry.tag_id,950 .tag_id = table_entry.tag_id,
...@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:...@@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
1042 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {1047 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
1043 e.* = .{ .path = &.{} };1048 e.* = .{ .path = &.{} };
1044 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {1049 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
1045 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);1050 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
1046 switch (ent_fmt.content_type_code) {1051 switch (ent_fmt.content_type_code) {
1047 DW.LNCT.path => e.path = try form_value.getString(d.*),1052 DW.LNCT.path => e.path = try form_value.getString(d.*),
1048 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1053 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
...@@ -1074,7 +1079,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:...@@ -1074,7 +1079,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit:
1074 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {1079 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
1075 e.* = .{ .path = &.{} };1080 e.* = .{ .path = &.{} };
1076 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {1081 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
1077 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null);1082 const form_value = try parseFormValue(&fr, ent_fmt.form_code, unit_header.format, endian, addr_size_bytes, null, version);
1078 switch (ent_fmt.content_type_code) {1083 switch (ent_fmt.content_type_code) {
1079 DW.LNCT.path => e.path = try form_value.getString(d.*),1084 DW.LNCT.path => e.path = try form_value.getString(d.*),
1080 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1085 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
...@@ -1285,6 +1290,7 @@ fn parseFormValue(...@@ -1285,6 +1290,7 @@ fn parseFormValue(
1285 endian: Endian,1290 endian: Endian,
1286 addr_size_bytes: u8,1291 addr_size_bytes: u8,
1287 implicit_const: ?i64,1292 implicit_const: ?i64,
1293 version: u16,
1288) ScanError!FormValue {1294) ScanError!FormValue {
1289 return switch (form_id) {1295 return switch (form_id) {
1290 // DWARF5.pdf page 213: the size of this value is encoded in the1296 // DWARF5.pdf page 213: the size of this value is encoded in the
...@@ -1319,7 +1325,12 @@ fn parseFormValue(...@@ -1319,7 +1325,12 @@ fn parseFormValue(
1319 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },1325 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
1320 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },1326 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },
13211327
1322 FORM.ref_addr => .{ .ref_addr = try readFormatSizedInt(r, format, endian) },1328 FORM.ref_addr => .{
1329 .ref_addr = switch (version) {
1330 2 => try readAddress(r, endian, addr_size_bytes),
1331 else => try readFormatSizedInt(r, format, endian),
1332 },
1333 },
1323 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },1334 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
13241335
1325 FORM.string => .{ .string = try r.takeSentinel(0) },1336 FORM.string => .{ .string = try r.takeSentinel(0) },
...@@ -1330,7 +1341,7 @@ fn parseFormValue(...@@ -1330,7 +1341,7 @@ fn parseFormValue(
1330 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },1341 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
1331 FORM.strx => .{ .strx = try r.takeLeb128(usize) },1342 FORM.strx => .{ .strx = try r.takeLeb128(usize) },
1332 FORM.line_strp => .{ .line_strp = try readFormatSizedInt(r, format, endian) },1343 FORM.line_strp => .{ .line_strp = try readFormatSizedInt(r, format, endian) },
1333 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const),1344 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, addr_size_bytes, implicit_const, version),
1334 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },1345 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
1335 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },1346 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
1336 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },1347 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },