From 7c1135555652311fcd069e15e99ecd37e21360be Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 25 Aug 2023 07:09:07 +0200 Subject: [PATCH] macho: collect rebase data by scanning atoms directly in objects --- src/link/MachO/zld.zig | 134 ++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 74 deletions(-) diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index 60bc1ec67f..862d89783d 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -1368,85 +1368,71 @@ pub const Zld = struct { } // Finally, unpack the rest. - const slice = self.sections.slice(); - for (slice.items(.header), 0..) |header, sect_id| { - switch (header.type()) { - macho.S_LITERAL_POINTERS, - macho.S_REGULAR, - macho.S_MOD_INIT_FUNC_POINTERS, - macho.S_MOD_TERM_FUNC_POINTERS, - => {}, - else => continue, - } - - const segment_index = slice.items(.segment_index)[sect_id]; - const segment = self.getSegment(@as(u8, @intCast(sect_id))); - if (segment.maxprot & macho.PROT.WRITE == 0) continue; - - log.debug("{s},{s}", .{ header.segName(), header.sectName() }); - - const cpu_arch = self.options.target.cpu.arch; - var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue; - - while (true) { + const cpu_arch = self.options.target.cpu.arch; + for (self.objects.items) |*object| { + for (object.atoms.items) |atom_index| { const atom = self.getAtom(atom_index); const sym = self.getSymbol(atom.getSymbolWithLoc()); + if (sym.n_desc == MachO.N_DEAD) continue; - const should_rebase = blk: { - if (atom_index == self.dyld_private_atom_index.?) break :blk false; - break :blk !sym.undf(); - }; - - if (should_rebase) { - log.debug(" ATOM({d}, %{d}, '{s}')", .{ - atom_index, - atom.sym_index, - self.getSymbolName(atom.getSymbolWithLoc()), - }); - - 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) { - .aarch64 => { - const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type)); - if (rel_type != .ARM64_RELOC_UNSIGNED) continue; - if (rel.r_length != 3) continue; - }, - .x86_64 => { - const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type)); - if (rel_type != .X86_64_RELOC_UNSIGNED) continue; - if (rel.r_length != 3) continue; - }, - else => unreachable, - } - 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 = @as(i32, @intCast(sym.n_value - segment.vmaddr)); - const rel_offset = rel.r_address - ctx.base_offset; - const offset = @as(u64, @intCast(base_offset + rel_offset)); - log.debug(" | rebase at {x}", .{offset}); - - try rebase.entries.append(self.gpa, .{ - .offset = offset, - .segment_id = segment_index, - }); - } + const sect_id = sym.n_sect - 1; + const section = self.sections.items(.header)[sect_id]; + const segment_id = self.sections.items(.segment_index)[sect_id]; + const segment = self.segments.items[segment_id]; + if (segment.maxprot & macho.PROT.WRITE == 0) continue; + switch (section.type()) { + macho.S_LITERAL_POINTERS, + macho.S_REGULAR, + macho.S_MOD_INIT_FUNC_POINTERS, + macho.S_MOD_TERM_FUNC_POINTERS, + => {}, + else => continue, } - if (atom.next_index) |next_index| { - atom_index = next_index; - } else break; + log.debug(" ATOM({d}, %{d}, '{s}')", .{ + atom_index, + atom.sym_index, + self.getSymbolName(atom.getSymbolWithLoc()), + }); + + 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) { + .aarch64 => { + const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type)); + if (rel_type != .ARM64_RELOC_UNSIGNED) continue; + if (rel.r_length != 3) continue; + }, + .x86_64 => { + const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type)); + if (rel_type != .X86_64_RELOC_UNSIGNED) continue; + if (rel.r_length != 3) continue; + }, + else => unreachable, + } + 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 = @as(i32, @intCast(sym.n_value - segment.vmaddr)); + const rel_offset = rel.r_address - ctx.base_offset; + const offset = @as(u64, @intCast(base_offset + rel_offset)); + log.debug(" | rebase at {x}", .{offset}); + + try rebase.entries.append(self.gpa, .{ + .offset = offset, + .segment_id = segment_id, + }); + } } }