Commit c984201ddb

Jakub Konka <kubkon@jakubkonka.com>
2023-03-22 13:57:43
macho+zld: refactor parsing of relocation target
1 parent 8bffe87
src/link/MachO/dead_strip.zig
@@ -130,14 +130,29 @@ fn markLive(zld: *Zld, atom_index: AtomIndex, alive: *AtomTable) void {
     const header = zld.sections.items(.header)[sym.n_sect - 1];
     if (header.isZerofill()) return;
 
+    const code = Atom.getAtomCode(zld, atom_index);
     const relocs = Atom.getAtomRelocs(zld, atom_index);
+    const ctx = Atom.getRelocContext(zld, atom_index);
+
     for (relocs) |rel| {
         const target = switch (cpu_arch) {
             .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) {
                 .ARM64_RELOC_ADDEND => continue,
-                else => Atom.parseRelocTarget(zld, atom_index, rel),
+                else => Atom.parseRelocTarget(zld, .{
+                    .object_id = atom.getFile().?,
+                    .rel = rel,
+                    .code = code,
+                    .base_offset = ctx.base_offset,
+                    .base_addr = ctx.base_addr,
+                }),
             },
-            .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel),
+            .x86_64 => Atom.parseRelocTarget(zld, .{
+                .object_id = atom.getFile().?,
+                .rel = rel,
+                .code = code,
+                .base_offset = ctx.base_offset,
+                .base_addr = ctx.base_addr,
+            }),
             else => unreachable,
         };
         const target_sym = zld.getSymbol(target);
