diff --git a/src/Elf.zig b/src/Elf.zig index 8f736472..1ddc7975 100644 --- a/src/Elf.zig +++ b/src/Elf.zig @@ -2236,6 +2236,8 @@ fn writeAtoms(self: *Elf) !void { const tracy = trace(@src()); defer tracy.end(); + const gpa = self.base.allocator; + const slice = self.sections.slice(); for (slice.items(.shdr), slice.items(.atoms)) |shdr, atoms| { if (atoms.items.len == 0) continue; @@ -2274,6 +2276,16 @@ fn writeAtoms(self: *Elf) !void { try self.base.file.pwriteAll(buffer, shdr.sh_offset); } + for (self.thunks.items) |thunk| { + const shdr = slice.items(.shdr)[thunk.out_shndx]; + const offset = thunk.value + shdr.sh_offset; + const buffer = try gpa.alloc(u8, thunk.size(self)); + defer gpa.free(buffer); + var stream = std.io.fixedBufferStream(buffer); + try thunk.write(self, stream.writer()); + try self.base.file.pwriteAll(buffer, offset); + } + try self.reportUndefs(); } diff --git a/src/Elf/thunks.zig b/src/Elf/thunks.zig index ecf8f646..3f7ce6d4 100644 --- a/src/Elf/thunks.zig +++ b/src/Elf/thunks.zig @@ -18,12 +18,12 @@ 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.getAtom(atom_index).?; assert(atom.flags.alive); + const alignment = try math.powi(u32, 2, atom.alignment); + if (mem.alignForward(u64, shdr.sh_size, alignment) - start_atom.value >= maxAllowedDistance(cpu_arch)) break; atom.value = try advance(shdr, atom.size, atom.alignment); } diff --git a/test/elf.zig b/test/elf.zig index 4947776f..532d55c7 100644 --- a/test/elf.zig +++ b/test/elf.zig @@ -62,6 +62,7 @@ pub fn addElfTests(b: *Build, options: common.Options) *Step { elf_step.dependOn(testSharedAbsSymbol(b, opts)); elf_step.dependOn(testStrip(b, opts)); elf_step.dependOn(testThunks(b, opts)); + elf_step.dependOn(testThunks2(b, opts)); elf_step.dependOn(testTlsCommon(b, opts)); elf_step.dependOn(testTlsDesc(b, opts)); elf_step.dependOn(testTlsDescImport(b, opts)); @@ -2165,6 +2166,65 @@ fn testThunks(b: *Build, opts: Options) *Step { return test_step; } +fn testThunks2(b: *Build, opts: Options) *Step { + const test_step = b.step("test-elf-thunks2", ""); + + if (builtin.target.cpu.arch != .aarch64) return skipTestStep(test_step); + + const src = + \\#include + \\__attribute__((aligned(0x8000000))) int bar() { + \\ return 42; + \\} + \\int foobar(); + \\int foo() { + \\ return bar() - foobar(); + \\} + \\__attribute__((aligned(0x8000000))) int foobar() { + \\ return 42; + \\} + \\int main() { + \\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar()); + \\ return foo(); + \\} + ; + + { + const exe = cc(b, "a.out", opts); + exe.addCSource(src); + exe.addArg("-ffunction-sections"); + + const run = exe.run(); + run.expectStdOutEqual("bar=42, foo=0, foobar=42"); + run.expectExitCode(0); + test_step.dependOn(run.step()); + + const check = exe.check(); + check.max_bytes = std.math.maxInt(u32); + check.checkInSymtab(); + check.checkContains("_libc_start_main$thunk"); + test_step.dependOn(&check.step); + } + + { + const exe = cc(b, "a.out", opts); + exe.addCSource(src); + + const run = exe.run(); + run.expectStdOutEqual("bar=42, foo=0, foobar=42"); + run.expectExitCode(0); + test_step.dependOn(run.step()); + + const check = exe.check(); + check.max_bytes = std.math.maxInt(u32); + check.checkInSymtab(); + check.checkContains("_libc_start_main$thunk"); + test_step.dependOn(&check.step); + } + + return test_step; +} + fn testTlsCommon(b: *Build, opts: Options) *Step { const test_step = b.step("test-elf-tls-common", "");