coff: populate missing section metadata

This commit is contained in:
Jakub Konka 2022-08-28 14:25:58 +02:00
parent f36029a385
commit 2a994ba4a7

View File

@ -43,7 +43,9 @@ sections: std.MultiArrayList(Section) = .{},
data_directories: [16]coff.ImageDataDirectory,
text_section_index: ?u16 = null,
got_section_index: ?u16 = null,
rdata_section_index: ?u16 = null,
pdata_section_index: ?u16 = null,
data_section_index: ?u16 = null,
locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
@ -212,12 +214,103 @@ fn populateMissingMetadata(self: *Coff) !void {
const file_size = self.base.options.program_code_size_hint;
const off = self.findFreeSpace(file_size, self.page_size); // TODO we are over-aligning in file; we should track both in file and in memory pointers
log.debug("found .text free space 0x{x} to 0x{x}", .{ off, off + file_size });
var header = coff.SectionHeader{
.name = undefined,
.virtual_size = @intCast(u32, file_size),
.virtual_address = @intCast(u32, off),
.size_of_raw_data = @intCast(u32, file_size),
.pointer_to_raw_data = @intCast(u32, off),
.pointer_to_relocations = 0,
.pointer_to_linenumbers = 0,
.number_of_relocations = 0,
.number_of_linenumbers = 0,
.flags = .{
.CNT_CODE = 1,
.MEM_EXECUTE = 1,
.MEM_READ = 1,
},
};
try self.setSectionName(&header, ".text");
try self.sections.append(gpa, .{ .header = header });
}
if (self.got_section_index == null) {}
if (self.pdata_section_index == null) {
self.pdata_section_index = @intCast(u16, self.sections.slice().len);
const file_size = self.base.options.symbol_count_hint;
const off = self.findFreeSpace(file_size, self.page_size);
log.debug("found .pdata free space 0x{x} to 0x{x}", .{ off, off + file_size });
var header = coff.SectionHeader{
.name = undefined,
.virtual_size = @intCast(u32, file_size),
.virtual_address = @intCast(u32, off),
.size_of_raw_data = @intCast(u32, file_size),
.pointer_to_raw_data = @intCast(u32, off),
.pointer_to_relocations = 0,
.pointer_to_linenumbers = 0,
.number_of_relocations = 0,
.number_of_linenumbers = 0,
.flags = .{
.CNT_INITIALIZED_DATA = 1,
.MEM_READ = 1,
},
};
try self.setSectionName(&header, ".pdata");
try self.sections.append(gpa, .{ .header = header });
}
if (self.rdata_section_index == null) {
self.rdata_section_index = @intCast(u16, self.sections.slice().len);
const file_size = 1024;
const off = self.findFreeSpace(file_size, self.page_size);
log.debug("found .rdata free space 0x{x} to 0x{x}", .{ off, off + file_size });
var header = coff.SectionHeader{
.name = undefined,
.virtual_size = @intCast(u32, file_size),
.virtual_address = @intCast(u32, off),
.size_of_raw_data = @intCast(u32, file_size),
.pointer_to_raw_data = @intCast(u32, off),
.pointer_to_relocations = 0,
.pointer_to_linenumbers = 0,
.number_of_relocations = 0,
.number_of_linenumbers = 0,
.flags = .{
.CNT_INITIALIZED_DATA = 1,
.MEM_READ = 1,
},
};
try self.setSectionName(&header, ".rdata");
try self.sections.append(gpa, .{ .header = header });
}
if (self.data_section_index == null) {
self.data_section_index = @intCast(u16, self.sections.slice().len);
const file_size = 1024;
const off = self.findFreeSpace(file_size, self.page_size);
log.debug("found .data free space 0x{x} to 0x{x}", .{ off, off + file_size });
var header = coff.SectionHeader{
.name = undefined,
.virtual_size = @intCast(u32, file_size),
.virtual_address = @intCast(u32, off),
.size_of_raw_data = @intCast(u32, file_size),
.pointer_to_raw_data = @intCast(u32, off),
.pointer_to_relocations = 0,
.pointer_to_linenumbers = 0,
.number_of_relocations = 0,
.number_of_linenumbers = 0,
.flags = .{
.CNT_INITIALIZED_DATA = 1,
.MEM_READ = 1,
.MEM_WRITE = 1,
},
};
try self.setSectionName(&header, ".data");
try self.sections.append(gpa, .{ .header = header });
}
if (self.strtab_offset == null) {
try self.strtab.buffer.append(gpa, 0);
self.strtab_offset = @intCast(u32, self.findFreeSpace(self.strtab.len(), 1));
log.debug("found strtab free space 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + self.strtab.len() });
}
// Index 0 is always a null symbol.
@ -677,6 +770,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
sub_prog_node.activate();
defer sub_prog_node.end();
try self.writeStrtab();
try self.writeDataDirectoriesHeaders();
try self.writeSectionHeaders();
try self.writeHeader();
@ -709,6 +803,19 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
log.debug("TODO implement updateDeclLineNumber", .{});
}
fn writeStrtab(self: *Coff) !void {
const allocated_size = self.allocatedSize(self.strtab_offset.?);
const needed_size = self.strtab.len();
if (needed_size > allocated_size) {
self.strtab_offset = null;
self.strtab_offset = @intCast(u32, self.findFreeSpace(needed_size, 1));
}
log.debug("writing strtab from 0x{x} to 0x{x}", .{ self.strtab_offset.?, self.strtab_offset.? + needed_size });
try self.base.file.?.pwriteAll(self.strtab.buffer.items, self.strtab_offset.?);
}
fn writeSectionHeaders(self: *Coff) !void {
const offset = self.getSectionHeadersOffset();
try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset);
@ -729,7 +836,7 @@ fn writeHeader(self: *Coff) !void {
writer.writeAll(msdos_stub) catch unreachable;
writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes
writer.writeAll("PE\x00\x00") catch unreachable;
buffer.items[0x3c] = @intCast(u8, msdos_stub.len + 4);
mem.writeIntLittle(u32, buffer.items[0x3c..][0..4], msdos_stub.len + 4);
var flags = coff.CoffHeaderFlags{
.EXECUTABLE_IMAGE = 1,
@ -743,10 +850,7 @@ fn writeHeader(self: *Coff) !void {
flags.DLL = 1;
}
const size_of_optional_header = @intCast(
u16,
self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize() + self.getSectionHeadersSize(),
);
const size_of_optional_header = @intCast(u16, self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize());
var coff_header = coff.CoffHeader{
.machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch),
.number_of_sections = @intCast(u16, self.sections.slice().len), // TODO what if we prune a section
@ -774,6 +878,13 @@ fn writeHeader(self: *Coff) !void {
.Lib => default_image_base_dll,
else => unreachable,
};
const text_section = self.sections.get(self.text_section_index.?).header;
var size_of_initialized_data: u32 = 0;
for (self.sections.items(.header)) |header| {
if (header.flags.CNT_INITIALIZED_DATA == 0) continue;
size_of_initialized_data += header.virtual_size;
}
switch (self.ptr_width) {
.p32 => {
@ -781,11 +892,11 @@ fn writeHeader(self: *Coff) !void {
.magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC,
.major_linker_version = 0,
.minor_linker_version = 0,
.size_of_code = 0,
.size_of_initialized_data = 0,
.size_of_code = text_section.virtual_size,
.size_of_initialized_data = size_of_initialized_data,
.size_of_uninitialized_data = 0,
.address_of_entry_point = self.entry_addr orelse 0,
.base_of_code = 0,
.base_of_code = text_section.virtual_address,
.base_of_data = 0,
.image_base = @intCast(u32, image_base),
.section_alignment = self.page_size,
@ -816,11 +927,11 @@ fn writeHeader(self: *Coff) !void {
.magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC,
.major_linker_version = 0,
.minor_linker_version = 0,
.size_of_code = 0,
.size_of_initialized_data = 0,
.size_of_code = text_section.virtual_size,
.size_of_initialized_data = size_of_initialized_data,
.size_of_uninitialized_data = 0,
.address_of_entry_point = self.entry_addr orelse 0,
.base_of_code = 0,
.base_of_code = text_section.virtual_address,
.image_base = image_base,
.section_alignment = self.page_size,
.file_alignment = default_file_alignment,
@ -971,6 +1082,7 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom {
fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void {
if (name.len <= 8) {
mem.copy(u8, &header.name, name);
mem.set(u8, header.name[name.len..], 0);
return;
}
const offset = try self.strtab.insert(self.base.allocator, name);
@ -981,6 +1093,7 @@ fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !v
fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void {
if (name.len <= 8) {
mem.copy(u8, &symbol.name, name);
mem.set(u8, symbol.name[name.len..], 0);
return;
}
const offset = try self.strtab.insert(self.base.allocator, name);