@@ -175,14 +190,29 @@ fn refersLive(zld: *Zld, atom_index: AtomIndex, alive: AtomTable) bool {
     const header = zld.sections.items(.header)[sym.n_sect - 1];
     assert(!header.isZerofill());
 
+    const code = Atom.getAtomCode(zld, atom_index);
     const relocs = Atom.getAtomRelocs(zld, atom_index);
+    const ctx = Atom.getRelocContext(zld, atom_index);
+
     for (relocs) |rel| {
         const target = switch (cpu_arch) {
             .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) {
                 .ARM64_RELOC_ADDEND => continue,
-                else => Atom.parseRelocTarget(zld, atom_index, rel),
+                else => Atom.parseRelocTarget(zld, .{
+                    .object_id = atom.getFile().?,
+                    .rel = rel,
+                    .code = code,
+                    .base_offset = ctx.base_offset,
+                    .base_addr = ctx.base_addr,
+                }),
             },
-            .x86_64 => Atom.parseRelocTarget(zld, atom_index, rel),
+            .x86_64 => Atom.parseRelocTarget(zld, .{
+                .object_id = atom.getFile().?,
+                .rel = rel,
+                .code = code,
+                .base_offset = ctx.base_offset,
+                .base_addr = ctx.base_addr,
+            }),
             else => unreachable,
         };
 
@@ -283,13 +313,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void {
             try markEhFrameRecord(zld, object_id, atom_index, alive);
         } else {
             if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| {
-                const target = UnwindInfo.parseRelocTarget(
-                    zld,
-                    object_id,
-                    rel,
-                    mem.asBytes(&record),
-                    @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
-                );
+                const target = Atom.parseRelocTarget(zld, .{
+                    .object_id = object_id,
+                    .rel = rel,
+                    .code = mem.asBytes(&record),
+                    .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
+                });
                 const target_sym = zld.getSymbol(target);
                 if (!target_sym.undf()) {
                     const target_object = zld.objects.items[target.getFile().?];
@@ -299,13 +328,12 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void {
             }
 
             if (UnwindInfo.getLsdaReloc(zld, object_id, record_id)) |rel| {
-                const target = UnwindInfo.parseRelocTarget(
-                    zld,
-                    object_id,
-                    rel,
-                    mem.asBytes(&record),
-                    @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
-                );
+                const target = Atom.parseRelocTarget(zld, .{
+                    .object_id = object_id,
+                    .rel = rel,
+                    .code = mem.asBytes(&record),
+                    .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
+                });
                 const target_object = zld.objects.items[target.getFile().?];
                 const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?;
                 markLive(zld, target_atom_index, alive);
@@ -333,13 +361,12 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A
             // Mark FDE references which should include any referenced LSDA record
             const relocs = eh_frame.getRelocs(zld, object_id, fde_offset);
             for (relocs) |rel| {
-                const target = UnwindInfo.parseRelocTarget(
-                    zld,
-                    object_id,
-                    rel,
-                    fde.data,
-                    @intCast(i32, fde_offset) + 4,
-                );
+                const target = Atom.parseRelocTarget(zld, .{
+                    .object_id = object_id,
+                    .rel = rel,
+                    .code = fde.data,
+                    .base_offset = @intCast(i32, fde_offset) + 4,
+                });
                 const target_sym = zld.getSymbol(target);
                 if (!target_sym.undf()) blk: {
                     const target_object = zld.objects.items[target.getFile().?];
src/link/MachO/eh_frame.zig
@@ -308,13 +308,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
                     },
                     else => unreachable,
                 }
-                const target = UnwindInfo.parseRelocTarget(
-                    zld,
-                    object_id,
-                    rel,
-                    rec.data,
-                    @intCast(i32, source_offset) + 4,
-                );
+                const target = Atom.parseRelocTarget(zld, .{
+                    .object_id = object_id,
+                    .rel = rel,
+                    .code = rec.data,
+                    .base_offset = @intCast(i32, source_offset) + 4,
+                });
                 return target;
             }
             return null;
@@ -331,13 +330,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
             const relocs = getRelocs(zld, object_id, ctx.source_offset);
 
             for (relocs) |rel| {
-                const target = UnwindInfo.parseRelocTarget(
-                    zld,
-                    object_id,
-                    rel,
-                    rec.data,
-                    @intCast(i32, ctx.source_offset) + 4,
-                );
+                const target = Atom.parseRelocTarget(zld, .{
+                    .object_id = object_id,
+                    .rel = rel,
+                    .code = rec.data,
+                    .base_offset = @intCast(i32, ctx.source_offset) + 4,
+                });
                 const rel_offset = @intCast(u32, rel.r_address - @intCast(i32, ctx.source_offset) - 4);
                 const source_addr = ctx.sect_addr + rel_offset + ctx.out_offset + 4;
 
src/link/MachO/Object.zig
@@ -735,13 +735,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
                         assert(rel_pos.len > 0); // TODO convert to an error as the FDE eh frame is malformed
                         // Find function symbol that this record describes
                         const rel = relocs[rel_pos.start..][rel_pos.len - 1];
-                        const target = UnwindInfo.parseRelocTarget(
-                            zld,
-                            object_id,
-                            rel,
-                            it.data[offset..],
-                            @intCast(i32, offset),
-                        );
+                        const target = Atom.parseRelocTarget(zld, .{
+                            .object_id = object_id,
+                            .rel = rel,
+                            .code = it.data[offset..],
+                            .base_offset = @intCast(i32, offset),
+                        });
                         break :blk target;
                     },
                     .x86_64 => {
@@ -825,13 +824,12 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
 
         // Find function symbol that this record describes
         const rel = relocs[rel_pos.start..][rel_pos.len - 1];
-        const target = UnwindInfo.parseRelocTarget(
-            zld,
-            object_id,
-            rel,
-            mem.asBytes(&record),
-            @intCast(i32, offset),
-        );
+        const target = Atom.parseRelocTarget(zld, .{
+            .object_id = object_id,
+            .rel = rel,
+            .code = mem.asBytes(&record),
+            .base_offset = @intCast(i32, offset),
+        });
         log.debug("unwind record {d} tracks {s}", .{ record_id, zld.getSymbolName(target) });
         if (target.getFile() != object_id) {
             self.unwind_relocs_lookup[record_id].dead = true;
src/link/MachO/thunks.zig
@@ -225,11 +225,20 @@ fn scanRelocs(
         break :blk @intCast(i32, source_sym.n_value - source_sect.addr);
     } else 0;
 
+    const code = Atom.getAtomCode(zld, atom_index);
     const relocs = Atom.getAtomRelocs(zld, atom_index);
+    const ctx = Atom.getRelocContext(zld, atom_index);
+
     for (relocs) |rel| {
         if (!relocNeedsThunk(rel)) continue;
 
-        const target = Atom.parseRelocTarget(zld, atom_index, rel);
+        const target = Atom.parseRelocTarget(zld, .{
+            .object_id = atom.getFile().?,
+            .rel = rel,
+            .code = code,
+            .base_offset = ctx.base_offset,
+            .base_addr = ctx.base_addr,
+        });
         if (isReachable(zld, atom_index, rel, base_offset, target, allocated)) continue;
 
         log.debug("{x}: source = {s}@{x}, target = {s}@{x} unreachable", .{
src/link/MachO/UnwindInfo.zig
@@ -218,13 +218,12 @@ pub fn scanRelocs(zld: *Zld) !void {
                     record_id,
                 )) |rel| {
                     // Personality function; add GOT pointer.
-                    const target = parseRelocTarget(
-                        zld,
-                        @intCast(u32, object_id),
-                        rel,
-                        mem.asBytes(&record),
-                        @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
-                    );
+                    const target = Atom.parseRelocTarget(zld, .{
+                        .object_id = @intCast(u32, object_id),
+                        .rel = rel,
+                        .code = mem.asBytes(&record),
+                        .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
+                    });
                     try Atom.addGotEntry(zld, target);
                 }
             }
@@ -266,13 +265,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
                         @intCast(u32, object_id),
                         record_id,
                     )) |rel| {
-                        const target = parseRelocTarget(
-                            zld,
-                            @intCast(u32, object_id),
-                            rel,
-                            mem.asBytes(&record),
-                            @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
-                        );
+                        const target = Atom.parseRelocTarget(zld, .{
+                            .object_id = @intCast(u32, object_id),
+                            .rel = rel,
+                            .code = mem.asBytes(&record),
+                            .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
+                        });
                         const personality_index = info.getPersonalityFunction(target) orelse inner: {
                             const personality_index = info.personalities_count;
                             info.personalities[personality_index] = target;
@@ -285,13 +283,12 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void {
                     }
 
                     if (getLsdaReloc(zld, @intCast(u32, object_id), record_id)) |rel| {
-                        const target = parseRelocTarget(
-                            zld,
-                            @intCast(u32, object_id),
-                            rel,
-                            mem.asBytes(&record),
-                            @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
-                        );
+                        const target = Atom.parseRelocTarget(zld, .{
+                            .object_id = @intCast(u32, object_id),
+                            .rel = rel,
+                            .code = mem.asBytes(&record),
+                            .base_offset = @intCast(i32, record_id * @sizeOf(macho.compact_unwind_entry)),
+                        });
                         record.lsda = @bitCast(u64, target);
                     }
                 }
@@ -668,41 +665,6 @@ pub fn write(info: *UnwindInfo, zld: *Zld) !void {
     try zld.file.pwriteAll(buffer.items, sect.offset);
 }
 
-pub fn parseRelocTarget(
-    zld: *Zld,
-    object_id: u32,
-    rel: macho.relocation_info,
-    code: []const u8,
-    base_offset: i32,
-) SymbolWithLoc {
-    const tracy = trace(@src());
-    defer tracy.end();
-
-    const object = &zld.objects.items[object_id];
-
-    const sym_index = if (rel.r_extern == 0) blk: {
-        const sect_id = @intCast(u8, rel.r_symbolnum - 1);
-        const rel_offset = @intCast(u32, rel.r_address - base_offset);
-        assert(rel.r_pcrel == 0 and rel.r_length == 3);
-        const address_in_section = mem.readIntLittle(u64, code[rel_offset..][0..8]);
-        const sym_index = object.getSymbolByAddress(address_in_section, sect_id);
-        break :blk sym_index;
-    } else object.reverse_symtab_lookup[rel.r_symbolnum];
-
-    const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };
-    const sym = zld.getSymbol(sym_loc);
-
-    if (sym.sect() and !sym.ext()) {
-        // Make sure we are not dealing with a local alias.
-        const atom_index = object.getAtomIndexForSymbol(sym_index) orelse
-            return sym_loc;
-        const atom = zld.getAtom(atom_index);
-        return atom.getSymbolWithLoc();
-    } else if (object.getGlobal(sym_index)) |global_index| {
-        return zld.globals.items[global_index];
-    } else return sym_loc;
-}
-
 fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info {
     const object = &zld.objects.items[object_id];
     assert(object.hasUnwindRecords());
src/link/MachO/zld.zig
@@ -1884,13 +1884,9 @@ pub const Zld = struct {
                 if (should_rebase) {
                     log.debug("  ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) });
 
-                    const object = self.objects.items[atom.getFile().?];
-                    const base_rel_offset: i32 = blk: {
-                        const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0;
-                        const source_sect = object.getSourceSection(source_sym.n_sect - 1);
-                        break :blk @intCast(i32, source_sym.n_value - source_sect.addr);
-                    };
+                    const code = Atom.getAtomCode(self, atom_index);
                     const relocs = Atom.getAtomRelocs(self, atom_index);
+                    const ctx = Atom.getRelocContext(self, atom_index);
 
                     for (relocs) |rel| {
                         switch (cpu_arch) {
@@ -1906,12 +1902,18 @@ pub const Zld = struct {
                             },
                             else => unreachable,
                         }
-                        const target = Atom.parseRelocTarget(self, atom_index, rel);
+                        const target = Atom.parseRelocTarget(self, .{
+                            .object_id = atom.getFile().?,
+                            .rel = rel,
+                            .code = code,
+                            .base_offset = ctx.base_offset,
+                            .base_addr = ctx.base_addr,
+                        });
                         const target_sym = self.getSymbol(target);
                         if (target_sym.undf()) continue;
 
                         const base_offset = @intCast(i32, sym.n_value - segment.vmaddr);
-                        const rel_offset = rel.r_address - base_rel_offset;
+                        const rel_offset = rel.r_address - ctx.base_offset;
                         const offset = @intCast(u64, base_offset + rel_offset);
                         log.debug("    | rebase at {x}", .{offset});
 
@@ -2021,13 +2023,9 @@ pub const Zld = struct {
                 };
 
                 if (should_bind) {
-                    const object = self.objects.items[atom.getFile().?];
-                    const base_rel_offset: i32 = blk: {
-                        const source_sym = object.getSourceSymbol(atom.sym_index) orelse break :blk 0;
-                        const source_sect = object.getSourceSection(source_sym.n_sect - 1);
-                        break :blk @intCast(i32, source_sym.n_value - source_sect.addr);
-                    };
+                    const code = Atom.getAtomCode(self, atom_index);
                     const relocs = Atom.getAtomRelocs(self, atom_index);
+                    const ctx = Atom.getRelocContext(self, atom_index);
 
                     for (relocs) |rel| {
                         switch (cpu_arch) {
@@ -2044,15 +2042,20 @@ pub const Zld = struct {
                             else => unreachable,
                         }
 
-                        const global = Atom.parseRelocTarget(self, atom_index, rel);
+                        const global = Atom.parseRelocTarget(self, .{
+                            .object_id = atom.getFile().?,
+                            .rel = rel,
+                            .code = code,
+                            .base_offset = ctx.base_offset,
+                            .base_addr = ctx.base_addr,
+                        });
                         const bind_sym_name = self.getSymbolName(global);
                         const bind_sym = self.getSymbol(global);
                         if (!bind_sym.undf()) continue;
 
                         const base_offset = sym.n_value - segment.vmaddr;
-                        const rel_offset = @intCast(u32, rel.r_address - base_rel_offset);
+                        const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset);
                         const offset = @intCast(u64, base_offset + rel_offset);
-                        const code = Atom.getAtomCode(self, atom_index);
                         const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]);
 
                         const dylib_ordinal = @divTrunc(@bitCast(i16, bind_sym.n_desc), macho.N_SYMBOL_RESOLVER);
src/link/MachO/ZldAtom.zig
@@ -15,6 +15,7 @@ const macho = std.macho;
 const math = std.math;
 const mem = std.mem;
 const meta = std.meta;
+const trace = @import("../../tracy.zig").trace;
 
 const Allocator = mem.Allocator;
 const Arch = std.Target.Cpu.Arch;
@@ -163,7 +164,7 @@ pub fn scanAtomRelocs(zld: *Zld, atom_index: AtomIndex, relocs: []align(1) const
 }
 
 const RelocContext = struct {
-    base_addr: u64 = 0,
+    base_addr: i64 = 0,
     base_offset: i32 = 0,
 };
 
@@ -175,7 +176,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext {
     if (object.getSourceSymbol(atom.sym_index)) |source_sym| {
         const source_sect = object.getSourceSection(source_sym.n_sect - 1);
         return .{
-            .base_addr = source_sect.addr,
+            .base_addr = @intCast(i64, source_sect.addr),
             .base_offset = @intCast(i32, source_sym.n_value - source_sect.addr),
         };
     }
@@ -183,55 +184,71 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext {
     const sect_id = @intCast(u8, atom.sym_index - nbase);
     const source_sect = object.getSourceSection(sect_id);
     return .{
-        .base_addr = source_sect.addr,
+        .base_addr = @intCast(i64, source_sect.addr),
         .base_offset = 0,
     };
 }
 
-pub fn parseRelocTarget(zld: *Zld, atom_index: AtomIndex, rel: macho.relocation_info) SymbolWithLoc {
-    const atom = zld.getAtom(atom_index);
-    const object = &zld.objects.items[atom.getFile().?];
+pub fn parseRelocTarget(zld: *Zld, ctx: struct {
+    object_id: u32,
+    rel: macho.relocation_info,
+    code: []const u8,
+    base_addr: i64 = 0,
+    base_offset: i32 = 0,
+}) SymbolWithLoc {
+    const tracy = trace(@src());
+    defer tracy.end();
+
+    const object = &zld.objects.items[ctx.object_id];
+    log.debug("parsing reloc target in object({d}) '{s}' ", .{ ctx.object_id, object.name });
 
-    const sym_index = if (rel.r_extern == 0) sym_index: {
-        const sect_id = @intCast(u8, rel.r_symbolnum - 1);
-        const ctx = getRelocContext(zld, atom_index);
-        const atom_code = getAtomCode(zld, atom_index);
-        const rel_offset = @intCast(u32, rel.r_address - ctx.base_offset);
+    const sym_index = if (ctx.rel.r_extern == 0) sym_index: {
+        const sect_id = @intCast(u8, ctx.rel.r_symbolnum - 1);
+        const rel_offset = @intCast(u32, ctx.rel.r_address - ctx.base_offset);
 
-        const address_in_section = if (rel.r_pcrel == 0) blk: {
-            break :blk if (rel.r_length == 3)
-                mem.readIntLittle(u64, atom_code[rel_offset..][0..8])
+        const address_in_section = if (ctx.rel.r_pcrel == 0) blk: {
+            break :blk if (ctx.rel.r_length == 3)
+                mem.readIntLittle(u64, ctx.code[rel_offset..][0..8])
             else
-                mem.readIntLittle(u32, atom_code[rel_offset..][0..4]);
+                mem.readIntLittle(u32, ctx.code[rel_offset..][0..4]);
         } else blk: {
-            const correction: u3 = switch (@intToEnum(macho.reloc_type_x86_64, rel.r_type)) {
+            assert(zld.options.target.cpu.arch == .x86_64);
+            const correction: u3 = switch (@intToEnum(macho.reloc_type_x86_64, ctx.rel.r_type)) {
                 .X86_64_RELOC_SIGNED => 0,
                 .X86_64_RELOC_SIGNED_1 => 1,
                 .X86_64_RELOC_SIGNED_2 => 2,
                 .X86_64_RELOC_SIGNED_4 => 4,
                 else => unreachable,
             };
-            const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]);
-            const target_address = @intCast(i64, ctx.base_addr) + rel.r_address + 4 + correction + addend;
+            const addend = mem.readIntLittle(i32, ctx.code[rel_offset..][0..4]);
+            const target_address = @intCast(i64, ctx.base_addr) + ctx.rel.r_address + 4 + correction + addend;
             break :blk @intCast(u64, target_address);
         };
 
         // Find containing atom
+        log.debug("  | locating symbol by address @{x} in section {d}", .{ address_in_section, sect_id });
         const sym_index = object.getSymbolByAddress(address_in_section, sect_id);
         break :sym_index sym_index;
-    } else object.reverse_symtab_lookup[rel.r_symbolnum];
+    } else object.reverse_symtab_lookup[ctx.rel.r_symbolnum];
 
-    const sym_loc = SymbolWithLoc{
-        .sym_index = sym_index,
-        .file = atom.file,
-    };
+    const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = ctx.object_id + 1 };
     const sym = zld.getSymbol(sym_loc);
-
-    if (sym.sect() and !sym.ext()) {
-        return sym_loc;
-    } else if (object.getGlobal(sym_index)) |global_index| {
-        return zld.globals.items[global_index];
-    } else return sym_loc;
+    const target = target: {
+        if (sym.sect() and !sym.ext()) {
+            // Make sure we are not dealing with a local alias.
+            const atom_index = object.getAtomIndexForSymbol(sym_index) orelse break :target sym_loc;
+            const atom = zld.getAtom(atom_index);
+            break :target atom.getSymbolWithLoc();
+        } else if (object.getGlobal(sym_index)) |global_index| {
+            break :target zld.globals.items[global_index];
+        } else break :target sym_loc;
+    };
+    log.debug("  | target %{d} ('{s}') in object({?d})", .{
+        target.sym_index,
+        zld.getSymbolName(target),
+        target.getFile(),
+    });
+    return target;
 }
 
 pub fn getRelocTargetAtomIndex(zld: *Zld, target: SymbolWithLoc, is_via_got: bool) ?AtomIndex {
@@ -499,13 +516,25 @@ fn resolveRelocsArm64(
                     atom.getFile(),
                 });
 
-                subtractor = parseRelocTarget(zld, atom_index, rel);
+                subtractor = parseRelocTarget(zld, .{
+                    .object_id = atom.getFile().?,
+                    .rel = rel,
+                    .code = atom_code,
+                    .base_addr = context.base_addr,
+                    .base_offset = context.base_offset,
+                });
                 continue;
             },
             else => {},
         }
 
-        const target = parseRelocTarget(zld, atom_index, rel);
+        const target = parseRelocTarget(zld, .{
+            .object_id = atom.getFile().?,
+            .rel = rel,
+            .code = atom_code,
+            .base_addr = context.base_addr,
+            .base_offset = context.base_offset,
+        });
         const rel_offset = @intCast(u32, rel.r_address - context.base_offset);
 
         log.debug("  RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{
@@ -781,13 +810,25 @@ fn resolveRelocsX86(
                     atom.getFile(),
                 });
 
-                subtractor = parseRelocTarget(zld, atom_index, rel);
+                subtractor = parseRelocTarget(zld, .{
+                    .object_id = atom.getFile().?,
+                    .rel = rel,
+                    .code = atom_code,
+                    .base_addr = context.base_addr,
+                    .base_offset = context.base_offset,
+                });
                 continue;
             },
             else => {},
         }
 
-        const target = parseRelocTarget(zld, atom_index, rel);
+        const target = parseRelocTarget(zld, .{
+            .object_id = atom.getFile().?,
+            .rel = rel,
+            .code = atom_code,
+            .base_addr = context.base_addr,
+            .base_offset = context.base_offset,
+        });
         const rel_offset = @intCast(u32, rel.r_address - context.base_offset);
 
         log.debug("  RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{