| author | |
| committer | |
| log | 6de8b4bc3d105c15cd473c5bf100db4c9328dd54 |
| tree | 6f15f1b038b04aaf50ed03d7663c7e54d255a9b4 |
| parent | 47e004d975669fea1297224e33a868742178c4b4 |
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.9 files changed, 310 insertions(+), 127 deletions(-)
lib/std/debug.zig+13| ... | ... | @@ -797,6 +797,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo |
| 797 | 797 | const debug_abbrev_data = di.coff.getSectionData(".debug_abbrev", allocator) catch null; |
| 798 | 798 | const debug_str_data = di.coff.getSectionData(".debug_str", allocator) catch null; |
| 799 | 799 | const debug_line_data = di.coff.getSectionData(".debug_line", allocator) catch null; |
| 800 | const debug_line_str_data = di.coff.getSectionData(".debug_line_str", allocator) catch null; | |
| 800 | 801 | const debug_ranges_data = di.coff.getSectionData(".debug_ranges", allocator) catch null; |
| 801 | 802 | |
| 802 | 803 | var dwarf = DW.DwarfInfo{ |
| ... | ... | @@ -805,6 +806,7 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo |
| 805 | 806 | .debug_abbrev = debug_abbrev_data orelse return error.MissingDebugInfo, |
| 806 | 807 | .debug_str = debug_str_data orelse return error.MissingDebugInfo, |
| 807 | 808 | .debug_line = debug_line_data orelse return error.MissingDebugInfo, |
| 809 | .debug_line_str = debug_line_str_data, | |
| 808 | 810 | .debug_ranges = debug_ranges_data, |
| 809 | 811 | }; |
| 810 | 812 | try DW.openDwarfDebugInfo(&dwarf, allocator); |
| ... | ... | @@ -871,6 +873,7 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn |
| 871 | 873 | var opt_debug_abbrev: ?[]const u8 = null; |
| 872 | 874 | var opt_debug_str: ?[]const u8 = null; |
| 873 | 875 | var opt_debug_line: ?[]const u8 = null; |
| 876 | var opt_debug_line_str: ?[]const u8 = null; | |
| 874 | 877 | var opt_debug_ranges: ?[]const u8 = null; |
| 875 | 878 | |
| 876 | 879 | for (shdrs) |*shdr| { |
| ... | ... | @@ -885,6 +888,8 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn |
| 885 | 888 | opt_debug_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); |
| 886 | 889 | } else if (mem.eql(u8, name, ".debug_line")) { |
| 887 | 890 | opt_debug_line = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); |
| 891 | } else if (mem.eql(u8, name, ".debug_line_str")) { | |
| 892 | opt_debug_line_str = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); | |
| 888 | 893 | } else if (mem.eql(u8, name, ".debug_ranges")) { |
| 889 | 894 | opt_debug_ranges = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size); |
| 890 | 895 | } |
| ... | ... | @@ -896,6 +901,7 @@ pub fn readElfDebugInfo(allocator: mem.Allocator, elf_file: File) !ModuleDebugIn |
| 896 | 901 | .debug_abbrev = opt_debug_abbrev orelse return error.MissingDebugInfo, |
| 897 | 902 | .debug_str = opt_debug_str orelse return error.MissingDebugInfo, |
| 898 | 903 | .debug_line = opt_debug_line orelse return error.MissingDebugInfo, |
| 904 | .debug_line_str = opt_debug_line_str, | |
| 899 | 905 | .debug_ranges = opt_debug_ranges, |
| 900 | 906 | }; |
| 901 | 907 | |
| ... | ... | @@ -1434,6 +1440,7 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1434 | 1440 | var opt_debug_info: ?*const macho.section_64 = null; |
| 1435 | 1441 | var opt_debug_abbrev: ?*const macho.section_64 = null; |
| 1436 | 1442 | var opt_debug_str: ?*const macho.section_64 = null; |
| 1443 | var opt_debug_line_str: ?*const macho.section_64 = null; | |
| 1437 | 1444 | var opt_debug_ranges: ?*const macho.section_64 = null; |
| 1438 | 1445 | |
| 1439 | 1446 | const sections = @ptrCast( |
| ... | ... | @@ -1456,6 +1463,8 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1456 | 1463 | opt_debug_abbrev = sect; |
| 1457 | 1464 | } else if (mem.eql(u8, name, "__debug_str")) { |
| 1458 | 1465 | opt_debug_str = sect; |
| 1466 | } else if (mem.eql(u8, name, "__debug_line_str")) { | |
| 1467 | opt_debug_line_str = sect; | |
| 1459 | 1468 | } else if (mem.eql(u8, name, "__debug_ranges")) { |
| 1460 | 1469 | opt_debug_ranges = sect; |
| 1461 | 1470 | } |
| ... | ... | @@ -1476,6 +1485,10 @@ pub const ModuleDebugInfo = switch (native_os) { |
| 1476 | 1485 | .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.offset, debug_abbrev.size), |
| 1477 | 1486 | .debug_str = try chopSlice(mapped_mem, debug_str.offset, debug_str.size), |
| 1478 | 1487 | .debug_line = try chopSlice(mapped_mem, debug_line.offset, debug_line.size), |
| 1488 | .debug_line_str = if (opt_debug_line_str) |debug_line_str| | |
| 1489 | try chopSlice(mapped_mem, debug_line_str.offset, debug_line_str.size) | |
| 1490 | else | |
| 1491 | null, | |
| 1479 | 1492 | .debug_ranges = if (opt_debug_ranges) |debug_ranges| |
| 1480 | 1493 | try chopSlice(mapped_mem, debug_ranges.offset, debug_ranges.size) |
| 1481 | 1494 | else |
lib/std/dwarf.zig+88-127| ... | ... | @@ -11,87 +11,20 @@ const ArrayList = std.ArrayList; |
| 11 | 11 | pub const TAG = @import("dwarf/TAG.zig"); |
| 12 | 12 | pub const AT = @import("dwarf/AT.zig"); |
| 13 | 13 | pub const OP = @import("dwarf/OP.zig"); |
| 14 | ||
| 15 | pub const FORM = struct { | |
| 16 | pub const addr = 0x01; | |
| 17 | pub const block2 = 0x03; | |
| 18 | pub const block4 = 0x04; | |
| 19 | pub const data2 = 0x05; | |
| 20 | pub const data4 = 0x06; | |
| 21 | pub const data8 = 0x07; | |
| 22 | pub const string = 0x08; | |
| 23 | pub const block = 0x09; | |
| 24 | pub const block1 = 0x0a; | |
| 25 | pub const data1 = 0x0b; | |
| 26 | pub const flag = 0x0c; | |
| 27 | pub const sdata = 0x0d; | |
| 28 | pub const strp = 0x0e; | |
| 29 | pub const udata = 0x0f; | |
| 30 | pub const ref_addr = 0x10; | |
| 31 | pub const ref1 = 0x11; | |
| 32 | pub const ref2 = 0x12; | |
| 33 | pub const ref4 = 0x13; | |
| 34 | pub const ref8 = 0x14; | |
| 35 | pub const ref_udata = 0x15; | |
| 36 | pub const indirect = 0x16; | |
| 37 | pub const sec_offset = 0x17; | |
| 38 | pub const exprloc = 0x18; | |
| 39 | pub const flag_present = 0x19; | |
| 40 | pub const ref_sig8 = 0x20; | |
| 41 | ||
| 42 | // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. | |
| 43 | pub const GNU_addr_index = 0x1f01; | |
| 44 | pub const GNU_str_index = 0x1f02; | |
| 45 | ||
| 46 | // Extensions for DWZ multifile. | |
| 47 | // See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . | |
| 48 | pub const GNU_ref_alt = 0x1f20; | |
| 49 | pub const GNU_strp_alt = 0x1f21; | |
| 50 | }; | |
| 51 | ||
| 52 | pub const ATE = struct { | |
| 53 | pub const @"void" = 0x0; | |
| 54 | pub const address = 0x1; | |
| 55 | pub const boolean = 0x2; | |
| 56 | pub const complex_float = 0x3; | |
| 57 | pub const float = 0x4; | |
| 58 | pub const signed = 0x5; | |
| 59 | pub const signed_char = 0x6; | |
| 60 | pub const unsigned = 0x7; | |
| 61 | pub const unsigned_char = 0x8; | |
| 62 | ||
| 63 | // DWARF 3. | |
| 64 | pub const imaginary_float = 0x9; | |
| 65 | pub const packed_decimal = 0xa; | |
| 66 | pub const numeric_string = 0xb; | |
| 67 | pub const edited = 0xc; | |
| 68 | pub const signed_fixed = 0xd; | |
| 69 | pub const unsigned_fixed = 0xe; | |
| 70 | pub const decimal_float = 0xf; | |
| 71 | ||
| 72 | // DWARF 4. | |
| 73 | pub const UTF = 0x10; | |
| 74 | ||
| 75 | pub const lo_user = 0x80; | |
| 76 | pub const hi_user = 0xff; | |
| 77 | ||
| 78 | // HP extensions. | |
| 79 | pub const HP_float80 = 0x80; // Floating-point (80 bit). | |
| 80 | pub const HP_complex_float80 = 0x81; // Complex floating-point (80 bit). | |
| 81 | pub const HP_float128 = 0x82; // Floating-point (128 bit). | |
| 82 | pub const HP_complex_float128 = 0x83; // Complex fp (128 bit). | |
| 83 | pub const HP_floathpintel = 0x84; // Floating-point (82 bit IA64). | |
| 84 | pub const HP_imaginary_float80 = 0x85; | |
| 85 | pub const HP_imaginary_float128 = 0x86; | |
| 86 | pub const HP_VAX_float = 0x88; // F or G floating. | |
| 87 | pub const HP_VAX_float_d = 0x89; // D floating. | |
| 88 | pub const HP_packed_decimal = 0x8a; // Cobol. | |
| 89 | pub const HP_zoned_decimal = 0x8b; // Cobol. | |
| 90 | pub const HP_edited = 0x8c; // Cobol. | |
| 91 | pub const HP_signed_fixed = 0x8d; // Cobol. | |
| 92 | pub const HP_unsigned_fixed = 0x8e; // Cobol. | |
| 93 | pub const HP_VAX_complex_float = 0x8f; // F or G floating complex. | |
| 94 | pub const HP_VAX_complex_float_d = 0x90; // D floating complex. | |
| 14 | pub const LANG = @import("dwarf/LANG.zig"); | |
| 15 | pub const FORM = @import("dwarf/FORM.zig"); | |
| 16 | pub const ATE = @import("dwarf/ATE.zig"); | |
| 17 | ||
| 18 | pub const LLE = struct { | |
| 19 | pub const end_of_list = 0x00; | |
| 20 | pub const base_addressx = 0x01; | |
| 21 | pub const startx_endx = 0x02; | |
| 22 | pub const startx_length = 0x03; | |
| 23 | pub const offset_pair = 0x04; | |
| 24 | pub const default_location = 0x05; | |
| 25 | pub const base_address = 0x06; | |
| 26 | pub const start_end = 0x07; | |
| 27 | pub const start_length = 0x08; | |
| 95 | 28 | }; |
| 96 | 29 | |
| 97 | 30 | pub const CFA = struct { |
| ... | ... | @@ -166,45 +99,6 @@ pub const LNE = struct { |
| 166 | 99 | pub const hi_user = 0xff; |
| 167 | 100 | }; |
| 168 | 101 | |
| 169 | pub const LANG = struct { | |
| 170 | pub const C89 = 0x0001; | |
| 171 | pub const C = 0x0002; | |
| 172 | pub const Ada83 = 0x0003; | |
| 173 | pub const C_plus_plus = 0x0004; | |
| 174 | pub const Cobol74 = 0x0005; | |
| 175 | pub const Cobol85 = 0x0006; | |
| 176 | pub const Fortran77 = 0x0007; | |
| 177 | pub const Fortran90 = 0x0008; | |
| 178 | pub const Pascal83 = 0x0009; | |
| 179 | pub const Modula2 = 0x000a; | |
| 180 | pub const Java = 0x000b; | |
| 181 | pub const C99 = 0x000c; | |
| 182 | pub const Ada95 = 0x000d; | |
| 183 | pub const Fortran95 = 0x000e; | |
| 184 | pub const PLI = 0x000f; | |
| 185 | pub const ObjC = 0x0010; | |
| 186 | pub const ObjC_plus_plus = 0x0011; | |
| 187 | pub const UPC = 0x0012; | |
| 188 | pub const D = 0x0013; | |
| 189 | pub const Python = 0x0014; | |
| 190 | pub const Go = 0x0016; | |
| 191 | pub const C_plus_plus_11 = 0x001a; | |
| 192 | pub const Rust = 0x001c; | |
| 193 | pub const C11 = 0x001d; | |
| 194 | pub const C_plus_plus_14 = 0x0021; | |
| 195 | pub const Fortran03 = 0x0022; | |
| 196 | pub const Fortran08 = 0x0023; | |
| 197 | pub const lo_user = 0x8000; | |
| 198 | pub const hi_user = 0xffff; | |
| 199 | pub const Mips_Assembler = 0x8001; | |
| 200 | pub const Upc = 0x8765; | |
| 201 | pub const HP_Bliss = 0x8003; | |
| 202 | pub const HP_Basic91 = 0x8004; | |
| 203 | pub const HP_Pascal91 = 0x8005; | |
| 204 | pub const HP_IMacro = 0x8006; | |
| 205 | pub const HP_Assembler = 0x8007; | |
| 206 | }; | |
| 207 | ||
| 208 | 102 | pub const UT = struct { |
| 209 | 103 | pub const compile = 0x01; |
| 210 | 104 | pub const @"type" = 0x02; |
| ... | ... | @@ -212,6 +106,7 @@ pub const UT = struct { |
| 212 | 106 | pub const skeleton = 0x04; |
| 213 | 107 | pub const split_compile = 0x05; |
| 214 | 108 | pub const split_type = 0x06; |
| 109 | ||
| 215 | 110 | pub const lo_user = 0x80; |
| 216 | 111 | pub const hi_user = 0xff; |
| 217 | 112 | }; |
| ... | ... | @@ -222,10 +117,22 @@ pub const LNCT = struct { |
| 222 | 117 | pub const timestamp = 0x3; |
| 223 | 118 | pub const size = 0x4; |
| 224 | 119 | pub const MD5 = 0x5; |
| 120 | ||
| 225 | 121 | pub const lo_user = 0x2000; |
| 226 | 122 | pub const hi_user = 0x3fff; |
| 227 | 123 | }; |
| 228 | 124 | |
| 125 | pub const RLE = struct { | |
| 126 | pub const end_of_list = 0x00; | |
| 127 | pub const base_addressx = 0x01; | |
| 128 | pub const startx_endx = 0x02; | |
| 129 | pub const startx_length = 0x03; | |
| 130 | pub const offset_pair = 0x04; | |
| 131 | pub const base_address = 0x05; | |
| 132 | pub const start_end = 0x06; | |
| 133 | pub const start_length = 0x07; | |
| 134 | }; | |
| 135 | ||
| 229 | 136 | pub const CC = enum(u8) { |
| 230 | 137 | normal = 0x1, |
| 231 | 138 | program = 0x2, |
| ... | ... | @@ -276,6 +183,8 @@ const AbbrevTableEntry = struct { |
| 276 | 183 | const AbbrevAttr = struct { |
| 277 | 184 | attr_id: u64, |
| 278 | 185 | form_id: u64, |
| 186 | /// Only valid if form_id is .implicit_const | |
| 187 | payload: i64, | |
| 279 | 188 | }; |
| 280 | 189 | |
| 281 | 190 | const FormValue = union(enum) { |
| ... | ... | @@ -289,6 +198,7 @@ const FormValue = union(enum) { |
| 289 | 198 | RefAddr: u64, |
| 290 | 199 | String: []const u8, |
| 291 | 200 | StrPtr: u64, |
| 201 | LineStrPtr: u64, | |
| 292 | 202 | }; |
| 293 | 203 | |
| 294 | 204 | const Constant = struct { |
| ... | ... | @@ -356,6 +266,7 @@ const Die = struct { |
| 356 | 266 | return switch (form_value.*) { |
| 357 | 267 | FormValue.String => |value| value, |
| 358 | 268 | FormValue.StrPtr => |offset| di.getString(offset), |
| 269 | FormValue.LineStrPtr => |offset| di.getLineString(offset), | |
| 359 | 270 | else => error.InvalidDebugInfo, |
| 360 | 271 | }; |
| 361 | 272 | } |
| ... | ... | @@ -588,6 +499,7 @@ fn parseFormValue(allocator: mem.Allocator, in_stream: anytype, form_id: u64, en |
| 588 | 499 | |
| 589 | 500 | FORM.string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) }, |
| 590 | 501 | FORM.strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) }, |
| 502 | FORM.line_strp => FormValue{ .LineStrPtr = try readAddress(in_stream, endian, is_64) }, | |
| 591 | 503 | FORM.indirect => { |
| 592 | 504 | const child_form_id = try nosuspend leb.readULEB128(u64, in_stream); |
| 593 | 505 | 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 |
| 595 | 507 | defer allocator.destroy(frame); |
| 596 | 508 | return await @asyncCall(frame, {}, parseFormValue, .{ allocator, in_stream, child_form_id, endian, is_64 }); |
| 597 | 509 | }, |
| 598 | else => error.InvalidDebugInfo, | |
| 510 | FORM.implicit_const => FormValue{ .Const = Constant{ .signed = true, .payload = undefined } }, | |
| 511 | ||
| 512 | else => { | |
| 513 | std.debug.print("dwarf: unhandled form_id: 0x{x}\n", .{form_id}); | |
| 514 | return error.InvalidDebugInfo; | |
| 515 | }, | |
| 599 | 516 | }; |
| 600 | 517 | } |
| 601 | 518 | |
| ... | ... | @@ -613,6 +530,7 @@ pub const DwarfInfo = struct { |
| 613 | 530 | debug_abbrev: []const u8, |
| 614 | 531 | debug_str: []const u8, |
| 615 | 532 | debug_line: []const u8, |
| 533 | debug_line_str: ?[]const u8, | |
| 616 | 534 | debug_ranges: ?[]const u8, |
| 617 | 535 | // Filled later by the initializer |
| 618 | 536 | abbrev_table_list: ArrayList(AbbrevTableHeader) = undefined, |
| ... | ... | @@ -652,9 +570,20 @@ pub const DwarfInfo = struct { |
| 652 | 570 | const version = try in.readInt(u16, di.endian); |
| 653 | 571 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 654 | 572 | |
| 655 | const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 656 | ||
| 657 | const address_size = try in.readByte(); | |
| 573 | var address_size: u8 = undefined; | |
| 574 | var debug_abbrev_offset: u64 = undefined; | |
| 575 | switch (version) { | |
| 576 | 5 => { | |
| 577 | const unit_type = try in.readInt(u8, di.endian); | |
| 578 | if (unit_type != UT.compile) return error.InvalidDebugInfo; | |
| 579 | address_size = try in.readByte(); | |
| 580 | debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 581 | }, | |
| 582 | else => { | |
| 583 | debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 584 | address_size = try in.readByte(); | |
| 585 | }, | |
| 586 | } | |
| 658 | 587 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 659 | 588 | |
| 660 | 589 | const compile_unit_pos = try seekable.getPos(); |
| ... | ... | @@ -756,9 +685,20 @@ pub const DwarfInfo = struct { |
| 756 | 685 | const version = try in.readInt(u16, di.endian); |
| 757 | 686 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 758 | 687 | |
| 759 | const debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 760 | ||
| 761 | const address_size = try in.readByte(); | |
| 688 | var address_size: u8 = undefined; | |
| 689 | var debug_abbrev_offset: u64 = undefined; | |
| 690 | switch (version) { | |
| 691 | 5 => { | |
| 692 | const unit_type = try in.readInt(u8, di.endian); | |
| 693 | if (unit_type != UT.compile) return error.InvalidDebugInfo; | |
| 694 | address_size = try in.readByte(); | |
| 695 | debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 696 | }, | |
| 697 | else => { | |
| 698 | debug_abbrev_offset = if (is_64) try in.readInt(u64, di.endian) else try in.readInt(u32, di.endian); | |
| 699 | address_size = try in.readByte(); | |
| 700 | }, | |
| 701 | } | |
| 762 | 702 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 763 | 703 | |
| 764 | 704 | const compile_unit_pos = try seekable.getPos(); |
| ... | ... | @@ -890,9 +830,12 @@ pub const DwarfInfo = struct { |
| 890 | 830 | const attr_id = try leb.readULEB128(u64, in); |
| 891 | 831 | const form_id = try leb.readULEB128(u64, in); |
| 892 | 832 | if (attr_id == 0 and form_id == 0) break; |
| 833 | // DW_FORM_implicit_const stores its value immediately after the attribute pair :( | |
| 834 | const payload = if (form_id == FORM.implicit_const) try leb.readILEB128(i64, in) else undefined; | |
| 893 | 835 | try attrs.append(AbbrevAttr{ |
| 894 | 836 | .attr_id = attr_id, |
| 895 | 837 | .form_id = form_id, |
| 838 | .payload = payload, | |
| 896 | 839 | }); |
| 897 | 840 | } |
| 898 | 841 | } |
| ... | ... | @@ -914,6 +857,9 @@ pub const DwarfInfo = struct { |
| 914 | 857 | .id = attr.attr_id, |
| 915 | 858 | .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, di.endian, is_64), |
| 916 | 859 | }; |
| 860 | if (attr.form_id == FORM.implicit_const) { | |
| 861 | result.attrs.items[i].value.Const.payload = @bitCast(u64, attr.payload); | |
| 862 | } | |
| 917 | 863 | } |
| 918 | 864 | return result; |
| 919 | 865 | } |
| ... | ... | @@ -1101,6 +1047,21 @@ pub const DwarfInfo = struct { |
| 1101 | 1047 | |
| 1102 | 1048 | return error.InvalidDebugInfo; |
| 1103 | 1049 | } |
| 1050 | ||
| 1051 | fn getLineString(di: *DwarfInfo, offset: u64) ![]const u8 { | |
| 1052 | const debug_line_str = di.debug_line_str orelse return error.InvalidDebugInfo; | |
| 1053 | if (offset > debug_line_str.len) | |
| 1054 | return error.InvalidDebugInfo; | |
| 1055 | const casted_offset = math.cast(usize, offset) catch | |
| 1056 | return error.InvalidDebugInfo; | |
| 1057 | ||
| 1058 | // Valid strings always have a terminating zero byte | |
| 1059 | if (mem.indexOfScalarPos(u8, debug_line_str, casted_offset, 0)) |last| { | |
| 1060 | return debug_line_str[casted_offset..last]; | |
| 1061 | } | |
| 1062 | ||
| 1063 | return error.InvalidDebugInfo; | |
| 1064 | } | |
| 1104 | 1065 | }; |
| 1105 | 1066 | |
| 1106 | 1067 | /// Initialize DWARF info. The caller has the responsibility to initialize most |
lib/std/dwarf/AT.zig+28| ... | ... | @@ -99,7 +99,35 @@ pub const enum_class = 0x6d; |
| 99 | 99 | pub const linkage_name = 0x6e; |
| 100 | 100 | |
| 101 | 101 | // DWARF 5 |
| 102 | pub const string_length_bit_size = 0x6f; | |
| 103 | pub const string_length_byte_size = 0x70; | |
| 104 | pub const rank = 0x71; | |
| 105 | pub const str_offsets_base = 0x72; | |
| 106 | pub const addr_base = 0x73; | |
| 107 | pub const rnglists_base = 0x74; | |
| 108 | pub const dwo_name = 0x76; | |
| 109 | pub const reference = 0x77; | |
| 110 | pub const rvalue_reference = 0x78; | |
| 111 | pub const macros = 0x79; | |
| 112 | pub const call_all_calls = 0x7a; | |
| 113 | pub const call_all_source_calls = 0x7b; | |
| 114 | pub const call_all_tail_calls = 0x7c; | |
| 115 | pub const call_return_pc = 0x7d; | |
| 116 | pub const call_value = 0x7e; | |
| 117 | pub const call_origin = 0x7f; | |
| 118 | pub const call_parameter = 0x80; | |
| 119 | pub const call_pc = 0x81; | |
| 120 | pub const call_tail_call = 0x82; | |
| 121 | pub const call_target = 0x83; | |
| 122 | pub const call_target_clobbered = 0x84; | |
| 123 | pub const call_data_location = 0x85; | |
| 124 | pub const call_data_value = 0x86; | |
| 125 | pub const @"noreturn" = 0x87; | |
| 102 | 126 | pub const alignment = 0x88; |
| 127 | pub const export_symbols = 0x89; | |
| 128 | pub const deleted = 0x8a; | |
| 129 | pub const defaulted = 0x8b; | |
| 130 | pub const loclists_base = 0x8c; | |
| 103 | 131 | |
| 104 | 132 | pub const lo_user = 0x2000; // Implementation-defined range start. |
| 105 | 133 | pub const hi_user = 0x3fff; // Implementation-defined range end. |
lib/std/dwarf/ATE.zig created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | pub const @"void" = 0x0; | |
| 2 | pub const address = 0x1; | |
| 3 | pub const boolean = 0x2; | |
| 4 | pub const complex_float = 0x3; | |
| 5 | pub const float = 0x4; | |
| 6 | pub const signed = 0x5; | |
| 7 | pub const signed_char = 0x6; | |
| 8 | pub const unsigned = 0x7; | |
| 9 | pub const unsigned_char = 0x8; | |
| 10 | ||
| 11 | // DWARF 3. | |
| 12 | pub const imaginary_float = 0x9; | |
| 13 | pub const packed_decimal = 0xa; | |
| 14 | pub const numeric_string = 0xb; | |
| 15 | pub const edited = 0xc; | |
| 16 | pub const signed_fixed = 0xd; | |
| 17 | pub const unsigned_fixed = 0xe; | |
| 18 | pub const decimal_float = 0xf; | |
| 19 | ||
| 20 | // DWARF 4. | |
| 21 | pub const UTF = 0x10; | |
| 22 | ||
| 23 | // DWARF 5. | |
| 24 | pub const UCS = 0x11; | |
| 25 | pub const ASCII = 0x12; | |
| 26 | ||
| 27 | pub const lo_user = 0x80; | |
| 28 | pub const hi_user = 0xff; | |
| 29 | ||
| 30 | // HP extensions. | |
| 31 | pub const HP_float80 = 0x80; // Floating-point (80 bit). | |
| 32 | pub const HP_complex_float80 = 0x81; // Complex floating-point (80 bit). | |
| 33 | pub const HP_float128 = 0x82; // Floating-point (128 bit). | |
| 34 | pub const HP_complex_float128 = 0x83; // Complex fp (128 bit). | |
| 35 | pub const HP_floathpintel = 0x84; // Floating-point (82 bit IA64). | |
| 36 | pub const HP_imaginary_float80 = 0x85; | |
| 37 | pub const HP_imaginary_float128 = 0x86; | |
| 38 | pub const HP_VAX_float = 0x88; // F or G floating. | |
| 39 | pub const HP_VAX_float_d = 0x89; // D floating. | |
| 40 | pub const HP_packed_decimal = 0x8a; // Cobol. | |
| 41 | pub const HP_zoned_decimal = 0x8b; // Cobol. | |
| 42 | pub const HP_edited = 0x8c; // Cobol. | |
| 43 | pub const HP_signed_fixed = 0x8d; // Cobol. | |
| 44 | pub const HP_unsigned_fixed = 0x8e; // Cobol. | |
| 45 | pub const HP_VAX_complex_float = 0x8f; // F or G floating complex. | |
| 46 | pub const HP_VAX_complex_float_d = 0x90; // D floating complex. |
lib/std/dwarf/FORM.zig created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | pub const addr = 0x01; | |
| 2 | pub const block2 = 0x03; | |
| 3 | pub const block4 = 0x04; | |
| 4 | pub const data2 = 0x05; | |
| 5 | pub const data4 = 0x06; | |
| 6 | pub const data8 = 0x07; | |
| 7 | pub const string = 0x08; | |
| 8 | pub const block = 0x09; | |
| 9 | pub const block1 = 0x0a; | |
| 10 | pub const data1 = 0x0b; | |
| 11 | pub const flag = 0x0c; | |
| 12 | pub const sdata = 0x0d; | |
| 13 | pub const strp = 0x0e; | |
| 14 | pub const udata = 0x0f; | |
| 15 | pub const ref_addr = 0x10; | |
| 16 | pub const ref1 = 0x11; | |
| 17 | pub const ref2 = 0x12; | |
| 18 | pub const ref4 = 0x13; | |
| 19 | pub const ref8 = 0x14; | |
| 20 | pub const ref_udata = 0x15; | |
| 21 | pub const indirect = 0x16; | |
| 22 | pub const sec_offset = 0x17; | |
| 23 | pub const exprloc = 0x18; | |
| 24 | pub const flag_present = 0x19; | |
| 25 | pub const strx = 0x1a; | |
| 26 | pub const addrx = 0x1b; | |
| 27 | pub const ref_sup4 = 0x1c; | |
| 28 | pub const strp_sup = 0x1d; | |
| 29 | pub const data16 = 0x1e; | |
| 30 | pub const line_strp = 0x1f; | |
| 31 | pub const ref_sig8 = 0x20; | |
| 32 | pub const implicit_const = 0x21; | |
| 33 | pub const loclistx = 0x22; | |
| 34 | pub const rnglistx = 0x23; | |
| 35 | pub const ref_sup8 = 0x24; | |
| 36 | pub const strx1 = 0x25; | |
| 37 | pub const strx2 = 0x26; | |
| 38 | pub const strx3 = 0x27; | |
| 39 | pub const strx4 = 0x28; | |
| 40 | pub const addrx1 = 0x29; | |
| 41 | pub const addrx2 = 0x2a; | |
| 42 | pub const addrx3 = 0x2b; | |
| 43 | pub const addrx4 = 0x2c; | |
| 44 | ||
| 45 | // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. | |
| 46 | pub const GNU_addr_index = 0x1f01; | |
| 47 | pub const GNU_str_index = 0x1f02; | |
| 48 | ||
| 49 | // Extensions for DWZ multifile. | |
| 50 | // See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . | |
| 51 | pub const GNU_ref_alt = 0x1f20; | |
| 52 | pub const GNU_strp_alt = 0x1f21; |
lib/std/dwarf/LANG.zig created+48| ... | ... | @@ -0,0 +1,48 @@ |
| 1 | pub const C89 = 0x0001; | |
| 2 | pub const C = 0x0002; | |
| 3 | pub const Ada83 = 0x0003; | |
| 4 | pub const C_plus_plus = 0x0004; | |
| 5 | pub const Cobol74 = 0x0005; | |
| 6 | pub const Cobol85 = 0x0006; | |
| 7 | pub const Fortran77 = 0x0007; | |
| 8 | pub const Fortran90 = 0x0008; | |
| 9 | pub const Pascal83 = 0x0009; | |
| 10 | pub const Modula2 = 0x000a; | |
| 11 | pub const Java = 0x000b; | |
| 12 | pub const C99 = 0x000c; | |
| 13 | pub const Ada95 = 0x000d; | |
| 14 | pub const Fortran95 = 0x000e; | |
| 15 | pub const PLI = 0x000f; | |
| 16 | pub const ObjC = 0x0010; | |
| 17 | pub const ObjC_plus_plus = 0x0011; | |
| 18 | pub const UPC = 0x0012; | |
| 19 | pub const D = 0x0013; | |
| 20 | pub const Python = 0x0014; | |
| 21 | pub const OpenCL = 0x0015; | |
| 22 | pub const Go = 0x0016; | |
| 23 | pub const Modula3 = 0x0017; | |
| 24 | pub const Haskell = 0x0018; | |
| 25 | pub const C_plus_plus_03 = 0x0019; | |
| 26 | pub const C_plus_plus_11 = 0x001a; | |
| 27 | pub const OCaml = 0x001b; | |
| 28 | pub const Rust = 0x001c; | |
| 29 | pub const C11 = 0x001d; | |
| 30 | pub const Swift = 0x001e; | |
| 31 | pub const Julia = 0x001f; | |
| 32 | pub const Dylan = 0x0020; | |
| 33 | pub const C_plus_plus_14 = 0x0021; | |
| 34 | pub const Fortran03 = 0x0022; | |
| 35 | pub const Fortran08 = 0x0023; | |
| 36 | pub const RenderScript = 0x0024; | |
| 37 | pub const BLISS = 0x0025; | |
| 38 | ||
| 39 | pub const lo_user = 0x8000; | |
| 40 | pub const hi_user = 0xffff; | |
| 41 | ||
| 42 | pub const Mips_Assembler = 0x8001; | |
| 43 | pub const Upc = 0x8765; | |
| 44 | pub const HP_Bliss = 0x8003; | |
| 45 | pub const HP_Basic91 = 0x8004; | |
| 46 | pub const HP_Pascal91 = 0x8005; | |
| 47 | pub const HP_IMacro = 0x8006; | |
| 48 | pub const HP_Assembler = 0x8007; |
lib/std/dwarf/OP.zig+12| ... | ... | @@ -157,6 +157,18 @@ pub const bit_piece = 0x9d; |
| 157 | 157 | pub const implicit_value = 0x9e; |
| 158 | 158 | pub const stack_value = 0x9f; |
| 159 | 159 | |
| 160 | // DWARF 5 extensions. | |
| 161 | pub const implicit_pointer = 0xa0; | |
| 162 | pub const addrx = 0xa1; | |
| 163 | pub const constx = 0xa2; | |
| 164 | pub const entry_value = 0xa3; | |
| 165 | pub const const_type = 0xa4; | |
| 166 | pub const regval_type = 0xa5; | |
| 167 | pub const deref_type = 0xa6; | |
| 168 | pub const xderef_type = 0xa7; | |
| 169 | pub const convert = 0xa8; | |
| 170 | pub const reinterpret = 0xa9; | |
| 171 | ||
| 160 | 172 | pub const lo_user = 0xe0; // Implementation-defined range start. |
| 161 | 173 | pub const hi_user = 0xff; // Implementation-defined range end. |
| 162 | 174 |
lib/std/dwarf/TAG.zig+10| ... | ... | @@ -65,6 +65,16 @@ pub const type_unit = 0x41; |
| 65 | 65 | pub const rvalue_reference_type = 0x42; |
| 66 | 66 | pub const template_alias = 0x43; |
| 67 | 67 | |
| 68 | // DWARF 5 | |
| 69 | pub const coarray_type = 0x44; | |
| 70 | pub const generic_subrange = 0x45; | |
| 71 | pub const dynamic_type = 0x46; | |
| 72 | pub const atomic_type = 0x47; | |
| 73 | pub const call_site = 0x48; | |
| 74 | pub const call_site_parameter = 0x49; | |
| 75 | pub const skeleton_unit = 0x4a; | |
| 76 | pub const immutable_type = 0x4b; | |
| 77 | ||
| 68 | 78 | pub const lo_user = 0x4080; |
| 69 | 79 | pub const hi_user = 0xffff; |
| 70 | 80 |
src/link/MachO/Object.zig+13| ... | ... | @@ -38,6 +38,7 @@ dwarf_debug_info_index: ?u16 = null, |
| 38 | 38 | dwarf_debug_abbrev_index: ?u16 = null, |
| 39 | 39 | dwarf_debug_str_index: ?u16 = null, |
| 40 | 40 | dwarf_debug_line_index: ?u16 = null, |
| 41 | dwarf_debug_line_str_index: ?u16 = null, | |
| 41 | 42 | dwarf_debug_ranges_index: ?u16 = null, |
| 42 | 43 | |
| 43 | 44 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| ... | ... | @@ -68,6 +69,7 @@ const DebugInfo = struct { |
| 68 | 69 | debug_abbrev: []u8, |
| 69 | 70 | debug_str: []u8, |
| 70 | 71 | debug_line: []u8, |
| 72 | debug_line_str: []u8, | |
| 71 | 73 | debug_ranges: []u8, |
| 72 | 74 | |
| 73 | 75 | pub fn parseFromObject(allocator: Allocator, object: *const Object) !?DebugInfo { |
| ... | ... | @@ -87,6 +89,12 @@ const DebugInfo = struct { |
| 87 | 89 | const index = object.dwarf_debug_line_index orelse return null; |
| 88 | 90 | break :blk try object.readSection(allocator, index); |
| 89 | 91 | }; |
| 92 | var debug_line_str = blk: { | |
| 93 | if (object.dwarf_debug_line_str_index) |ind| { | |
| 94 | break :blk try object.readSection(allocator, ind); | |
| 95 | } | |
| 96 | break :blk try allocator.alloc(u8, 0); | |
| 97 | }; | |
| 90 | 98 | var debug_ranges = blk: { |
| 91 | 99 | if (object.dwarf_debug_ranges_index) |ind| { |
| 92 | 100 | break :blk try object.readSection(allocator, ind); |
| ... | ... | @@ -100,6 +108,7 @@ const DebugInfo = struct { |
| 100 | 108 | .debug_abbrev = debug_abbrev, |
| 101 | 109 | .debug_str = debug_str, |
| 102 | 110 | .debug_line = debug_line, |
| 111 | .debug_line_str = debug_line_str, | |
| 103 | 112 | .debug_ranges = debug_ranges, |
| 104 | 113 | }; |
| 105 | 114 | try dwarf.openDwarfDebugInfo(&inner, allocator); |
| ... | ... | @@ -110,6 +119,7 @@ const DebugInfo = struct { |
| 110 | 119 | .debug_abbrev = debug_abbrev, |
| 111 | 120 | .debug_str = debug_str, |
| 112 | 121 | .debug_line = debug_line, |
| 122 | .debug_line_str = debug_line_str, | |
| 113 | 123 | .debug_ranges = debug_ranges, |
| 114 | 124 | }; |
| 115 | 125 | } |
| ... | ... | @@ -119,6 +129,7 @@ const DebugInfo = struct { |
| 119 | 129 | allocator.free(self.debug_abbrev); |
| 120 | 130 | allocator.free(self.debug_str); |
| 121 | 131 | allocator.free(self.debug_line); |
| 132 | allocator.free(self.debug_line_str); | |
| 122 | 133 | allocator.free(self.debug_ranges); |
| 123 | 134 | self.inner.abbrev_table_list.deinit(); |
| 124 | 135 | self.inner.compile_unit_list.deinit(); |
| ... | ... | @@ -285,6 +296,8 @@ pub fn readLoadCommands(self: *Object, allocator: Allocator, reader: anytype) !v |
| 285 | 296 | self.dwarf_debug_str_index = index; |
| 286 | 297 | } else if (mem.eql(u8, sectname, "__debug_line")) { |
| 287 | 298 | self.dwarf_debug_line_index = index; |
| 299 | } else if (mem.eql(u8, sectname, "__debug_line_str")) { | |
| 300 | self.dwarf_debug_line_str_index = index; | |
| 288 | 301 | } else if (mem.eql(u8, sectname, "__debug_ranges")) { |
| 289 | 302 | self.dwarf_debug_ranges_index = index; |
| 290 | 303 | } |