diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 4d19da1e97..3904192995 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -1533,7 +1533,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { } if (rel.target == .section) { const source_sect = object.sections.items[rel.target.section]; - args.source_sect_addr = source_sect.inner.addr; + args.source_source_sect_addr = sect.inner.addr; + args.source_target_sect_addr = source_sect.inner.addr; } rebases: { @@ -1588,7 +1589,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { else => |tt| { if (tt == .signed and rel.target == .section) { const source_sect = object.sections.items[rel.target.section]; - args.source_sect_addr = source_sect.inner.addr; + args.source_source_sect_addr = sect.inner.addr; + args.source_target_sect_addr = source_sect.inner.addr; } args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); }, diff --git a/src/link/MachO/reloc.zig b/src/link/MachO/reloc.zig index 1ce9fa2c2d..89b7aa4228 100644 --- a/src/link/MachO/reloc.zig +++ b/src/link/MachO/reloc.zig @@ -29,7 +29,8 @@ pub const Relocation = struct { source_addr: u64, target_addr: u64, subtractor: ?u64 = null, - source_sect_addr: ?u64 = null, + source_source_sect_addr: ?u64 = null, + source_target_sect_addr: ?u64 = null, }; pub fn resolve(base: *Relocation, args: ResolveArgs) !void { @@ -39,8 +40,10 @@ pub const Relocation = struct { log.debug(" | target address 0x{x}", .{args.target_addr}); if (args.subtractor) |sub| log.debug(" | subtractor address 0x{x}", .{sub}); - if (args.source_sect_addr) |addr| - log.debug(" | source section address 0x{x}", .{addr}); + if (args.source_source_sect_addr) |addr| + log.debug(" | source source section address 0x{x}", .{addr}); + if (args.source_target_sect_addr) |addr| + log.debug(" | source target section address 0x{x}", .{addr}); return switch (base.@"type") { .unsigned => @fieldParentPtr(Unsigned, "base", base).resolve(args), @@ -104,7 +107,7 @@ pub const Unsigned = struct { pub fn resolve(unsigned: Unsigned, args: Relocation.ResolveArgs) !void { const addend = if (unsigned.base.target == .section) - unsigned.addend - @intCast(i64, args.source_sect_addr.?) + unsigned.addend - @intCast(i64, args.source_target_sect_addr.?) else unsigned.addend; diff --git a/src/link/MachO/reloc/x86_64.zig b/src/link/MachO/reloc/x86_64.zig index 32f83924e8..a5e3ff2825 100644 --- a/src/link/MachO/reloc/x86_64.zig +++ b/src/link/MachO/reloc/x86_64.zig @@ -33,16 +33,19 @@ pub const Signed = struct { pub fn resolve(signed: Signed, args: Relocation.ResolveArgs) !void { const target_addr = target_addr: { if (signed.base.target == .section) { - const source_target = @intCast(i64, signed.base.offset) + signed.addend + 4 + signed.correction; - const source_disp = source_target - @intCast(i64, args.source_sect_addr.?); + const source_target = @intCast(i64, args.source_source_sect_addr.?) + @intCast(i64, signed.base.offset) + signed.addend + 4; + const source_disp = source_target - @intCast(i64, args.source_target_sect_addr.?); break :target_addr @intCast(i64, args.target_addr) + source_disp; } break :target_addr @intCast(i64, args.target_addr) + signed.addend; }; - const displacement = try math.cast(i32, target_addr - @intCast(i64, args.source_addr) - signed.correction - 4); + const displacement = try math.cast( + i32, + target_addr - @intCast(i64, args.source_addr) - signed.correction - 4, + ); - log.debug(" | calculated addend 0x{x}", .{signed.addend}); - log.debug(" | calculated correction 0x{x}", .{signed.correction}); + log.debug(" | addend 0x{x}", .{signed.addend}); + log.debug(" | correction 0x{x}", .{signed.correction}); log.debug(" | displacement 0x{x}", .{displacement}); mem.writeIntLittle(u32, signed.base.code[0..4], @bitCast(u32, displacement)); @@ -172,20 +175,14 @@ pub const Parser = struct { const offset = @intCast(u32, rel.r_address); const inst = parser.code[offset..][0..4]; - const addend = mem.readIntLittle(i32, inst); - - const correction: i4 = correction: { - if (is_extern) break :correction 0; - - const corr: i4 = switch (rel_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, - }; - break :correction corr; + const correction: i4 = switch (rel_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, inst) + correction; var signed = try parser.allocator.create(Signed); errdefer parser.allocator.destroy(signed);