authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-25 07:22:27+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
loge9ad9e04c988cbc5881fe75855bf4cfed16cb716
tree0267cecbc821bfc035515d18e2af0ff3d1251d3b
parent7c1135555652311fcd069e15e99ecd37e21360be

macho: collect bind data by scanning atoms directly in objects


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

src/link/MachO/zld.zig+70-79
......@@ -1456,94 +1456,85 @@ pub const Zld = struct {
14561456 }
14571457
14581458 // Finally, unpack the rest.
1459 const slice = self.sections.slice();
1460 for (slice.items(.header), 0..) |header, sect_id| {
1461 switch (header.type()) {
1462 macho.S_LITERAL_POINTERS,
1463 macho.S_REGULAR,
1464 macho.S_MOD_INIT_FUNC_POINTERS,
1465 macho.S_MOD_TERM_FUNC_POINTERS,
1466 => {},
1467 else => continue,
1468 }
1469
1470 const segment_index = slice.items(.segment_index)[sect_id];
1471 const segment = self.getSegment(@as(u8, @intCast(sect_id)));
1472 if (segment.maxprot & macho.PROT.WRITE == 0) continue;
1459 const cpu_arch = self.options.target.cpu.arch;
1460 for (self.objects.items) |*object| {
1461 for (object.atoms.items) |atom_index| {
1462 const atom = self.getAtom(atom_index);
1463 const sym = self.getSymbol(atom.getSymbolWithLoc());
1464 if (sym.n_desc == MachO.N_DEAD) continue;
14731465
1474 const cpu_arch = self.options.target.cpu.arch;
1475 var atom_index = slice.items(.first_atom_index)[sect_id] orelse continue;
1466 const sect_id = sym.n_sect - 1;
1467 const section = self.sections.items(.header)[sect_id];
1468 const segment_id = self.sections.items(.segment_index)[sect_id];
1469 const segment = self.segments.items[segment_id];
1470 if (segment.maxprot & macho.PROT.WRITE == 0) continue;
1471 switch (section.type()) {
1472 macho.S_LITERAL_POINTERS,
1473 macho.S_REGULAR,
1474 macho.S_MOD_INIT_FUNC_POINTERS,
1475 macho.S_MOD_TERM_FUNC_POINTERS,
1476 => {},
1477 else => continue,
1478 }
14761479
1477 log.debug("{s},{s}", .{ header.segName(), header.sectName() });
1480 log.debug(" ATOM({d}, %{d}, '{s}')", .{
1481 atom_index,
1482 atom.sym_index,
1483 self.getSymbolName(atom.getSymbolWithLoc()),
1484 });
14781485
1479 while (true) {
1480 const atom = self.getAtom(atom_index);
1481 const sym = self.getSymbol(atom.getSymbolWithLoc());
1486 const code = Atom.getAtomCode(self, atom_index);
1487 const relocs = Atom.getAtomRelocs(self, atom_index);
1488 const ctx = Atom.getRelocContext(self, atom_index);
14821489
1483 log.debug(" ATOM({d}, %{d}, '{s}')", .{ atom_index, atom.sym_index, self.getSymbolName(atom.getSymbolWithLoc()) });
1490 for (relocs) |rel| {
1491 switch (cpu_arch) {
1492 .aarch64 => {
1493 const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type));
1494 if (rel_type != .ARM64_RELOC_UNSIGNED) continue;
1495 if (rel.r_length != 3) continue;
1496 },
1497 .x86_64 => {
1498 const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type));
1499 if (rel_type != .X86_64_RELOC_UNSIGNED) continue;
1500 if (rel.r_length != 3) continue;
1501 },
1502 else => unreachable,
1503 }
14841504
1485 const should_bind = blk: {
1486 if (atom_index == self.dyld_private_atom_index.?) break :blk false;
1487 break :blk true;
1488 };
1505 const global = Atom.parseRelocTarget(self, .{
1506 .object_id = atom.getFile().?,
1507 .rel = rel,
1508 .code = code,
1509 .base_offset = ctx.base_offset,
1510 .base_addr = ctx.base_addr,
1511 });
1512 const bind_sym_name = self.getSymbolName(global);
1513 const bind_sym = self.getSymbol(global);
1514 if (!bind_sym.undf()) continue;
14891515
1490 if (should_bind) {
1491 const code = Atom.getAtomCode(self, atom_index);
1492 const relocs = Atom.getAtomRelocs(self, atom_index);
1493 const ctx = Atom.getRelocContext(self, atom_index);
1494
1495 for (relocs) |rel| {
1496 switch (cpu_arch) {
1497 .aarch64 => {
1498 const rel_type = @as(macho.reloc_type_arm64, @enumFromInt(rel.r_type));
1499 if (rel_type != .ARM64_RELOC_UNSIGNED) continue;
1500 if (rel.r_length != 3) continue;
1501 },
1502 .x86_64 => {
1503 const rel_type = @as(macho.reloc_type_x86_64, @enumFromInt(rel.r_type));
1504 if (rel_type != .X86_64_RELOC_UNSIGNED) continue;
1505 if (rel.r_length != 3) continue;
1506 },
1507 else => unreachable,
1508 }
1516 const base_offset = sym.n_value - segment.vmaddr;
1517 const rel_offset = @as(u32, @intCast(rel.r_address - ctx.base_offset));
1518 const offset = @as(u64, @intCast(base_offset + rel_offset));
1519 const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]);
15091520
1510 const global = Atom.parseRelocTarget(self, .{
1511 .object_id = atom.getFile().?,
1512 .rel = rel,
1513 .code = code,
1514 .base_offset = ctx.base_offset,
1515 .base_addr = ctx.base_addr,
1516 });
1517 const bind_sym_name = self.getSymbolName(global);
1518 const bind_sym = self.getSymbol(global);
1519 if (!bind_sym.undf()) continue;
1520
1521 const base_offset = sym.n_value - segment.vmaddr;
1522 const rel_offset = @as(u32, @intCast(rel.r_address - ctx.base_offset));
1523 const offset = @as(u64, @intCast(base_offset + rel_offset));
1524 const addend = mem.readIntLittle(i64, code[rel_offset..][0..8]);
1525
1526 const dylib_ordinal = @divTrunc(@as(i16, @bitCast(bind_sym.n_desc)), macho.N_SYMBOL_RESOLVER);
1527 log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{
1528 base_offset,
1529 bind_sym_name,
1530 dylib_ordinal,
1531 });
1532 log.debug(" | with addend {x}", .{addend});
1533 if (bind_sym.weakRef()) {
1534 log.debug(" | marking as weak ref ", .{});
1535 }
1536 try bind.entries.append(self.gpa, .{
1537 .target = global,
1538 .offset = offset,
1539 .segment_id = segment_index,
1540 .addend = addend,
1541 });
1521 const dylib_ordinal = @divTrunc(@as(i16, @bitCast(bind_sym.n_desc)), macho.N_SYMBOL_RESOLVER);
1522 log.debug(" | bind at {x}, import('{s}') in dylib({d})", .{
1523 base_offset,
1524 bind_sym_name,
1525 dylib_ordinal,
1526 });
1527 log.debug(" | with addend {x}", .{addend});
1528 if (bind_sym.weakRef()) {
1529 log.debug(" | marking as weak ref ", .{});
15421530 }
1531 try bind.entries.append(self.gpa, .{
1532 .target = global,
1533 .offset = offset,
1534 .segment_id = segment_id,
1535 .addend = addend,
1536 });
15431537 }
1544 if (atom.next_index) |next_index| {
1545 atom_index = next_index;
1546 } else break;
15471538 }
15481539 }
15491540