authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-09 11:55:43+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-20 19:41:29+01:00
logb0b60cd46854f05c830b51693acd2f1ea7b1ee1a
treef0861ec4424acacc877b32863ce27c018329ca3a
parent3620b67c264c853442f0c1156f72ed699efe5fea

tmp


1 files changed, 139 insertions(+), 18 deletions(-)

lib/std/debug.zig+139-18
......@@ -726,32 +726,38 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
726726}
727727
728728pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
729 const compile_unit = debug_info.findCompileUnit(address) catch {
729 // XXX Print as much as possible anyway
730 const module = try debug_info.lookupByAddress(address);
731
732 const reloc_address = address - module.base_address;
733 warn("reloc {x} => {x}\n", .{ address, reloc_address });
734
735 if (module.dwarf.findCompileUnit(reloc_address) catch null) |compile_unit| {
736 const compile_unit_name = try compile_unit.die.getAttrString(&module.dwarf, DW.AT_name);
737 const symbol_name = module.dwarf.getSymbolName(reloc_address) orelse "???";
738 const line_info = module.dwarf.getLineNumberInfo(compile_unit.*, reloc_address) catch |err| switch (err) {
739 error.MissingDebugInfo, error.InvalidDebugInfo => null,
740 else => return err,
741 };
742 defer if (line_info) |li| li.deinit();
743
730744 return printLineInfo(
731745 out_stream,
732 null,
746 line_info,
733747 address,
734 "???",
735 "???",
748 symbol_name,
749 compile_unit_name,
736750 tty_config,
737751 printLineFromFileAnyOs,
738752 );
739 };
740
741 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
742 const symbol_name = debug_info.getSymbolName(address) orelse "???";
743 const line_info = debug_info.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
744 error.MissingDebugInfo, error.InvalidDebugInfo => null,
745 else => return err,
746 };
747 defer if (line_info) |li| li.deinit();
753 }
748754
749 try printLineInfo(
755 return printLineInfo(
750756 out_stream,
751 line_info,
757 null,
752758 address,
753 symbol_name,
754 compile_unit_name,
759 "???",
760 "???",
755761 tty_config,
756762 printLineFromFileAnyOs,
757763 );
......@@ -824,6 +830,10 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
824830 if (comptime std.Target.current.isDarwin()) {
825831 return noasync openSelfDebugInfoMacOs(allocator);
826832 }
833 if (builtin.os == .linux) {
834 _ = try allocator.create(u32);
835 return DebugInfo.init(allocator);
836 }
827837 return noasync openSelfDebugInfoPosix(allocator);
828838}
829839
......@@ -1190,7 +1200,113 @@ const MachoSymbol = struct {
11901200 }
11911201};
11921202
1193pub const DebugInfo = switch (builtin.os) {
1203pub const DebugInfo = struct {
1204 allocator: *mem.Allocator,
1205 address_map: std.StringHashMap(*ObjectDebugInfo),
1206
1207 pub fn init(allocator: *mem.Allocator) DebugInfo {
1208 return DebugInfo{
1209 .allocator = allocator,
1210 .address_map = std.StringHashMap(*ObjectDebugInfo).init(allocator),
1211 };
1212 }
1213
1214 pub fn deinit(self: *DebugInfo) void {
1215 self.address_map.deinit();
1216 }
1217
1218 pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1219 const obj_di = try self.lookupModuleDl(address);
1220 return obj_di;
1221 }
1222
1223 fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo {
1224 var ctx = DIPContext{ .address = address };
1225
1226 warn("lookup {x}\n", .{address});
1227
1228 // XXX Locking?
1229 if (os.dl_iterate_phdr(DIPContext, dl_iterate_phdr_callback, &ctx) == 0)
1230 return error.DebugInfoNotFound;
1231
1232 warn("found in \"{s}\"\n", .{ctx.name});
1233
1234 if (self.address_map.getValue(ctx.name)) |obj_di| {
1235 warn("cache hit!\n", .{});
1236 return obj_di;
1237 }
1238
1239 const exe_file = if (ctx.name.len > 0)
1240 try fs.openFileAbsolute(ctx.name, .{})
1241 else
1242 try fs.openSelfExe();
1243 defer exe_file.close();
1244
1245 const exe_len = math.cast(usize, try exe_file.getEndPos()) catch
1246 return error.DebugInfoTooLarge;
1247 const exe_mmap = try os.mmap(
1248 null,
1249 exe_len,
1250 os.PROT_READ,
1251 os.MAP_SHARED,
1252 exe_file.handle,
1253 0,
1254 );
1255 errdefer os.munmap(exe_mmap);
1256
1257 const obj_di = try self.allocator.create(ObjectDebugInfo);
1258 errdefer self.allocator.destroy(obj_di);
1259
1260 try self.address_map.putNoClobber(ctx.name, obj_di);
1261
1262 obj_di.* = .{
1263 .dwarf = try openElfDebugInfo(self.allocator, exe_mmap),
1264 .mapped_memory = exe_mmap,
1265 .base_address = ctx.base_address,
1266 };
1267
1268 return obj_di;
1269 }
1270};
1271
1272const DIPContext = struct {
1273 address: usize,
1274 base_address: usize = undefined,
1275 name: []const u8 = undefined,
1276};
1277
1278fn dl_iterate_phdr_callback(info: *os.dl_phdr_info, size: usize, context: ?*DIPContext) callconv(.C) i32 {
1279 const address = context.?.address;
1280
1281 // The base address is too high
1282 if (address < info.dlpi_addr)
1283 return 0;
1284
1285 const phdrs = info.dlpi_phdr[0..info.dlpi_phnum];
1286 for (phdrs) |*phdr| {
1287 if (phdr.p_type != elf.PT_LOAD) continue;
1288
1289 const seg_start = info.dlpi_addr + phdr.p_vaddr;
1290 const seg_end = seg_start + phdr.p_memsz;
1291
1292 if (address > seg_start and address <= seg_end) {
1293 // Android libc uses NULL instead of an empty string to mark the
1294 // main program
1295 context.?.name = if (info.dlpi_name) |dlpi_name|
1296 mem.toSliceConst(u8, dlpi_name)
1297 else
1298 "";
1299 context.?.base_address = info.dlpi_addr;
1300 // Stop the iteration
1301 return 1;
1302 }
1303 }
1304
1305 // Continue the iteration
1306 return 0;
1307}
1308
1309pub const ObjectDebugInfo = switch (builtin.os) {
11941310 .macosx, .ios, .watchos, .tvos => struct {
11951311 symbols: []const MachoSymbol,
11961312 strings: []const u8,
......@@ -1213,6 +1329,11 @@ pub const DebugInfo = switch (builtin.os) {
12131329 sect_contribs: []pdb.SectionContribEntry,
12141330 modules: []Module,
12151331 },
1332 .linux => struct {
1333 base_address: usize,
1334 dwarf: DW.DwarfInfo,
1335 mapped_memory: []u8,
1336 },
12161337 else => DW.DwarfInfo,
12171338};
12181339