diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-07-04 20:40:10 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-07-22 16:58:20 +0200 |
| commit | 03feea0fb200f273dd74bf778997e6a6bead86cc (patch) | |
| tree | c439ed641e01ec4d860abb181ee585a2a287494c /src/link/MachO/Atom.zig | |
| parent | d042b88c112aa919386bc76294225d4f7bd9a7b3 (diff) | |
| download | zig-03feea0fb200f273dd74bf778997e6a6bead86cc.tar.gz zig-03feea0fb200f273dd74bf778997e6a6bead86cc.zip | |
macho: split section into subsections if requested and/or possible
Diffstat (limited to 'src/link/MachO/Atom.zig')
| -rw-r--r-- | src/link/MachO/Atom.zig | 64 |
1 files changed, 61 insertions, 3 deletions
diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index d7c595dbba..e6adb0cc1c 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -236,6 +236,7 @@ pub fn freeListEligible(self: Atom, macho_file: MachO) bool { const RelocContext = struct { base_addr: u64 = 0, + base_offset: i32 = 0, allocator: Allocator, object: *Object, macho_file: *MachO, @@ -366,7 +367,7 @@ pub fn parseRelocs(self: *Atom, relocs: []const macho.relocation_info, context: ) orelse unreachable; break :target Relocation.Target{ .global = n_strx }; }; - const offset = @intCast(u32, rel.r_address); + const offset = @intCast(u32, rel.r_address - context.base_offset); switch (arch) { .aarch64 => { @@ -487,7 +488,7 @@ fn addPtrBindingOrRebase( .global => |n_strx| { try self.bindings.append(context.allocator, .{ .n_strx = n_strx, - .offset = @intCast(u32, rel.r_address), + .offset = @intCast(u32, rel.r_address - context.base_offset), }); }, .local => { @@ -529,7 +530,10 @@ fn addPtrBindingOrRebase( }; if (should_rebase) { - try self.rebases.append(context.allocator, @intCast(u32, rel.r_address)); + try self.rebases.append( + context.allocator, + @intCast(u32, rel.r_address - context.base_offset), + ); } }, } @@ -650,6 +654,60 @@ fn addStub(target: Relocation.Target, context: RelocContext) !void { context.macho_file.stubs.items[stub_index] = atom; } +pub fn getTargetAtom(rel: Relocation, macho_file: *MachO) !?*Atom { + const is_via_got = got: { + switch (macho_file.base.options.target.cpu.arch) { + .aarch64 => break :got switch (@intToEnum(macho.reloc_type_arm64, rel.@"type")) { + .ARM64_RELOC_GOT_LOAD_PAGE21, + .ARM64_RELOC_GOT_LOAD_PAGEOFF12, + .ARM64_RELOC_POINTER_TO_GOT, + => true, + else => false, + }, + .x86_64 => break :got switch (@intToEnum(macho.reloc_type_x86_64, rel.@"type")) { + .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => true, + else => false, + }, + else => unreachable, + } + }; + + if (is_via_got) { + const got_index = macho_file.got_entries_table.get(rel.target) orelse { + log.err("expected GOT entry for symbol", .{}); + switch (rel.target) { + .local => |sym_index| log.err(" local @{d}", .{sym_index}), + .global => |n_strx| log.err(" global @'{s}'", .{macho_file.getString(n_strx)}), + } + log.err(" this is an internal linker error", .{}); + return error.FailedToResolveRelocationTarget; + }; + return macho_file.got_entries.items[got_index].atom; + } + + switch (rel.target) { + .local => |sym_index| { + return macho_file.atom_by_index_table.get(sym_index); + }, + .global => |n_strx| { + const resolv = macho_file.symbol_resolver.get(n_strx).?; + switch (resolv.where) { + .global => return macho_file.atom_by_index_table.get(resolv.local_sym_index), + .undef => { + if (macho_file.stubs_table.get(n_strx)) |stub_index| { + return macho_file.stubs.items[stub_index]; + } else { + if (macho_file.tlv_ptr_entries_table.get(rel.target)) |tlv_ptr_index| { + return macho_file.tlv_ptr_entries.items[tlv_ptr_index].atom; + } + return null; + } + }, + } + }, + } +} + pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); |
