diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-29 09:21:52 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-29 09:21:52 +0200 |
| commit | 46b2f1f705bec886ffb8b0473e0ce43c74145a8d (patch) | |
| tree | 0b542353cbe2c5aa438c605832838179e3f46281 /src/link/Coff | |
| parent | dd66e0addb30d795a04324096c913ca89ccbcf40 (diff) | |
| parent | 17ec2cea6455148526f56fa17cb704fd1d656b06 (diff) | |
| download | zig-46b2f1f705bec886ffb8b0473e0ce43c74145a8d.tar.gz zig-46b2f1f705bec886ffb8b0473e0ce43c74145a8d.zip | |
Merge pull request #15105 from ziglang/hcs-win-poc
coff: improve handling of relocs and general linker fixes
Diffstat (limited to 'src/link/Coff')
| -rw-r--r-- | src/link/Coff/Atom.zig | 4 | ||||
| -rw-r--r-- | src/link/Coff/ImportTable.zig | 2 | ||||
| -rw-r--r-- | src/link/Coff/Relocation.zig | 72 |
3 files changed, 26 insertions, 52 deletions
diff --git a/src/link/Coff/Atom.zig b/src/link/Coff/Atom.zig index 80c04a8fa1..4afc1f7cb2 100644 --- a/src/link/Coff/Atom.zig +++ b/src/link/Coff/Atom.zig @@ -121,8 +121,8 @@ pub fn addBaseRelocation(coff_file: *Coff, atom_index: Index, offset: u32) !void pub fn freeRelocations(coff_file: *Coff, atom_index: Index) void { const gpa = coff_file.base.allocator; - var removed_relocs = coff_file.relocs.fetchRemove(atom_index); + var removed_relocs = coff_file.relocs.fetchOrderedRemove(atom_index); if (removed_relocs) |*relocs| relocs.value.deinit(gpa); - var removed_base_relocs = coff_file.base_relocs.fetchRemove(atom_index); + var removed_base_relocs = coff_file.base_relocs.fetchOrderedRemove(atom_index); if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(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 45f3a97052..37bd3e292f 100644 --- a/src/link/Coff/Relocation.zig +++ b/src/link/Coff/Relocation.zig @@ -72,62 +72,50 @@ pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 { } } -pub fn resolve(self: *Relocation, atom_index: Atom.Index, 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_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 = self.getTargetAddress(coff_file) orelse return false; 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; + return true; } 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 +176,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 +184,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 +199,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, }, } |
