authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-22 11:51:45+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-22 11:51:45+01:00
logc060cae3ce1a47032b36bd295a3725760145e811
treea93f5fccb2254d38e81979ac1bd372e605b2bfab
parent8df4d7e4f445e8e9598b79bc495503d919c0d99a

unification: osx debug info


1 files changed, 183 insertions(+), 193 deletions(-)

lib/std/debug.zig+183-193
......@@ -396,9 +396,6 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us
396396 if (builtin.os == .windows) {
397397 return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
398398 }
399 if (comptime std.Target.current.isDarwin()) {
400 return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_config);
401 }
402399 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
403400}
404401
......@@ -411,7 +408,7 @@ fn printSourceAtAddressWindows(
411408) !void {
412409 const allocator = debug_info.allocator;
413410
414 const module = debug_info.lookupByAddress(address) catch |err| switch (err) {
411 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
415412 error.MissingDebugInfo, error.InvalidDebugInfo => {
416413 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
417414 },
......@@ -637,7 +634,7 @@ pub const TTY = struct {
637634};
638635
639636/// TODO resources https://github.com/ziglang/zig/issues/4353
640fn populateModule(di: *ObjectDebugInfo, mod: *Module) !void {
637fn populateModule(di: *ModuleDebugInfo, mod: *Module) !void {
641638 if (mod.populated)
642639 return;
643640 const allocator = getDebugInfoAllocator();
......@@ -701,46 +698,8 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
701698 return null;
702699}
703700
704fn printSourceAtAddressMacOs(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
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 };
711
712 const relocated_address = address - module.base_address;
713 assert(relocated_address >= 0x100000000);
714
715 const symbol = machoSearchSymbols(module.symbols, relocated_address) orelse {
716 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
717 };
718
719 const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, module.strings.ptr + symbol.nlist.n_strx));
720 const compile_unit_name = if (symbol.ofile) |ofile| blk: {
721 const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, module.strings.ptr + ofile.n_strx));
722 break :blk fs.path.basename(ofile_path);
723 } else "???";
724
725 const line_info = getLineNumberInfoMacOs(module, symbol.*, relocated_address) catch |err| switch (err) {
726 error.MissingDebugInfo, error.InvalidDebugInfo => null,
727 else => return err,
728 };
729 defer if (line_info) |li| li.deinit();
730
731 try printLineInfo(
732 out_stream,
733 line_info,
734 address,
735 symbol_name,
736 compile_unit_name,
737 tty_config,
738 printLineFromFileAnyOs,
739 );
740}
741
742701pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
743 const module = debug_info.lookupByAddress(address) catch |err| switch (err) {
702 const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
744703 error.MissingDebugInfo, error.InvalidDebugInfo => {
745704 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
746705 },
......@@ -748,7 +707,7 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres
748707 };
749708
750709 const info = try module.getSymbolAtAddress(address);
751 defer if (info.line_info) |li| li.deinit();
710 defer info.deinit();
752711
753712 return printLineInfo(
754713 out_stream,
......@@ -833,14 +792,14 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
833792}
834793
835794/// TODO resources https://github.com/ziglang/zig/issues/4353
836fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ObjectDebugInfo {
795fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ModuleDebugInfo {
837796 const coff_file = try std.fs.openFileAbsoluteW(coff_file_path.ptr, .{});
838797 errdefer coff_file.close();
839798
840799 const coff_obj = try allocator.create(coff.Coff);
841800 coff_obj.* = coff.Coff.init(allocator, coff_file);
842801
843 var di = ObjectDebugInfo{
802 var di = ModuleDebugInfo{
844803 .base_address = undefined,
845804 .coff = coff_obj,
846805 .pdb = undefined,
......@@ -1012,7 +971,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {
1012971}
1013972
1014973/// TODO resources https://github.com/ziglang/zig/issues/4353
1015pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ObjectDebugInfo {
974pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo {
1016975 const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo;
1017976
1018977 var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);
......@@ -1047,7 +1006,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O
10471006
10481007 try DW.openDwarfDebugInfo(&di, allocator);
10491008
1050 return ObjectDebugInfo{
1009 return ModuleDebugInfo{
10511010 .base_address = undefined,
10521011 .dwarf = di,
10531012 .mapped_memory = mapped_mem,
......@@ -1055,14 +1014,15 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O
10551014}
10561015
10571016/// TODO resources https://github.com/ziglang/zig/issues/4353
1058fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ObjectDebugInfo {
1017fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ModuleDebugInfo {
10591018 const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo;
10601019
10611020 const hdr = @ptrCast(
10621021 *const macho.mach_header_64,
10631022 @alignCast(@alignOf(macho.mach_header_64), mapped_mem.ptr),
10641023 );
1065 assert(hdr.magic == std.macho.MH_MAGIC_64);
1024 if (hdr.magic != macho.MH_MAGIC_64)
1025 return error.InvalidDebugInfo;
10661026
10671027 const hdr_base = @ptrCast([*]const u8, hdr);
10681028 var ptr = hdr_base + @sizeOf(macho.mach_header_64);
......@@ -1078,7 +1038,7 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !O
10781038 return error.MissingDebugInfo;
10791039 };
10801040 const syms = @ptrCast([*]const macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];
1081 const strings = @ptrCast([*]const u8, hdr_base + symtab.stroff)[0..symtab.strsize];
1041 const strings = @ptrCast([*]const u8, hdr_base + symtab.stroff)[0..symtab.strsize :0];
10821042
10831043 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
10841044
......@@ -1130,10 +1090,10 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !O
11301090 // This sort is so that we can binary search later.
11311091 std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);
11321092
1133 return ObjectDebugInfo{
1093 return ModuleDebugInfo{
11341094 .base_address = undefined,
11351095 .mapped_memory = mapped_mem,
1136 .ofiles = ObjectDebugInfo.OFileTable.init(allocator),
1096 .ofiles = ModuleDebugInfo.OFileTable.init(allocator),
11371097 .symbols = symbols,
11381098 .strings = strings,
11391099 };
......@@ -1206,12 +1166,12 @@ fn mapWholeFile(path: []const u8) ![]const u8 {
12061166
12071167pub const DebugInfo = struct {
12081168 allocator: *mem.Allocator,
1209 address_map: std.AutoHashMap(usize, *ObjectDebugInfo),
1169 address_map: std.AutoHashMap(usize, *ModuleDebugInfo),
12101170
12111171 pub fn init(allocator: *mem.Allocator) DebugInfo {
12121172 return DebugInfo{
12131173 .allocator = allocator,
1214 .address_map = std.AutoHashMap(usize, *ObjectDebugInfo).init(allocator),
1174 .address_map = std.AutoHashMap(usize, *ModuleDebugInfo).init(allocator),
12151175 };
12161176 }
12171177
......@@ -1220,17 +1180,16 @@ pub const DebugInfo = struct {
12201180 self.address_map.deinit();
12211181 }
12221182
1223 pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1224 const obj_di = if (comptime std.Target.current.isDarwin())
1225 try self.lookupModuleDyld(address)
1183 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1184 if (comptime std.Target.current.isDarwin())
1185 return self.lookupModuleDyld(address)
12261186 else if (builtin.os == .windows)
1227 try self.lookupModuleWin32(address)
1187 return self.lookupModuleWin32(address)
12281188 else
1229 try self.lookupModuleDl(address);
1230 return obj_di;
1189 return self.lookupModuleDl(address);
12311190 }
12321191
1233 fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1192 fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
12341193 const image_count = std.c._dyld_image_count();
12351194
12361195 var i: u32 = 0;
......@@ -1266,7 +1225,7 @@ pub const DebugInfo = struct {
12661225 return obj_di;
12671226 }
12681227
1269 const obj_di = try self.allocator.create(ObjectDebugInfo);
1228 const obj_di = try self.allocator.create(ModuleDebugInfo);
12701229 errdefer self.allocator.destroy(obj_di);
12711230
12721231 try self.address_map.putNoClobber(base_address, obj_di);
......@@ -1283,7 +1242,7 @@ pub const DebugInfo = struct {
12831242 return error.MissingDebugInfo;
12841243 }
12851244
1286 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1245 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
12871246 const process_handle = windows.kernel32.GetCurrentProcess();
12881247
12891248 // Find how many modules are actually loaded
......@@ -1345,7 +1304,7 @@ pub const DebugInfo = struct {
13451304 );
13461305 assert(len > 0);
13471306
1348 const obj_di = try self.allocator.create(ObjectDebugInfo);
1307 const obj_di = try self.allocator.create(ModuleDebugInfo);
13491308 errdefer self.allocator.destroy(obj_di);
13501309
13511310 try self.address_map.putNoClobber(seg_start, obj_di);
......@@ -1360,7 +1319,7 @@ pub const DebugInfo = struct {
13601319 return error.MissingDebugInfo;
13611320 }
13621321
1363 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1322 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
13641323 var ctx: struct {
13651324 // Input
13661325 address: usize,
......@@ -1414,7 +1373,7 @@ pub const DebugInfo = struct {
14141373 break :blk try fs.selfExePath(&buf);
14151374 };
14161375
1417 const obj_di = try self.allocator.create(ObjectDebugInfo);
1376 const obj_di = try self.allocator.create(ModuleDebugInfo);
14181377 errdefer self.allocator.destroy(obj_di);
14191378
14201379 try self.address_map.putNoClobber(ctx.base_address, obj_di);
......@@ -1427,29 +1386,173 @@ pub const DebugInfo = struct {
14271386};
14281387
14291388const SymbolInfo = struct {
1430 symbol_name: []const u8,
1431 compile_unit_name: []const u8,
1432 line_info: ?LineInfo,
1389 symbol_name: []const u8 = "???",
1390 compile_unit_name: []const u8 = "???",
1391 line_info: ?LineInfo = null,
1392
1393 fn deinit(self: @This()) void {
1394 if (self.line_info) |li| {
1395 li.deinit();
1396 }
1397 }
14331398};
14341399
1435pub const ObjectDebugInfo = switch (builtin.os) {
1400pub const ModuleDebugInfo = switch (builtin.os) {
14361401 .macosx, .ios, .watchos, .tvos => struct {
14371402 base_address: usize,
14381403 mapped_memory: []const u8,
14391404 symbols: []const MachoSymbol,
1440 strings: []const u8,
1405 strings: [:0]const u8,
14411406 ofiles: OFileTable,
14421407
1443 const OFileTable = std.HashMap(
1444 *const macho.nlist_64,
1445 DW.DwarfInfo,
1446 std.hash_map.getHashPtrAddrFn(*const macho.nlist_64),
1447 std.hash_map.getTrivialEqlFn(*const macho.nlist_64),
1448 );
1408 const OFileTable = std.StringHashMap(DW.DwarfInfo);
14491409
14501410 pub fn allocator(self: @This()) *mem.Allocator {
14511411 return self.ofiles.allocator;
14521412 }
1413
1414 fn loadOFile(self: *@This(), o_file_path: []const u8) !DW.DwarfInfo {
1415 const mapped_mem = mapWholeFile(o_file_path) catch |_| return error.InvalidDebugInfo;
1416
1417 const hdr = @ptrCast(
1418 *const macho.mach_header_64,
1419 @alignCast(@alignOf(macho.mach_header_64), mapped_mem.ptr),
1420 );
1421 if (hdr.magic != std.macho.MH_MAGIC_64)
1422 return error.InvalidDebugInfo;
1423
1424 const hdr_base = @ptrCast([*]const u8, hdr);
1425 var ptr = hdr_base + @sizeOf(macho.mach_header_64);
1426 var ncmd: u32 = hdr.ncmds;
1427 const segcmd = while (ncmd != 0) : (ncmd -= 1) {
1428 const lc = @ptrCast(*const std.macho.load_command, ptr);
1429 switch (lc.cmd) {
1430 std.macho.LC_SEGMENT_64 => {
1431 break @ptrCast(
1432 *const std.macho.segment_command_64,
1433 @alignCast(@alignOf(std.macho.segment_command_64), ptr),
1434 );
1435 },
1436 else => {},
1437 }
1438 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
1439 } else {
1440 return error.MissingDebugInfo;
1441 };
1442
1443 var opt_debug_line: ?*const macho.section_64 = null;
1444 var opt_debug_info: ?*const macho.section_64 = null;
1445 var opt_debug_abbrev: ?*const macho.section_64 = null;
1446 var opt_debug_str: ?*const macho.section_64 = null;
1447 var opt_debug_ranges: ?*const macho.section_64 = null;
1448
1449 const sections = @ptrCast(
1450 [*]const macho.section_64,
1451 @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)),
1452 )[0..segcmd.nsects];
1453 for (sections) |*sect| {
1454 // The section name may not exceed 16 chars and a trailing null may
1455 // not be present
1456 const name = if (mem.indexOfScalar(u8, sect.sectname[0..], 0)) |last|
1457 sect.sectname[0..last]
1458 else
1459 sect.sectname[0..];
1460
1461 if (mem.eql(u8, name, "__debug_line")) {
1462 opt_debug_line = sect;
1463 } else if (mem.eql(u8, name, "__debug_info")) {
1464 opt_debug_info = sect;
1465 } else if (mem.eql(u8, name, "__debug_abbrev")) {
1466 opt_debug_abbrev = sect;
1467 } else if (mem.eql(u8, name, "__debug_str")) {
1468 opt_debug_str = sect;
1469 } else if (mem.eql(u8, name, "__debug_ranges")) {
1470 opt_debug_ranges = sect;
1471 }
1472 }
1473
1474 const debug_line = opt_debug_line orelse
1475 return error.MissingDebugInfo;
1476 const debug_info = opt_debug_info orelse
1477 return error.MissingDebugInfo;
1478 const debug_str = opt_debug_str orelse
1479 return error.MissingDebugInfo;
1480 const debug_abbrev = opt_debug_abbrev orelse
1481 return error.MissingDebugInfo;
1482
1483 var di = DW.DwarfInfo{
1484 .endian = .Little,
1485 .debug_info = try chopSlice(mapped_mem, debug_info.offset, debug_info.size),
1486 .debug_abbrev = try chopSlice(mapped_mem, debug_abbrev.offset, debug_abbrev.size),
1487 .debug_str = try chopSlice(mapped_mem, debug_str.offset, debug_str.size),
1488 .debug_line = try chopSlice(mapped_mem, debug_line.offset, debug_line.size),
1489 .debug_ranges = if (opt_debug_ranges) |debug_ranges|
1490 try chopSlice(mapped_mem, debug_ranges.offset, debug_ranges.size)
1491 else
1492 null,
1493 };
1494
1495 try DW.openDwarfDebugInfo(&di, self.allocator());
1496
1497 // Add the debug info to the cache
1498 try self.ofiles.putNoClobber(o_file_path, di);
1499
1500 return di;
1501 }
1502
1503 fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
1504 // Translate the VA into an address into this object
1505 const relocated_address = address - self.base_address;
1506 assert(relocated_address >= 0x100000000);
1507
1508 // Find the .o file where this symbol is defined
1509 const symbol = machoSearchSymbols(self.symbols, relocated_address) orelse
1510 return SymbolInfo{};
1511
1512 // XXX: Return the symbol name
1513 if (symbol.ofile == null)
1514 return SymbolInfo{};
1515
1516 assert(symbol.ofile.?.n_strx < self.strings.len);
1517 const o_file_path = mem.toSliceConst(u8, self.strings.ptr + symbol.ofile.?.n_strx);
1518
1519 warn("Loading .o file: {s}\n", .{o_file_path});
1520
1521 // Check if its debug infos are already in the cache
1522 var o_file_di = self.ofiles.getValue(o_file_path) orelse
1523 (self.loadOFile(o_file_path) catch |err| switch (err) {
1524 error.MissingDebugInfo, error.InvalidDebugInfo => {
1525 // XXX: Return the symbol name
1526 return SymbolInfo{};
1527 },
1528 else => return err,
1529 });
1530
1531 // Translate again the address, this time into an address inside the
1532 // .o file
1533 const relocated_address_o = relocated_address - symbol.reloc;
1534
1535 if (o_file_di.findCompileUnit(relocated_address_o)) |compile_unit| {
1536 return SymbolInfo{
1537 .symbol_name = o_file_di.getSymbolName(relocated_address_o) orelse "???",
1538 .compile_unit_name = compile_unit.die.getAttrString(&o_file_di, DW.AT_name) catch |err| switch (err) {
1539 error.MissingDebugInfo, error.InvalidDebugInfo => "???",
1540 else => return err,
1541 },
1542 .line_info = o_file_di.getLineNumberInfo(compile_unit.*, relocated_address_o) catch |err| switch (err) {
1543 error.MissingDebugInfo, error.InvalidDebugInfo => null,
1544 else => return err,
1545 },
1546 };
1547 } else |err| switch (err) {
1548 error.MissingDebugInfo, error.InvalidDebugInfo => {
1549 return SymbolInfo{};
1550 },
1551 else => return err,
1552 }
1553
1554 unreachable;
1555 }
14531556 },
14541557 .uefi, .windows => struct {
14551558 base_address: usize,
......@@ -1481,11 +1584,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {
14811584 };
14821585 } else |err| switch (err) {
14831586 error.MissingDebugInfo, error.InvalidDebugInfo => {
1484 return SymbolInfo{
1485 .symbol_name = "???",
1486 .compile_unit_name = "???",
1487 .line_info = null,
1488 };
1587 return SymbolInfo{};
14891588 },
14901589 else => return err,
14911590 }
......@@ -1496,115 +1595,6 @@ pub const ObjectDebugInfo = switch (builtin.os) {
14961595 else => DW.DwarfInfo,
14971596};
14981597
1499/// TODO resources https://github.com/ziglang/zig/issues/4353
1500fn getLineNumberInfoMacOs(di: *ObjectDebugInfo, symbol: MachoSymbol, address: usize) !LineInfo {
1501 const ofile = symbol.ofile orelse return error.MissingDebugInfo;
1502 const gop = try di.ofiles.getOrPut(ofile);
1503 const dwarf_info = if (gop.found_existing) &gop.kv.value else blk: {
1504 errdefer _ = di.ofiles.remove(ofile);
1505 const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
1506
1507 var exe_file = try std.fs.openFileAbsoluteC(ofile_path, .{});
1508 errdefer exe_file.close();
1509
1510 const exe_len = math.cast(usize, try exe_file.getEndPos()) catch
1511 return error.DebugInfoTooLarge;
1512 const exe_mmap = try os.mmap(
1513 null,
1514 exe_len,
1515 os.PROT_READ,
1516 os.MAP_SHARED,
1517 exe_file.handle,
1518 0,
1519 );
1520 errdefer os.munmap(exe_mmap);
1521
1522 const hdr = @ptrCast(
1523 *const macho.mach_header_64,
1524 @alignCast(@alignOf(macho.mach_header_64), exe_mmap.ptr),
1525 );
1526 if (hdr.magic != std.macho.MH_MAGIC_64) return error.InvalidDebugInfo;
1527
1528 const hdr_base = @ptrCast([*]const u8, hdr);
1529 var ptr = hdr_base + @sizeOf(macho.mach_header_64);
1530 var ncmd: u32 = hdr.ncmds;
1531 const segcmd = while (ncmd != 0) : (ncmd -= 1) {
1532 const lc = @ptrCast(*const std.macho.load_command, ptr);
1533 switch (lc.cmd) {
1534 std.macho.LC_SEGMENT_64 => {
1535 break @ptrCast(
1536 *const std.macho.segment_command_64,
1537 @alignCast(@alignOf(std.macho.segment_command_64), ptr),
1538 );
1539 },
1540 else => {},
1541 }
1542 ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
1543 } else {
1544 return error.MissingDebugInfo;
1545 };
1546
1547 var opt_debug_line: ?*const macho.section_64 = null;
1548 var opt_debug_info: ?*const macho.section_64 = null;
1549 var opt_debug_abbrev: ?*const macho.section_64 = null;
1550 var opt_debug_str: ?*const macho.section_64 = null;
1551 var opt_debug_ranges: ?*const macho.section_64 = null;
1552
1553 const sections = @ptrCast(
1554 [*]const macho.section_64,
1555 @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)),
1556 )[0..segcmd.nsects];
1557 for (sections) |*sect| {
1558 // The section name may not exceed 16 chars and a trailing null may
1559 // not be present
1560 const name = if (mem.indexOfScalar(u8, sect.sectname[0..], 0)) |last|
1561 sect.sectname[0..last]
1562 else
1563 sect.sectname[0..];
1564
1565 if (mem.eql(u8, name, "__debug_line")) {
1566 opt_debug_line = sect;
1567 } else if (mem.eql(u8, name, "__debug_info")) {
1568 opt_debug_info = sect;
1569 } else if (mem.eql(u8, name, "__debug_abbrev")) {
1570 opt_debug_abbrev = sect;
1571 } else if (mem.eql(u8, name, "__debug_str")) {
1572 opt_debug_str = sect;
1573 } else if (mem.eql(u8, name, "__debug_ranges")) {
1574 opt_debug_ranges = sect;
1575 }
1576 }
1577
1578 var debug_line = opt_debug_line orelse
1579 return error.MissingDebugInfo;
1580 var debug_info = opt_debug_info orelse
1581 return error.MissingDebugInfo;
1582 var debug_str = opt_debug_str orelse
1583 return error.MissingDebugInfo;
1584 var debug_abbrev = opt_debug_abbrev orelse
1585 return error.MissingDebugInfo;
1586
1587 gop.kv.value = DW.DwarfInfo{
1588 .endian = .Little,
1589 .debug_info = try chopSlice(exe_mmap, debug_info.offset, debug_info.size),
1590 .debug_abbrev = try chopSlice(exe_mmap, debug_abbrev.offset, debug_abbrev.size),
1591 .debug_str = try chopSlice(exe_mmap, debug_str.offset, debug_str.size),
1592 .debug_line = try chopSlice(exe_mmap, debug_line.offset, debug_line.size),
1593 .debug_ranges = if (opt_debug_ranges) |debug_ranges|
1594 try chopSlice(exe_mmap, debug_ranges.offset, debug_ranges.size)
1595 else
1596 null,
1597 };
1598 try DW.openDwarfDebugInfo(&gop.kv.value, di.allocator());
1599
1600 break :blk &gop.kv.value;
1601 };
1602
1603 const o_file_address = address - symbol.reloc;
1604 const compile_unit = try dwarf_info.findCompileUnit(o_file_address);
1605 return dwarf_info.getLineNumberInfo(compile_unit.*, o_file_address);
1606}
1607
16081598/// TODO multithreaded awareness
16091599var debug_info_allocator: ?*mem.Allocator = null;
16101600var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;