| ... | @@ -284,7 +284,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres | ... | @@ -284,7 +284,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 284 | const mod_index = for (di.sect_contribs) |sect_contrib| { | 284 | const mod_index = for (di.sect_contribs) |sect_contrib| { |
| 285 | if (sect_contrib.Section > di.coff.sections.len) continue; | 285 | if (sect_contrib.Section > di.coff.sections.len) continue; |
| 286 | // Remember that SectionContribEntry.Section is 1-based. | 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 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; | 289 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| 290 | const vaddr_end = vaddr_start + sect_contrib.Size; | 290 | const vaddr_end = vaddr_start + sect_contrib.Size; |
| ... | @@ -872,9 +872,14 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { | ... | @@ -872,9 +872,14 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { |
| 872 | return list.toOwnedSlice(); | 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 | var di = DebugInfo{ | 880 | var di = DebugInfo{ |
| 877 | .self_exe_file = undefined, | 881 | .dwarf_seekable_stream = dwarf_seekable_stream, |
| | 882 | .dwarf_in_stream = dwarf_in_stream, |
| 878 | .elf = undefined, | 883 | .elf = undefined, |
| 879 | .debug_info = undefined, | 884 | .debug_info = undefined, |
| 880 | .debug_abbrev = undefined, | 885 | .debug_abbrev = undefined, |
| ... | @@ -884,10 +889,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -884,10 +889,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 884 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | 889 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), |
| 885 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | 890 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), |
| 886 | }; | 891 | }; |
| 887 | di.self_exe_file = try os.openSelfExe(); | 892 | try di.elf.openStream(allocator, dwarf_seekable_stream, dwarf_in_stream); |
| 888 | errdefer di.self_exe_file.close(); | | |
| 889 | | | |
| 890 | try di.elf.openFile(allocator, di.self_exe_file); | | |
| 891 | errdefer di.elf.close(); | 893 | errdefer di.elf.close(); |
| 892 | | 894 | |
| 893 | di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; | 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,6 +901,27 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { |
| 899 | return di; | 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 | pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { | 925 | pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { |
| 903 | var file_stream = elf.in_file.inStream(); | 926 | var file_stream = elf.in_file.inStream(); |
| 904 | const in = &file_stream.stream; | 927 | const in = &file_stream.stream; |
| ... | @@ -1053,6 +1076,9 @@ const MachOFile = struct { | ... | @@ -1053,6 +1076,9 @@ const MachOFile = struct { |
| 1053 | sect_debug_line: ?*const macho.section_64, | 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 | pub const DebugInfo = switch (builtin.os) { | 1082 | pub const DebugInfo = switch (builtin.os) { |
| 1057 | builtin.Os.macosx => struct { | 1083 | builtin.Os.macosx => struct { |
| 1058 | symbols: []const MachoSymbol, | 1084 | symbols: []const MachoSymbol, |
| ... | @@ -1077,7 +1103,8 @@ pub const DebugInfo = switch (builtin.os) { | ... | @@ -1077,7 +1103,8 @@ pub const DebugInfo = switch (builtin.os) { |
| 1077 | modules: []Module, | 1103 | modules: []Module, |
| 1078 | }, | 1104 | }, |
| 1079 | builtin.Os.linux => struct { | 1105 | builtin.Os.linux => struct { |
| 1080 | self_exe_file: os.File, | 1106 | dwarf_seekable_stream: *DwarfSeekableStream, |
| | 1107 | dwarf_in_stream: *DwarfInStream, |
| 1081 | elf: elf.Elf, | 1108 | elf: elf.Elf, |
| 1082 | debug_info: *elf.SectionHeader, | 1109 | debug_info: *elf.SectionHeader, |
| 1083 | debug_abbrev: *elf.SectionHeader, | 1110 | debug_abbrev: *elf.SectionHeader, |
| ... | @@ -1092,13 +1119,10 @@ pub const DebugInfo = switch (builtin.os) { | ... | @@ -1092,13 +1119,10 @@ pub const DebugInfo = switch (builtin.os) { |
| 1092 | } | 1119 | } |
| 1093 | | 1120 | |
| 1094 | pub fn readString(self: *DebugInfo) ![]u8 { | 1121 | pub fn readString(self: *DebugInfo) ![]u8 { |
| 1095 | var in_file_stream = self.self_exe_file.inStream(); | 1122 | return readStringRaw(self.allocator(), self.dwarf_in_stream); |
| 1096 | const in_stream = &in_file_stream.stream; | | |
| 1097 | return readStringRaw(self.allocator(), in_stream); | | |
| 1098 | } | 1123 | } |
| 1099 | | 1124 | |
| 1100 | pub fn close(self: *DebugInfo) void { | 1125 | pub fn close(self: *DebugInfo) void { |
| 1101 | self.self_exe_file.close(); | | |
| 1102 | self.elf.close(); | 1126 | self.elf.close(); |
| 1103 | } | 1127 | } |
| 1104 | }, | 1128 | }, |
| ... | @@ -1206,11 +1230,11 @@ const Die = struct { | ... | @@ -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 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; | 1234 | const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; |
| 1211 | return switch (form_value.*) { | 1235 | return switch (form_value.*) { |
| 1212 | FormValue.String => |value| value, | 1236 | FormValue.String => |value| value, |
| 1213 | FormValue.StrPtr => |offset| getString(st, offset), | 1237 | FormValue.StrPtr => |offset| getString(di, offset), |
| 1214 | else => error.InvalidDebugInfo, | 1238 | else => error.InvalidDebugInfo, |
| 1215 | }; | 1239 | }; |
| 1216 | } | 1240 | } |
| ... | @@ -1321,10 +1345,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { | ... | @@ -1321,10 +1345,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { |
| 1321 | return buf.toSlice(); | 1345 | return buf.toSlice(); |
| 1322 | } | 1346 | } |
| 1323 | | 1347 | |
| 1324 | fn getString(st: *DebugInfo, offset: u64) ![]u8 { | 1348 | fn getString(di: *DebugInfo, offset: u64) ![]u8 { |
| 1325 | const pos = st.debug_str.offset + offset; | 1349 | const pos = di.debug_str.offset + offset; |
| 1326 | try st.self_exe_file.seekTo(pos); | 1350 | try di.dwarf_seekable_stream.seekTo(pos); |
| 1327 | return st.readString(); | 1351 | return di.readString(); |
| 1328 | } | 1352 | } |
| 1329 | | 1353 | |
| 1330 | fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { | 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,14 +1395,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type |
| 1371 | return parseFormValueRefLen(allocator, in_stream, block_len); | 1395 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 1372 | } | 1396 | } |
| 1373 | | 1397 | |
| 1374 | const ParseFormValueError = error{ | 1398 | fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { |
| 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 { | | |
| 1382 | return switch (form_id) { | 1399 | return switch (form_id) { |
| 1383 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, | 1400 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 1384 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | 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,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 { | 1448 | fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable { |
| 1432 | const in_file = st.self_exe_file; | 1449 | var result = AbbrevTable.init(di.allocator()); |
| 1433 | var in_file_stream = in_file.inStream(); | | |
| 1434 | const in_stream = &in_file_stream.stream; | | |
| 1435 | var result = AbbrevTable.init(st.allocator()); | | |
| 1436 | while (true) { | 1450 | while (true) { |
| 1437 | const abbrev_code = try readULeb128(in_stream); | 1451 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1438 | if (abbrev_code == 0) return result; | 1452 | if (abbrev_code == 0) return result; |
| 1439 | try result.append(AbbrevTableEntry{ | 1453 | try result.append(AbbrevTableEntry{ |
| 1440 | .abbrev_code = abbrev_code, | 1454 | .abbrev_code = abbrev_code, |
| 1441 | .tag_id = try readULeb128(in_stream), | 1455 | .tag_id = try readULeb128(di.dwarf_in_stream), |
| 1442 | .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, | 1456 | .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, |
| 1443 | .attrs = ArrayList(AbbrevAttr).init(st.allocator()), | 1457 | .attrs = ArrayList(AbbrevAttr).init(di.allocator()), |
| 1444 | }); | 1458 | }); |
| 1445 | const attrs = &result.items[result.len - 1].attrs; | 1459 | const attrs = &result.items[result.len - 1].attrs; |
| 1446 | | 1460 | |
| 1447 | while (true) { | 1461 | while (true) { |
| 1448 | const attr_id = try readULeb128(in_stream); | 1462 | const attr_id = try readULeb128(di.dwarf_in_stream); |
| 1449 | const form_id = try readULeb128(in_stream); | 1463 | const form_id = try readULeb128(di.dwarf_in_stream); |
| 1450 | if (attr_id == 0 and form_id == 0) break; | 1464 | if (attr_id == 0 and form_id == 0) break; |
| 1451 | try attrs.append(AbbrevAttr{ | 1465 | try attrs.append(AbbrevAttr{ |
| 1452 | .attr_id = attr_id, | 1466 | .attr_id = attr_id, |
| ... | @@ -1458,18 +1472,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { | ... | @@ -1458,18 +1472,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { |
| 1458 | | 1472 | |
| 1459 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, | 1473 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 1460 | /// seeks in the stream and parses it. | 1474 | /// seeks in the stream and parses it. |
| 1461 | fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { | 1475 | fn getAbbrevTable(di: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { |
| 1462 | for (st.abbrev_table_list.toSlice()) |*header| { | 1476 | for (di.abbrev_table_list.toSlice()) |*header| { |
| 1463 | if (header.offset == abbrev_offset) { | 1477 | if (header.offset == abbrev_offset) { |
| 1464 | return &header.table; | 1478 | return &header.table; |
| 1465 | } | 1479 | } |
| 1466 | } | 1480 | } |
| 1467 | try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); | 1481 | try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); |
| 1468 | try st.abbrev_table_list.append(AbbrevTableHeader{ | 1482 | try di.abbrev_table_list.append(AbbrevTableHeader{ |
| 1469 | .offset = abbrev_offset, | 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 | fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry { | 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,23 +1493,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con |
| 1479 | return null; | 1493 | return null; |
| 1480 | } | 1494 | } |
| 1481 | | 1495 | |
| 1482 | fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { | 1496 | fn parseDie(di: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { |
| 1483 | const in_file = st.self_exe_file; | 1497 | const abbrev_code = try readULeb128(di.dwarf_in_stream); |
| 1484 | var in_file_stream = in_file.inStream(); | | |
| 1485 | const in_stream = &in_file_stream.stream; | | |
| 1486 | const abbrev_code = try readULeb128(in_stream); | | |
| 1487 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; | 1498 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; |
| 1488 | | 1499 | |
| 1489 | var result = Die{ | 1500 | var result = Die{ |
| 1490 | .tag_id = table_entry.tag_id, | 1501 | .tag_id = table_entry.tag_id, |
| 1491 | .has_children = table_entry.has_children, | 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 | try result.attrs.resize(table_entry.attrs.len); | 1505 | try result.attrs.resize(table_entry.attrs.len); |
| 1495 | for (table_entry.attrs.toSliceConst()) |attr, i| { | 1506 | for (table_entry.attrs.toSliceConst()) |attr, i| { |
| 1496 | result.attrs.items[i] = Die.Attr{ | 1507 | result.attrs.items[i] = Die.Attr{ |
| 1497 | .id = attr.attr_id, | 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 | return result; | 1512 | return result; |
| ... | @@ -1702,19 +1713,15 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u | ... | @@ -1702,19 +1713,15 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u |
| 1702 | fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo { | 1713 | fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo { |
| 1703 | const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); | 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 | const debug_line_end = di.debug_line.offset + di.debug_line.size; | 1716 | const debug_line_end = di.debug_line.offset + di.debug_line.size; |
| 1707 | var this_offset = di.debug_line.offset; | 1717 | var this_offset = di.debug_line.offset; |
| 1708 | var this_index: usize = 0; | 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 | while (this_offset < debug_line_end) : (this_index += 1) { | 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 | var is_64: bool = undefined; | 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 | if (unit_length == 0) return error.MissingDebugInfo; | 1725 | if (unit_length == 0) return error.MissingDebugInfo; |
| 1719 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 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,35 +1730,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1723 | continue; | 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 | // TODO support 3 and 5 | 1734 | // TODO support 3 and 5 |
| 1728 | if (version != 2 and version != 4) return error.InvalidDebugInfo; | 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); | 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); |
| 1731 | const prog_start_offset = (try in_file.getPos()) + prologue_length; | 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 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; | 1741 | if (minimum_instruction_length == 0) return error.InvalidDebugInfo; |
| 1735 | | 1742 | |
| 1736 | if (version >= 4) { | 1743 | if (version >= 4) { |
| 1737 | // maximum_operations_per_instruction | 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; | 1748 | const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; |
| 1742 | const line_base = try in_stream.readByteSigned(); | 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 | if (line_range == 0) return error.InvalidDebugInfo; | 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 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); | 1756 | const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); |
| 1750 | | 1757 | |
| 1751 | { | 1758 | { |
| 1752 | var i: usize = 0; | 1759 | var i: usize = 0; |
| 1753 | while (i < opcode_base - 1) : (i += 1) { | 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,9 +1776,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1769 | while (true) { | 1776 | while (true) { |
| 1770 | const file_name = try di.readString(); | 1777 | const file_name = try di.readString(); |
| 1771 | if (file_name.len == 0) break; | 1778 | if (file_name.len == 0) break; |
| 1772 | const dir_index = try readULeb128(in_stream); | 1779 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1773 | const mtime = try readULeb128(in_stream); | 1780 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1774 | const len_bytes = try readULeb128(in_stream); | 1781 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1775 | try file_entries.append(FileEntry{ | 1782 | try file_entries.append(FileEntry{ |
| 1776 | .file_name = file_name, | 1783 | .file_name = file_name, |
| 1777 | .dir_index = dir_index, | 1784 | .dir_index = dir_index, |
| ... | @@ -1780,15 +1787,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -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 | while (true) { | 1792 | while (true) { |
| 1786 | const opcode = try in_stream.readByte(); | 1793 | const opcode = try di.dwarf_in_stream.readByte(); |
| 1787 | | 1794 | |
| 1788 | if (opcode == DW.LNS_extended_op) { | 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 | if (op_size < 1) return error.InvalidDebugInfo; | 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 | switch (sub_op) { | 1799 | switch (sub_op) { |
| 1793 | DW.LNE_end_sequence => { | 1800 | DW.LNE_end_sequence => { |
| 1794 | prog.end_sequence = true; | 1801 | prog.end_sequence = true; |
| ... | @@ -1796,14 +1803,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1796,14 +1803,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1796 | return error.MissingDebugInfo; | 1803 | return error.MissingDebugInfo; |
| 1797 | }, | 1804 | }, |
| 1798 | DW.LNE_set_address => { | 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 | prog.address = addr; | 1807 | prog.address = addr; |
| 1801 | }, | 1808 | }, |
| 1802 | DW.LNE_define_file => { | 1809 | DW.LNE_define_file => { |
| 1803 | const file_name = try di.readString(); | 1810 | const file_name = try di.readString(); |
| 1804 | const dir_index = try readULeb128(in_stream); | 1811 | const dir_index = try readULeb128(di.dwarf_in_stream); |
| 1805 | const mtime = try readULeb128(in_stream); | 1812 | const mtime = try readULeb128(di.dwarf_in_stream); |
| 1806 | const len_bytes = try readULeb128(in_stream); | 1813 | const len_bytes = try readULeb128(di.dwarf_in_stream); |
| 1807 | try file_entries.append(FileEntry{ | 1814 | try file_entries.append(FileEntry{ |
| 1808 | .file_name = file_name, | 1815 | .file_name = file_name, |
| 1809 | .dir_index = dir_index, | 1816 | .dir_index = dir_index, |
| ... | @@ -1813,7 +1820,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1813,7 +1820,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1813 | }, | 1820 | }, |
| 1814 | else => { | 1821 | else => { |
| 1815 | const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; | 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 | } else if (opcode >= opcode_base) { | 1826 | } else if (opcode >= opcode_base) { |
| ... | @@ -1832,19 +1839,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1832,19 +1839,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1832 | prog.basic_block = false; | 1839 | prog.basic_block = false; |
| 1833 | }, | 1840 | }, |
| 1834 | DW.LNS_advance_pc => { | 1841 | DW.LNS_advance_pc => { |
| 1835 | const arg = try readULeb128(in_stream); | 1842 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1836 | prog.address += arg * minimum_instruction_length; | 1843 | prog.address += arg * minimum_instruction_length; |
| 1837 | }, | 1844 | }, |
| 1838 | DW.LNS_advance_line => { | 1845 | DW.LNS_advance_line => { |
| 1839 | const arg = try readILeb128(in_stream); | 1846 | const arg = try readILeb128(di.dwarf_in_stream); |
| 1840 | prog.line += arg; | 1847 | prog.line += arg; |
| 1841 | }, | 1848 | }, |
| 1842 | DW.LNS_set_file => { | 1849 | DW.LNS_set_file => { |
| 1843 | const arg = try readULeb128(in_stream); | 1850 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1844 | prog.file = arg; | 1851 | prog.file = arg; |
| 1845 | }, | 1852 | }, |
| 1846 | DW.LNS_set_column => { | 1853 | DW.LNS_set_column => { |
| 1847 | const arg = try readULeb128(in_stream); | 1854 | const arg = try readULeb128(di.dwarf_in_stream); |
| 1848 | prog.column = arg; | 1855 | prog.column = arg; |
| 1849 | }, | 1856 | }, |
| 1850 | DW.LNS_negate_stmt => { | 1857 | DW.LNS_negate_stmt => { |
| ... | @@ -1858,14 +1865,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ | ... | @@ -1858,14 +1865,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1858 | prog.address += inc_addr; | 1865 | prog.address += inc_addr; |
| 1859 | }, | 1866 | }, |
| 1860 | DW.LNS_fixed_advance_pc => { | 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 | prog.address += arg; | 1869 | prog.address += arg; |
| 1863 | }, | 1870 | }, |
| 1864 | DW.LNS_set_prologue_end => {}, | 1871 | DW.LNS_set_prologue_end => {}, |
| 1865 | else => { | 1872 | else => { |
| 1866 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; | 1873 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; |
| 1867 | const len_bytes = standard_opcode_lengths[opcode - 1]; | 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,36 +1884,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ |
| 1877 | return error.MissingDebugInfo; | 1884 | return error.MissingDebugInfo; |
| 1878 | } | 1885 | } |
| 1879 | | 1886 | |
| 1880 | fn scanAllCompileUnits(st: *DebugInfo) !void { | 1887 | fn scanAllCompileUnits(di: *DebugInfo) !void { |
| 1881 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | 1888 | const debug_info_end = di.debug_info.offset + di.debug_info.size; |
| 1882 | var this_unit_offset = st.debug_info.offset; | 1889 | var this_unit_offset = di.debug_info.offset; |
| 1883 | var cu_index: usize = 0; | 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 | while (this_unit_offset < debug_info_end) { | 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 | var is_64: bool = undefined; | 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 | if (unit_length == 0) return; | 1897 | if (unit_length == 0) return; |
| 1894 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); | 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 | if (version < 2 or version > 5) return error.InvalidDebugInfo; | 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 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; | 1906 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| 1903 | | 1907 | |
| 1904 | const compile_unit_pos = try st.self_exe_file.getPos(); | 1908 | const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); |
| 1905 | const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset); | 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 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; | 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,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 | .version = version, | 1942 | .version = version, |
| 1939 | .is_64 = is_64, | 1943 | .is_64 = is_64, |
| 1940 | .pc_range = pc_range, | 1944 | .pc_range = pc_range, |
| ... | @@ -1947,20 +1951,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { | ... | @@ -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 { | 1954 | fn findCompileUnit(di: *DebugInfo, target_address: u64) !*const CompileUnit { |
| 1951 | var in_file_stream = st.self_exe_file.inStream(); | 1955 | for (di.compile_unit_list.toSlice()) |*compile_unit| { |
| 1952 | const in_stream = &in_file_stream.stream; | | |
| 1953 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | | |
| 1954 | if (compile_unit.pc_range) |range| { | 1956 | if (compile_unit.pc_range) |range| { |
| 1955 | if (target_address >= range.start and target_address < range.end) return compile_unit; | 1957 | if (target_address >= range.start and target_address < range.end) return compile_unit; |
| 1956 | } | 1958 | } |
| 1957 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { | 1959 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| 1958 | var base_address: usize = 0; | 1960 | var base_address: usize = 0; |
| 1959 | if (st.debug_ranges) |debug_ranges| { | 1961 | if (di.debug_ranges) |debug_ranges| { |
| 1960 | try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); | 1962 | try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); |
| 1961 | while (true) { | 1963 | while (true) { |
| 1962 | const begin_addr = try in_stream.readIntLe(usize); | 1964 | const begin_addr = try di.dwarf_in_stream.readIntLe(usize); |
| 1963 | const end_addr = try in_stream.readIntLe(usize); | 1965 | const end_addr = try di.dwarf_in_stream.readIntLe(usize); |
| 1964 | if (begin_addr == 0 and end_addr == 0) { | 1966 | if (begin_addr == 0 and end_addr == 0) { |
| 1965 | break; | 1967 | break; |
| 1966 | } | 1968 | } |