diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-28 18:59:44 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-28 18:59:44 +0200 |
| commit | 004f32e79d61cb549b6cf71499138db0df56e152 (patch) | |
| tree | 33d16cd1890d3db5493869347d9b295fcbc5cbfc /src/link/Coff/Relocation.zig | |
| parent | 43487eb3ef0933c1da53b917c44ba6070d8e5a21 (diff) | |
| download | zig-004f32e79d61cb549b6cf71499138db0df56e152.tar.gz zig-004f32e79d61cb549b6cf71499138db0df56e152.zip | |
coff: resolve relocs on bytes buffer directly
Diffstat (limited to 'src/link/Coff/Relocation.zig')
| -rw-r--r-- | src/link/Coff/Relocation.zig | 68 |
1 files changed, 19 insertions, 49 deletions
diff --git a/src/link/Coff/Relocation.zig b/src/link/Coff/Relocation.zig index 45f3a97052..c0fd5562e4 100644 --- a/src/link/Coff/Relocation.zig +++ b/src/link/Coff/Relocation.zig @@ -72,62 +72,46 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 { } } -pub fn resolve(self: *Relocation, atom_index: Atom.Index, coff_file: *Coff) !void { +pub fn resolve(self: *Relocation, atom_index: Atom.Index, code: []u8, coff_file: *Coff) void { const atom = coff_file.getAtom(atom_index); const source_sym = atom.getSymbol(coff_file); - const source_section = coff_file.sections.get(@enumToInt(source_sym.section_number) - 1).header; const source_vaddr = source_sym.value + self.offset; - const file_offset = source_section.pointer_to_raw_data + source_sym.value - source_section.virtual_address; - const target_vaddr = self.getTargetAddress(coff_file) orelse return; const target_vaddr_with_addend = target_vaddr + self.addend; - log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) (in file at 0x{x})", .{ + log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) ", .{ source_vaddr, target_vaddr_with_addend, coff_file.getSymbolName(self.target), @tagName(self.type), - file_offset + self.offset, }); const ctx: Context = .{ .source_vaddr = source_vaddr, .target_vaddr = target_vaddr_with_addend, - .file_offset = file_offset, .image_base = coff_file.getImageBase(), + .code = code, + .ptr_width = coff_file.ptr_width, }; switch (coff_file.base.options.target.cpu.arch) { - .aarch64 => try self.resolveAarch64(ctx, coff_file), - .x86, .x86_64 => try self.resolveX86(ctx, coff_file), + .aarch64 => self.resolveAarch64(ctx), + .x86, .x86_64 => self.resolveX86(ctx), else => unreachable, // unhandled target architecture } - - self.dirty = false; } const Context = struct { source_vaddr: u32, target_vaddr: u32, - file_offset: u32, image_base: u64, + code: []u8, + ptr_width: Coff.PtrWidth, }; -fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void { - var buffer: [@sizeOf(u64)]u8 = undefined; - switch (self.length) { - 2 => { - const amt = try coff_file.base.file.?.preadAll(buffer[0..4], ctx.file_offset + self.offset); - if (amt != 4) return error.InputOutput; - }, - 3 => { - const amt = try coff_file.base.file.?.preadAll(&buffer, ctx.file_offset + self.offset); - if (amt != 8) return error.InputOutput; - }, - else => unreachable, - } - +fn resolveAarch64(self: Relocation, ctx: Context) void { + var buffer = ctx.code[self.offset..]; switch (self.type) { .got_page, .import_page, .page => { const source_page = @intCast(i32, ctx.source_vaddr >> 12); @@ -188,7 +172,7 @@ fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void { buffer[0..4], @truncate(u32, ctx.target_vaddr + ctx.image_base), ), - 3 => mem.writeIntLittle(u64, &buffer, ctx.target_vaddr + ctx.image_base), + 3 => mem.writeIntLittle(u64, buffer[0..8], ctx.target_vaddr + ctx.image_base), else => unreachable, } }, @@ -196,15 +180,10 @@ fn resolveAarch64(self: Relocation, ctx: Context, coff_file: *Coff) !void { .got => unreachable, .import => unreachable, } - - switch (self.length) { - 2 => try coff_file.base.file.?.pwriteAll(buffer[0..4], ctx.file_offset + self.offset), - 3 => try coff_file.base.file.?.pwriteAll(&buffer, ctx.file_offset + self.offset), - else => unreachable, - } } -fn resolveX86(self: Relocation, ctx: Context, coff_file: *Coff) !void { +fn resolveX86(self: Relocation, ctx: Context) void { + var buffer = ctx.code[self.offset..]; switch (self.type) { .got_page => unreachable, .got_pageoff => unreachable, @@ -216,26 +195,17 @@ fn resolveX86(self: Relocation, ctx: Context, coff_file: *Coff) !void { .got, .import => { assert(self.pcrel); const disp = @intCast(i32, ctx.target_vaddr) - @intCast(i32, ctx.source_vaddr) - 4; - try coff_file.base.file.?.pwriteAll(mem.asBytes(&disp), ctx.file_offset + self.offset); + mem.writeIntLittle(i32, buffer[0..4], disp); }, .direct => { if (self.pcrel) { const disp = @intCast(i32, ctx.target_vaddr) - @intCast(i32, ctx.source_vaddr) - 4; - try coff_file.base.file.?.pwriteAll(mem.asBytes(&disp), ctx.file_offset + self.offset); - } else switch (coff_file.ptr_width) { - .p32 => try coff_file.base.file.?.pwriteAll( - mem.asBytes(&@intCast(u32, ctx.target_vaddr + ctx.image_base)), - ctx.file_offset + self.offset, - ), + mem.writeIntLittle(i32, buffer[0..4], disp); + } else switch (ctx.ptr_width) { + .p32 => mem.writeIntLittle(u32, buffer[0..4], @intCast(u32, ctx.target_vaddr + ctx.image_base)), .p64 => switch (self.length) { - 2 => try coff_file.base.file.?.pwriteAll( - mem.asBytes(&@truncate(u32, ctx.target_vaddr + ctx.image_base)), - ctx.file_offset + self.offset, - ), - 3 => try coff_file.base.file.?.pwriteAll( - mem.asBytes(&(ctx.target_vaddr + ctx.image_base)), - ctx.file_offset + self.offset, - ), + 2 => mem.writeIntLittle(u32, buffer[0..4], @truncate(u32, ctx.target_vaddr + ctx.image_base)), + 3 => mem.writeIntLittle(u64, buffer[0..8], ctx.target_vaddr + ctx.image_base), else => unreachable, }, } |
