Commit faa4bdb017

Jakub Konka <kubkon@jakubkonka.com>
2024-03-12 00:07:07
elf+aarch64: fix off-by-one in converging on groups interleaved with thunks
1 parent b1bd382
Changed files (2)
src
link
test
link
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);
         }
 
test/link/elf.zig
@@ -2671,36 +2671,56 @@ fn testStrip(b: *Build, opts: Options) *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 src =
+        \\#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();
+        \\}
+    ;
 
-    const run = addRunArtifact(exe);
-    run.expectStdOutEqual("bar=42, foo=0, foobar=42");
-    run.expectExitCode(0);
-    test_step.dependOn(&run.step);
+    {
+        const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = src });
+        exe.link_function_sections = true;
+        exe.linkLibC();
 
-    const check = exe.checkObject();
-    check.max_bytes = std.math.maxInt(u32);
-    check.checkInSymtab();
-    check.checkContains("_libc_start_main$thunk");
-    test_step.dependOn(&check.step);
+        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);
+    }
+
+    {
+        const exe = addExecutable(b, opts, .{ .name = "main2", .c_source_bytes = src });
+        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;
 }