authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-05 23:17:53+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-13 23:53:36+01:00
log51a13f8ea6f1596a3163ac656e0ddb1156d1399a
tree0c77270d675af8bcfe70c67416bb99b8096329b7
parent3d07f057b1ccbc20258114fde762969bcfddf1d3

macho: add missing data sections


1 files changed, 168 insertions(+), 4 deletions(-)

src/link/MachO.zig+168-4
...@@ -89,6 +89,16 @@ code_signature_cmd_index: ?u16 = null,...@@ -89,6 +89,16 @@ code_signature_cmd_index: ?u16 = null,
89text_section_index: ?u16 = null,89text_section_index: ?u16 = null,
90/// Index into __TEXT,__ziggot section.90/// Index into __TEXT,__ziggot section.
91got_section_index: ?u16 = null,91got_section_index: ?u16 = null,
92/// Index into __TEXT,__stubs section.
93stubs_section_index: ?u16 = null,
94/// Index into __TEXT,__stub_helper section.
95stub_helper_section_index: ?u16 = null,
96/// Index into __DATA_CONST,__got section.
97data_got_section_index: ?u16 = null,
98/// Index into __DATA,__la_symbol_ptr section.
99la_symbol_ptr_section_index: ?u16 = null,
100/// Index into __DATA,__data section.
101data_section_index: ?u16 = null,
92/// The absolute address of the entry point.102/// The absolute address of the entry point.
93entry_addr: ?u64 = null,103entry_addr: ?u64 = null,
94104
...@@ -1437,7 +1447,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1437,7 +1447,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
14371447
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);
14421452
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);
14991508
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();
15581666
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);
15611669
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);
15841748