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