| ... | ... | @@ -284,7 +284,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 284 | 284 | const mod_index = for (di.sect_contribs) |sect_contrib| { |
| 285 | 285 | if (sect_contrib.Section > di.coff.sections.len) continue; |
| 286 | 286 | // Remember that SectionContribEntry.Section is 1-based. |
| 287 | | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section-1]; |
| 287 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1]; |
| 288 | 288 | |
| 289 | 289 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| 290 | 290 | const vaddr_end = vaddr_start + sect_contrib.Size; |
| ... | ... | @@ -872,9 +872,14 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 872 | 872 | return list.toOwnedSlice(); |
| 873 | 873 | } |
| 874 | 874 | |
| 875 | | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 875 | pub fn openDwarfDebugInfo( |
| 876 | allocator: *mem.Allocator, |
| 877 | dwarf_seekable_stream: *DwarfSeekableStream, |
| 878 | dwarf_in_stream: *DwarfInStream, |
| 879 | ) !DebugInfo { |
| 876 | 880 | var di = DebugInfo{ |
| 877 | | .self_exe_file = undefined, |
| 881 | .dwarf_seekable_stream = dwarf_seekable_stream, |
| 882 | .dwarf_in_stream = dwarf_in_stream, |
| 878 | 883 | .elf = undefined, |
| 879 | 884 | .debug_info = undefined, |
| 880 | 885 | .debug_abbrev = undefined, |
| ... | ... | @@ -884,10 +889,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 884 | 889 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), |
| 885 | 890 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), |
| 886 | 891 | }; |
| 887 | | di.self_exe_file = try os.openSelfExe(); |
| 888 | | errdefer di.self_exe_file.close(); |
| 889 | | |
| 890 | | try di.elf.openFile(allocator, di.self_exe_file); |
| 892 | try di.elf.openStream(allocator, dwarf_seekable_stream, dwarf_in_stream); |
| 891 | 893 | errdefer di.elf.close(); |
| 892 | 894 | |
| 893 | 895 | di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; |
| ... | ... | @@ -899,6 +901,27 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 899 | 901 | return di; |
| 900 | 902 | } |
| 901 | 903 | |
| 904 | fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 905 | const S = struct { |
| 906 | var self_exe_file: os.File = undefined; |
| 907 | var self_exe_seekable_stream: os.File.SeekableStream = undefined; |
| 908 | var self_exe_in_stream: os.File.InStream = undefined; |
| 909 | }; |
| 910 | S.self_exe_file = try os.openSelfExe(); |
| 911 | errdefer S.self_exe_file.close(); |
| 912 | |
| 913 | S.self_exe_seekable_stream = S.self_exe_file.seekableStream(); |
| 914 | S.self_exe_in_stream = S.self_exe_file.inStream(); |
| 915 | |
| 916 | return openDwarfDebugInfo( |
| 917 | allocator, |
| 918 | // TODO https://github.com/ziglang/zig/issues/764 |
| 919 | @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream), |
| 920 | // TODO https://github.com/ziglang/zig/issues/764 |
| 921 | @ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream), |
| 922 | ); |
| 923 | } |
| 924 | |
| 902 | 925 | pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { |
| 903 | 926 | var file_stream = elf.in_file.inStream(); |
| 904 | 927 | const in = &file_stream.stream; |
| ... | ... | @@ -1053,6 +1076,9 @@ const MachOFile = struct { |
| 1053 | 1076 | sect_debug_line: ?*const macho.section_64, |
| 1054 | 1077 | }; |
| 1055 | 1078 | |
| 1079 | pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror); |
| 1080 | pub const DwarfInStream = io.InStream(anyerror); |
| 1081 | |
| 1056 | 1082 | pub const DebugInfo = switch (builtin.os) { |
| 1057 | 1083 | builtin.Os.macosx => struct { |
| 1058 | 1084 | symbols: []const MachoSymbol, |
| ... | ... | @@ -1077,7 +1103,8 @@ pub const DebugInfo = switch (builtin.os) { |
| 1077 | 1103 | modules: []Module, |
| 1078 | 1104 | }, |
| 1079 | 1105 | builtin.Os.linux => struct { |
| 1080 | | self_exe_file: os.File, |
| 1106 | dwarf_seekable_stream: *DwarfSeekableStream, |
| 1107 | dwarf_in_stream: *DwarfInStream, |
| 1081 | 1108 | elf: elf.Elf, |
| 1082 | 1109 | debug_info: *elf.SectionHeader, |
| 1083 | 1110 | debug_abbrev: *elf.SectionHeader, |
| ... | ... | @@ -1092,13 +1119,10 @@ pub const DebugInfo = switch (builtin.os) { |
| 1092 | 1119 | } |
| 1093 | 1120 | |
| 1094 | 1121 | pub fn readString(self: *DebugInfo) ![]u8 { |
| 1095 | | var in_file_stream = self.self_exe_file.inStream(); |
| 1096 | | const in_stream = &in_file_stream.stream; |
| 1097 | | return readStringRaw(self.allocator(), in_stream); |
| 1122 | return readStringRaw(self.allocator(), self.dwarf_in_stream); |
| 1098 | 1123 | } |
| 1099 | 1124 | |
| 1100 | 1125 | pub fn close(self: *DebugInfo) void { |
| 1101 | | self.self_exe_file.close(); |
| 1102 | 1126 | self.elf.close(); |
| 1103 | 1127 | } |
| 1104 | 1128 | }, |
| ... | ... | @@ -1206,11 +1230,11 @@ const Die = struct { |
| 1206 | 1230 | }; |
| 1207 | 1231 | } |
| 1208 | 1232 | |
| 1209 | | fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 { |
| 1233 | fn getAttrString(self: *const Die, di: *DebugInfo, id: u64) ![]u8 { |
| 1210 | 1234 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; |
| 1211 | 1235 | return switch (form_value.*) { |
| 1212 | 1236 | FormValue.String => |value| value, |
| 1213 | | FormValue.StrPtr => |offset| getString(st, offset), |
| 1237 | FormValue.StrPtr => |offset| getString(di, offset), |
| 1214 | 1238 | else => error.InvalidDebugInfo, |
| 1215 | 1239 | }; |
| 1216 | 1240 | } |
| ... | ... | @@ -1321,10 +1345,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { |
| 1321 | 1345 | return buf.toSlice(); |
| 1322 | 1346 | } |
| 1323 | 1347 | |
| 1324 | | fn getString(st: *DebugInfo, offset: u64) ![]u8 { |
| 1325 | | const pos = st.debug_str.offset + offset; |
| 1326 | | try st.self_exe_file.seekTo(pos); |
| 1327 | | return st.readString(); |
| 1348 | fn getString(di: *DebugInfo, offset: u64) ![]u8 { |
| 1349 | const pos = di.debug_str.offset + offset; |
| 1350 | try di.dwarf_seekable_stream.seekTo(pos); |
| 1351 | return di.readString(); |
| 1328 | 1352 | } |
| 1329 | 1353 | |
| 1330 | 1354 | fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { |
| ... | ... | @@ -1371,14 +1395,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type |
| 1371 | 1395 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 1372 | 1396 | } |
| 1373 | 1397 | |
| 1374 | | const ParseFormValueError = error{ |
| 1375 | | EndOfStream, |
| 1376 | | InvalidDebugInfo, |
| 1377 | | EndOfFile, |
| 1378 | | OutOfMemory, |
| 1379 | | } || std.os.File.ReadError; |
| 1380 | | |
| 1381 | | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue { |
| 1398 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { |
| 1382 | 1399 | return switch (form_id) { |
| 1383 | 1400 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 1384 | 1401 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| ... | ... | @@ -1428,25 +1445,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 |
| 1428 | 1445 | }; |
| 1429 | 1446 | } |
| 1430 | 1447 | |
| 1431 | | fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { |
| 1432 | | const in_file = st.self_exe_file; |
| 1433 | | var in_file_stream = in_file.inStream(); |
| 1434 | | const in_stream = &in_file_stream.stream; |
| 1435 | | var result = AbbrevTable.init(st.allocator()); |
| 1448 | fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable { |
| 1449 | var result = AbbrevTable.init(di.allocator()); |
| 1436 | 1450 | while (true) { |
| 1437 | | const abbrev_code = try readULeb128(in_stream); |
| 1451 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1438 | 1452 | if (abbrev_code == 0) return result; |
| 1439 | 1453 | try result.append(AbbrevTableEntry{ |
| 1440 | 1454 | .abbrev_code = abbrev_code, |
| 1441 | | .tag_id = try readULeb128(in_stream), |
| 1442 | | .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, |
| 1443 | | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), |
| 1455 | .tag_id = try readULeb128(di.dwarf_in_stream), |
| 1456 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, |
| 1457 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), |
| 1444 | 1458 | }); |
| 1445 | 1459 | const attrs = &result.items[result.len - 1].attrs; |
| 1446 | 1460 | |
| 1447 | 1461 | while (true) { |
| 1448 | | const attr_id = try readULeb128(in_stream); |
| 1449 | | const form_id = try readULeb128(in_stream); |
| 1462 | const attr_id = try readULeb128(di.dwarf_in_stream); |
| 1463 | const form_id = try readULeb128(di.dwarf_in_stream); |
| 1450 | 1464 | if (attr_id == 0 and form_id == 0) break; |
| 1451 | 1465 | try attrs.append(AbbrevAttr{ |
| 1452 | 1466 | .attr_id = attr_id, |
| ... | ... | @@ -1458,18 +1472,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { |
| 1458 | 1472 | |
| 1459 | 1473 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 1460 | 1474 | /// seeks in the stream and parses it. |
| 1461 | | fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { |
| 1462 | | for (st.abbrev_table_list.toSlice()) |*header| { |
| 1475 | fn getAbbrevTable(di: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { |
| 1476 | for (di.abbrev_table_list.toSlice()) |*header| { |
| 1463 | 1477 | if (header.offset == abbrev_offset) { |
| 1464 | 1478 | return &header.table; |
| 1465 | 1479 | } |
| 1466 | 1480 | } |
| 1467 | | try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); |
| 1468 | | try st.abbrev_table_list.append(AbbrevTableHeader{ |
| 1481 | try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); |
| 1482 | try di.abbrev_table_list.append(AbbrevTableHeader{ |
| 1469 | 1483 | .offset = abbrev_offset, |
| 1470 | | .table = try parseAbbrevTable(st), |
| 1484 | .table = try parseAbbrevTable(di), |
| 1471 | 1485 | }); |
| 1472 | | return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; |
| 1486 | return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table; |
| 1473 | 1487 | } |
| 1474 | 1488 | |
| 1475 | 1489 | fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry { |
| ... | ... | @@ -1479,23 +1493,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con |
| 1479 | 1493 | return null; |
| 1480 | 1494 | } |
| 1481 | 1495 | |
| 1482 | | fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { |
| 1483 | | const in_file = st.self_exe_file; |
| 1484 | | var in_file_stream = in_file.inStream(); |
| 1485 | | const in_stream = &in_file_stream.stream; |
| 1486 | | const abbrev_code = try readULeb128(in_stream); |
| 1496 | fn parseDie(di: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { |
| 1497 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1487 | 1498 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1488 | 1499 | |
| 1489 | 1500 | var result = Die{ |
| 1490 | 1501 | .tag_id = table_entry.tag_id, |
| 1491 | 1502 | .has_children = table_entry.has_children, |
| 1492 | | .attrs = ArrayList(Die.Attr).init(st.allocator()), |
| 1503 | .attrs = ArrayList(Die.Attr).init(di.allocator()), |
| 1493 | 1504 | }; |
| 1494 | 1505 | try result.attrs.resize(table_entry.attrs.len); |
| 1495 | 1506 | for (table_entry.attrs.toSliceConst()) |attr, i| { |
| 1496 | 1507 | result.attrs.items[i] = Die.Attr{ |
| 1497 | 1508 | .id = attr.attr_id, |
| 1498 | | .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), |
| 1509 | .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64), |
| 1499 | 1510 | }; |
| 1500 | 1511 | } |
| 1501 | 1512 | return result; |
| ... | ... | @@ -1702,19 +1713,15 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1702 | 1713 | fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo { |
| 1703 | 1714 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); |
| 1704 | 1715 | |
| 1705 | | const in_file = di.self_exe_file; |
| 1706 | 1716 | const debug_line_end = di.debug_line.offset + di.debug_line.size; |
| 1707 | 1717 | var this_offset = di.debug_line.offset; |
| 1708 | 1718 | var this_index: usize = 0; |
| 1709 | 1719 | |
| 1710 | | var in_file_stream = in_file.inStream(); |
| 1711 | | const in_stream = &in_file_stream.stream; |
| 1712 | | |
| 1713 | 1720 | while (this_offset < debug_line_end) : (this_index += 1) { |
| 1714 | | try in_file.seekTo(this_offset); |
| 1721 | try di.dwarf_seekable_stream.seekTo(this_offset); |
| 1715 | 1722 | |
| 1716 | 1723 | var is_64: bool = undefined; |
| 1717 | | const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); |
| 1724 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); |
| 1718 | 1725 | if (unit_length == 0) return error.MissingDebugInfo; |
| 1719 | 1726 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1720 | 1727 | |
| ... | ... | @@ -1723,35 +1730,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1723 | 1730 | continue; |
| 1724 | 1731 | } |
| 1725 | 1732 | |
| 1726 | | const version = try in_stream.readInt(di.elf.endian, u16); |
| 1733 | const version = try di.dwarf_in_stream.readInt(di.elf.endian, u16); |
| 1727 | 1734 | // TODO support 3 and 5 |
| 1728 | 1735 | if (version != 2 and version != 4) return error.InvalidDebugInfo; |
| 1729 | 1736 | |
| 1730 | | const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32); |
| 1731 | | const prog_start_offset = (try in_file.getPos()) + prologue_length; |
| 1737 | const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.elf.endian, u64) else try di.dwarf_in_stream.readInt(di.elf.endian, u32); |
| 1738 | const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; |
| 1732 | 1739 | |
| 1733 | | const minimum_instruction_length = try in_stream.readByte(); |
| 1740 | const minimum_instruction_length = try di.dwarf_in_stream.readByte(); |
| 1734 | 1741 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; |
| 1735 | 1742 | |
| 1736 | 1743 | if (version >= 4) { |
| 1737 | 1744 | // maximum_operations_per_instruction |
| 1738 | | _ = try in_stream.readByte(); |
| 1745 | _ = try di.dwarf_in_stream.readByte(); |
| 1739 | 1746 | } |
| 1740 | 1747 | |
| 1741 | | const default_is_stmt = (try in_stream.readByte()) != 0; |
| 1742 | | const line_base = try in_stream.readByteSigned(); |
| 1748 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; |
| 1749 | const line_base = try di.dwarf_in_stream.readByteSigned(); |
| 1743 | 1750 | |
| 1744 | | const line_range = try in_stream.readByte(); |
| 1751 | const line_range = try di.dwarf_in_stream.readByte(); |
| 1745 | 1752 | if (line_range == 0) return error.InvalidDebugInfo; |
| 1746 | 1753 | |
| 1747 | | const opcode_base = try in_stream.readByte(); |
| 1754 | const opcode_base = try di.dwarf_in_stream.readByte(); |
| 1748 | 1755 | |
| 1749 | 1756 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); |
| 1750 | 1757 | |
| 1751 | 1758 | { |
| 1752 | 1759 | var i: usize = 0; |
| 1753 | 1760 | while (i < opcode_base - 1) : (i += 1) { |
| 1754 | | standard_opcode_lengths[i] = try in_stream.readByte(); |
| 1761 | standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); |
| 1755 | 1762 | } |
| 1756 | 1763 | } |
| 1757 | 1764 | |
| ... | ... | @@ -1769,9 +1776,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1769 | 1776 | while (true) { |
| 1770 | 1777 | const file_name = try di.readString(); |
| 1771 | 1778 | if (file_name.len == 0) break; |
| 1772 | | const dir_index = try readULeb128(in_stream); |
| 1773 | | const mtime = try readULeb128(in_stream); |
| 1774 | | const len_bytes = try readULeb128(in_stream); |
| 1779 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1780 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1781 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1775 | 1782 | try file_entries.append(FileEntry{ |
| 1776 | 1783 | .file_name = file_name, |
| 1777 | 1784 | .dir_index = dir_index, |
| ... | ... | @@ -1780,15 +1787,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1780 | 1787 | }); |
| 1781 | 1788 | } |
| 1782 | 1789 | |
| 1783 | | try in_file.seekTo(prog_start_offset); |
| 1790 | try di.dwarf_seekable_stream.seekTo(prog_start_offset); |
| 1784 | 1791 | |
| 1785 | 1792 | while (true) { |
| 1786 | | const opcode = try in_stream.readByte(); |
| 1793 | const opcode = try di.dwarf_in_stream.readByte(); |
| 1787 | 1794 | |
| 1788 | 1795 | if (opcode == DW.LNS_extended_op) { |
| 1789 | | const op_size = try readULeb128(in_stream); |
| 1796 | const op_size = try readULeb128(di.dwarf_in_stream); |
| 1790 | 1797 | if (op_size < 1) return error.InvalidDebugInfo; |
| 1791 | | var sub_op = try in_stream.readByte(); |
| 1798 | var sub_op = try di.dwarf_in_stream.readByte(); |
| 1792 | 1799 | switch (sub_op) { |
| 1793 | 1800 | DW.LNE_end_sequence => { |
| 1794 | 1801 | prog.end_sequence = true; |
| ... | ... | @@ -1796,14 +1803,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1796 | 1803 | return error.MissingDebugInfo; |
| 1797 | 1804 | }, |
| 1798 | 1805 | DW.LNE_set_address => { |
| 1799 | | const addr = try in_stream.readInt(di.elf.endian, usize); |
| 1806 | const addr = try di.dwarf_in_stream.readInt(di.elf.endian, usize); |
| 1800 | 1807 | prog.address = addr; |
| 1801 | 1808 | }, |
| 1802 | 1809 | DW.LNE_define_file => { |
| 1803 | 1810 | const file_name = try di.readString(); |
| 1804 | | const dir_index = try readULeb128(in_stream); |
| 1805 | | const mtime = try readULeb128(in_stream); |
| 1806 | | const len_bytes = try readULeb128(in_stream); |
| 1811 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1812 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1813 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1807 | 1814 | try file_entries.append(FileEntry{ |
| 1808 | 1815 | .file_name = file_name, |
| 1809 | 1816 | .dir_index = dir_index, |
| ... | ... | @@ -1813,7 +1820,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1813 | 1820 | }, |
| 1814 | 1821 | else => { |
| 1815 | 1822 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; |
| 1816 | | try in_file.seekForward(fwd_amt); |
| 1823 | try di.dwarf_seekable_stream.seekForward(fwd_amt); |
| 1817 | 1824 | }, |
| 1818 | 1825 | } |
| 1819 | 1826 | } else if (opcode >= opcode_base) { |
| ... | ... | @@ -1832,19 +1839,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1832 | 1839 | prog.basic_block = false; |
| 1833 | 1840 | }, |
| 1834 | 1841 | DW.LNS_advance_pc => { |
| 1835 | | const arg = try readULeb128(in_stream); |
| 1842 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1836 | 1843 | prog.address += arg * minimum_instruction_length; |
| 1837 | 1844 | }, |
| 1838 | 1845 | DW.LNS_advance_line => { |
| 1839 | | const arg = try readILeb128(in_stream); |
| 1846 | const arg = try readILeb128(di.dwarf_in_stream); |
| 1840 | 1847 | prog.line += arg; |
| 1841 | 1848 | }, |
| 1842 | 1849 | DW.LNS_set_file => { |
| 1843 | | const arg = try readULeb128(in_stream); |
| 1850 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1844 | 1851 | prog.file = arg; |
| 1845 | 1852 | }, |
| 1846 | 1853 | DW.LNS_set_column => { |
| 1847 | | const arg = try readULeb128(in_stream); |
| 1854 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1848 | 1855 | prog.column = arg; |
| 1849 | 1856 | }, |
| 1850 | 1857 | DW.LNS_negate_stmt => { |
| ... | ... | @@ -1858,14 +1865,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1858 | 1865 | prog.address += inc_addr; |
| 1859 | 1866 | }, |
| 1860 | 1867 | DW.LNS_fixed_advance_pc => { |
| 1861 | | const arg = try in_stream.readInt(di.elf.endian, u16); |
| 1868 | const arg = try di.dwarf_in_stream.readInt(di.elf.endian, u16); |
| 1862 | 1869 | prog.address += arg; |
| 1863 | 1870 | }, |
| 1864 | 1871 | DW.LNS_set_prologue_end => {}, |
| 1865 | 1872 | else => { |
| 1866 | 1873 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; |
| 1867 | 1874 | const len_bytes = standard_opcode_lengths[opcode - 1]; |
| 1868 | | try in_file.seekForward(len_bytes); |
| 1875 | try di.dwarf_seekable_stream.seekForward(len_bytes); |
| 1869 | 1876 | }, |
| 1870 | 1877 | } |
| 1871 | 1878 | } |
| ... | ... | @@ -1877,36 +1884,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1877 | 1884 | return error.MissingDebugInfo; |
| 1878 | 1885 | } |
| 1879 | 1886 | |
| 1880 | | fn scanAllCompileUnits(st: *DebugInfo) !void { |
| 1881 | | const debug_info_end = st.debug_info.offset + st.debug_info.size; |
| 1882 | | var this_unit_offset = st.debug_info.offset; |
| 1887 | fn scanAllCompileUnits(di: *DebugInfo) !void { |
| 1888 | const debug_info_end = di.debug_info.offset + di.debug_info.size; |
| 1889 | var this_unit_offset = di.debug_info.offset; |
| 1883 | 1890 | var cu_index: usize = 0; |
| 1884 | 1891 | |
| 1885 | | var in_file_stream = st.self_exe_file.inStream(); |
| 1886 | | const in_stream = &in_file_stream.stream; |
| 1887 | | |
| 1888 | 1892 | while (this_unit_offset < debug_info_end) { |
| 1889 | | try st.self_exe_file.seekTo(this_unit_offset); |
| 1893 | try di.dwarf_seekable_stream.seekTo(this_unit_offset); |
| 1890 | 1894 | |
| 1891 | 1895 | var is_64: bool = undefined; |
| 1892 | | const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); |
| 1896 | const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); |
| 1893 | 1897 | if (unit_length == 0) return; |
| 1894 | 1898 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 1895 | 1899 | |
| 1896 | | const version = try in_stream.readInt(st.elf.endian, u16); |
| 1900 | const version = try di.dwarf_in_stream.readInt(di.elf.endian, u16); |
| 1897 | 1901 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 1898 | 1902 | |
| 1899 | | const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32); |
| 1903 | const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.elf.endian, u64) else try di.dwarf_in_stream.readInt(di.elf.endian, u32); |
| 1900 | 1904 | |
| 1901 | | const address_size = try in_stream.readByte(); |
| 1905 | const address_size = try di.dwarf_in_stream.readByte(); |
| 1902 | 1906 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 1903 | 1907 | |
| 1904 | | const compile_unit_pos = try st.self_exe_file.getPos(); |
| 1905 | | const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset); |
| 1908 | const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); |
| 1909 | const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset); |
| 1906 | 1910 | |
| 1907 | | try st.self_exe_file.seekTo(compile_unit_pos); |
| 1911 | try di.dwarf_seekable_stream.seekTo(compile_unit_pos); |
| 1908 | 1912 | |
| 1909 | | const compile_unit_die = try st.allocator().create(try parseDie(st, abbrev_table, is_64)); |
| 1913 | const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64)); |
| 1910 | 1914 | |
| 1911 | 1915 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; |
| 1912 | 1916 | |
| ... | ... | @@ -1934,7 +1938,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { |
| 1934 | 1938 | } |
| 1935 | 1939 | }; |
| 1936 | 1940 | |
| 1937 | | try st.compile_unit_list.append(CompileUnit{ |
| 1941 | try di.compile_unit_list.append(CompileUnit{ |
| 1938 | 1942 | .version = version, |
| 1939 | 1943 | .is_64 = is_64, |
| 1940 | 1944 | .pc_range = pc_range, |
| ... | ... | @@ -1947,20 +1951,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { |
| 1947 | 1951 | } |
| 1948 | 1952 | } |
| 1949 | 1953 | |
| 1950 | | fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { |
| 1951 | | var in_file_stream = st.self_exe_file.inStream(); |
| 1952 | | const in_stream = &in_file_stream.stream; |
| 1953 | | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| 1954 | fn findCompileUnit(di: *DebugInfo, target_address: u64) !*const CompileUnit { |
| 1955 | for (di.compile_unit_list.toSlice()) |*compile_unit| { |
| 1954 | 1956 | if (compile_unit.pc_range) |range| { |
| 1955 | 1957 | if (target_address >= range.start and target_address < range.end) return compile_unit; |
| 1956 | 1958 | } |
| 1957 | 1959 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| 1958 | 1960 | var base_address: usize = 0; |
| 1959 | | if (st.debug_ranges) |debug_ranges| { |
| 1960 | | try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); |
| 1961 | if (di.debug_ranges) |debug_ranges| { |
| 1962 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); |
| 1961 | 1963 | while (true) { |
| 1962 | | const begin_addr = try in_stream.readIntLe(usize); |
| 1963 | | const end_addr = try in_stream.readIntLe(usize); |
| 1964 | const begin_addr = try di.dwarf_in_stream.readIntLe(usize); |
| 1965 | const end_addr = try di.dwarf_in_stream.readIntLe(usize); |
| 1964 | 1966 | if (begin_addr == 0 and end_addr == 0) { |
| 1965 | 1967 | break; |
| 1966 | 1968 | } |