diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-28 21:42:55 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-28 21:42:55 +0200 |
| commit | cde722a7117b6da129d3c49dabd445136ed5edb5 (patch) | |
| tree | 5fa9aae95c52832d53d0b2ee3f4a635e28135bf9 /src/link | |
| parent | 25f3175217dace219af643bce7bd28913a970362 (diff) | |
| download | zig-cde722a7117b6da129d3c49dabd445136ed5edb5.tar.gz zig-cde722a7117b6da129d3c49dabd445136ed5edb5.zip | |
coff: put section growing in helper; only mark section if actually resolved
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Coff.zig | 111 | ||||
| -rw-r--r-- | src/link/Coff/ImportTable.zig | 2 | ||||
| -rw-r--r-- | src/link/Coff/Relocation.zig | 8 |
3 files changed, 51 insertions, 70 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 9f7cd6be1c..7b5539287d 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -444,7 +444,44 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section return index; } -fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void { +fn growSection(self: *Coff, sect_id: u32, needed_size: u32) !void { + const header = &self.sections.items(.header)[sect_id]; + const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id]; + const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); + + if (needed_size > sect_capacity) { + const new_offset = self.findFreeSpace(needed_size, default_file_alignment); + const current_size = if (maybe_last_atom_index) |last_atom_index| blk: { + const last_atom = self.getAtom(last_atom_index); + const sym = last_atom.getSymbol(self); + break :blk (sym.value + last_atom.size) - header.virtual_address; + } else 0; + log.debug("moving {s} from 0x{x} to 0x{x}", .{ + self.getSectionName(header), + header.pointer_to_raw_data, + new_offset, + }); + const amt = try self.base.file.?.copyRangeAll( + header.pointer_to_raw_data, + self.base.file.?, + new_offset, + current_size, + ); + if (amt != current_size) return error.InputOutput; + header.pointer_to_raw_data = new_offset; + } + + const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); + if (needed_size > sect_vm_capacity) { + try self.growSectionVirtualMemory(sect_id, needed_size); + self.markRelocsDirtyByAddress(header.virtual_address + needed_size); + } + + header.virtual_size = @max(header.virtual_size, needed_size); + header.size_of_raw_data = needed_size; +} + +fn growSectionVirtualMemory(self: *Coff, sect_id: u32, needed_size: u32) !void { const header = &self.sections.items(.header)[sect_id]; const increased_size = padToIdeal(needed_size); const old_aligned_end = header.virtual_address + mem.alignForwardGeneric(u32, header.virtual_size, self.page_size); @@ -551,38 +588,8 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme else true; if (expand_section) { - const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address; - if (needed_size > sect_capacity) { - const new_offset = self.findFreeSpace(needed_size, default_file_alignment); - const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: { - const last_atom = self.getAtom(last_atom_index); - const sym = last_atom.getSymbol(self); - break :blk (sym.value + last_atom.size) - header.virtual_address; - } else 0; - log.debug("moving {s} from 0x{x} to 0x{x}", .{ - self.getSectionName(header), - header.pointer_to_raw_data, - new_offset, - }); - const amt = try self.base.file.?.copyRangeAll( - header.pointer_to_raw_data, - self.base.file.?, - new_offset, - current_size, - ); - if (amt != current_size) return error.InputOutput; - header.pointer_to_raw_data = new_offset; - } - - const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); - if (needed_size > sect_vm_capacity) { - try self.growSectionVM(sect_id, needed_size); - self.markRelocsDirtyByAddress(header.virtual_address + needed_size); - } - - header.virtual_size = @max(header.virtual_size, needed_size); - header.size_of_raw_data = needed_size; + try self.growSection(sect_id, needed_size); maybe_last_atom_index.* = atom_index; } @@ -814,8 +821,9 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { for (relocs.items) |*reloc| { if (!reloc.dirty) continue; - reloc.resolve(atom_index, code, self); - reloc.dirty = false; + if (reloc.resolve(atom_index, code, self)) { + reloc.dirty = false; + } } } @@ -1581,25 +1589,8 @@ fn writeBaseRelocations(self: *Coff) !void { } const header = &self.sections.items(.header)[self.reloc_section_index.?]; - const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); const needed_size = @intCast(u32, buffer.items.len); - if (needed_size > sect_capacity) { - const new_offset = self.findFreeSpace(needed_size, default_file_alignment); - log.debug("moving {s} from 0x{x} to 0x{x}", .{ - self.getSectionName(header), - header.pointer_to_raw_data, - new_offset, - }); - header.pointer_to_raw_data = new_offset; - - const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); - if (needed_size > sect_vm_capacity) { - // TODO: we want to enforce .reloc after every alloc section. - try self.growSectionVM(self.reloc_section_index.?, needed_size); - } - } - header.virtual_size = @max(header.virtual_size, needed_size); - header.size_of_raw_data = needed_size; + try self.growSection(self.reloc_section_index.?, needed_size); try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); @@ -1638,21 +1629,7 @@ fn writeImportTables(self: *Coff) !void { } const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size; - const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); - if (needed_size > sect_capacity) { - const new_offset = self.findFreeSpace(needed_size, default_file_alignment); - log.debug("moving .idata from 0x{x} to 0x{x}", .{ header.pointer_to_raw_data, new_offset }); - header.pointer_to_raw_data = new_offset; - - const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); - if (needed_size > sect_vm_capacity) { - try self.growSectionVM(self.idata_section_index.?, needed_size); - self.markRelocsDirtyByAddress(header.virtual_address + needed_size); - } - - header.virtual_size = @max(header.virtual_size, needed_size); - header.size_of_raw_data = needed_size; - } + try self.growSection(self.idata_section_index.?, needed_size); // Do the actual writes var buffer = std.ArrayList(u8).init(gpa); diff --git a/src/link/Coff/ImportTable.zig b/src/link/Coff/ImportTable.zig index ba58af2fe0..c3ba77e855 100644 --- a/src/link/Coff/ImportTable.zig +++ b/src/link/Coff/ImportTable.zig @@ -121,7 +121,7 @@ pub fn fmtDebug(itab: ImportTable, ctx: Context) std.fmt.Formatter(fmt) { return .{ .data = .{ .itab = itab, .ctx = ctx } }; } -const ImportIndex = u32; +pub const ImportIndex = u32; const ImportTable = @This(); const std = @import("std"); diff --git a/src/link/Coff/Relocation.zig b/src/link/Coff/Relocation.zig index 4e2f772524..37bd3e292f 100644 --- a/src/link/Coff/Relocation.zig +++ b/src/link/Coff/Relocation.zig @@ -72,12 +72,14 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 { } } -pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) void { +/// Returns `false` if obtaining the target address has been deferred until `flushModule`. +/// This can happen when trying to resolve address of an import table entry ahead of time. +pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) bool { const atom = coff_file.getAtom(atom_index); const source_sym = atom.getSymbol(coff_file); const source_vaddr = source_sym.value + self.offset; - const target_vaddr = self.getTargetAddress(coff_file) orelse return; + const target_vaddr = self.getTargetAddress(coff_file) orelse return false; const target_vaddr_with_addend = target_vaddr + self.addend; log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) ", .{ @@ -100,6 +102,8 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file: .x86, .x86_64 => self.resolveX86(ctx), else => unreachable, // unhandled target architecture } + + return true; } const Context = struct { |
