| ... | @@ -89,6 +89,16 @@ code_signature_cmd_index: ?u16 = null, | ... | @@ -89,6 +89,16 @@ code_signature_cmd_index: ?u16 = null, |
| 89 | text_section_index: ?u16 = null, | 89 | text_section_index: ?u16 = null, |
| 90 | /// Index into __TEXT,__ziggot section. | 90 | /// Index into __TEXT,__ziggot section. |
| 91 | got_section_index: ?u16 = null, | 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 | /// The absolute address of the entry point. | 102 | /// The absolute address of the entry point. |
| 93 | entry_addr: ?u64 = null, | 103 | entry_addr: ?u64 = null, |
| 94 | | 104 | |
| ... | @@ -1437,7 +1447,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1437,7 +1447,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1437 | | 1447 | |
| 1438 | const program_code_size_hint = self.base.options.program_code_size_hint; | 1448 | const program_code_size_hint = self.base.options.program_code_size_hint; |
| 1439 | const offset_table_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint; | 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 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); | 1451 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| 1442 | | 1452 | |
| 1443 | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); | 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,9 +1504,13 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1494 | } | 1504 | } |
| 1495 | if (self.got_section_index == null) { | 1505 | if (self.got_section_index == null) { |
| 1496 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 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 | self.got_section_index = @intCast(u16, text_segment.sections.items.len); | 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 | const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; | 1514 | const flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS; |
| 1501 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 1515 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 1502 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); | 1516 | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| ... | @@ -1510,7 +1524,73 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1510,7 +1524,73 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1510 | .addr = text_segment.inner.vmaddr + off, | 1524 | .addr = text_segment.inner.vmaddr + off, |
| 1511 | .size = needed_size, | 1525 | .size = needed_size, |
| 1512 | .offset = @intCast(u32, off), | 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 | .reloff = 0, | 1594 | .reloff = 0, |
| 1515 | .nreloc = 0, | 1595 | .nreloc = 0, |
| 1516 | .flags = flags, | 1596 | .flags = flags, |
| ... | @@ -1550,13 +1630,41 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1550,13 +1630,41 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1550 | self.header_dirty = true; | 1630 | self.header_dirty = true; |
| 1551 | self.load_commands_dirty = true; | 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 | if (self.data_segment_cmd_index == null) { | 1661 | if (self.data_segment_cmd_index == null) { |
| 1554 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 1662 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1555 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; | 1663 | const maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE; |
| 1556 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; | 1664 | const initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE; |
| 1557 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 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 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); | 1668 | const needed_size = mem.alignForwardGeneric(u64, satMul(ideal_size, alloc_num) / alloc_den, self.page_size); |
| 1561 | | 1669 | |
| 1562 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); | 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,6 +1687,62 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1579 | self.header_dirty = true; | 1687 | self.header_dirty = true; |
| 1580 | self.load_commands_dirty = true; | 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 | if (self.linkedit_segment_cmd_index == null) { | 1746 | if (self.linkedit_segment_cmd_index == null) { |
| 1583 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 1747 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1584 | | 1748 | |