From b0b60cd46854f05c830b51693acd2f1ea7b1ee1a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 9 Feb 2020 11:55:43 +0100 Subject: tmp --- lib/std/debug.zig | 157 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 18 deletions(-) (limited to 'lib/std/debug.zig') diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 65b591199b..a36efe441b 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -726,32 +726,38 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt } pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { - const compile_unit = debug_info.findCompileUnit(address) catch { + // XXX Print as much as possible anyway + const module = try debug_info.lookupByAddress(address); + + const reloc_address = address - module.base_address; + warn("reloc {x} => {x}\n", .{ address, reloc_address }); + + if (module.dwarf.findCompileUnit(reloc_address) catch null) |compile_unit| { + const compile_unit_name = try compile_unit.die.getAttrString(&module.dwarf, DW.AT_name); + const symbol_name = module.dwarf.getSymbolName(reloc_address) orelse "???"; + const line_info = module.dwarf.getLineNumberInfo(compile_unit.*, reloc_address) catch |err| switch (err) { + error.MissingDebugInfo, error.InvalidDebugInfo => null, + else => return err, + }; + defer if (line_info) |li| li.deinit(); + return printLineInfo( out_stream, - null, + line_info, address, - "???", - "???", + symbol_name, + compile_unit_name, tty_config, printLineFromFileAnyOs, ); - }; - - const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); - const symbol_name = debug_info.getSymbolName(address) orelse "???"; - const line_info = debug_info.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) { - error.MissingDebugInfo, error.InvalidDebugInfo => null, - else => return err, - }; - defer if (line_info) |li| li.deinit(); + } - try printLineInfo( + return printLineInfo( out_stream, - line_info, + null, address, - symbol_name, - compile_unit_name, + "???", + "???", tty_config, printLineFromFileAnyOs, ); @@ -824,6 +830,10 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { if (comptime std.Target.current.isDarwin()) { return noasync openSelfDebugInfoMacOs(allocator); } + if (builtin.os == .linux) { + _ = try allocator.create(u32); + return DebugInfo.init(allocator); + } return noasync openSelfDebugInfoPosix(allocator); } @@ -1190,7 +1200,113 @@ const MachoSymbol = struct { } }; -pub const DebugInfo = switch (builtin.os) { +pub const DebugInfo = struct { + allocator: *mem.Allocator, + address_map: std.StringHashMap(*ObjectDebugInfo), + + pub fn init(allocator: *mem.Allocator) DebugInfo { + return DebugInfo{ + .allocator = allocator, + .address_map = std.StringHashMap(*ObjectDebugInfo).init(allocator), + }; + } + + pub fn deinit(self: *DebugInfo) void { + self.address_map.deinit(); + } + + pub fn lookupByAddress(self: *DebugInfo, address: usize) !*ObjectDebugInfo { + const obj_di = try self.lookupModuleDl(address); + return obj_di; + } + + fn lookupModuleDl(self: *DebugInfo, address: usize) !*ObjectDebugInfo { + var ctx = DIPContext{ .address = address }; + + warn("lookup {x}\n", .{address}); + + // XXX Locking? + if (os.dl_iterate_phdr(DIPContext, dl_iterate_phdr_callback, &ctx) == 0) + return error.DebugInfoNotFound; + + warn("found in \"{s}\"\n", .{ctx.name}); + + if (self.address_map.getValue(ctx.name)) |obj_di| { + warn("cache hit!\n", .{}); + return obj_di; + } + + const exe_file = if (ctx.name.len > 0) + try fs.openFileAbsolute(ctx.name, .{}) + else + try fs.openSelfExe(); + defer exe_file.close(); + + const exe_len = math.cast(usize, try exe_file.getEndPos()) catch + return error.DebugInfoTooLarge; + const exe_mmap = try os.mmap( + null, + exe_len, + os.PROT_READ, + os.MAP_SHARED, + exe_file.handle, + 0, + ); + errdefer os.munmap(exe_mmap); + + const obj_di = try self.allocator.create(ObjectDebugInfo); + errdefer self.allocator.destroy(obj_di); + + try self.address_map.putNoClobber(ctx.name, obj_di); + + obj_di.* = .{ + .dwarf = try openElfDebugInfo(self.allocator, exe_mmap), + .mapped_memory = exe_mmap, + .base_address = ctx.base_address, + }; + + return obj_di; + } +}; + +const DIPContext = struct { + address: usize, + base_address: usize = undefined, + name: []const u8 = undefined, +}; + +fn dl_iterate_phdr_callback(info: *os.dl_phdr_info, size: usize, context: ?*DIPContext) callconv(.C) i32 { + const address = context.?.address; + + // The base address is too high + if (address < info.dlpi_addr) + return 0; + + const phdrs = info.dlpi_phdr[0..info.dlpi_phnum]; + for (phdrs) |*phdr| { + if (phdr.p_type != elf.PT_LOAD) continue; + + const seg_start = info.dlpi_addr + phdr.p_vaddr; + const seg_end = seg_start + phdr.p_memsz; + + if (address > seg_start and address <= seg_end) { + // Android libc uses NULL instead of an empty string to mark the + // main program + context.?.name = if (info.dlpi_name) |dlpi_name| + mem.toSliceConst(u8, dlpi_name) + else + ""; + context.?.base_address = info.dlpi_addr; + // Stop the iteration + return 1; + } + } + + // Continue the iteration + return 0; +} + +pub const ObjectDebugInfo = switch (builtin.os) { .macosx, .ios, .watchos, .tvos => struct { symbols: []const MachoSymbol, strings: []const u8, @@ -1213,6 +1329,11 @@ pub const DebugInfo = switch (builtin.os) { sect_contribs: []pdb.SectionContribEntry, modules: []Module, }, + .linux => struct { + base_address: usize, + dwarf: DW.DwarfInfo, + mapped_memory: []u8, + }, else => DW.DwarfInfo, }; -- cgit v1.2.3