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...@@ -396,9 +396,6 @@ pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: us
396 if (builtin.os == .windows) {396 if (builtin.os == .windows) {
397 return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);397 return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
398 }398 }
399 if (comptime std.Target.current.isDarwin()) {
400 return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_config);
401 }
402 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);399 return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
403}400}
404401
...@@ -411,7 +408,7 @@ fn printSourceAtAddressWindows(...@@ -411,7 +408,7 @@ fn printSourceAtAddressWindows(
411) !void {408) !void {
412 const allocator = debug_info.allocator;409 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) {
415 error.MissingDebugInfo, error.InvalidDebugInfo => {412 error.MissingDebugInfo, error.InvalidDebugInfo => {
416 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);413 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
417 },414 },
...@@ -637,7 +634,7 @@ pub const TTY = struct {...@@ -637,7 +634,7 @@ pub const TTY = struct {
637};634};
638635
639/// TODO resources https://github.com/ziglang/zig/issues/4353636/// TODO resources https://github.com/ziglang/zig/issues/4353
640fn populateModule(di: *ObjectDebugInfo, mod: *Module) !void {637fn populateModule(di: *ModuleDebugInfo, mod: *Module) !void {
641 if (mod.populated)638 if (mod.populated)
642 return;639 return;
643 const allocator = getDebugInfoAllocator();640 const allocator = getDebugInfoAllocator();
...@@ -701,46 +698,8 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach...@@ -701,46 +698,8 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
701 return null;698 return null;
702}699}
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
742pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {701pub 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) {
744 error.MissingDebugInfo, error.InvalidDebugInfo => {703 error.MissingDebugInfo, error.InvalidDebugInfo => {
745 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);704 return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
746 },705 },
...@@ -748,7 +707,7 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres...@@ -748,7 +707,7 @@ pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, addres
748 };707 };
749708
750 const info = try module.getSymbolAtAddress(address);709 const info = try module.getSymbolAtAddress(address);
751 defer if (info.line_info) |li| li.deinit();710 defer info.deinit();
752711
753 return printLineInfo(712 return printLineInfo(
754 out_stream,713 out_stream,
...@@ -833,14 +792,14 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {...@@ -833,14 +792,14 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
833}792}
834793
835/// TODO resources https://github.com/ziglang/zig/issues/4353794/// 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 {
837 const coff_file = try std.fs.openFileAbsoluteW(coff_file_path.ptr, .{});796 const coff_file = try std.fs.openFileAbsoluteW(coff_file_path.ptr, .{});
838 errdefer coff_file.close();797 errdefer coff_file.close();
839798
840 const coff_obj = try allocator.create(coff.Coff);799 const coff_obj = try allocator.create(coff.Coff);
841 coff_obj.* = coff.Coff.init(allocator, coff_file);800 coff_obj.* = coff.Coff.init(allocator, coff_file);
842801
843 var di = ObjectDebugInfo{802 var di = ModuleDebugInfo{
844 .base_address = undefined,803 .base_address = undefined,
845 .coff = coff_obj,804 .coff = coff_obj,
846 .pdb = undefined,805 .pdb = undefined,
...@@ -1012,7 +971,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {...@@ -1012,7 +971,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {
1012}971}
1013972
1014/// TODO resources https://github.com/ziglang/zig/issues/4353973/// 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 {
1016 const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo;975 const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo;
1017976
1018 var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);977 var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);
...@@ -1047,7 +1006,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O...@@ -1047,7 +1006,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O
10471006
1048 try DW.openDwarfDebugInfo(&di, allocator);1007 try DW.openDwarfDebugInfo(&di, allocator);
10491008
1050 return ObjectDebugInfo{1009 return ModuleDebugInfo{
1051 .base_address = undefined,1010 .base_address = undefined,
1052 .dwarf = di,1011 .dwarf = di,
1053 .mapped_memory = mapped_mem,1012 .mapped_memory = mapped_mem,
...@@ -1055,14 +1014,15 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O...@@ -1055,14 +1014,15 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !O
1055}1014}
10561015
1057/// TODO resources https://github.com/ziglang/zig/issues/43531016/// 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 {
1059 const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo;1018 const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo;
10601019
1061 const hdr = @ptrCast(1020 const hdr = @ptrCast(
1062 *const macho.mach_header_64,1021 *const macho.mach_header_64,
1063 @alignCast(@alignOf(macho.mach_header_64), mapped_mem.ptr),1022 @alignCast(@alignOf(macho.mach_header_64), mapped_mem.ptr),
1064 );1023 );
1065 assert(hdr.magic == std.macho.MH_MAGIC_64);1024 if (hdr.magic != macho.MH_MAGIC_64)
1025 return error.InvalidDebugInfo;
10661026
1067 const hdr_base = @ptrCast([*]const u8, hdr);1027 const hdr_base = @ptrCast([*]const u8, hdr);
1068 var ptr = hdr_base + @sizeOf(macho.mach_header_64);1028 var ptr = hdr_base + @sizeOf(macho.mach_header_64);
...@@ -1078,7 +1038,7 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !O...@@ -1078,7 +1038,7 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !O
1078 return error.MissingDebugInfo;1038 return error.MissingDebugInfo;
1079 };1039 };
1080 const syms = @ptrCast([*]const macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];1040 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
1083 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);1043 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...@@ -1130,10 +1090,10 @@ fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !O
1130 // This sort is so that we can binary search later.1090 // This sort is so that we can binary search later.
1131 std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);1091 std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);
11321092
1133 return ObjectDebugInfo{1093 return ModuleDebugInfo{
1134 .base_address = undefined,1094 .base_address = undefined,
1135 .mapped_memory = mapped_mem,1095 .mapped_memory = mapped_mem,
1136 .ofiles = ObjectDebugInfo.OFileTable.init(allocator),1096 .ofiles = ModuleDebugInfo.OFileTable.init(allocator),
1137 .symbols = symbols,1097 .symbols = symbols,
1138 .strings = strings,1098 .strings = strings,
1139 };1099 };
...@@ -1206,12 +1166,12 @@ fn mapWholeFile(path: []const u8) ![]const u8 {...@@ -1206,12 +1166,12 @@ fn mapWholeFile(path: []const u8) ![]const u8 {
12061166
1207pub const DebugInfo = struct {1167pub const DebugInfo = struct {
1208 allocator: *mem.Allocator,1168 allocator: *mem.Allocator,
1209 address_map: std.AutoHashMap(usize, *ObjectDebugInfo),1169 address_map: std.AutoHashMap(usize, *ModuleDebugInfo),
12101170
1211 pub fn init(allocator: *mem.Allocator) DebugInfo {1171 pub fn init(allocator: *mem.Allocator) DebugInfo {
1212 return DebugInfo{1172 return DebugInfo{
1213 .allocator = allocator,1173 .allocator = allocator,
1214 .address_map = std.AutoHashMap(usize, *ObjectDebugInfo).init(allocator),1174 .address_map = std.AutoHashMap(usize, *ModuleDebugInfo).init(allocator),
1215 };1175 };
1216 }1176 }
12171177
...@@ -1220,17 +1180,16 @@ pub const DebugInfo = struct {...@@ -1220,17 +1180,16 @@ pub const DebugInfo = struct {
1220 self.address_map.deinit();1180 self.address_map.deinit();
1221 }1181 }
12221182
1223 pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1183 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1224 const obj_di = if (comptime std.Target.current.isDarwin())1184 if (comptime std.Target.current.isDarwin())
1225 try self.lookupModuleDyld(address)1185 return self.lookupModuleDyld(address)
1226 else if (builtin.os == .windows)1186 else if (builtin.os == .windows)
1227 try self.lookupModuleWin32(address)1187 return self.lookupModuleWin32(address)
1228 else1188 else
1229 try self.lookupModuleDl(address);1189 return self.lookupModuleDl(address);
1230 return obj_di;
1231 }1190 }
12321191
1233 fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1192 fn lookupModuleDyld(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1234 const image_count = std.c._dyld_image_count();1193 const image_count = std.c._dyld_image_count();
12351194
1236 var i: u32 = 0;1195 var i: u32 = 0;
...@@ -1266,7 +1225,7 @@ pub const DebugInfo = struct {...@@ -1266,7 +1225,7 @@ pub const DebugInfo = struct {
1266 return obj_di;1225 return obj_di;
1267 }1226 }
12681227
1269 const obj_di = try self.allocator.create(ObjectDebugInfo);1228 const obj_di = try self.allocator.create(ModuleDebugInfo);
1270 errdefer self.allocator.destroy(obj_di);1229 errdefer self.allocator.destroy(obj_di);
12711230
1272 try self.address_map.putNoClobber(base_address, obj_di);1231 try self.address_map.putNoClobber(base_address, obj_di);
...@@ -1283,7 +1242,7 @@ pub const DebugInfo = struct {...@@ -1283,7 +1242,7 @@ pub const DebugInfo = struct {
1283 return error.MissingDebugInfo;1242 return error.MissingDebugInfo;
1284 }1243 }
12851244
1286 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1245 fn lookupModuleWin32(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1287 const process_handle = windows.kernel32.GetCurrentProcess();1246 const process_handle = windows.kernel32.GetCurrentProcess();
12881247
1289 // Find how many modules are actually loaded1248 // Find how many modules are actually loaded
...@@ -1345,7 +1304,7 @@ pub const DebugInfo = struct {...@@ -1345,7 +1304,7 @@ pub const DebugInfo = struct {
1345 );1304 );
1346 assert(len > 0);1305 assert(len > 0);
13471306
1348 const obj_di = try self.allocator.create(ObjectDebugInfo);1307 const obj_di = try self.allocator.create(ModuleDebugInfo);
1349 errdefer self.allocator.destroy(obj_di);1308 errdefer self.allocator.destroy(obj_di);
13501309
1351 try self.address_map.putNoClobber(seg_start, obj_di);1310 try self.address_map.putNoClobber(seg_start, obj_di);
...@@ -1360,7 +1319,7 @@ pub const DebugInfo = struct {...@@ -1360,7 +1319,7 @@ pub const DebugInfo = struct {
1360 return error.MissingDebugInfo;1319 return error.MissingDebugInfo;
1361 }1320 }
13621321
1363 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {1322 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1364 var ctx: struct {1323 var ctx: struct {
1365 // Input1324 // Input
1366 address: usize,1325 address: usize,
...@@ -1414,7 +1373,7 @@ pub const DebugInfo = struct {...@@ -1414,7 +1373,7 @@ pub const DebugInfo = struct {
1414 break :blk try fs.selfExePath(&buf);1373 break :blk try fs.selfExePath(&buf);
1415 };1374 };
14161375
1417 const obj_di = try self.allocator.create(ObjectDebugInfo);1376 const obj_di = try self.allocator.create(ModuleDebugInfo);
1418 errdefer self.allocator.destroy(obj_di);1377 errdefer self.allocator.destroy(obj_di);
14191378
1420 try self.address_map.putNoClobber(ctx.base_address, obj_di);1379 try self.address_map.putNoClobber(ctx.base_address, obj_di);
...@@ -1427,29 +1386,173 @@ pub const DebugInfo = struct {...@@ -1427,29 +1386,173 @@ pub const DebugInfo = struct {
1427};1386};
14281387
1429const SymbolInfo = struct {1388const SymbolInfo = struct {
1430 symbol_name: []const u8,1389 symbol_name: []const u8 = "???",
1431 compile_unit_name: []const u8,1390 compile_unit_name: []const u8 = "???",
1432 line_info: ?LineInfo,1391 line_info: ?LineInfo = null,
1392
1393 fn deinit(self: @This()) void {
1394 if (self.line_info) |li| {
1395 li.deinit();
1396 }
1397 }
1433};1398};
14341399
1435pub const ObjectDebugInfo = switch (builtin.os) {1400pub const ModuleDebugInfo = switch (builtin.os) {
1436 .macosx, .ios, .watchos, .tvos => struct {1401 .macosx, .ios, .watchos, .tvos => struct {
1437 base_address: usize,1402 base_address: usize,
1438 mapped_memory: []const u8,1403 mapped_memory: []const u8,
1439 symbols: []const MachoSymbol,1404 symbols: []const MachoSymbol,
1440 strings: []const u8,1405 strings: [:0]const u8,
1441 ofiles: OFileTable,1406 ofiles: OFileTable,
14421407
1443 const OFileTable = std.HashMap(1408 const OFileTable = std.StringHashMap(DW.DwarfInfo);
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 );
14491409
1450 pub fn allocator(self: @This()) *mem.Allocator {1410 pub fn allocator(self: @This()) *mem.Allocator {
1451 return self.ofiles.allocator;1411 return self.ofiles.allocator;
1452 }1412 }
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 }
1453 },1556 },
1454 .uefi, .windows => struct {1557 .uefi, .windows => struct {
1455 base_address: usize,1558 base_address: usize,
...@@ -1481,11 +1584,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {...@@ -1481,11 +1584,7 @@ pub const ObjectDebugInfo = switch (builtin.os) {
1481 };1584 };
1482 } else |err| switch (err) {1585 } else |err| switch (err) {
1483 error.MissingDebugInfo, error.InvalidDebugInfo => {1586 error.MissingDebugInfo, error.InvalidDebugInfo => {
1484 return SymbolInfo{1587 return SymbolInfo{};
1485 .symbol_name = "???",
1486 .compile_unit_name = "???",
1487 .line_info = null,
1488 };
1489 },1588 },
1490 else => return err,1589 else => return err,
1491 }1590 }
...@@ -1496,115 +1595,6 @@ pub const ObjectDebugInfo = switch (builtin.os) {...@@ -1496,115 +1595,6 @@ pub const ObjectDebugInfo = switch (builtin.os) {
1496 else => DW.DwarfInfo,1595 else => DW.DwarfInfo,
1497};1596};
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
1608/// TODO multithreaded awareness1598/// TODO multithreaded awareness
1609var debug_info_allocator: ?*mem.Allocator = null;1599var debug_info_allocator: ?*mem.Allocator = null;
1610var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;1600var debug_info_arena_allocator: std.heap.ArenaAllocator = undefined;