diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-04-22 13:39:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-22 13:39:07 +0200 |
| commit | c4a63389e4eefb78c1ee2028047447094bb864dc (patch) | |
| tree | 95edea0e36efa81c2a6ea8d0574feeb5ba90f25e /src/link/MachO/Relocation.zig | |
| parent | 68e4a5784791f733774e161b72a283b69a75b0de (diff) | |
| parent | 14dfbbc21365131c7ac85f08f543058f43fca0c2 (diff) | |
| download | zig-c4a63389e4eefb78c1ee2028047447094bb864dc.tar.gz zig-c4a63389e4eefb78c1ee2028047447094bb864dc.zip | |
Merge pull request #15371 from ziglang/better-elf
link: make GOT (and other synthetic sections) handling common across linkers
Diffstat (limited to 'src/link/MachO/Relocation.zig')
| -rw-r--r-- | src/link/MachO/Relocation.zig | 88 |
1 files changed, 66 insertions, 22 deletions
diff --git a/src/link/MachO/Relocation.zig b/src/link/MachO/Relocation.zig index 81340b1120..e511901009 100644 --- a/src/link/MachO/Relocation.zig +++ b/src/link/MachO/Relocation.zig @@ -15,7 +15,7 @@ pub const Type = enum { got, /// RIP-relative displacement signed, - /// RIP-relative displacement to GOT pointer to TLV thunk + /// RIP-relative displacement to a TLV thunk tlv, // aarch64 @@ -39,25 +39,35 @@ pub const Type = enum { /// Returns true if and only if the reloc is dirty AND the target address is available. pub fn isResolvable(self: Relocation, macho_file: *MachO) bool { - _ = self.getTargetAtomIndex(macho_file) orelse return false; + const addr = self.getTargetBaseAddress(macho_file) orelse return false; + if (addr == 0) return false; return self.dirty; } -pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index { - return switch (self.type) { - .got, .got_page, .got_pageoff => macho_file.got_table.getAtomIndex(macho_file, self.target), +pub fn getTargetBaseAddress(self: Relocation, macho_file: *MachO) ?u64 { + switch (self.type) { + .got, .got_page, .got_pageoff => { + const got_index = macho_file.got_table.lookup.get(self.target) orelse return null; + const header = macho_file.sections.items(.header)[macho_file.got_section_index.?]; + return header.addr + got_index * @sizeOf(u64); + }, .tlv => { - const thunk_atom_index = macho_file.tlv_table.getAtomIndex(macho_file, self.target) orelse - return null; - const thunk_atom = macho_file.getAtom(thunk_atom_index); - return macho_file.got_table.getAtomIndex(macho_file, thunk_atom.getSymbolWithLoc()); + const atom_index = macho_file.tlv_table.get(self.target) orelse return null; + const atom = macho_file.getAtom(atom_index); + return atom.getSymbol(macho_file).n_value; }, - .branch => if (macho_file.stubs_table.getAtomIndex(macho_file, self.target)) |index| - index - else - macho_file.getAtomIndexForSymbol(self.target), - else => macho_file.getAtomIndexForSymbol(self.target), - }; + .branch => { + if (macho_file.stub_table.lookup.get(self.target)) |index| { + const header = macho_file.sections.items(.header)[macho_file.stubs_section_index.?]; + return header.addr + + index * @import("stubs.zig").calcStubEntrySize(macho_file.base.options.target.cpu.arch); + } + const atom_index = macho_file.getAtomIndexForSymbol(self.target) orelse return null; + const atom = macho_file.getAtom(atom_index); + return atom.getSymbol(macho_file).n_value; + }, + else => return macho_file.getSymbol(self.target).n_value, + } } pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, code: []u8) void { @@ -66,17 +76,14 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod const source_sym = atom.getSymbol(macho_file); const source_addr = source_sym.n_value + self.offset; - const target_atom_index = self.getTargetAtomIndex(macho_file).?; // Oops, you didn't check if the relocation can be resolved with isResolvable(). - const target_atom = macho_file.getAtom(target_atom_index); - + const target_base_addr = self.getTargetBaseAddress(macho_file).?; // Oops, you didn't check if the relocation can be resolved with isResolvable(). const target_addr: i64 = switch (self.type) { .tlv_initializer => blk: { assert(self.addend == 0); // Addend here makes no sense. const header = macho_file.sections.items(.header)[macho_file.thread_data_section_index.?]; - const target_sym = target_atom.getSymbol(macho_file); - break :blk @intCast(i64, target_sym.n_value - header.addr); + break :blk @intCast(i64, target_base_addr - header.addr); }, - else => @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend, + else => @intCast(i64, target_base_addr) + self.addend, }; log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{ @@ -189,11 +196,48 @@ fn resolveX8664(self: Relocation, source_addr: u64, target_addr: i64, code: []u8 } } -inline fn isArithmeticOp(inst: *const [4]u8) bool { +pub inline fn isArithmeticOp(inst: *const [4]u8) bool { const group_decode = @truncate(u5, inst[3]); return ((group_decode >> 2) == 4); } +pub fn calcPcRelativeDisplacementX86(source_addr: u64, target_addr: u64, correction: u3) error{Overflow}!i32 { + const disp = @intCast(i64, target_addr) - @intCast(i64, source_addr + 4 + correction); + return math.cast(i32, disp) orelse error.Overflow; +} + +pub fn calcPcRelativeDisplacementArm64(source_addr: u64, target_addr: u64) error{Overflow}!i28 { + const disp = @intCast(i64, target_addr) - @intCast(i64, source_addr); + return math.cast(i28, disp) orelse error.Overflow; +} + +pub fn calcNumberOfPages(source_addr: u64, target_addr: u64) i21 { + const source_page = @intCast(i32, source_addr >> 12); + const target_page = @intCast(i32, target_addr >> 12); + const pages = @intCast(i21, target_page - source_page); + return pages; +} + +pub const PageOffsetInstKind = enum { + arithmetic, + load_store_8, + load_store_16, + load_store_32, + load_store_64, + load_store_128, +}; + +pub fn calcPageOffset(target_addr: u64, kind: PageOffsetInstKind) !u12 { + const narrowed = @truncate(u12, target_addr); + return switch (kind) { + .arithmetic, .load_store_8 => narrowed, + .load_store_16 => try math.divExact(u12, narrowed, 2), + .load_store_32 => try math.divExact(u12, narrowed, 4), + .load_store_64 => try math.divExact(u12, narrowed, 8), + .load_store_128 => try math.divExact(u12, narrowed, 16), + }; +} + const Relocation = @This(); const std = @import("std"); |
