delete extra code, more forgiveness

This commit is contained in:
LemonBoy 2020-02-22 12:44:21 +01:00
parent 41bca1ce76
commit 495e894225
2 changed files with 48 additions and 192 deletions

View file

@ -390,179 +390,6 @@ pub fn writeCurrentStackTraceWindows(
} }
} }
/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
/// make this `noasync fn` and remove the individual noasync calls.
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
// if (builtin.os == .windows) {
// return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
// }
return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
}
/// TODO resources https://github.com/ziglang/zig/issues/4353
fn printSourceAtAddressWindows(
debug_info: *DebugInfo,
out_stream: var,
address: usize,
tty_config: TTY.Config,
) !void {
const allocator = debug_info.allocator;
const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
},
else => return err,
};
const relocated_address = address - module.base_address;
var coff_section: *coff.Section = undefined;
const mod_index = for (module.sect_contribs) |sect_contrib| {
if (sect_contrib.Section > module.coff.sections.len) continue;
// Remember that SectionContribEntry.Section is 1-based.
coff_section = &module.coff.sections.toSlice()[sect_contrib.Section - 1];
const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
const vaddr_end = vaddr_start + sect_contrib.Size;
if (relocated_address >= vaddr_start and relocated_address < vaddr_end) {
break sect_contrib.ModuleIndex;
}
} else {
// we have no information to add to the address
return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs);
};
const mod = &module.modules[mod_index];
try populateModule(module, mod);
const obj_basename = fs.path.basename(mod.obj_file_name);
var symbol_i: usize = 0;
const symbol_name = if (!mod.populated) "???" else while (symbol_i != mod.symbols.len) {
const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);
if (prefix.RecordLen < 2)
return error.InvalidDebugInfo;
switch (prefix.RecordKind) {
.S_LPROC32, .S_GPROC32 => {
const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]);
const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
const vaddr_end = vaddr_start + proc_sym.CodeSize;
if (relocated_address >= vaddr_start and relocated_address < vaddr_end) {
break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym));
}
},
else => {},
}
symbol_i += prefix.RecordLen + @sizeOf(u16);
if (symbol_i > mod.symbols.len)
return error.InvalidDebugInfo;
} else "???";
const subsect_info = mod.subsect_info;
var sect_offset: usize = 0;
var skip_len: usize = undefined;
const opt_line_info = subsections: {
const checksum_offset = mod.checksum_offset orelse break :subsections null;
while (sect_offset != subsect_info.len) : (sect_offset += skip_len) {
const subsect_hdr = @ptrCast(*pdb.DebugSubsectionHeader, &subsect_info[sect_offset]);
skip_len = subsect_hdr.Length;
sect_offset += @sizeOf(pdb.DebugSubsectionHeader);
switch (subsect_hdr.Kind) {
pdb.DebugSubsectionKind.Lines => {
var line_index = sect_offset;
const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);
if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
line_index += @sizeOf(pdb.LineFragmentHeader);
const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
if (relocated_address >= frag_vaddr_start and relocated_address < frag_vaddr_end) {
// There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
// from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
// breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
const subsection_end_index = sect_offset + subsect_hdr.Length;
while (line_index < subsection_end_index) {
const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
line_index += @sizeOf(pdb.LineBlockFragmentHeader);
const start_line_index = line_index;
const has_column = line_hdr.Flags.LF_HaveColumns;
// All line entries are stored inside their line block by ascending start address.
// Heuristic: we want to find the last line entry
// that has a vaddr_start <= relocated_address.
// This is done with a simple linear search.
var line_i: u32 = 0;
while (line_i < block_hdr.NumLines) : (line_i += 1) {
const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
line_index += @sizeOf(pdb.LineNumberEntry);
const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
if (relocated_address < vaddr_start) {
break;
}
}
// line_i == 0 would mean that no matching LineNumberEntry was found.
if (line_i > 0) {
const subsect_index = checksum_offset + block_hdr.NameIndex;
const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);
const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;
try module.pdb.string_table.seekTo(strtab_offset);
const source_file_name = try module.pdb.string_table.readNullTermString(allocator);
const line_entry_idx = line_i - 1;
const column = if (has_column) blk: {
const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx;
const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]);
break :blk col_num_entry.StartColumn;
} else 0;
const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry);
const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]);
const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
break :subsections LineInfo{
.allocator = allocator,
.file_name = source_file_name,
.line = flags.Start,
.column = column,
};
}
}
// Checking that we are not reading garbage after the (possibly) multiple block fragments.
if (line_index != subsection_end_index) {
return error.InvalidDebugInfo;
}
}
},
else => {},
}
if (sect_offset > subsect_info.len)
return error.InvalidDebugInfo;
} else {
break :subsections null;
}
};
try printLineInfo(
out_stream,
opt_line_info,
relocated_address,
symbol_name,
obj_basename,
tty_config,
printLineFromFileAnyOs,
);
}
pub const TTY = struct { pub const TTY = struct {
pub const Color = enum { pub const Color = enum {
Red, Red,
@ -698,23 +525,32 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
return null; return null;
} }
pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void { /// TODO resources https://github.com/ziglang/zig/issues/4353
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => { error.MissingDebugInfo, error.InvalidDebugInfo => {
return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs); return printLineInfo(
out_stream,
null,
address,
"???",
"???",
tty_config,
printLineFromFileAnyOs,
);
}, },
else => return err, else => return err,
}; };
const info = try module.getSymbolAtAddress(address); const symbol_info = try module.getSymbolAtAddress(address);
defer info.deinit(); defer symbol_info.deinit();
return printLineInfo( return printLineInfo(
out_stream, out_stream,
info.line_info, symbol_info.line_info,
address, address,
info.symbol_name, symbol_info.symbol_name,
info.compile_unit_name, symbol_info.compile_unit_name,
tty_config, tty_config,
printLineFromFileAnyOs, printLineFromFileAnyOs,
); );
@ -972,7 +808,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 {
/// TODO resources https://github.com/ziglang/zig/issues/4353 /// TODO resources https://github.com/ziglang/zig/issues/4353
pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo { pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo {
const mapped_mem = mapWholeFile(elf_file_path) catch |_| return error.InvalidDebugInfo; const mapped_mem = try mapWholeFile(elf_file_path);
var seekable_stream = io.SliceSeekableInStream.init(mapped_mem); var seekable_stream = io.SliceSeekableInStream.init(mapped_mem);
var efile = try elf.Elf.openStream( var efile = try elf.Elf.openStream(
@ -1015,7 +851,7 @@ pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !M
/// TODO resources https://github.com/ziglang/zig/issues/4353 /// TODO resources https://github.com/ziglang/zig/issues/4353
fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ModuleDebugInfo { fn openMachODebugInfo(allocator: *mem.Allocator, macho_file_path: []const u8) !ModuleDebugInfo {
const mapped_mem = mapWholeFile(macho_file_path) catch |_| return error.InvalidDebugInfo; const mapped_mem = try mapWholeFile(macho_file_path);
const hdr = @ptrCast( const hdr = @ptrCast(
*const macho.mach_header_64, *const macho.mach_header_64,
@ -1228,12 +1064,15 @@ pub const DebugInfo = struct {
const obj_di = try self.allocator.create(ModuleDebugInfo); const obj_di = try self.allocator.create(ModuleDebugInfo);
errdefer self.allocator.destroy(obj_di); errdefer self.allocator.destroy(obj_di);
try self.address_map.putNoClobber(base_address, obj_di);
const macho_path = mem.toSliceConst(u8, std.c._dyld_get_image_name(i)); const macho_path = mem.toSliceConst(u8, std.c._dyld_get_image_name(i));
obj_di.* = try openMachODebugInfo(self.allocator, macho_path); obj_di.* = openMachODebugInfo(self.allocator, macho_path) catch |err| switch (err) {
error.FileNotFound => return error.MissingDebugInfo,
else => return err,
};
obj_di.base_address = base_address; obj_di.base_address = base_address;
try self.address_map.putNoClobber(base_address, obj_di);
return obj_di; return obj_di;
} }
} }
@ -1307,11 +1146,14 @@ pub const DebugInfo = struct {
const obj_di = try self.allocator.create(ModuleDebugInfo); const obj_di = try self.allocator.create(ModuleDebugInfo);
errdefer self.allocator.destroy(obj_di); errdefer self.allocator.destroy(obj_di);
try self.address_map.putNoClobber(seg_start, obj_di); obj_di.* = openCoffDebugInfo(self.allocator, name_buffer[0..:0]) catch |err| switch (err) {
error.FileNotFound => return error.MissingDebugInfo,
obj_di.* = try openCoffDebugInfo(self.allocator, name_buffer[0..:0]); else => return err,
};
obj_di.base_address = seg_start; obj_di.base_address = seg_start;
try self.address_map.putNoClobber(seg_start, obj_di);
return obj_di; return obj_di;
} }
} }
@ -1376,11 +1218,14 @@ pub const DebugInfo = struct {
const obj_di = try self.allocator.create(ModuleDebugInfo); const obj_di = try self.allocator.create(ModuleDebugInfo);
errdefer self.allocator.destroy(obj_di); errdefer self.allocator.destroy(obj_di);
try self.address_map.putNoClobber(ctx.base_address, obj_di); obj_di.* = openElfDebugInfo(self.allocator, elf_path) catch |err| switch (err) {
error.FileNotFound => return error.MissingDebugInfo,
obj_di.* = try openElfDebugInfo(self.allocator, elf_path); else => return err,
};
obj_di.base_address = ctx.base_address; obj_di.base_address = ctx.base_address;
try self.address_map.putNoClobber(ctx.base_address, obj_di);
return obj_di; return obj_di;
} }
}; };
@ -1412,7 +1257,7 @@ pub const ModuleDebugInfo = switch (builtin.os) {
} }
fn loadOFile(self: *@This(), o_file_path: []const u8) !DW.DwarfInfo { fn loadOFile(self: *@This(), o_file_path: []const u8) !DW.DwarfInfo {
const mapped_mem = mapWholeFile(o_file_path) catch |_| return error.InvalidDebugInfo; const mapped_mem = try mapWholeFile(o_file_path);
const hdr = @ptrCast( const hdr = @ptrCast(
*const macho.mach_header_64, *const macho.mach_header_64,

View file

@ -24,6 +24,17 @@ pub const load_command = extern struct {
cmdsize: u32, cmdsize: u32,
}; };
pub const uuid_command = extern struct {
/// LC_UUID
cmd: u32,
/// sizeof(struct uuid_command)
cmdsize: u32,
/// the 128-bit uuid
uuid: [16]u8,
};
/// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD /// The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
/// "stab" style symbol table information as described in the header files /// "stab" style symbol table information as described in the header files
/// <nlist.h> and <stab.h>. /// <nlist.h> and <stab.h>.