aboutsummaryrefslogtreecommitdiff
path: root/src/link/Coff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-03-29 09:21:52 +0200
committerGitHub <noreply@github.com>2023-03-29 09:21:52 +0200
commit46b2f1f705bec886ffb8b0473e0ce43c74145a8d (patch)
tree0b542353cbe2c5aa438c605832838179e3f46281 /src/link/Coff
parentdd66e0addb30d795a04324096c913ca89ccbcf40 (diff)
parent17ec2cea6455148526f56fa17cb704fd1d656b06 (diff)
downloadzig-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.zig4
-rw-r--r--src/link/Coff/ImportTable.zig2
-rw-r--r--src/link/Coff/Relocation.zig72
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,
},
}