| ... | @@ -404,26 +404,30 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us | ... | @@ -404,26 +404,30 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us |
| 404 | | 404 | |
| 405 | /// TODO resources https://github.com/ziglang/zig/issues/4353 | 405 | /// TODO resources https://github.com/ziglang/zig/issues/4353 |
| 406 | fn printSourceAtAddressWindows( | 406 | fn printSourceAtAddressWindows( |
| 407 | di1: *DebugInfo, | 407 | debug_info: *DebugInfo, |
| 408 | out_stream: var, | 408 | out_stream: var, |
| 409 | relocated_address: usize, | 409 | address: usize, |
| 410 | tty_config: TTY.Config, | 410 | tty_config: TTY.Config, |
| 411 | ) !void { | 411 | ) !void { |
| 412 | const di = try di1.lookupByAddress(relocated_address); | 412 | const allocator = debug_info.allocator; |
| 413 | | 413 | |
| 414 | const allocator = getDebugInfoAllocator(); | 414 | const module = debug_info.lookupByAddress(address) catch |err| switch (err) { |
| 415 | const base_address = di.base_address; | 415 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 416 | const relative_address = relocated_address - base_address; | 416 | return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); |
| | 417 | }, |
| | 418 | else => return err, |
| | 419 | }; |
| | 420 | const relocated_address = address - module.base_address; |
| 417 | | 421 | |
| 418 | var coff_section: *coff.Section = undefined; | 422 | var coff_section: *coff.Section = undefined; |
| 419 | const mod_index = for (di.sect_contribs) |sect_contrib| { | 423 | const mod_index = for (module.sect_contribs) |sect_contrib| { |
| 420 | if (sect_contrib.Section > di.coff.sections.len) continue; | 424 | if (sect_contrib.Section > module.coff.sections.len) continue; |
| 421 | // Remember that SectionContribEntry.Section is 1-based. | 425 | // Remember that SectionContribEntry.Section is 1-based. |
| 422 | coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1]; | 426 | coff_section = &module.coff.sections.toSlice()[sect_contrib.Section - 1]; |
| 423 | | 427 | |
| 424 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; | 428 | const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; |
| 425 | const vaddr_end = vaddr_start + sect_contrib.Size; | 429 | const vaddr_end = vaddr_start + sect_contrib.Size; |
| 426 | if (relative_address >= vaddr_start and relative_address < vaddr_end) { | 430 | if (relocated_address >= vaddr_start and relocated_address < vaddr_end) { |
| 427 | break sect_contrib.ModuleIndex; | 431 | break sect_contrib.ModuleIndex; |
| 428 | } | 432 | } |
| 429 | } else { | 433 | } else { |
| ... | @@ -431,8 +435,8 @@ fn printSourceAtAddressWindows( | ... | @@ -431,8 +435,8 @@ fn printSourceAtAddressWindows( |
| 431 | return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs); | 435 | return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs); |
| 432 | }; | 436 | }; |
| 433 | | 437 | |
| 434 | const mod = &di.modules[mod_index]; | 438 | const mod = &module.modules[mod_index]; |
| 435 | try populateModule(di, mod); | 439 | try populateModule(module, mod); |
| 436 | const obj_basename = fs.path.basename(mod.obj_file_name); | 440 | const obj_basename = fs.path.basename(mod.obj_file_name); |
| 437 | | 441 | |
| 438 | var symbol_i: usize = 0; | 442 | var symbol_i: usize = 0; |
| ... | @@ -445,7 +449,7 @@ fn printSourceAtAddressWindows( | ... | @@ -445,7 +449,7 @@ fn printSourceAtAddressWindows( |
| 445 | const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]); | 449 | const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]); |
| 446 | const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset; | 450 | const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset; |
| 447 | const vaddr_end = vaddr_start + proc_sym.CodeSize; | 451 | const vaddr_end = vaddr_start + proc_sym.CodeSize; |
| 448 | if (relative_address >= vaddr_start and relative_address < vaddr_end) { | 452 | if (relocated_address >= vaddr_start and relocated_address < vaddr_end) { |
| 449 | break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym)); | 453 | break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym)); |
| 450 | } | 454 | } |
| 451 | }, | 455 | }, |
| ... | @@ -477,7 +481,7 @@ fn printSourceAtAddressWindows( | ... | @@ -477,7 +481,7 @@ fn printSourceAtAddressWindows( |
| 477 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; | 481 | const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset; |
| 478 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; | 482 | const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize; |
| 479 | | 483 | |
| 480 | if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) { | 484 | if (relocated_address >= frag_vaddr_start and relocated_address < frag_vaddr_end) { |
| 481 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) | 485 | // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) |
| 482 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, | 486 | // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, |
| 483 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. | 487 | // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. |
| ... | @@ -491,7 +495,8 @@ fn printSourceAtAddressWindows( | ... | @@ -491,7 +495,8 @@ fn printSourceAtAddressWindows( |
| 491 | const has_column = line_hdr.Flags.LF_HaveColumns; | 495 | const has_column = line_hdr.Flags.LF_HaveColumns; |
| 492 | | 496 | |
| 493 | // All line entries are stored inside their line block by ascending start address. | 497 | // All line entries are stored inside their line block by ascending start address. |
| 494 | // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address. | 498 | // Heuristic: we want to find the last line entry |
| | 499 | // that has a vaddr_start <= relocated_address. |
| 495 | // This is done with a simple linear search. | 500 | // This is done with a simple linear search. |
| 496 | var line_i: u32 = 0; | 501 | var line_i: u32 = 0; |
| 497 | while (line_i < block_hdr.NumLines) : (line_i += 1) { | 502 | while (line_i < block_hdr.NumLines) : (line_i += 1) { |
| ... | @@ -499,7 +504,7 @@ fn printSourceAtAddressWindows( | ... | @@ -499,7 +504,7 @@ fn printSourceAtAddressWindows( |
| 499 | line_index += @sizeOf(pdb.LineNumberEntry); | 504 | line_index += @sizeOf(pdb.LineNumberEntry); |
| 500 | | 505 | |
| 501 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; | 506 | const vaddr_start = frag_vaddr_start + line_num_entry.Offset; |
| 502 | if (relative_address < vaddr_start) { | 507 | if (relocated_address < vaddr_start) { |
| 503 | break; | 508 | break; |
| 504 | } | 509 | } |
| 505 | } | 510 | } |
| ... | @@ -509,8 +514,8 @@ fn printSourceAtAddressWindows( | ... | @@ -509,8 +514,8 @@ fn printSourceAtAddressWindows( |
| 509 | const subsect_index = checksum_offset + block_hdr.NameIndex; | 514 | const subsect_index = checksum_offset + block_hdr.NameIndex; |
| 510 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); | 515 | const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]); |
| 511 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; | 516 | const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset; |
| 512 | try di.pdb.string_table.seekTo(strtab_offset); | 517 | try module.pdb.string_table.seekTo(strtab_offset); |
| 513 | const source_file_name = try di.pdb.string_table.readNullTermString(allocator); | 518 | const source_file_name = try module.pdb.string_table.readNullTermString(allocator); |
| 514 | | 519 | |
| 515 | const line_entry_idx = line_i - 1; | 520 | const line_entry_idx = line_i - 1; |
| 516 | | 521 | |
| ... | @@ -696,24 +701,28 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach | ... | @@ -696,24 +701,28 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach |
| 696 | return null; | 701 | return null; |
| 697 | } | 702 | } |
| 698 | | 703 | |
| 699 | fn printSourceAtAddressMacOs(di1: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { | 704 | fn printSourceAtAddressMacOs(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { |
| 700 | const di = try di1.lookupByAddress(address); | 705 | const module = debug_info.lookupByAddress(address) catch |err| switch (err) { |
| | 706 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| | 707 | return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); |
| | 708 | }, |
| | 709 | else => return err, |
| | 710 | }; |
| 701 | | 711 | |
| 702 | const base_addr = di.base_address; | 712 | const relocated_address = address - module.base_address; |
| 703 | const adjusted_addr = address - base_addr; | 713 | assert(relocated_address >= 0x100000000); |
| 704 | assert(adjusted_addr >= 0x100000000); | | |
| 705 | | 714 | |
| 706 | const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse { | 715 | const symbol = machoSearchSymbols(module.symbols, relocated_address) orelse { |
| 707 | return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); | 716 | return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); |
| 708 | }; | 717 | }; |
| 709 | | 718 | |
| 710 | const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx)); | 719 | const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, module.strings.ptr + symbol.nlist.n_strx)); |
| 711 | const compile_unit_name = if (symbol.ofile) |ofile| blk: { | 720 | const compile_unit_name = if (symbol.ofile) |ofile| blk: { |
| 712 | const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx)); | 721 | const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, module.strings.ptr + ofile.n_strx)); |
| 713 | break :blk fs.path.basename(ofile_path); | 722 | break :blk fs.path.basename(ofile_path); |
| 714 | } else "???"; | 723 | } else "???"; |
| 715 | | 724 | |
| 716 | const line_info = getLineNumberInfoMacOs(di, symbol.*, adjusted_addr) catch |err| switch (err) { | 725 | const line_info = getLineNumberInfoMacOs(module, symbol.*, relocated_address) catch |err| switch (err) { |
| 717 | error.MissingDebugInfo, error.InvalidDebugInfo => null, | 726 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| 718 | else => return err, | 727 | else => return err, |
| 719 | }; | 728 | }; |
| ... | @@ -731,37 +740,41 @@ fn printSourceAtAddressMacOs(di1: *DebugInfo, out_stream: var, address: usize, t | ... | @@ -731,37 +740,41 @@ fn printSourceAtAddressMacOs(di1: *DebugInfo, out_stream: var, address: usize, t |
| 731 | } | 740 | } |
| 732 | | 741 | |
| 733 | pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { | 742 | pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { |
| 734 | // XXX Print as much as possible anyway | 743 | var symbol_name: []const u8 = ""; |
| 735 | const module = try debug_info.lookupByAddress(address); | 744 | var compile_unit_name: []const u8 = ""; |
| 736 | | 745 | var line_info: ?LineInfo = null; |
| 737 | const reloc_address = address - module.base_address; | 746 | |
| 738 | | 747 | if (debug_info.lookupByAddress(address)) |module| { |
| 739 | if (module.dwarf.findCompileUnit(reloc_address) catch null) |compile_unit| { | 748 | // Translate the VA into an address into this object |
| 740 | const compile_unit_name = try compile_unit.die.getAttrString(&module.dwarf, DW.AT_name); | 749 | const relocated_address = address - module.base_address; |
| 741 | const symbol_name = module.dwarf.getSymbolName(reloc_address) orelse "???"; | 750 | |
| 742 | const line_info = module.dwarf.getLineNumberInfo(compile_unit.*, reloc_address) catch |err| switch (err) { | 751 | if (module.dwarf.findCompileUnit(relocated_address)) |compile_unit| { |
| 743 | error.MissingDebugInfo, error.InvalidDebugInfo => null, | 752 | symbol_name = module.dwarf.getSymbolName(relocated_address) orelse "???"; |
| | 753 | compile_unit_name = compile_unit.die.getAttrString(&module.dwarf, DW.AT_name) catch |err| switch (err) { |
| | 754 | error.MissingDebugInfo, error.InvalidDebugInfo => "???", |
| | 755 | else => return err, |
| | 756 | }; |
| | 757 | line_info = module.dwarf.getLineNumberInfo(compile_unit.*, relocated_address) catch |err| switch (err) { |
| | 758 | error.MissingDebugInfo, error.InvalidDebugInfo => null, |
| | 759 | else => return err, |
| | 760 | }; |
| | 761 | } else |err| switch (err) { |
| | 762 | error.MissingDebugInfo, error.InvalidDebugInfo => {}, |
| 744 | else => return err, | 763 | else => return err, |
| 745 | }; | 764 | } |
| 746 | defer if (line_info) |li| li.deinit(); | 765 | } else |err| switch (err) { |
| 747 | | 766 | error.MissingDebugInfo, error.InvalidDebugInfo => {}, |
| 748 | return printLineInfo( | 767 | else => return err, |
| 749 | out_stream, | | |
| 750 | line_info, | | |
| 751 | address, | | |
| 752 | symbol_name, | | |
| 753 | compile_unit_name, | | |
| 754 | tty_config, | | |
| 755 | printLineFromFileAnyOs, | | |
| 756 | ); | | |
| 757 | } | 768 | } |
| 758 | | 769 | |
| | 770 | defer if (line_info) |li| li.deinit(); |
| | 771 | |
| 759 | return printLineInfo( | 772 | return printLineInfo( |
| 760 | out_stream, | 773 | out_stream, |
| 761 | null, | 774 | line_info, |
| 762 | address, | 775 | address, |
| 763 | "???", | 776 | symbol_name, |
| 764 | "???", | 777 | compile_unit_name, |
| 765 | tty_config, | 778 | tty_config, |
| 766 | printLineFromFileAnyOs, | 779 | printLineFromFileAnyOs, |
| 767 | ); | 780 | ); |
| ... | @@ -1286,7 +1299,7 @@ pub const DebugInfo = struct { | ... | @@ -1286,7 +1299,7 @@ pub const DebugInfo = struct { |
| 1286 | } | 1299 | } |
| 1287 | } | 1300 | } |
| 1288 | | 1301 | |
| 1289 | return error.DebugInfoNotFound; | 1302 | return error.MissingDebugInfo; |
| 1290 | } | 1303 | } |
| 1291 | | 1304 | |
| 1292 | fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo { | 1305 | fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo { |
| ... | @@ -1301,7 +1314,7 @@ pub const DebugInfo = struct { | ... | @@ -1301,7 +1314,7 @@ pub const DebugInfo = struct { |
| 1301 | 0, | 1314 | 0, |
| 1302 | &bytes_needed, | 1315 | &bytes_needed, |
| 1303 | ) == 0) | 1316 | ) == 0) |
| 1304 | return error.DebugInfoNotFound; | 1317 | return error.MissingDebugInfo; |
| 1305 | | 1318 | |
| 1306 | const needed_modules = bytes_needed / @sizeOf(windows.HMODULE); | 1319 | const needed_modules = bytes_needed / @sizeOf(windows.HMODULE); |
| 1307 | | 1320 | |
| ... | @@ -1314,7 +1327,7 @@ pub const DebugInfo = struct { | ... | @@ -1314,7 +1327,7 @@ pub const DebugInfo = struct { |
| 1314 | try math.cast(windows.DWORD, modules.len * @sizeOf(windows.HMODULE)), | 1327 | try math.cast(windows.DWORD, modules.len * @sizeOf(windows.HMODULE)), |
| 1315 | &bytes_needed, | 1328 | &bytes_needed, |
| 1316 | ) == 0) | 1329 | ) == 0) |
| 1317 | return error.DebugInfoNotFound; | 1330 | return error.MissingDebugInfo; |
| 1318 | | 1331 | |
| 1319 | // There's an unavoidable TOCTOU problem here, the module list may have | 1332 | // There's an unavoidable TOCTOU problem here, the module list may have |
| 1320 | // changed between the two EnumProcessModules call. | 1333 | // changed between the two EnumProcessModules call. |
| ... | @@ -1330,7 +1343,7 @@ pub const DebugInfo = struct { | ... | @@ -1330,7 +1343,7 @@ pub const DebugInfo = struct { |
| 1330 | &info, | 1343 | &info, |
| 1331 | @sizeOf(@TypeOf(info)), | 1344 | @sizeOf(@TypeOf(info)), |
| 1332 | ) == 0) | 1345 | ) == 0) |
| 1333 | return error.DebugInfoNotFound; | 1346 | return error.MissingDebugInfo; |
| 1334 | | 1347 | |
| 1335 | const seg_start = @ptrToInt(info.lpBaseOfDll); | 1348 | const seg_start = @ptrToInt(info.lpBaseOfDll); |
| 1336 | const seg_end = seg_start + info.SizeOfImage; | 1349 | const seg_end = seg_start + info.SizeOfImage; |
| ... | @@ -1363,7 +1376,7 @@ pub const DebugInfo = struct { | ... | @@ -1363,7 +1376,7 @@ pub const DebugInfo = struct { |
| 1363 | } | 1376 | } |
| 1364 | } | 1377 | } |
| 1365 | | 1378 | |
| 1366 | return error.DebugInfoNotFound; | 1379 | return error.MissingDebugInfo; |
| 1367 | } | 1380 | } |
| 1368 | | 1381 | |
| 1369 | fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo { | 1382 | fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo { |
| ... | @@ -1403,10 +1416,10 @@ pub const DebugInfo = struct { | ... | @@ -1403,10 +1416,10 @@ pub const DebugInfo = struct { |
| 1403 | } | 1416 | } |
| 1404 | } | 1417 | } |
| 1405 | }.callback)) { | 1418 | }.callback)) { |
| 1406 | return error.DebugInfoNotFound; | 1419 | return error.MissingDebugInfo; |
| 1407 | } else |err| switch (err) { | 1420 | } else |err| switch (err) { |
| 1408 | error.Found => {}, | 1421 | error.Found => {}, |
| 1409 | else => return error.DebugInfoNotFound, | 1422 | else => return error.MissingDebugInfo, |
| 1410 | } | 1423 | } |
| 1411 | | 1424 | |
| 1412 | if (self.address_map.getValue(ctx.base_address)) |obj_di| { | 1425 | if (self.address_map.getValue(ctx.base_address)) |obj_di| { |