| ... | ... | @@ -89,6 +89,16 @@ code_signature_cmd_index: ?u16 = null, |
| 89 | 89 | text_section_index: ?u16 = null, |
| 90 | 90 | /// Index into __TEXT,__ziggot section. |
| 91 | 91 | got_section_index: ?u16 = null, |
| 92 | /// Index into __TEXT,__stubs section. |
| 93 | stubs_section_index: ?u16 = null, |
| 94 | /// Index into __TEXT,__stub_helper section. |
| 95 | stub_helper_section_index: ?u16 = null, |
| 96 | /// Index into __DATA_CONST,__got section. |
| 97 | data_got_section_index: ?u16 = null, |
| 98 | /// Index into __DATA,__la_symbol_ptr section. |
| 99 | la_symbol_ptr_section_index: ?u16 = null, |
| 100 | /// Index into __DATA,__data section. |
| 101 | data_section_index: ?u16 = null, |
| 92 | 102 | /// The absolute address of the entry point. |
| 93 | 103 | entry_addr: ?u64 = null, |
| 94 | 104 | |
| ... | ... | @@ -1437,7 +1447,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1437 | 1447 | |
| 1438 | 1448 | const program_code_size_hint = self.base.options.program_code_size_hint; |
| 1439 | 1449 | const offset_table_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1440 | | const ideal_size = self.header_pad + program_code_size_hint + offset_table_size_hint; |
| 1450 | const ideal_size = self.header_pad + program_code_size_hint + 3 * offset_table_size_hint; |
| 1441 | 1451 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| 1442 | 1452 | |
| 1443 | 1453 | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| ... | ... | @@ -1494,9 +1504,13 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1494 | 1504 | } |
| 1495 | 1505 | if (self.got_section_index == null) { |
| 1496 | 1506 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1497 | | const text_section = &text_segment.sections.items[self.text_section_index.?]; |
| 1498 | 1507 | self.got_section_index = @intCast(u16, text_segment.sections.items.len); |
| 1499 | 1508 | |
| 1509 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 1510 | .x86_64 => 0, |
| 1511 | .aarch64 => 2, |
| 1512 | else => unreachable, // unhandled architecture type |
| 1513 | }; |
| 1500 | 1514 | const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; |
| 1501 | 1515 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1502 | 1516 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| ... | ... | @@ -1510,7 +1524,73 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1510 | 1524 | .addr = text_segment.inner.vmaddr + off, |
| 1511 | 1525 | .size = needed_size, |
| 1512 | 1526 | .offset = @intCast(u32, off), |
| 1513 | | .@"align" = 3, // 2^@sizeOf(u64) |
| 1527 | .@"align" = alignment, |
| 1528 | .reloff = 0, |
| 1529 | .nreloc = 0, |
| 1530 | .flags = flags, |
| 1531 | .reserved1 = 0, |
| 1532 | .reserved2 = 0, |
| 1533 | .reserved3 = 0, |
| 1534 | }); |
| 1535 | self.header_dirty = true; |
| 1536 | self.load_commands_dirty = true; |
| 1537 | } |
| 1538 | if (self.stubs_section_index == null) { |
| 1539 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1540 | self.stubs_section_index = @intCast(u16, text_segment.sections.items.len); |
| 1541 | |
| 1542 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 1543 | .x86_64 => 0, |
| 1544 | .aarch64 => 2, |
| 1545 | else => unreachable, // unhandled architecture type |
| 1546 | }; |
| 1547 | const flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; |
| 1548 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1549 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| 1550 | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. |
| 1551 | |
| 1552 | log.debug("found __stubs section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 1553 | |
| 1554 | try text_segment.addSection(self.base.allocator, .{ |
| 1555 | .sectname = makeStaticString("__stubs"), |
| 1556 | .segname = makeStaticString("__TEXT"), |
| 1557 | .addr = text_segment.inner.vmaddr + off, |
| 1558 | .size = 0, // This will be populated later in tandem with .reserved2 field. |
| 1559 | .offset = @intCast(u32, off), |
| 1560 | .@"align" = alignment, |
| 1561 | .reloff = 0, |
| 1562 | .nreloc = 0, |
| 1563 | .flags = flags, |
| 1564 | .reserved1 = 0, |
| 1565 | .reserved2 = 0, |
| 1566 | .reserved3 = 0, |
| 1567 | }); |
| 1568 | self.header_dirty = true; |
| 1569 | self.load_commands_dirty = true; |
| 1570 | } |
| 1571 | if (self.stub_helper_section_index == null) { |
| 1572 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1573 | self.stub_helper_section_index = @intCast(u16, text_segment.sections.items.len); |
| 1574 | |
| 1575 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 1576 | .x86_64 => 0, |
| 1577 | .aarch64 => 2, |
| 1578 | else => unreachable, // unhandled architecture type |
| 1579 | }; |
| 1580 | const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; |
| 1581 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1582 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| 1583 | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. |
| 1584 | |
| 1585 | log.debug("found __stubs section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 1586 | |
| 1587 | try text_segment.addSection(self.base.allocator, .{ |
| 1588 | .sectname = makeStaticString("__stub_helper"), |
| 1589 | .segname = makeStaticString("__TEXT"), |
| 1590 | .addr = text_segment.inner.vmaddr + off, |
| 1591 | .size = needed_size, |
| 1592 | .offset = @intCast(u32, off), |
| 1593 | .@"align" = alignment, |
| 1514 | 1594 | .reloff = 0, |
| 1515 | 1595 | .nreloc = 0, |
| 1516 | 1596 | .flags = flags, |
| ... | ... | @@ -1550,13 +1630,41 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1550 | 1630 | self.header_dirty = true; |
| 1551 | 1631 | self.load_commands_dirty = true; |
| 1552 | 1632 | } |
| 1633 | if (self.data_got_section_index == null) { |
| 1634 | const dc_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 1635 | self.data_got_section_index = @intCast(u16, dc_segment.sections.items.len); |
| 1636 | |
| 1637 | const flags = macho.S_NON_LAZY_SYMBOL_POINTERS; |
| 1638 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1639 | const off = dc_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 1640 | assert(off + needed_size <= dc_segment.inner.fileoff + dc_segment.inner.filesize); // TODO Must expand __DATA_CONST segment. |
| 1641 | |
| 1642 | log.debug("found __got section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 1643 | |
| 1644 | try dc_segment.addSection(self.base.allocator, .{ |
| 1645 | .sectname = makeStaticString("__got"), |
| 1646 | .segname = makeStaticString("__DATA_CONST"), |
| 1647 | .addr = dc_segment.inner.vmaddr + off - dc_segment.inner.fileoff, |
| 1648 | .size = needed_size, |
| 1649 | .offset = @intCast(u32, off), |
| 1650 | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 1651 | .reloff = 0, |
| 1652 | .nreloc = 0, |
| 1653 | .flags = flags, |
| 1654 | .reserved1 = 0, |
| 1655 | .reserved2 = 0, |
| 1656 | .reserved3 = 0, |
| 1657 | }); |
| 1658 | self.header_dirty = true; |
| 1659 | self.load_commands_dirty = true; |
| 1660 | } |
| 1553 | 1661 | if (self.data_segment_cmd_index == null) { |
| 1554 | 1662 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1555 | 1663 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; |
| 1556 | 1664 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; |
| 1557 | 1665 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 1558 | 1666 | |
| 1559 | | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1667 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1560 | 1668 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| 1561 | 1669 | |
| 1562 | 1670 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| ... | ... | @@ -1579,6 +1687,62 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1579 | 1687 | self.header_dirty = true; |
| 1580 | 1688 | self.load_commands_dirty = true; |
| 1581 | 1689 | } |
| 1690 | if (self.la_symbol_ptr_section_index == null) { |
| 1691 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1692 | self.la_symbol_ptr_section_index = @intCast(u16, data_segment.sections.items.len); |
| 1693 | |
| 1694 | const flags = macho.S_LAZY_SYMBOL_POINTERS; |
| 1695 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1696 | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 1697 | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 1698 | |
| 1699 | log.debug("found __la_symbol_ptr section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 1700 | |
| 1701 | try data_segment.addSection(self.base.allocator, .{ |
| 1702 | .sectname = makeStaticString("__la_symbol_ptr"), |
| 1703 | .segname = makeStaticString("__DATA"), |
| 1704 | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 1705 | .size = needed_size, |
| 1706 | .offset = @intCast(u32, off), |
| 1707 | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 1708 | .reloff = 0, |
| 1709 | .nreloc = 0, |
| 1710 | .flags = flags, |
| 1711 | .reserved1 = 0, |
| 1712 | .reserved2 = 0, |
| 1713 | .reserved3 = 0, |
| 1714 | }); |
| 1715 | self.header_dirty = true; |
| 1716 | self.load_commands_dirty = true; |
| 1717 | } |
| 1718 | if (self.data_section_index == null) { |
| 1719 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1720 | self.data_section_index = @intCast(u16, data_segment.sections.items.len); |
| 1721 | |
| 1722 | const flags = macho.S_REGULAR; |
| 1723 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1724 | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 1725 | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 1726 | |
| 1727 | log.debug("found __data section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 1728 | |
| 1729 | try data_segment.addSection(self.base.allocator, .{ |
| 1730 | .sectname = makeStaticString("__data"), |
| 1731 | .segname = makeStaticString("__DATA"), |
| 1732 | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 1733 | .size = needed_size, |
| 1734 | .offset = @intCast(u32, off), |
| 1735 | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 1736 | .reloff = 0, |
| 1737 | .nreloc = 0, |
| 1738 | .flags = flags, |
| 1739 | .reserved1 = 0, |
| 1740 | .reserved2 = 0, |
| 1741 | .reserved3 = 0, |
| 1742 | }); |
| 1743 | self.header_dirty = true; |
| 1744 | self.load_commands_dirty = true; |
| 1745 | } |
| 1582 | 1746 | if (self.linkedit_segment_cmd_index == null) { |
| 1583 | 1747 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1584 | 1748 | |