mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
coff: improve default COFF/PE object parser
We now do not allocate memory for headers and other metadata unless requested by the caller. Instead, we read-in the entire contents of the image into memory and operate on pointers and casts wherever possible. I have a left a TODO to hook up Windows' memory-mapped API here in-place of standard `readToEndAlloc` which should be more memory proof on memory constrained hosts. This commit also supplements our `std.coff` with a lot missing basic extern structs required to make our COFF linker.
This commit is contained in:
parent
9043e665a5
commit
c84e5ee878
1242
lib/std/coff.zig
1242
lib/std/coff.zig
File diff suppressed because it is too large
Load Diff
@ -816,11 +816,11 @@ pub fn openSelfDebugInfo(allocator: mem.Allocator) anyerror!DebugInfo {
|
||||
/// TODO it's weird to take ownership even on error, rework this code.
|
||||
fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo {
|
||||
nosuspend {
|
||||
errdefer coff_file.close();
|
||||
defer coff_file.close();
|
||||
|
||||
const coff_obj = try allocator.create(coff.Coff);
|
||||
errdefer allocator.destroy(coff_obj);
|
||||
coff_obj.* = coff.Coff.init(allocator, coff_file);
|
||||
coff_obj.* = .{ .allocator = allocator };
|
||||
|
||||
var di = ModuleDebugInfo{
|
||||
.base_address = undefined,
|
||||
@ -828,18 +828,21 @@ fn readCoffDebugInfo(allocator: mem.Allocator, coff_file: File) !ModuleDebugInfo
|
||||
.debug_data = undefined,
|
||||
};
|
||||
|
||||
try di.coff.loadHeader();
|
||||
try di.coff.loadSections();
|
||||
if (di.coff.getSection(".debug_info")) |sec| {
|
||||
// TODO convert to Windows' memory-mapped file API
|
||||
const file_len = math.cast(usize, try coff_file.getEndPos()) orelse math.maxInt(usize);
|
||||
const data = try coff_file.readToEndAlloc(allocator, file_len);
|
||||
try di.coff.parse(data);
|
||||
|
||||
if (di.coff.getSectionByName(".debug_info")) |sec| {
|
||||
// This coff file has embedded DWARF debug info
|
||||
_ = sec;
|
||||
// TODO: free the section data slices
|
||||
const debug_info_data = di.coff.getSectionData(".debug_info", allocator) catch null;
|
||||
const debug_abbrev_data = di.coff.getSectionData(".debug_abbrev", allocator) catch null;
|
||||
const debug_str_data = di.coff.getSectionData(".debug_str", allocator) catch null;
|
||||
const debug_line_data = di.coff.getSectionData(".debug_line", allocator) catch null;
|
||||
const debug_line_str_data = di.coff.getSectionData(".debug_line_str", allocator) catch null;
|
||||
const debug_ranges_data = di.coff.getSectionData(".debug_ranges", allocator) catch null;
|
||||
const debug_info_data = di.coff.getSectionDataAlloc(".debug_info", allocator) catch null;
|
||||
const debug_abbrev_data = di.coff.getSectionDataAlloc(".debug_abbrev", allocator) catch null;
|
||||
const debug_str_data = di.coff.getSectionDataAlloc(".debug_str", allocator) catch null;
|
||||
const debug_line_data = di.coff.getSectionDataAlloc(".debug_line", allocator) catch null;
|
||||
const debug_line_str_data = di.coff.getSectionDataAlloc(".debug_line_str", allocator) catch null;
|
||||
const debug_ranges_data = di.coff.getSectionDataAlloc(".debug_ranges", allocator) catch null;
|
||||
|
||||
var dwarf = DW.DwarfInfo{
|
||||
.endian = native_endian,
|
||||
@ -1628,7 +1631,7 @@ pub const ModuleDebugInfo = switch (native_os) {
|
||||
|
||||
switch (self.debug_data) {
|
||||
.dwarf => |*dwarf| {
|
||||
const dwarf_address = relocated_address + self.coff.pe_header.image_base;
|
||||
const dwarf_address = relocated_address + self.coff.getImageBase();
|
||||
return getSymbolFromDwarf(allocator, dwarf_address, dwarf);
|
||||
},
|
||||
.pdb => {
|
||||
@ -1636,13 +1639,14 @@ pub const ModuleDebugInfo = switch (native_os) {
|
||||
},
|
||||
}
|
||||
|
||||
var coff_section: *coff.Section = undefined;
|
||||
var coff_section: *align(1) const coff.SectionHeader = undefined;
|
||||
const mod_index = for (self.debug_data.pdb.sect_contribs) |sect_contrib| {
|
||||
if (sect_contrib.Section > self.coff.sections.items.len) continue;
|
||||
const sections = self.coff.getSectionHeaders();
|
||||
if (sect_contrib.Section > sections.len) continue;
|
||||
// Remember that SectionContribEntry.Section is 1-based.
|
||||
coff_section = &self.coff.sections.items[sect_contrib.Section - 1];
|
||||
coff_section = §ions[sect_contrib.Section - 1];
|
||||
|
||||
const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
|
||||
const vaddr_start = coff_section.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;
|
||||
@ -1658,11 +1662,11 @@ pub const ModuleDebugInfo = switch (native_os) {
|
||||
|
||||
const symbol_name = self.debug_data.pdb.getSymbolName(
|
||||
module,
|
||||
relocated_address - coff_section.header.virtual_address,
|
||||
relocated_address - coff_section.virtual_address,
|
||||
) orelse "???";
|
||||
const opt_line_info = try self.debug_data.pdb.getLineNumberInfo(
|
||||
module,
|
||||
relocated_address - coff_section.header.virtual_address,
|
||||
relocated_address - coff_section.virtual_address,
|
||||
);
|
||||
|
||||
return SymbolInfo{
|
||||
|
@ -204,15 +204,18 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
|
||||
index += 2;
|
||||
|
||||
// Characteristics
|
||||
var characteristics: u16 = std.coff.IMAGE_FILE_DEBUG_STRIPPED | std.coff.IMAGE_FILE_RELOCS_STRIPPED; // TODO Remove debug info stripped flag when necessary
|
||||
var characteristics: std.coff.CoffHeaderFlags = .{
|
||||
.DEBUG_STRIPPED = 1, // TODO remove debug info stripped flag when necessary
|
||||
.RELOCS_STRIPPED = 1,
|
||||
};
|
||||
if (options.output_mode == .Exe) {
|
||||
characteristics |= std.coff.IMAGE_FILE_EXECUTABLE_IMAGE;
|
||||
characteristics.EXECUTABLE_IMAGE = 1;
|
||||
}
|
||||
switch (self.ptr_width) {
|
||||
.p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
|
||||
.p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
|
||||
.p32 => characteristics.@"32BIT_MACHINE" = 1,
|
||||
.p64 => characteristics.LARGE_ADDRESS_AWARE = 1,
|
||||
}
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], @bitCast(u16, characteristics));
|
||||
index += 2;
|
||||
|
||||
assert(index == 20);
|
||||
@ -352,7 +355,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
|
||||
mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
index += 12;
|
||||
// Section flags
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
|
||||
.CNT_INITIALIZED_DATA = 1,
|
||||
.MEM_READ = 1,
|
||||
}));
|
||||
index += 4;
|
||||
// Then, the .text section
|
||||
hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
|
||||
@ -378,11 +384,12 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
|
||||
mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
index += 12;
|
||||
// Section flags
|
||||
mem.writeIntLittle(
|
||||
u32,
|
||||
hdr_data[index..][0..4],
|
||||
std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
|
||||
);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
|
||||
.CNT_CODE = 1,
|
||||
.MEM_EXECUTE = 1,
|
||||
.MEM_READ = 1,
|
||||
.MEM_WRITE = 1,
|
||||
}));
|
||||
index += 4;
|
||||
|
||||
assert(index == optional_header_size + section_table_size);
|
||||
|
Loading…
Reference in New Issue
Block a user