From 6de8b4bc3d105c15cd473c5bf100db4c9328dd54 Mon Sep 17 00:00:00 2001 From: William Sengir Date: Tue, 15 Mar 2022 02:07:46 -0700 Subject: [PATCH] std.dwarf: implement basic DWARF 5 parsing DWARF 5 moves around some fields and adds a few new ones that can't be parsed or ignored by our current DWARF 4 parser. This isn't a complete implementation of DWARF 5, but this is enough to make stack traces mostly work. Line numbers from C++ don't show up, but I know the info is there. I think the answer is to iterate through .debug_line_str in getLineNumberInfo, but I didn't want to fall into an even deeper rabbit hole tonight. --- lib/std/debug.zig | 13 +++ lib/std/dwarf.zig | 213 ++++++++++++++++---------------------- lib/std/dwarf/AT.zig | 28 +++++ lib/std/dwarf/ATE.zig | 46 ++++++++ lib/std/dwarf/FORM.zig | 52 ++++++++++ lib/std/dwarf/LANG.zig | 48 +++++++++ lib/std/dwarf/OP.zig | 12 +++ lib/std/dwarf/TAG.zig | 10 ++ src/link/MachO/Object.zig | 13 +++ 9 files changed, 309 insertions(+), 126 deletions(-) create mode 100644 lib/std/dwarf/ATE.zig create mode 100644 lib/std/dwarf/FORM.zig create mode 100644 lib/std/dwarf/LANG.zig diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 3d06c16d57..9b02d418c5 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -797,6 +797,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo const debug_abbrev_data = di.coff.getSectionData(".debug_abbrev", allocator) catch null; const debug_str_data = di.coff.getSectionData(".debug_str", allocator) catch null; const debug_line_data = di.coff.getSectionData(".debug_line", allocator) catch null; + const debug_line_str_data = di.coff.getSectionData(".debug_line_str", allocator) catch null; const debug_ranges_data = di.coff.getSectionData(".debug_ranges", allocator) catch null; var dwarf = DW.DwarfInfo{ @@ -805,6 +806,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo .debug_abbrev = debug_abbrev_data orelse return error.MissingDebugInfo, .debug_str = debug_str_data orelse return error.MissingDebugInfo, .debug_line = debug_line_data orelse return error.MissingDebugInfo, + .debug_line_str = debug_line_str_data, .debug_ranges = debug_ranges_data, }; try DW.openDwarfDebugInfo(&dwarf, allocator); @@ -871,6 +873,7 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn var opt_debug_abbrev: ?[]const u8 = null; var opt_debug_str: ?[]const u8 = null; var opt_debug_line: ?[]const u8 = null; + var opt_debug_line_str: ?[]const u8 = null; var opt_debug_ranges: ?[]const u8 = null; for (shdrs) |*shdr| { @@ -885,6 +888,8 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn opt_debug_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); } else if (mem.eql(u8, name, ".debug_line")) { opt_debug_line = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); + } else if (mem.eql(u8, name, ".debug_line_str")) { + opt_debug_line_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); } else if (mem.eql(u8, name, ".debug_ranges")) { opt_debug_ranges = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); } @@ -896,6 +901,7 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn .debug_abbrev = opt_debug_abbrev orelse return error.MissingDebugInfo, .debug_str = opt_debug_str orelse return error.MissingDebugInfo, .debug_line = opt_debug_line orelse return error.MissingDebugInfo, + .debug_line_str = opt_debug_line_str, .debug_ranges = opt_debug_ranges, }; @@ -1434,6 +1440,7 @@ pub const ModuleDebugInfo = switch (native_os) { var opt_debug_info: ?*const macho.section_64 = null; var opt_debug_abbrev: ?*const macho.section_64 = null; var opt_debug_str: ?*const macho.section_64 = null; + var opt_debug_line_str: ?*const macho.section_64 = null; var opt_debug_ranges: ?*const macho.section_64 = null; const sections = @ptrCast( @@ -1456,6 +1463,8 @@ pub const ModuleDebugInfo = switch (native_os) { opt_debug_abbrev = sect; } else if (mem.eql(u8, name, "__debug_str")) { opt_debug_str = sect; + } else if (mem.eql(u8, name, "__debug_line_str")) { + opt_debug_line_str = sect; } else if (mem.eql(u8, name, "__debug_ranges")) { opt_debug_ranges = sect; } @@ -1476,6 +1485,10 @@ pub const ModuleDebugInfo = switch (native_os) { .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.offset, debug_abbrev.size), .debug_str = try chopSlice(mapped_mem, debug_str.offset, debug_str.size), .debug_line = try chopSlice(mapped_mem, debug_line.offset, debug_line.size), + .debug_line_str = if (opt_debug_line_str) |debug_line_str| + try chopSlice(mapped_mem, debug_line_str.offset, debug_line_str.size) + else + null, .debug_ranges = if (opt_debug_ranges) |debug_ranges| try chopSlice(mapped_mem, debug_ranges.offset, debug_ranges.size) else diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 93d744ca5f..1f53820c68 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -11,87 +11,20 @@ const ArrayList = std.ArrayList; pub const TAG = @import("dwarf/TAG.zig"); pub const AT = @import("dwarf/AT.zig"); pub const OP = @import("dwarf/OP.zig"); +pub const LANG = @import("dwarf/LANG.zig"); +pub const FORM = @import("dwarf/FORM.zig"); +pub const ATE = @import("dwarf/ATE.zig"); -pub const FORM = struct { - pub const addr = 0x01; - pub const block2 = 0x03; - pub const block4 = 0x04; - pub const data2 = 0x05; - pub const data4 = 0x06; - pub const data8 = 0x07; - pub const string = 0x08; - pub const block = 0x09; - pub const block1 = 0x0a; - pub const data1 = 0x0b; - pub const flag = 0x0c; - pub const sdata = 0x0d; - pub const strp = 0x0e; - pub const udata = 0x0f; - pub const ref_addr = 0x10; - pub const ref1 = 0x11; - pub const ref2 = 0x12; - pub const ref4 = 0x13; - pub const ref8 = 0x14; - pub const ref_udata = 0x15; - pub const indirect = 0x16; - pub const sec_offset = 0x17; - pub const exprloc = 0x18; - pub const flag_present = 0x19; - pub const ref_sig8 = 0x20; - - // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. - pub const GNU_addr_index = 0x1f01; - pub const GNU_str_index = 0x1f02; - - // Extensions for DWZ multifile. - // See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . - pub const GNU_ref_alt = 0x1f20; - pub const GNU_strp_alt = 0x1f21; -}; - -pub const ATE = struct { - pub const @"void" = 0x0; - pub const address = 0x1; - pub const boolean = 0x2; - pub const complex_float = 0x3; - pub const float = 0x4; - pub const signed = 0x5; - pub const signed_char = 0x6; - pub const unsigned = 0x7; - pub const unsigned_char = 0x8; - - // DWARF 3. - pub const imaginary_float = 0x9; - pub const packed_decimal = 0xa; - pub const numeric_string = 0xb; - pub const edited = 0xc; - pub const signed_fixed = 0xd; - pub const unsigned_fixed = 0xe; - pub const decimal_float = 0xf; - - // DWARF 4. - pub const UTF = 0x10; - - pub const lo_user = 0x80; - pub const hi_user = 0xff; - - // HP extensions. - pub const HP_float80 = 0x80; // Floating-point (80 bit). - pub const HP_complex_float80 = 0x81; // Complex floating-point (80 bit). - pub const HP_float128 = 0x82; // Floating-point (128 bit). - pub const HP_complex_float128 = 0x83; // Complex fp (128 bit). - pub const HP_floathpintel = 0x84; // Floating-point (82 bit IA64). - pub const HP_imaginary_float80 = 0x85; - pub const HP_imaginary_float128 = 0x86; - pub const HP_VAX_float = 0x88; // F or G floating. - pub const HP_VAX_float_d = 0x89; // D floating. - pub const HP_packed_decimal = 0x8a; // Cobol. - pub const HP_zoned_decimal = 0x8b; // Cobol. - pub const HP_edited = 0x8c; // Cobol. - pub const HP_signed_fixed = 0x8d; // Cobol. - pub const HP_unsigned_fixed = 0x8e; // Cobol. - pub const HP_VAX_complex_float = 0x8f; // F or G floating complex. - pub const HP_VAX_complex_float_d = 0x90; // D floating complex. +pub const LLE = struct { + pub const end_of_list = 0x00; + pub const base_addressx = 0x01; + pub const startx_endx = 0x02; + pub const startx_length = 0x03; + pub const offset_pair = 0x04; + pub const default_location = 0x05; + pub const base_address = 0x06; + pub const start_end = 0x07; + pub const start_length = 0x08; }; pub const CFA = struct { @@ -166,45 +99,6 @@ pub const LNE = struct { pub const hi_user = 0xff; }; -pub const LANG = struct { - pub const C89 = 0x0001; - pub const C = 0x0002; - pub const Ada83 = 0x0003; - pub const C_plus_plus = 0x0004; - pub const Cobol74 = 0x0005; - pub const Cobol85 = 0x0006; - pub const Fortran77 = 0x0007; - pub const Fortran90 = 0x0008; - pub const Pascal83 = 0x0009; - pub const Modula2 = 0x000a; - pub const Java = 0x000b; - pub const C99 = 0x000c; - pub const Ada95 = 0x000d; - pub const Fortran95 = 0x000e; - pub const PLI = 0x000f; - pub const ObjC = 0x0010; - pub const ObjC_plus_plus = 0x0011; - pub const UPC = 0x0012; - pub const D = 0x0013; - pub const Python = 0x0014; - pub const Go = 0x0016; - pub const C_plus_plus_11 = 0x001a; - pub const Rust = 0x001c; - pub const C11 = 0x001d; - pub const C_plus_plus_14 = 0x0021; - pub const Fortran03 = 0x0022; - pub const Fortran08 = 0x0023; - pub const lo_user = 0x8000; - pub const hi_user = 0xffff; - pub const Mips_Assembler = 0x8001; - pub const Upc = 0x8765; - pub const HP_Bliss = 0x8003; - pub const HP_Basic91 = 0x8004; - pub const HP_Pascal91 = 0x8005; - pub const HP_IMacro = 0x8006; - pub const HP_Assembler = 0x8007; -}; - pub const UT = struct { pub const compile = 0x01; pub const @"type" = 0x02; @@ -212,6 +106,7 @@ pub const UT = struct { pub const skeleton = 0x04; pub const split_compile = 0x05; pub const split_type = 0x06; + pub const lo_user = 0x80; pub const hi_user = 0xff; }; @@ -222,10 +117,22 @@ pub const LNCT = struct { pub const timestamp = 0x3; pub const size = 0x4; pub const MD5 = 0x5; + pub const lo_user = 0x2000; pub const hi_user = 0x3fff; }; +pub const RLE = struct { + pub const end_of_list = 0x00; + pub const base_addressx = 0x01; + pub const startx_endx = 0x02; + pub const startx_length = 0x03; + pub const offset_pair = 0x04; + pub const base_address = 0x05; + pub const start_end = 0x06; + pub const start_length = 0x07; +}; + pub const CC = enum(u8) { normal = 0x1, program = 0x2, @@ -276,6 +183,8 @@ const AbbrevTableEntry = struct { const AbbrevAttr = struct { attr_id: u64, form_id: u64, + /// Only valid if form_id is .implicit_const + payload: i64, }; const FormValue = union(enum) { @@ -289,6 +198,7 @@ const FormValue = union(enum) { RefAddr: u64, String: []const u8, StrPtr: u64, + LineStrPtr: u64, }; const Constant = struct { @@ -356,6 +266,7 @@ const Die = struct { return switch (form_value.*) { FormValue.String => |value| value, FormValue.StrPtr => |offset| di.getString(offset), + FormValue.LineStrPtr => |offset| di.getLineString(offset), else => error.InvalidDebugInfo, }; } @@ -588,6 +499,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en FORM.string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) }, FORM.strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) }, + FORM.line_strp => FormValue{ .LineStrPtr = try readAddress(in_stream, endian, is_64) }, FORM.indirect => { const child_form_id = try nosuspend leb.readULEB128(u64, in_stream); const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64)); @@ -595,7 +507,12 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en defer allocator.destroy(frame); return await @asyncCall(frame, {}, parseFormValue, .{ allocator, in_stream, child_form_id, endian, is_64 }); }, - else => error.InvalidDebugInfo, + FORM.implicit_const => FormValue{ .Const = Constant{ .signed = true, .payload = undefined } }, + + else => { + std.debug.print("dwarf: unhandled form_id: 0x{x}\n", .{form_id}); + return error.InvalidDebugInfo; + }, }; } @@ -613,6 +530,7 @@ pub const DwarfInfo = struct { debug_abbrev: []const u8, debug_str: []const u8, debug_line: []const u8, + debug_line_str: ?[]const u8, debug_ranges: ?[]const u8, // Filled later by the initializer abbrev_table_list: ArrayList(AbbrevTableHeader) = undefined, @@ -652,9 +570,20 @@ pub const DwarfInfo = struct { const version = try in.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); - - const address_size = try in.readByte(); + var address_size: u8 = undefined; + var debug_abbrev_offset: u64 = undefined; + switch (version) { + 5 => { + const unit_type = try in.readInt(u8, di.endian); + if (unit_type != UT.compile) return error.InvalidDebugInfo; + address_size = try in.readByte(); + debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); + }, + else => { + debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); + address_size = try in.readByte(); + }, + } if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; const compile_unit_pos = try seekable.getPos(); @@ -756,9 +685,20 @@ pub const DwarfInfo = struct { const version = try in.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); - - const address_size = try in.readByte(); + var address_size: u8 = undefined; + var debug_abbrev_offset: u64 = undefined; + switch (version) { + 5 => { + const unit_type = try in.readInt(u8, di.endian); + if (unit_type != UT.compile) return error.InvalidDebugInfo; + address_size = try in.readByte(); + debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); + }, + else => { + debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); + address_size = try in.readByte(); + }, + } if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; const compile_unit_pos = try seekable.getPos(); @@ -890,9 +830,12 @@ pub const DwarfInfo = struct { const attr_id = try leb.readULEB128(u64, in); const form_id = try leb.readULEB128(u64, in); if (attr_id == 0 and form_id == 0) break; + // DW_FORM_implicit_const stores its value immediately after the attribute pair :( + const payload = if (form_id == FORM.implicit_const) try leb.readILEB128(i64, in) else undefined; try attrs.append(AbbrevAttr{ .attr_id = attr_id, .form_id = form_id, + .payload = payload, }); } } @@ -914,6 +857,9 @@ pub const DwarfInfo = struct { .id = attr.attr_id, .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, di.endian, is_64), }; + if (attr.form_id == FORM.implicit_const) { + result.attrs.items[i].value.Const.payload = @bitCast(u64, attr.payload); + } } return result; } @@ -1101,6 +1047,21 @@ pub const DwarfInfo = struct { return error.InvalidDebugInfo; } + + fn getLineString(di: *DwarfInfo, offset: u64) ![]const u8 { + const debug_line_str = di.debug_line_str orelse return error.InvalidDebugInfo; + if (offset > debug_line_str.len) + return error.InvalidDebugInfo; + const casted_offset = math.cast(usize, offset) catch + return error.InvalidDebugInfo; + + // Valid strings always have a terminating zero byte + if (mem.indexOfScalarPos(u8, debug_line_str, casted_offset, 0)) |last| { + return debug_line_str[casted_offset..last]; + } + + return error.InvalidDebugInfo; + } }; /// Initialize DWARF info. The caller has the responsibility to initialize most diff --git a/lib/std/dwarf/AT.zig b/lib/std/dwarf/AT.zig index a4d03ad3d3..8a242d8330 100644 --- a/lib/std/dwarf/AT.zig +++ b/lib/std/dwarf/AT.zig @@ -99,7 +99,35 @@ pub const enum_class = 0x6d; pub const linkage_name = 0x6e; // DWARF 5 +pub const string_length_bit_size = 0x6f; +pub const string_length_byte_size = 0x70; +pub const rank = 0x71; +pub const str_offsets_base = 0x72; +pub const addr_base = 0x73; +pub const rnglists_base = 0x74; +pub const dwo_name = 0x76; +pub const reference = 0x77; +pub const rvalue_reference = 0x78; +pub const macros = 0x79; +pub const call_all_calls = 0x7a; +pub const call_all_source_calls = 0x7b; +pub const call_all_tail_calls = 0x7c; +pub const call_return_pc = 0x7d; +pub const call_value = 0x7e; +pub const call_origin = 0x7f; +pub const call_parameter = 0x80; +pub const call_pc = 0x81; +pub const call_tail_call = 0x82; +pub const call_target = 0x83; +pub const call_target_clobbered = 0x84; +pub const call_data_location = 0x85; +pub const call_data_value = 0x86; +pub const @"noreturn" = 0x87; pub const alignment = 0x88; +pub const export_symbols = 0x89; +pub const deleted = 0x8a; +pub const defaulted = 0x8b; +pub const loclists_base = 0x8c; pub const lo_user = 0x2000; // Implementation-defined range start. pub const hi_user = 0x3fff; // Implementation-defined range end. diff --git a/lib/std/dwarf/ATE.zig b/lib/std/dwarf/ATE.zig new file mode 100644 index 0000000000..3e5d192e6e --- /dev/null +++ b/lib/std/dwarf/ATE.zig @@ -0,0 +1,46 @@ +pub const @"void" = 0x0; +pub const address = 0x1; +pub const boolean = 0x2; +pub const complex_float = 0x3; +pub const float = 0x4; +pub const signed = 0x5; +pub const signed_char = 0x6; +pub const unsigned = 0x7; +pub const unsigned_char = 0x8; + +// DWARF 3. +pub const imaginary_float = 0x9; +pub const packed_decimal = 0xa; +pub const numeric_string = 0xb; +pub const edited = 0xc; +pub const signed_fixed = 0xd; +pub const unsigned_fixed = 0xe; +pub const decimal_float = 0xf; + +// DWARF 4. +pub const UTF = 0x10; + +// DWARF 5. +pub const UCS = 0x11; +pub const ASCII = 0x12; + +pub const lo_user = 0x80; +pub const hi_user = 0xff; + +// HP extensions. +pub const HP_float80 = 0x80; // Floating-point (80 bit). +pub const HP_complex_float80 = 0x81; // Complex floating-point (80 bit). +pub const HP_float128 = 0x82; // Floating-point (128 bit). +pub const HP_complex_float128 = 0x83; // Complex fp (128 bit). +pub const HP_floathpintel = 0x84; // Floating-point (82 bit IA64). +pub const HP_imaginary_float80 = 0x85; +pub const HP_imaginary_float128 = 0x86; +pub const HP_VAX_float = 0x88; // F or G floating. +pub const HP_VAX_float_d = 0x89; // D floating. +pub const HP_packed_decimal = 0x8a; // Cobol. +pub const HP_zoned_decimal = 0x8b; // Cobol. +pub const HP_edited = 0x8c; // Cobol. +pub const HP_signed_fixed = 0x8d; // Cobol. +pub const HP_unsigned_fixed = 0x8e; // Cobol. +pub const HP_VAX_complex_float = 0x8f; // F or G floating complex. +pub const HP_VAX_complex_float_d = 0x90; // D floating complex. diff --git a/lib/std/dwarf/FORM.zig b/lib/std/dwarf/FORM.zig new file mode 100644 index 0000000000..eb50c1dc93 --- /dev/null +++ b/lib/std/dwarf/FORM.zig @@ -0,0 +1,52 @@ +pub const addr = 0x01; +pub const block2 = 0x03; +pub const block4 = 0x04; +pub const data2 = 0x05; +pub const data4 = 0x06; +pub const data8 = 0x07; +pub const string = 0x08; +pub const block = 0x09; +pub const block1 = 0x0a; +pub const data1 = 0x0b; +pub const flag = 0x0c; +pub const sdata = 0x0d; +pub const strp = 0x0e; +pub const udata = 0x0f; +pub const ref_addr = 0x10; +pub const ref1 = 0x11; +pub const ref2 = 0x12; +pub const ref4 = 0x13; +pub const ref8 = 0x14; +pub const ref_udata = 0x15; +pub const indirect = 0x16; +pub const sec_offset = 0x17; +pub const exprloc = 0x18; +pub const flag_present = 0x19; +pub const strx = 0x1a; +pub const addrx = 0x1b; +pub const ref_sup4 = 0x1c; +pub const strp_sup = 0x1d; +pub const data16 = 0x1e; +pub const line_strp = 0x1f; +pub const ref_sig8 = 0x20; +pub const implicit_const = 0x21; +pub const loclistx = 0x22; +pub const rnglistx = 0x23; +pub const ref_sup8 = 0x24; +pub const strx1 = 0x25; +pub const strx2 = 0x26; +pub const strx3 = 0x27; +pub const strx4 = 0x28; +pub const addrx1 = 0x29; +pub const addrx2 = 0x2a; +pub const addrx3 = 0x2b; +pub const addrx4 = 0x2c; + +// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. +pub const GNU_addr_index = 0x1f01; +pub const GNU_str_index = 0x1f02; + +// Extensions for DWZ multifile. +// See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . +pub const GNU_ref_alt = 0x1f20; +pub const GNU_strp_alt = 0x1f21; diff --git a/lib/std/dwarf/LANG.zig b/lib/std/dwarf/LANG.zig new file mode 100644 index 0000000000..e24b61ecae --- /dev/null +++ b/lib/std/dwarf/LANG.zig @@ -0,0 +1,48 @@ +pub const C89 = 0x0001; +pub const C = 0x0002; +pub const Ada83 = 0x0003; +pub const C_plus_plus = 0x0004; +pub const Cobol74 = 0x0005; +pub const Cobol85 = 0x0006; +pub const Fortran77 = 0x0007; +pub const Fortran90 = 0x0008; +pub const Pascal83 = 0x0009; +pub const Modula2 = 0x000a; +pub const Java = 0x000b; +pub const C99 = 0x000c; +pub const Ada95 = 0x000d; +pub const Fortran95 = 0x000e; +pub const PLI = 0x000f; +pub const ObjC = 0x0010; +pub const ObjC_plus_plus = 0x0011; +pub const UPC = 0x0012; +pub const D = 0x0013; +pub const Python = 0x0014; +pub const OpenCL = 0x0015; +pub const Go = 0x0016; +pub const Modula3 = 0x0017; +pub const Haskell = 0x0018; +pub const C_plus_plus_03 = 0x0019; +pub const C_plus_plus_11 = 0x001a; +pub const OCaml = 0x001b; +pub const Rust = 0x001c; +pub const C11 = 0x001d; +pub const Swift = 0x001e; +pub const Julia = 0x001f; +pub const Dylan = 0x0020; +pub const C_plus_plus_14 = 0x0021; +pub const Fortran03 = 0x0022; +pub const Fortran08 = 0x0023; +pub const RenderScript = 0x0024; +pub const BLISS = 0x0025; + +pub const lo_user = 0x8000; +pub const hi_user = 0xffff; + +pub const Mips_Assembler = 0x8001; +pub const Upc = 0x8765; +pub const HP_Bliss = 0x8003; +pub const HP_Basic91 = 0x8004; +pub const HP_Pascal91 = 0x8005; +pub const HP_IMacro = 0x8006; +pub const HP_Assembler = 0x8007; diff --git a/lib/std/dwarf/OP.zig b/lib/std/dwarf/OP.zig index 92e13e8158..57fb7b7532 100644 --- a/lib/std/dwarf/OP.zig +++ b/lib/std/dwarf/OP.zig @@ -157,6 +157,18 @@ pub const bit_piece = 0x9d; pub const implicit_value = 0x9e; pub const stack_value = 0x9f; +// DWARF 5 extensions. +pub const implicit_pointer = 0xa0; +pub const addrx = 0xa1; +pub const constx = 0xa2; +pub const entry_value = 0xa3; +pub const const_type = 0xa4; +pub const regval_type = 0xa5; +pub const deref_type = 0xa6; +pub const xderef_type = 0xa7; +pub const convert = 0xa8; +pub const reinterpret = 0xa9; + pub const lo_user = 0xe0; // Implementation-defined range start. pub const hi_user = 0xff; // Implementation-defined range end. diff --git a/lib/std/dwarf/TAG.zig b/lib/std/dwarf/TAG.zig index a6434cf3ec..50e7cb3889 100644 --- a/lib/std/dwarf/TAG.zig +++ b/lib/std/dwarf/TAG.zig @@ -65,6 +65,16 @@ pub const type_unit = 0x41; pub const rvalue_reference_type = 0x42; pub const template_alias = 0x43; +// DWARF 5 +pub const coarray_type = 0x44; +pub const generic_subrange = 0x45; +pub const dynamic_type = 0x46; +pub const atomic_type = 0x47; +pub const call_site = 0x48; +pub const call_site_parameter = 0x49; +pub const skeleton_unit = 0x4a; +pub const immutable_type = 0x4b; + pub const lo_user = 0x4080; pub const hi_user = 0xffff; diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 70cdda6c2f..6620c99b49 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -38,6 +38,7 @@ dwarf_debug_info_index: ?u16 = null, dwarf_debug_abbrev_index: ?u16 = null, dwarf_debug_str_index: ?u16 = null, dwarf_debug_line_index: ?u16 = null, +dwarf_debug_line_str_index: ?u16 = null, dwarf_debug_ranges_index: ?u16 = null, symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, @@ -68,6 +69,7 @@ const DebugInfo = struct { debug_abbrev: []u8, debug_str: []u8, debug_line: []u8, + debug_line_str: []u8, debug_ranges: []u8, pub fn parseFromObject(allocator: Allocator, object: *const Object) !?DebugInfo { @@ -87,6 +89,12 @@ const DebugInfo = struct { const index = object.dwarf_debug_line_index orelse return null; break :blk try object.readSection(allocator, index); }; + var debug_line_str = blk: { + if (object.dwarf_debug_line_str_index) |ind| { + break :blk try object.readSection(allocator, ind); + } + break :blk try allocator.alloc(u8, 0); + }; var debug_ranges = blk: { if (object.dwarf_debug_ranges_index) |ind| { break :blk try object.readSection(allocator, ind); @@ -100,6 +108,7 @@ const DebugInfo = struct { .debug_abbrev = debug_abbrev, .debug_str = debug_str, .debug_line = debug_line, + .debug_line_str = debug_line_str, .debug_ranges = debug_ranges, }; try dwarf.openDwarfDebugInfo(&inner, allocator); @@ -110,6 +119,7 @@ const DebugInfo = struct { .debug_abbrev = debug_abbrev, .debug_str = debug_str, .debug_line = debug_line, + .debug_line_str = debug_line_str, .debug_ranges = debug_ranges, }; } @@ -119,6 +129,7 @@ const DebugInfo = struct { allocator.free(self.debug_abbrev); allocator.free(self.debug_str); allocator.free(self.debug_line); + allocator.free(self.debug_line_str); allocator.free(self.debug_ranges); self.inner.abbrev_table_list.deinit(); self.inner.compile_unit_list.deinit(); @@ -285,6 +296,8 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v self.dwarf_debug_str_index = index; } else if (mem.eql(u8, sectname, "__debug_line")) { self.dwarf_debug_line_index = index; + } else if (mem.eql(u8, sectname, "__debug_line_str")) { + self.dwarf_debug_line_str_index = index; } else if (mem.eql(u8, sectname, "__debug_ranges")) { self.dwarf_debug_ranges_index = index; }