authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 21:42:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 21:42:55+02:00
logcde722a7117b6da129d3c49dabd445136ed5edb5
tree5fa9aae95c52832d53d0b2ee3f4a635e28135bf9
parent25f3175217dace219af643bce7bd28913a970362

coff: put section growing in helper; only mark section if actually resolved


3 files changed, 51 insertions(+), 70 deletions(-)

src/link/Coff.zig+44-67
...@@ -444,7 +444,44 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section...@@ -444,7 +444,44 @@ fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.Section
444 return index;444 return index;
445}445}
446446
447fn growSectionVM(self: *Coff, sect_id: u32, needed_size: u32) !void {447fn growSection(self: *Coff, sect_id: u32, needed_size: u32) !void {
448 const header = &self.sections.items(.header)[sect_id];
449 const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id];
450 const sect_capacity = self.allocatedSize(header.pointer_to_raw_data);
451
452 if (needed_size > sect_capacity) {
453 const new_offset = self.findFreeSpace(needed_size, default_file_alignment);
454 const current_size = if (maybe_last_atom_index) |last_atom_index| blk: {
455 const last_atom = self.getAtom(last_atom_index);
456 const sym = last_atom.getSymbol(self);
457 break :blk (sym.value + last_atom.size) - header.virtual_address;
458 } else 0;
459 log.debug("moving {s} from 0x{x} to 0x{x}", .{
460 self.getSectionName(header),
461 header.pointer_to_raw_data,
462 new_offset,
463 });
464 const amt = try self.base.file.?.copyRangeAll(
465 header.pointer_to_raw_data,
466 self.base.file.?,
467 new_offset,
468 current_size,
469 );
470 if (amt != current_size) return error.InputOutput;
471 header.pointer_to_raw_data = new_offset;
472 }
473
474 const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address);
475 if (needed_size > sect_vm_capacity) {
476 try self.growSectionVirtualMemory(sect_id, needed_size);
477 self.markRelocsDirtyByAddress(header.virtual_address + needed_size);
478 }
479
480 header.virtual_size = @max(header.virtual_size, needed_size);
481 header.size_of_raw_data = needed_size;
482}
483
484fn growSectionVirtualMemory(self: *Coff, sect_id: u32, needed_size: u32) !void {
448 const header = &self.sections.items(.header)[sect_id];485 const header = &self.sections.items(.header)[sect_id];
449 const increased_size = padToIdeal(needed_size);486 const increased_size = padToIdeal(needed_size);
450 const old_aligned_end = header.virtual_address + mem.alignForwardGeneric(u32, header.virtual_size, self.page_size);487 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...@@ -551,38 +588,8 @@ fn allocateAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignme
551 else588 else
552 true;589 true;
553 if (expand_section) {590 if (expand_section) {
554 const sect_capacity = self.allocatedSize(header.pointer_to_raw_data);
555 const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address;591 const needed_size: u32 = (vaddr + new_atom_size) - header.virtual_address;
556 if (needed_size > sect_capacity) {592 try self.growSection(sect_id, needed_size);
557 const new_offset = self.findFreeSpace(needed_size, default_file_alignment);
558 const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: {
559 const last_atom = self.getAtom(last_atom_index);
560 const sym = last_atom.getSymbol(self);
561 break :blk (sym.value + last_atom.size) - header.virtual_address;
562 } else 0;
563 log.debug("moving {s} from 0x{x} to 0x{x}", .{
564 self.getSectionName(header),
565 header.pointer_to_raw_data,
566 new_offset,
567 });
568 const amt = try self.base.file.?.copyRangeAll(
569 header.pointer_to_raw_data,
570 self.base.file.?,
571 new_offset,
572 current_size,
573 );
574 if (amt != current_size) return error.InputOutput;
575 header.pointer_to_raw_data = new_offset;
576 }
577
578 const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address);
579 if (needed_size > sect_vm_capacity) {
580 try self.growSectionVM(sect_id, needed_size);
581 self.markRelocsDirtyByAddress(header.virtual_address + needed_size);
582 }
583
584 header.virtual_size = @max(header.virtual_size, needed_size);
585 header.size_of_raw_data = needed_size;
586 maybe_last_atom_index.* = atom_index;593 maybe_last_atom_index.* = atom_index;
587 }594 }
588595
...@@ -814,8 +821,9 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void {...@@ -814,8 +821,9 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void {
814821
815 for (relocs.items) |*reloc| {822 for (relocs.items) |*reloc| {
816 if (!reloc.dirty) continue;823 if (!reloc.dirty) continue;
817 reloc.resolve(atom_index, code, self);824 if (reloc.resolve(atom_index, code, self)) {
818 reloc.dirty = false;825 reloc.dirty = false;
826 }
819 }827 }
820}828}
821829
...@@ -1581,25 +1589,8 @@ fn writeBaseRelocations(self: *Coff) !void {...@@ -1581,25 +1589,8 @@ fn writeBaseRelocations(self: *Coff) !void {
1581 }1589 }
15821590
1583 const header = &self.sections.items(.header)[self.reloc_section_index.?];1591 const header = &self.sections.items(.header)[self.reloc_section_index.?];
1584 const sect_capacity = self.allocatedSize(header.pointer_to_raw_data);
1585 const needed_size = @intCast(u32, buffer.items.len);1592 const needed_size = @intCast(u32, buffer.items.len);
1586 if (needed_size > sect_capacity) {1593 try self.growSection(self.reloc_section_index.?, needed_size);
1587 const new_offset = self.findFreeSpace(needed_size, default_file_alignment);
1588 log.debug("moving {s} from 0x{x} to 0x{x}", .{
1589 self.getSectionName(header),
1590 header.pointer_to_raw_data,
1591 new_offset,
1592 });
1593 header.pointer_to_raw_data = new_offset;
1594
1595 const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address);
1596 if (needed_size > sect_vm_capacity) {
1597 // TODO: we want to enforce .reloc after every alloc section.
1598 try self.growSectionVM(self.reloc_section_index.?, needed_size);
1599 }
1600 }
1601 header.virtual_size = @max(header.virtual_size, needed_size);
1602 header.size_of_raw_data = needed_size;
16031594
1604 try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data);1595 try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data);
16051596
...@@ -1638,21 +1629,7 @@ fn writeImportTables(self: *Coff) !void {...@@ -1638,21 +1629,7 @@ fn writeImportTables(self: *Coff) !void {
1638 }1629 }
16391630
1640 const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size;1631 const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size;
1641 const sect_capacity = self.allocatedSize(header.pointer_to_raw_data);1632 try self.growSection(self.idata_section_index.?, needed_size);
1642 if (needed_size > sect_capacity) {
1643 const new_offset = self.findFreeSpace(needed_size, default_file_alignment);
1644 log.debug("moving .idata from 0x{x} to 0x{x}", .{ header.pointer_to_raw_data, new_offset });
1645 header.pointer_to_raw_data = new_offset;
1646
1647 const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address);
1648 if (needed_size > sect_vm_capacity) {
1649 try self.growSectionVM(self.idata_section_index.?, needed_size);
1650 self.markRelocsDirtyByAddress(header.virtual_address + needed_size);
1651 }
1652
1653 header.virtual_size = @max(header.virtual_size, needed_size);
1654 header.size_of_raw_data = needed_size;
1655 }
16561633
1657 // Do the actual writes1634 // Do the actual writes
1658 var buffer = std.ArrayList(u8).init(gpa);1635 var buffer = std.ArrayList(u8).init(gpa);
src/link/Coff/ImportTable.zig+1-1
...@@ -121,7 +121,7 @@ pub fn fmtDebug(itab: ImportTable, ctx: Context) std.fmt.Formatter(fmt) {...@@ -121,7 +121,7 @@ pub fn fmtDebug(itab: ImportTable, ctx: Context) std.fmt.Formatter(fmt) {
121 return .{ .data = .{ .itab = itab, .ctx = ctx } };121 return .{ .data = .{ .itab = itab, .ctx = ctx } };
122}122}
123123
124const ImportIndex = u32;124pub const ImportIndex = u32;
125const ImportTable = @This();125const ImportTable = @This();
126126
127const std = @import("std");127const std = @import("std");
src/link/Coff/Relocation.zig+6-2
...@@ -72,12 +72,14 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 {...@@ -72,12 +72,14 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 {
72 }72 }
73}73}
7474
75pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) void {75/// Returns `false` if obtaining the target address has been deferred until `flushModule`.
76/// This can happen when trying to resolve address of an import table entry ahead of time.
77pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) bool {
76 const atom = coff_file.getAtom(atom_index);78 const atom = coff_file.getAtom(atom_index);
77 const source_sym = atom.getSymbol(coff_file);79 const source_sym = atom.getSymbol(coff_file);
78 const source_vaddr = source_sym.value + self.offset;80 const source_vaddr = source_sym.value + self.offset;
7981
80 const target_vaddr = self.getTargetAddress(coff_file) orelse return;82 const target_vaddr = self.getTargetAddress(coff_file) orelse return false;
81 const target_vaddr_with_addend = target_vaddr + self.addend;83 const target_vaddr_with_addend = target_vaddr + self.addend;
8284
83 log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) ", .{85 log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) ", .{
...@@ -100,6 +102,8 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file:...@@ -100,6 +102,8 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file:
100 .x86, .x86_64 => self.resolveX86(ctx),102 .x86, .x86_64 => self.resolveX86(ctx),
101 else => unreachable, // unhandled target architecture103 else => unreachable, // unhandled target architecture
102 }104 }
105
106 return true;
103}107}
104108
105const Context = struct {109const Context = struct {