| ... | ... | @@ -152,7 +152,6 @@ globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 152 | 152 | |
| 153 | 153 | dyld_stub_binder_index: ?u32 = null, |
| 154 | 154 | dyld_private_atom_index: ?Atom.Index = null, |
| 155 | | stub_helper_preamble_atom_index: ?Atom.Index = null, |
| 156 | 155 | |
| 157 | 156 | strtab: StringTable(.strtab) = .{}, |
| 158 | 157 | |
| ... | ... | @@ -167,6 +166,7 @@ got_table_count_dirty: bool = false, |
| 167 | 166 | got_table_contents_dirty: bool = false, |
| 168 | 167 | stub_table_count_dirty: bool = false, |
| 169 | 168 | stub_table_contents_dirty: bool = false, |
| 169 | stub_helper_preamble_allocated: bool = false, |
| 170 | 170 | |
| 171 | 171 | /// A helper var to indicate if we are at the start of the incremental updates, or |
| 172 | 172 | /// 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 |
| 723 | 723 | return error.UndefinedSymbolReference; |
| 724 | 724 | } |
| 725 | 725 | |
| 726 | | try self.createDyldPrivateAtom(); |
| 727 | | try self.createStubHelperPreambleAtom(); |
| 728 | | |
| 729 | 726 | for (actions.items) |action| switch (action.kind) { |
| 730 | 727 | .none => {}, |
| 731 | 728 | .add_got => try self.addGotEntry(action.target), |
| 732 | 729 | .add_stub => try self.addStubEntry(action.target), |
| 733 | 730 | }; |
| 734 | 731 | |
| 732 | try self.createDyldPrivateAtom(); |
| 733 | try self.writeStubHelperPreamble(); |
| 734 | |
| 735 | 735 | try self.allocateSpecialSymbols(); |
| 736 | 736 | |
| 737 | 737 | for (self.relocs.keys()) |atom_index| { |
| ... | ... | @@ -1321,6 +1321,35 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void { |
| 1321 | 1321 | } |
| 1322 | 1322 | } |
| 1323 | 1323 | |
| 1324 | fn 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 | |
| 1324 | 1353 | fn writeStubTableEntry(self: *MachO, index: usize) !void { |
| 1325 | 1354 | const stubs_sect_id = self.stubs_section_index.?; |
| 1326 | 1355 | const stub_helper_sect_id = self.stub_helper_section_index.?; |
| ... | ... | @@ -1401,11 +1430,6 @@ fn writeStubTableEntry(self: *MachO, index: usize) !void { |
| 1401 | 1430 | } |
| 1402 | 1431 | } |
| 1403 | 1432 | |
| 1404 | | fn 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 | | |
| 1409 | 1433 | fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { |
| 1410 | 1434 | log.debug("marking relocs dirty by target: {}", .{target}); |
| 1411 | 1435 | // TODO: reverse-lookup might come in handy here |
| ... | ... | @@ -1492,131 +1516,8 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 1492 | 1516 | |
| 1493 | 1517 | sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64)); |
| 1494 | 1518 | log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value}); |
| 1495 | | try self.writePtrWidthAtom(atom_index); |
| 1496 | | } |
| 1497 | | |
| 1498 | | fn 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); |
| 1620 | 1521 | } |
| 1621 | 1522 | |
| 1622 | 1523 | fn createThreadLocalDescriptorAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index { |
| ... | ... | @@ -3415,7 +3316,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void |
| 3415 | 3316 | if (lazy_bind.size() == 0) return; |
| 3416 | 3317 | |
| 3417 | 3318 | 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); |
| 3419 | 3320 | |
| 3420 | 3321 | const header = self.sections.items(.header)[stub_helper_section_index]; |
| 3421 | 3322 | |