Commit b1eba5a996

Jakub Konka <kubkon@jakubkonka.com>
2024-03-10 23:45:29
elf+aarch64: actually write out thunks, and add a proper link test
1 parent da5b16f
Changed files (3)
src
test
link
src/link/Elf/thunks.zig
@@ -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"),
src/link/Elf.zig
@@ -4565,6 +4565,16 @@ fn writeAtoms(self: *Elf) !void {
         try self.base.file.?.pwriteAll(buffer, sh_offset);
     }
 
+    for (self.thunks.items) |th| {
+        const shdr = self.shdrs.items[th.output_section_index];
+        const offset = th.value + shdr.sh_offset;
+        const buffer = try gpa.alloc(u8, th.size(self));
+        defer gpa.free(buffer);
+        var stream = std.io.fixedBufferStream(buffer);
+        try th.write(self, stream.writer());
+        try self.base.file.?.pwriteAll(buffer, offset);
+    }
+
     try self.reportUndefinedSymbols(&undefs);
 
     if (has_reloc_errors) return error.FlushFailure;
test/link/elf.zig
@@ -20,16 +20,11 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
         .os_tag = .linux,
         .abi = .gnu,
     });
-    // const aarch64_musl = b.resolveTargetQuery(.{
-    //     .cpu_arch = .aarch64,
-    //     .os_tag = .linux,
-    //     .abi = .musl,
-    // });
-    // const aarch64_gnu = b.resolveTargetQuery(.{
-    //     .cpu_arch = .aarch64,
-    //     .os_tag = .linux,
-    //     .abi = .gnu,
-    // });
+    const aarch64_musl = b.resolveTargetQuery(.{
+        .cpu_arch = .aarch64,
+        .os_tag = .linux,
+        .abi = .musl,
+    });
     const riscv64_musl = b.resolveTargetQuery(.{
         .cpu_arch = .riscv64,
         .os_tag = .linux,
@@ -153,6 +148,9 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
     elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_musl }));
     elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu }));
 
+    // aarch64 specific tests
+    elf_step.dependOn(testThunks(b, .{ .target = aarch64_musl }));
+
     // x86_64 self-hosted backend
     elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));
     elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));
@@ -2670,6 +2668,43 @@ fn testStrip(b: *Build, opts: Options) *Step {
     return test_step;
 }
 
+fn testThunks(b: *Build, opts: Options) *Step {
+    const test_step = addTestStep(b, "thunks", opts);
+
+    const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 
+    \\#include <stdio.h>
+    \\__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();
+    \\}
+    });
+    exe.link_function_sections = true;
+    exe.linkLibC();
+
+    const run = addRunArtifact(exe);
+    run.expectStdOutEqual("bar=42, foo=0, foobar=42");
+    run.expectExitCode(0);
+    test_step.dependOn(&run.step);
+
+    const check = exe.checkObject();
+    check.max_bytes = std.math.maxInt(u32);
+    check.checkInSymtab();
+    check.checkContains("_libc_start_main$thunk");
+    test_step.dependOn(&check.step);
+
+    return test_step;
+}
+
 fn testTlsDfStaticTls(b: *Build, opts: Options) *Step {
     const test_step = addTestStep(b, "tls-df-static-tls", opts);