authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-19 17:48:33+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-21 22:44:27+02:00
logcec475531022b0ed13e708f4991c197b2b838b2c
tree451cb132b6d4dc34e13b442a55633851d4108eff
parentfa40267b04e29fa8e36e73cb54eb68d58d26fa8d

macho: do not allocate atom for __stub_helper preamble


1 files changed, 36 insertions(+), 135 deletions(-)

src/link/MachO.zig+36-135
......@@ -152,7 +152,6 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{},
152152
153153dyld_stub_binder_index: ?u32 = null,
154154dyld_private_atom_index: ?Atom.Index = null,
155stub_helper_preamble_atom_index: ?Atom.Index = null,
156155
157156strtab: StringTable(.strtab) = .{},
158157
......@@ -167,6 +166,7 @@ got_table_count_dirty: bool = false,
167166got_table_contents_dirty: bool = false,
168167stub_table_count_dirty: bool = false,
169168stub_table_contents_dirty: bool = false,
169stub_helper_preamble_allocated: bool = false,
170170
171171/// A helper var to indicate if we are at the start of the incremental updates, or
172172/// already somewhere further along the update-and-run chain.
......@@ -723,15 +723,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
723723 return error.UndefinedSymbolReference;
724724 }
725725
726 try self.createDyldPrivateAtom();
727 try self.createStubHelperPreambleAtom();
728
729726 for (actions.items) |action| switch (action.kind) {
730727 .none => {},
731728 .add_got => try self.addGotEntry(action.target),
732729 .add_stub => try self.addStubEntry(action.target),
733730 };
734731
732 try self.createDyldPrivateAtom();
733 try self.writeStubHelperPreamble();
734
735735 try self.allocateSpecialSymbols();
736736
737737 for (self.relocs.keys()) |atom_index| {
......@@ -1321,6 +1321,35 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
13211321 }
13221322}
13231323
1324fn writeStubHelperPreamble(self: *MachO) !void {
1325 if (self.stub_helper_preamble_allocated) return;
1326
1327 const gpa = self.base.allocator;
1328 const cpu_arch = self.base.options.target.cpu.arch;
1329 const size = stubs.calcStubHelperPreambleSize(cpu_arch);
1330
1331 var buf = try std.ArrayList(u8).initCapacity(gpa, size);
1332 defer buf.deinit();
1333
1334 const dyld_private_addr = self.getAtom(self.dyld_private_atom_index.?).getSymbol(self).n_value;
1335 const dyld_stub_binder_got_addr = blk: {
1336 const index = self.got_table.lookup.get(self.getGlobalByIndex(self.dyld_stub_binder_index.?)).?;
1337 const header = self.sections.items(.header)[self.got_section_index.?];
1338 break :blk header.addr + @sizeOf(u64) * index;
1339 };
1340 const header = self.sections.items(.header)[self.stub_helper_section_index.?];
1341
1342 try stubs.writeStubHelperPreambleCode(.{
1343 .cpu_arch = cpu_arch,
1344 .source_addr = header.addr,
1345 .dyld_private_addr = dyld_private_addr,
1346 .dyld_stub_binder_got_addr = dyld_stub_binder_got_addr,
1347 }, buf.writer());
1348 try self.base.file.?.pwriteAll(buf.items, header.offset);
1349
1350 self.stub_helper_preamble_allocated = true;
1351}
1352
13241353fn writeStubTableEntry(self: *MachO, index: usize) !void {
13251354 const stubs_sect_id = self.stubs_section_index.?;
13261355 const stub_helper_sect_id = self.stub_helper_section_index.?;
......@@ -1401,11 +1430,6 @@ fn writeStubTableEntry(self: *MachO, index: usize) !void {
14011430 }
14021431}
14031432
1404fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void {
1405 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);
1406 try self.writeAtom(atom_index, &buffer);
1407}
1408
14091433fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
14101434 log.debug("marking relocs dirty by target: {}", .{target});
14111435 // TODO: reverse-lookup might come in handy here
......@@ -1492,131 +1516,8 @@ fn createDyldPrivateAtom(self: *MachO) !void {
14921516
14931517 sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64));
14941518 log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value});
1495 try self.writePtrWidthAtom(atom_index);
1496}
1497
1498fn createStubHelperPreambleAtom(self: *MachO) !void {
1499 if (self.stub_helper_preamble_atom_index != null) return;
1500
1501 const gpa = self.base.allocator;
1502 const arch = self.base.options.target.cpu.arch;
1503 const size: u5 = switch (arch) {
1504 .x86_64 => 15,
1505 .aarch64 => 6 * @sizeOf(u32),
1506 else => unreachable,
1507 };
1508 const atom_index = try self.createAtom();
1509 const atom = self.getAtomPtr(atom_index);
1510 atom.size = size;
1511
1512 const required_alignment: u32 = switch (arch) {
1513 .x86_64 => 1,
1514 .aarch64 => @alignOf(u32),
1515 else => unreachable,
1516 };
1517
1518 const sym = atom.getSymbolPtr(self);
1519 sym.n_type = macho.N_SECT;
1520 sym.n_sect = self.stub_helper_section_index.? + 1;
1521
1522 const dyld_private = self.getAtom(self.dyld_private_atom_index.?).getSymbolWithLoc();
1523 const dyld_stub_binder = self.globals.items[self.dyld_stub_binder_index.?];
1524
1525 const code = try gpa.alloc(u8, size);
1526 defer gpa.free(code);
1527 mem.set(u8, code, 0);
1528
1529 switch (arch) {
1530 .x86_64 => {
1531 // lea %r11, [rip + disp]
1532 code[0] = 0x4c;
1533 code[1] = 0x8d;
1534 code[2] = 0x1d;
1535 // push %r11
1536 code[7] = 0x41;
1537 code[8] = 0x53;
1538 // jmp [rip + disp]
1539 code[9] = 0xff;
1540 code[10] = 0x25;
1541
1542 try Atom.addRelocations(self, atom_index, &[_]Relocation{ .{
1543 .type = .signed,
1544 .target = dyld_private,
1545 .offset = 3,
1546 .addend = 0,
1547 .pcrel = true,
1548 .length = 2,
1549 }, .{
1550 .type = .got,
1551 .target = dyld_stub_binder,
1552 .offset = 11,
1553 .addend = 0,
1554 .pcrel = true,
1555 .length = 2,
1556 } });
1557 },
1558
1559 .aarch64 => {
1560 // adrp x17, 0
1561 mem.writeIntLittle(u32, code[0..][0..4], aarch64.Instruction.adrp(.x17, 0).toU32());
1562 // add x17, x17, 0
1563 mem.writeIntLittle(u32, code[4..][0..4], aarch64.Instruction.add(.x17, .x17, 0, false).toU32());
1564 // stp x16, x17, [sp, #-16]!
1565 mem.writeIntLittle(u32, code[8..][0..4], aarch64.Instruction.stp(
1566 .x16,
1567 .x17,
1568 aarch64.Register.sp,
1569 aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
1570 ).toU32());
1571 // adrp x16, 0
1572 mem.writeIntLittle(u32, code[12..][0..4], aarch64.Instruction.adrp(.x16, 0).toU32());
1573 // ldr x16, [x16, 0]
1574 mem.writeIntLittle(u32, code[16..][0..4], aarch64.Instruction.ldr(
1575 .x16,
1576 .x16,
1577 aarch64.Instruction.LoadStoreOffset.imm(0),
1578 ).toU32());
1579 // br x16
1580 mem.writeIntLittle(u32, code[20..][0..4], aarch64.Instruction.br(.x16).toU32());
1581
1582 try Atom.addRelocations(self, atom_index, &[_]Relocation{ .{
1583 .type = .page,
1584 .target = dyld_private,
1585 .offset = 0,
1586 .addend = 0,
1587 .pcrel = true,
1588 .length = 2,
1589 }, .{
1590 .type = .pageoff,
1591 .target = dyld_private,
1592 .offset = 4,
1593 .addend = 0,
1594 .pcrel = false,
1595 .length = 2,
1596 }, .{
1597 .type = .got_page,
1598 .target = dyld_stub_binder,
1599 .offset = 12,
1600 .addend = 0,
1601 .pcrel = true,
1602 .length = 2,
1603 }, .{
1604 .type = .got_pageoff,
1605 .target = dyld_stub_binder,
1606 .offset = 16,
1607 .addend = 0,
1608 .pcrel = false,
1609 .length = 2,
1610 } });
1611 },
1612
1613 else => unreachable,
1614 }
1615 self.stub_helper_preamble_atom_index = atom_index;
1616
1617 sym.n_value = try self.allocateAtom(atom_index, size, required_alignment);
1618 log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value});
1619 try self.writeAtom(atom_index, code);
1519 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);
1520 try self.writeAtom(atom_index, &buffer);
16201521}
16211522
16221523fn createThreadLocalDescriptorAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index {
......@@ -3415,7 +3316,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
34153316 if (lazy_bind.size() == 0) return;
34163317
34173318 const stub_helper_section_index = self.stub_helper_section_index.?;
3418 assert(self.stub_helper_preamble_atom_index != null);
3319 assert(self.stub_helper_preamble_allocated);
34193320
34203321 const header = self.sections.items(.header)[stub_helper_section_index];
34213322