Commit 0a0f90f949

Jakub Konka <kubkon@jakubkonka.com>
2024-02-03 10:52:29
macho: migrate thunks to use new relative addressing mechanism
1 parent aa1aa98
Changed files (4)
src/link/MachO/Atom.zig
@@ -706,7 +706,7 @@ fn resolveRelocInner(
                 .aarch64 => {
                     const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
                         const thunk = self.getThunk(macho_file);
-                        const S_: i64 = @intCast(thunk.getAddress(rel.target));
+                        const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));
                         break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
                     };
                     var inst = aarch64.Instruction{
src/link/MachO/relocatable.zig
@@ -61,7 +61,6 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
     try createSegment(macho_file);
     try allocateSections(macho_file);
     allocateSegment(macho_file);
-    macho_file.allocateAtoms();
 
     var off = off: {
         const seg = macho_file.segments.items[0];
src/link/MachO/thunks.zig
@@ -66,7 +66,7 @@ fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {
     if (atom.out_n_sect != target.out_n_sect) return false;
     const target_atom = target.getAtom(macho_file).?;
     if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false;
-    const saddr = @as(i64, @intCast(atom.value)) + @as(i64, @intCast(rel.offset - atom.off));
+    const saddr = @as(i64, @intCast(atom.getAddress(macho_file))) + @as(i64, @intCast(rel.offset - atom.off));
     const taddr: i64 = @intCast(rel.getTargetAddress(macho_file));
     _ = math.cast(i28, taddr + rel.addend - saddr) orelse return false;
     return true;
@@ -85,14 +85,19 @@ pub const Thunk = struct {
         return thunk.symbols.keys().len * trampoline_size;
     }
 
-    pub fn getAddress(thunk: Thunk, sym_index: Symbol.Index) u64 {
-        return thunk.value + thunk.symbols.getIndex(sym_index).? * trampoline_size;
+    pub fn getAddress(thunk: Thunk, macho_file: *MachO) u64 {
+        const header = macho_file.sections.items(.header)[thunk.out_n_sect];
+        return header.addr + thunk.value;
+    }
+
+    pub fn getTargetAddress(thunk: Thunk, sym_index: Symbol.Index, macho_file: *MachO) u64 {
+        return thunk.getAddress(macho_file) + thunk.symbols.getIndex(sym_index).? * trampoline_size;
     }
 
     pub fn write(thunk: Thunk, macho_file: *MachO, writer: anytype) !void {
         for (thunk.symbols.keys(), 0..) |sym_index, i| {
             const sym = macho_file.getSymbol(sym_index);
-            const saddr = thunk.value + i * trampoline_size;
+            const saddr = thunk.getAddress(macho_file) + i * trampoline_size;
             const taddr = sym.getAddress(.{}, macho_file);
             const pages = try Relocation.calcNumberOfPages(saddr, taddr);
             try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
src/link/MachO.zig
@@ -596,7 +596,6 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
 
     try self.allocateSections();
     self.allocateSegments();
-    self.allocateAtoms();
     self.allocateSyntheticSymbols();
     try self.allocateLinkeditSegment();
 
@@ -2392,14 +2391,6 @@ fn allocateSegments(self: *MachO) void {
     }
 }
 
-pub fn allocateAtoms(self: *MachO) void {
-    // TODO: redo this like atoms
-    for (self.thunks.items) |*thunk| {
-        const header = self.sections.items(.header)[thunk.out_n_sect];
-        thunk.value += header.addr;
-    }
-}
-
 fn allocateSyntheticSymbols(self: *MachO) void {
     const text_seg = self.getTextSegment();
 
@@ -2608,7 +2599,7 @@ fn writeAtoms(self: *MachO) !void {
 
     for (self.thunks.items) |thunk| {
         const header = slice.items(.header)[thunk.out_n_sect];
-        const offset = thunk.value - header.addr + header.offset;
+        const offset = thunk.value + header.offset;
         const buffer = try gpa.alloc(u8, thunk.size());
         defer gpa.free(buffer);
         var stream = std.io.fixedBufferStream(buffer);