authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 18:59:44+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 18:59:44+02:00
log004f32e79d61cb549b6cf71499138db0df56e152
tree33d16cd1890d3db5493869347d9b295fcbc5cbfc
parent43487eb3ef0933c1da53b917c44ba6070d8e5a21

coff: resolve relocs on bytes buffer directly


3 files changed, 53 insertions(+), 59 deletions(-)

src/link.zig+2
......@@ -395,6 +395,7 @@ pub const File = struct {
395395 .macos => base.cast(MachO).?.ptraceAttach(pid) catch |err| {
396396 log.warn("attaching failed with error: {s}", .{@errorName(err)});
397397 },
398 .windows => {},
398399 else => return error.HotSwapUnavailableOnHostOperatingSystem,
399400 }
400401 }
......@@ -436,6 +437,7 @@ pub const File = struct {
436437 .macos => base.cast(MachO).?.ptraceDetach(pid) catch |err| {
437438 log.warn("detaching failed with error: {s}", .{@errorName(err)});
438439 },
440 .windows => {},
439441 else => return error.HotSwapUnavailableOnHostOperatingSystem,
440442 }
441443 }
src/link/Coff.zig+32-10
......@@ -771,7 +771,7 @@ fn shrinkAtom(self: *Coff, atom_index: Atom.Index, new_block_size: u32) void {
771771 // capacity, insert a free list node for it.
772772}
773773
774fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []const u8) !void {
774fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {
775775 const atom = self.getAtom(atom_index);
776776 const sym = atom.getSymbol(self);
777777 const section = self.sections.get(@enumToInt(sym.section_number) - 1);
......@@ -781,8 +781,8 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []const u8) !void {
781781 file_offset,
782782 file_offset + code.len,
783783 });
784 self.resolveRelocs(atom_index, code);
784785 try self.base.file.?.pwriteAll(code, file_offset);
785 try self.resolveRelocs(atom_index);
786786}
787787
788788fn writePtrWidthAtom(self: *Coff, atom_index: Atom.Index) !void {
......@@ -820,14 +820,15 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void {
820820 }
821821}
822822
823fn resolveRelocs(self: *Coff, atom_index: Atom.Index) !void {
823fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void {
824824 const relocs = self.relocs.get(atom_index) orelse return;
825825
826826 log.debug("relocating '{s}'", .{self.getAtom(atom_index).getName(self)});
827827
828828 for (relocs.items) |*reloc| {
829829 if (!reloc.dirty) continue;
830 try reloc.resolve(atom_index, self);
830 reloc.resolve(atom_index, code, self);
831 reloc.dirty = false;
831832 }
832833}
833834
......@@ -944,7 +945,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
944945 &code_buffer,
945946 .none,
946947 );
947 const code = switch (res) {
948 var code = switch (res) {
948949 .ok => code_buffer.items,
949950 .fail => |em| {
950951 decl.analysis = .codegen_failure;
......@@ -994,7 +995,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
994995 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .none, .{
995996 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
996997 });
997 const code = switch (res) {
998 var code = switch (res) {
998999 .ok => code_buffer.items,
9991000 .fail => |em| {
10001001 decl.analysis = .codegen_failure;
......@@ -1057,7 +1058,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !
10571058 }, &code_buffer, .none, .{
10581059 .parent_atom_index = atom.getSymbolIndex().?,
10591060 });
1060 const code = switch (res) {
1061 var code = switch (res) {
10611062 .ok => code_buffer.items,
10621063 .fail => |em| {
10631064 decl.analysis = .codegen_failure;
......@@ -1110,7 +1111,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
11101111 return index;
11111112}
11121113
1113fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, complex_type: coff.ComplexType) !void {
1114fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, complex_type: coff.ComplexType) !void {
11141115 const gpa = self.base.allocator;
11151116 const mod = self.base.options.module.?;
11161117 const decl = mod.declPtr(decl_index);
......@@ -1424,8 +1425,28 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
14241425 try self.writeImportTables();
14251426 {
14261427 var it = self.relocs.keyIterator();
1427 while (it.next()) |atom| {
1428 try self.resolveRelocs(atom.*);
1428 while (it.next()) |atom_index_ptr| {
1429 const atom_index = atom_index_ptr.*;
1430 const relocs = self.relocs.get(atom_index).?;
1431 const needs_update = for (relocs.items) |reloc| {
1432 if (reloc.dirty) break true;
1433 } else false;
1434
1435 if (!needs_update) continue;
1436
1437 const atom = self.getAtom(atom_index);
1438 const sym = atom.getSymbol(self);
1439 const section = self.sections.get(@enumToInt(sym.section_number) - 1).header;
1440 const file_offset = section.pointer_to_raw_data + sym.value - section.virtual_address;
1441
1442 var code = std.ArrayList(u8).init(gpa);
1443 defer code.deinit();
1444 try code.resize(math.cast(usize, atom.size) orelse return error.Overflow);
1445
1446 const amt = try self.base.file.?.preadAll(code.items, file_offset);
1447 if (amt != code.items.len) return error.InputOutput;
1448
1449 try self.writeAtom(atom_index, code.items);
14291450 }
14301451 }
14311452 try self.writeBaseRelocations();
......@@ -1642,6 +1663,7 @@ fn writeImportTables(self: *Coff) !void {
16421663 const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address);
16431664 if (needed_size > sect_vm_capacity) {
16441665 try self.growSectionVM(self.idata_section_index.?, needed_size);
1666 self.markRelocsDirtyByAddress(header.virtual_address + needed_size);
16451667 }
16461668
16471669 header.virtual_size = @max(header.virtual_size, needed_size);
src/link/Coff/Relocation.zig+19-49
......@@ -72,62 +72,46 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 {
7272 }
7373}
7474
75pub fn resolve(self: *Relocation, atom_index: Atom.Index, coff_file: *Coff) !void {
75pub fn resolve(self: *Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) void {
7676 const atom = coff_file.getAtom(atom_index);
7777 const source_sym = atom.getSymbol(coff_file);
78 const source_section = coff_file.sections.get(@enumToInt(source_sym.section_number) - 1).header;
7978 const source_vaddr = source_sym.value + self.offset;
8079
81 const file_offset = source_section.pointer_to_raw_data + source_sym.value - source_section.virtual_address;
82
8380 const target_vaddr = self.getTargetAddress(coff_file) orelse return;
8481 const target_vaddr_with_addend = target_vaddr + self.addend;
8582
86 log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) (in file at 0x{x})", .{
83 log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) ", .{
8784 source_vaddr,
8885 target_vaddr_with_addend,
8986 coff_file.getSymbolName(self.target),
9087 @tagName(self.type),
91 file_offset + self.offset,
9288 });
9389
9490 const ctx: Context = .{
9591 .source_vaddr = source_vaddr,
9692 .target_vaddr = target_vaddr_with_addend,
97 .file_offset = file_offset,
9893 .image_base = coff_file.getImageBase(),
94 .code = code,
95 .ptr_width = coff_file.ptr_width,
9996 };
10097
10198 switch (coff_file.base.options.target.cpu.arch) {
102 .aarch64 => try self.resolveAarch64(ctx, coff_file),
103 .x86, .x86_64 => try self.resolveX86(ctx, coff_file),
99 .aarch64 => self.resolveAarch64(ctx),
100 .x86, .x86_64 => self.resolveX86(ctx),
104101 else => unreachable, // unhandled target architecture
105102 }
106
107 self.dirty = false;
108103}
109104
110105const Context = struct {
111106 source_vaddr: u32,
112107 target_vaddr: u32,
113 file_offset: u32,
114108 image_base: u64,
109 code: []u8,
110 ptr_width: Coff.PtrWidth,
115111};
116112
117fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void {
118 var buffer: [@sizeOf(u64)]u8 = undefined;
119 switch (self.length) {
120 2 => {
121 const amt = try coff_file.base.file.?.preadAll(buffer[0..4], ctx.file_offset + self.offset);
122 if (amt != 4) return error.InputOutput;
123 },
124 3 => {
125 const amt = try coff_file.base.file.?.preadAll(&buffer, ctx.file_offset + self.offset);
126 if (amt != 8) return error.InputOutput;
127 },
128 else => unreachable,
129 }
130
113fn resolveAarch64(self: Relocation, ctx: Context) void {
114 var buffer = ctx.code[self.offset..];
131115 switch (self.type) {
132116 .got_page, .import_page, .page => {
133117 const source_page = @intCast(i32, ctx.source_vaddr >> 12);
......@@ -188,7 +172,7 @@ fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void {
188172 buffer[0..4],
189173 @truncate(u32, ctx.target_vaddr + ctx.image_base),
190174 ),
191 3 => mem.writeIntLittle(u64, &buffer, ctx.target_vaddr + ctx.image_base),
175 3 => mem.writeIntLittle(u64, buffer[0..8], ctx.target_vaddr + ctx.image_base),
192176 else => unreachable,
193177 }
194178 },
......@@ -196,15 +180,10 @@ fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void {
196180 .got => unreachable,
197181 .import => unreachable,
198182 }
199
200 switch (self.length) {
201 2 => try coff_file.base.file.?.pwriteAll(buffer[0..4], ctx.file_offset + self.offset),
202 3 => try coff_file.base.file.?.pwriteAll(&buffer, ctx.file_offset + self.offset),
203 else => unreachable,
204 }
205183}
206184
207fn resolveX86(self: Relocation, ctx: Context, coff_file: *Coff) !void {
185fn resolveX86(self: Relocation, ctx: Context) void {
186 var buffer = ctx.code[self.offset..];
208187 switch (self.type) {
209188 .got_page => unreachable,
210189 .got_pageoff => unreachable,
......@@ -216,26 +195,17 @@ fn resolveX86(self: Relocation, ctx: Context, coff_file: *Coff) !void {
216195 .got, .import => {
217196 assert(self.pcrel);
218197 const disp = @intCast(i32, ctx.target_vaddr) - @intCast(i32, ctx.source_vaddr) - 4;
219 try coff_file.base.file.?.pwriteAll(mem.asBytes(&disp), ctx.file_offset + self.offset);
198 mem.writeIntLittle(i32, buffer[0..4], disp);
220199 },
221200 .direct => {
222201 if (self.pcrel) {
223202 const disp = @intCast(i32, ctx.target_vaddr) - @intCast(i32, ctx.source_vaddr) - 4;
224 try coff_file.base.file.?.pwriteAll(mem.asBytes(&disp), ctx.file_offset + self.offset);
225 } else switch (coff_file.ptr_width) {
226 .p32 => try coff_file.base.file.?.pwriteAll(
227 mem.asBytes(&@intCast(u32, ctx.target_vaddr + ctx.image_base)),
228 ctx.file_offset + self.offset,
229 ),
203 mem.writeIntLittle(i32, buffer[0..4], disp);
204 } else switch (ctx.ptr_width) {
205 .p32 => mem.writeIntLittle(u32, buffer[0..4], @intCast(u32, ctx.target_vaddr + ctx.image_base)),
230206 .p64 => switch (self.length) {
231 2 => try coff_file.base.file.?.pwriteAll(
232 mem.asBytes(&@truncate(u32, ctx.target_vaddr + ctx.image_base)),
233 ctx.file_offset + self.offset,
234 ),
235 3 => try coff_file.base.file.?.pwriteAll(
236 mem.asBytes(&(ctx.target_vaddr + ctx.image_base)),
237 ctx.file_offset + self.offset,
238 ),
207 2 => mem.writeIntLittle(u32, buffer[0..4], @truncate(u32, ctx.target_vaddr + ctx.image_base)),
208 3 => mem.writeIntLittle(u64, buffer[0..8], ctx.target_vaddr + ctx.image_base),
239209 else => unreachable,
240210 },
241211 }