authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-25 07:09:07+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log7c1135555652311fcd069e15e99ecd37e21360be
treeaec14057058f3871b5f08763633eab5b8ba087a4
parentbf5c35145da5cdaa9290d000728c0b8f307d89df

macho: collect rebase data by scanning atoms directly in objects


1 files changed, 56 insertions(+), 70 deletions(-)

src/link/MachO/zld.zig+56-70
...@@ -1368,85 +1368,71 @@ pub const Zld = struct {...@@ -1368,85 +1368,71 @@ pub const Zld = struct {
1368 }1368 }
13691369
1370 // Finally, unpack the rest.1370 // Finally, unpack the rest.
1371 const slice = self.sections.slice();1371 const cpu_arch = self.options.target.cpu.arch;
1372 for (slice.items(.header), 0..) |header, sect_id| {1372 for (self.objects.items) |*object| {
1373 switch (header.type()) {1373 for (object.atoms.items) |atom_index| {
1374 macho.S_LITERAL_POINTERS,
1375 macho.S_REGULAR,
1376 macho.S_MOD_INIT_FUNC_POINTERS,
1377 macho.S_MOD_TERM_FUNC_POINTERS,
1378 => {},
1379 else => continue,
1380 }
1381
1382 const segment_index = slice.items(.segment_index)[sect_id];
1383 const segment = self.getSegment(@as(u8, @intCast(sect_id)));
1384 if (segment.maxprot & macho.PROT.WRITE == 0) continue;
1385
1386 log.debug("{s},{s}", .{ header.segName(), header.sectName() });
1387
1388 const cpu_arch = self.options.target.cpu.arch;
1389 var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue;
1390
1391 while (true) {
1392 const atom = self.getAtom(atom_index);1374 const atom = self.getAtom(atom_index);
1393 const sym = self.getSymbol(atom.getSymbolWithLoc());1375 const sym = self.getSymbol(atom.getSymbolWithLoc());
1376 if (sym.n_desc == MachO.N_DEAD) continue;
13941377
1395 const should_rebase = blk: {1378 const sect_id = sym.n_sect - 1;
1396 if (atom_index == self.dyld_private_atom_index.?) break :blk false;1379 const section = self.sections.items(.header)[sect_id];
1397 break :blk !sym.undf();1380 const segment_id = self.sections.items(.segment_index)[sect_id];
1398 };1381 const segment = self.segments.items[segment_id];
1382 if (segment.maxprot & macho.PROT.WRITE == 0) continue;
1383 switch (section.type()) {
1384 macho.S_LITERAL_POINTERS,
1385 macho.S_REGULAR,
1386 macho.S_MOD_INIT_FUNC_POINTERS,
1387 macho.S_MOD_TERM_FUNC_POINTERS,
1388 => {},
1389 else => continue,
1390 }
13991391
1400 if (should_rebase) {1392 log.debug(" ATOM({d}, %{d}, '{s}')", .{
1401 log.debug(" ATOM({d}, %{d}, '{s}')", .{1393 atom_index,
1402 atom_index,1394 atom.sym_index,
1403 atom.sym_index,1395 self.getSymbolName(atom.getSymbolWithLoc()),
1404 self.getSymbolName(atom.getSymbolWithLoc()),1396 });
1405 });
14061397
1407 const code = Atom.getAtomCode(self, atom_index);1398 const code = Atom.getAtomCode(self, atom_index);
1408 const relocs = Atom.getAtomRelocs(self, atom_index);1399 const relocs = Atom.getAtomRelocs(self, atom_index);
1409 const ctx = Atom.getRelocContext(self, atom_index);1400 const ctx = Atom.getRelocContext(self, atom_index);
14101401
1411 for (relocs) |rel| {1402 for (relocs) |rel| {
1412 switch (cpu_arch) {1403 switch (cpu_arch) {
1413 .aarch64 => {1404 .aarch64 => {
1414 const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type));1405 const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type));
1415 if (rel_type != .ARM64_RELOC_UNSIGNED) continue;1406 if (rel_type != .ARM64_RELOC_UNSIGNED) continue;
1416 if (rel.r_length != 3) continue;1407 if (rel.r_length != 3) continue;
1417 },1408 },
1418 .x86_64 => {1409 .x86_64 => {
1419 const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type));1410 const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type));
1420 if (rel_type != .X86_64_RELOC_UNSIGNED) continue;1411 if (rel_type != .X86_64_RELOC_UNSIGNED) continue;
1421 if (rel.r_length != 3) continue;1412 if (rel.r_length != 3) continue;
1422 },1413 },
1423 else => unreachable,1414 else => unreachable,
1424 }1415 }
1425 const target = Atom.parseRelocTarget(self, .{1416 const target = Atom.parseRelocTarget(self, .{
1426 .object_id = atom.getFile().?,1417 .object_id = atom.getFile().?,
1427 .rel = rel,1418 .rel = rel,
1428 .code = code,1419 .code = code,
1429 .base_offset = ctx.base_offset,1420 .base_offset = ctx.base_offset,
1430 .base_addr = ctx.base_addr,1421 .base_addr = ctx.base_addr,
1431 });1422 });
1432 const target_sym = self.getSymbol(target);1423 const target_sym = self.getSymbol(target);
1433 if (target_sym.undf()) continue;1424 if (target_sym.undf()) continue;
14341425
1435 const base_offset = @as(i32, @intCast(sym.n_value - segment.vmaddr));1426 const base_offset = @as(i32, @intCast(sym.n_value - segment.vmaddr));
1436 const rel_offset = rel.r_address - ctx.base_offset;1427 const rel_offset = rel.r_address - ctx.base_offset;
1437 const offset = @as(u64, @intCast(base_offset + rel_offset));1428 const offset = @as(u64, @intCast(base_offset + rel_offset));
1438 log.debug(" | rebase at {x}", .{offset});1429 log.debug(" | rebase at {x}", .{offset});
14391430
1440 try rebase.entries.append(self.gpa, .{1431 try rebase.entries.append(self.gpa, .{
1441 .offset = offset,1432 .offset = offset,
1442 .segment_id = segment_index,1433 .segment_id = segment_id,
1443 });1434 });
1444 }
1445 }1435 }
1446
1447 if (atom.next_index) |next_index| {
1448 atom_index = next_index;
1449 } else break;
1450 }1436 }
1451 }1437 }
14521438