aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/link/Elf.zig34
-rw-r--r--src/link/Elf/thunks.zig8
2 files changed, 31 insertions, 11 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index d26f49ca09..e6182b4333 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -4565,6 +4565,22 @@ fn writeAtoms(self: *Elf) !void {
try self.base.file.?.pwriteAll(buffer, sh_offset);
}
+ if (self.requiresThunks()) {
+ var buffer = std.ArrayList(u8).init(gpa);
+ defer buffer.deinit();
+
+ for (self.thunks.items) |th| {
+ const thunk_size = th.size(self);
+ try buffer.ensureUnusedCapacity(thunk_size);
+ const shdr = self.shdrs.items[th.output_section_index];
+ const offset = th.value + shdr.sh_offset;
+ try th.write(self, buffer.writer());
+ assert(buffer.items.len == thunk_size);
+ try self.base.file.?.pwriteAll(buffer.items, offset);
+ buffer.clearRetainingCapacity();
+ }
+ }
+
try self.reportUndefinedSymbols(&undefs);
if (has_reloc_errors) return error.FlushFailure;
@@ -4593,12 +4609,12 @@ pub fn updateSymtabSize(self: *Elf) !void {
nlocals += 1;
}
- for (self.thunks.items) |*th| {
+ if (self.requiresThunks()) for (self.thunks.items) |*th| {
th.output_symtab_ctx.ilocal = nlocals + 1;
th.calcSymtabSize(self);
nlocals += th.output_symtab_ctx.nlocals;
strsize += th.output_symtab_ctx.strsize;
- }
+ };
for (files.items) |index| {
const file_ptr = self.file(index).?;
@@ -4830,9 +4846,9 @@ pub fn writeSymtab(self: *Elf) !void {
self.writeSectionSymbols();
- for (self.thunks.items) |th| {
+ if (self.requiresThunks()) for (self.thunks.items) |th| {
th.writeSymtab(self);
- }
+ };
if (self.zigObjectPtr()) |zig_object| {
zig_object.asFile().writeSymtab(self);
@@ -5997,10 +6013,14 @@ fn fmtDumpState(
try writer.print("linker_defined({d}) : (linker defined)\n", .{index});
try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
}
- try writer.writeAll("thunks\n");
- for (self.thunks.items, 0..) |th, index| {
- try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });
+
+ if (self.requiresThunks()) {
+ try writer.writeAll("thunks\n");
+ for (self.thunks.items, 0..) |th, index| {
+ try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });
+ }
}
+
try writer.print("{}\n", .{self.zig_got.fmt(self)});
try writer.print("{}\n", .{self.got.fmt(self)});
try writer.print("{}\n", .{self.plt.fmt(self)});
diff --git a/src/link/Elf/thunks.zig b/src/link/Elf/thunks.zig
index 398a2acd93..119529b512 100644
--- a/src/link/Elf/thunks.zig
+++ b/src/link/Elf/thunks.zig
@@ -1,6 +1,7 @@
pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
+ const max_distance = maxAllowedDistance(cpu_arch);
const shdr = &elf_file.shdrs.items[shndx];
const atoms = elf_file.output_sections.get(shndx).?.items;
assert(atoms.len > 0);
@@ -17,12 +18,11 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment);
i += 1;
- while (i < atoms.len and
- shdr.sh_size - start_atom.value < maxAllowedDistance(cpu_arch)) : (i += 1)
- {
+ while (i < atoms.len) : (i += 1) {
const atom_index = atoms[i];
const atom = elf_file.atom(atom_index).?;
assert(atom.flags.alive);
+ if (atom.alignment.forward(shdr.sh_size) - start_atom.value >= max_distance) break;
atom.value = try advance(shdr, atom.size, atom.alignment);
}
@@ -103,7 +103,7 @@ pub const Thunk = struct {
}
pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
- switch (elf_file.options.cpu_arch.?) {
+ switch (elf_file.getTarget().cpu.arch) {
.aarch64 => try aarch64.write(thunk, elf_file, writer),
.x86_64, .riscv64 => unreachable,
else => @panic("unhandled arch"),