This commit is contained in:
LemonBoy 2020-02-09 11:55:43 +01:00
parent 3620b67c26
commit b0b60cd468

View File

@ -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,
};