| ... | ... | @@ -63,6 +63,11 @@ page_size: u16, |
| 63 | 63 | /// https://github.com/ziglang/zig/issues/9567 |
| 64 | 64 | requires_adhoc_codesig: bool, |
| 65 | 65 | |
| 66 | /// If true, the linker will preallocate several sections and segments before starting the linking |
| 67 | /// process. This is for example true for stage2 debug builds, however, this is false for stage1 |
| 68 | /// and potentially stage2 release builds in the future. |
| 69 | needs_prealloc: bool = true, |
| 70 | |
| 66 | 71 | /// We commit 0x1000 = 4096 bytes of space to the header and |
| 67 | 72 | /// the table of load commands. This should be plenty for any |
| 68 | 73 | /// potential future extensions. |
| ... | ... | @@ -375,6 +380,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { |
| 375 | 380 | // Adhoc code signature is required when targeting aarch64-macos either directly or indirectly via the simulator |
| 376 | 381 | // ABI such as aarch64-ios-simulator, etc. |
| 377 | 382 | const requires_adhoc_codesig = cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator); |
| 383 | const needs_prealloc = !(build_options.is_stage1 and options.use_stage1); |
| 378 | 384 | |
| 379 | 385 | self.* = .{ |
| 380 | 386 | .base = .{ |
| ... | ... | @@ -385,6 +391,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO { |
| 385 | 391 | }, |
| 386 | 392 | .page_size = page_size, |
| 387 | 393 | .requires_adhoc_codesig = requires_adhoc_codesig, |
| 394 | .needs_prealloc = needs_prealloc, |
| 388 | 395 | }; |
| 389 | 396 | |
| 390 | 397 | return self; |
| ... | ... | @@ -911,6 +918,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 911 | 918 | |
| 912 | 919 | try self.createTentativeDefAtoms(); |
| 913 | 920 | try self.parseObjectsIntoAtoms(); |
| 921 | |
| 922 | if (use_stage1) { |
| 923 | try self.allocateTextSegment(); |
| 924 | try self.allocateDataConstSegment(); |
| 925 | try self.allocateDataSegment(); |
| 926 | self.allocateLinkeditSegment(); |
| 927 | try self.allocLocalSymbols(); |
| 928 | } |
| 929 | |
| 914 | 930 | try self.allocateGlobalSymbols(); |
| 915 | 931 | |
| 916 | 932 | log.debug("locals:", .{}); |
| ... | ... | @@ -946,6 +962,18 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 946 | 962 | log.debug(" {} => {s}", .{ key, self.getString(key) }); |
| 947 | 963 | } |
| 948 | 964 | |
| 965 | for (self.section_ordinals.keys()) |match, i| { |
| 966 | const seg = self.load_commands.items[match.seg].Segment; |
| 967 | const sect = seg.sections.items[match.sect]; |
| 968 | log.debug("{d}: {d},{d} == {s},{s}", .{ |
| 969 | i + 1, |
| 970 | match.seg, |
| 971 | match.sect, |
| 972 | commands.segmentName(sect), |
| 973 | commands.sectionName(sect), |
| 974 | }); |
| 975 | } |
| 976 | |
| 949 | 977 | try self.writeAtoms(); |
| 950 | 978 | |
| 951 | 979 | if (self.bss_section_index) |idx| { |
| ... | ... | @@ -1337,7 +1365,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1337 | 1365 | switch (commands.sectionType(sect)) { |
| 1338 | 1366 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1339 | 1367 | if (self.text_const_section_index == null) { |
| 1340 | | self.text_const_section_index = try self.allocateSection( |
| 1368 | self.text_const_section_index = try self.initSection( |
| 1341 | 1369 | self.text_segment_cmd_index.?, |
| 1342 | 1370 | "__const", |
| 1343 | 1371 | sect.size, |
| ... | ... | @@ -1356,7 +1384,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1356 | 1384 | // TODO it seems the common values within the sections in objects are deduplicated/merged |
| 1357 | 1385 | // on merging the sections' contents. |
| 1358 | 1386 | if (self.objc_methname_section_index == null) { |
| 1359 | | self.objc_methname_section_index = try self.allocateSection( |
| 1387 | self.objc_methname_section_index = try self.initSection( |
| 1360 | 1388 | self.text_segment_cmd_index.?, |
| 1361 | 1389 | "__objc_methname", |
| 1362 | 1390 | sect.size, |
| ... | ... | @@ -1371,7 +1399,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1371 | 1399 | }; |
| 1372 | 1400 | } else if (mem.eql(u8, sectname, "__objc_methtype")) { |
| 1373 | 1401 | if (self.objc_methtype_section_index == null) { |
| 1374 | | self.objc_methtype_section_index = try self.allocateSection( |
| 1402 | self.objc_methtype_section_index = try self.initSection( |
| 1375 | 1403 | self.text_segment_cmd_index.?, |
| 1376 | 1404 | "__objc_methtype", |
| 1377 | 1405 | sect.size, |
| ... | ... | @@ -1386,7 +1414,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1386 | 1414 | }; |
| 1387 | 1415 | } else if (mem.eql(u8, sectname, "__objc_classname")) { |
| 1388 | 1416 | if (self.objc_classname_section_index == null) { |
| 1389 | | self.objc_classname_section_index = try self.allocateSection( |
| 1417 | self.objc_classname_section_index = try self.initSection( |
| 1390 | 1418 | self.text_segment_cmd_index.?, |
| 1391 | 1419 | "__objc_classname", |
| 1392 | 1420 | sect.size, |
| ... | ... | @@ -1402,7 +1430,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1402 | 1430 | } |
| 1403 | 1431 | |
| 1404 | 1432 | if (self.cstring_section_index == null) { |
| 1405 | | self.cstring_section_index = try self.allocateSection( |
| 1433 | self.cstring_section_index = try self.initSection( |
| 1406 | 1434 | self.text_segment_cmd_index.?, |
| 1407 | 1435 | "__cstring", |
| 1408 | 1436 | sect.size, |
| ... | ... | @@ -1421,7 +1449,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1421 | 1449 | macho.S_LITERAL_POINTERS => { |
| 1422 | 1450 | if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) { |
| 1423 | 1451 | if (self.objc_selrefs_section_index == null) { |
| 1424 | | self.objc_selrefs_section_index = try self.allocateSection( |
| 1452 | self.objc_selrefs_section_index = try self.initSection( |
| 1425 | 1453 | self.data_segment_cmd_index.?, |
| 1426 | 1454 | "__objc_selrefs", |
| 1427 | 1455 | sect.size, |
| ... | ... | @@ -1443,7 +1471,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1443 | 1471 | }, |
| 1444 | 1472 | macho.S_MOD_INIT_FUNC_POINTERS => { |
| 1445 | 1473 | if (self.mod_init_func_section_index == null) { |
| 1446 | | self.mod_init_func_section_index = try self.allocateSection( |
| 1474 | self.mod_init_func_section_index = try self.initSection( |
| 1447 | 1475 | self.data_const_segment_cmd_index.?, |
| 1448 | 1476 | "__mod_init_func", |
| 1449 | 1477 | sect.size, |
| ... | ... | @@ -1461,7 +1489,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1461 | 1489 | }, |
| 1462 | 1490 | macho.S_MOD_TERM_FUNC_POINTERS => { |
| 1463 | 1491 | if (self.mod_term_func_section_index == null) { |
| 1464 | | self.mod_term_func_section_index = try self.allocateSection( |
| 1492 | self.mod_term_func_section_index = try self.initSection( |
| 1465 | 1493 | self.data_const_segment_cmd_index.?, |
| 1466 | 1494 | "__mod_term_func", |
| 1467 | 1495 | sect.size, |
| ... | ... | @@ -1479,7 +1507,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1479 | 1507 | }, |
| 1480 | 1508 | macho.S_ZEROFILL => { |
| 1481 | 1509 | if (self.bss_section_index == null) { |
| 1482 | | self.bss_section_index = try self.allocateSection( |
| 1510 | self.bss_section_index = try self.initSection( |
| 1483 | 1511 | self.data_segment_cmd_index.?, |
| 1484 | 1512 | "__bss", |
| 1485 | 1513 | sect.size, |
| ... | ... | @@ -1497,7 +1525,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1497 | 1525 | }, |
| 1498 | 1526 | macho.S_THREAD_LOCAL_VARIABLES => { |
| 1499 | 1527 | if (self.tlv_section_index == null) { |
| 1500 | | self.tlv_section_index = try self.allocateSection( |
| 1528 | self.tlv_section_index = try self.initSection( |
| 1501 | 1529 | self.data_segment_cmd_index.?, |
| 1502 | 1530 | "__thread_vars", |
| 1503 | 1531 | sect.size, |
| ... | ... | @@ -1515,7 +1543,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1515 | 1543 | }, |
| 1516 | 1544 | macho.S_THREAD_LOCAL_REGULAR => { |
| 1517 | 1545 | if (self.tlv_data_section_index == null) { |
| 1518 | | self.tlv_data_section_index = try self.allocateSection( |
| 1546 | self.tlv_data_section_index = try self.initSection( |
| 1519 | 1547 | self.data_segment_cmd_index.?, |
| 1520 | 1548 | "__thread_data", |
| 1521 | 1549 | sect.size, |
| ... | ... | @@ -1533,7 +1561,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1533 | 1561 | }, |
| 1534 | 1562 | macho.S_THREAD_LOCAL_ZEROFILL => { |
| 1535 | 1563 | if (self.tlv_bss_section_index == null) { |
| 1536 | | self.tlv_bss_section_index = try self.allocateSection( |
| 1564 | self.tlv_bss_section_index = try self.initSection( |
| 1537 | 1565 | self.data_segment_cmd_index.?, |
| 1538 | 1566 | "__thread_bss", |
| 1539 | 1567 | sect.size, |
| ... | ... | @@ -1554,7 +1582,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1554 | 1582 | // TODO I believe __eh_frame is currently part of __unwind_info section |
| 1555 | 1583 | // in the latest ld64 output. |
| 1556 | 1584 | if (self.eh_frame_section_index == null) { |
| 1557 | | self.eh_frame_section_index = try self.allocateSection( |
| 1585 | self.eh_frame_section_index = try self.initSection( |
| 1558 | 1586 | self.text_segment_cmd_index.?, |
| 1559 | 1587 | "__eh_frame", |
| 1560 | 1588 | sect.size, |
| ... | ... | @@ -1571,7 +1599,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1571 | 1599 | |
| 1572 | 1600 | // TODO audit this: is this the right mapping? |
| 1573 | 1601 | if (self.data_const_section_index == null) { |
| 1574 | | self.data_const_section_index = try self.allocateSection( |
| 1602 | self.data_const_section_index = try self.initSection( |
| 1575 | 1603 | self.data_const_segment_cmd_index.?, |
| 1576 | 1604 | "__const", |
| 1577 | 1605 | sect.size, |
| ... | ... | @@ -1588,7 +1616,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1588 | 1616 | macho.S_REGULAR => { |
| 1589 | 1617 | if (commands.sectionIsCode(sect)) { |
| 1590 | 1618 | if (self.text_section_index == null) { |
| 1591 | | self.text_section_index = try self.allocateSection( |
| 1619 | self.text_section_index = try self.initSection( |
| 1592 | 1620 | self.text_segment_cmd_index.?, |
| 1593 | 1621 | "__text", |
| 1594 | 1622 | sect.size, |
| ... | ... | @@ -1619,7 +1647,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1619 | 1647 | if (mem.eql(u8, segname, "__TEXT")) { |
| 1620 | 1648 | if (mem.eql(u8, sectname, "__ustring")) { |
| 1621 | 1649 | if (self.ustring_section_index == null) { |
| 1622 | | self.ustring_section_index = try self.allocateSection( |
| 1650 | self.ustring_section_index = try self.initSection( |
| 1623 | 1651 | self.text_segment_cmd_index.?, |
| 1624 | 1652 | "__ustring", |
| 1625 | 1653 | sect.size, |
| ... | ... | @@ -1634,7 +1662,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1634 | 1662 | }; |
| 1635 | 1663 | } else if (mem.eql(u8, sectname, "__gcc_except_tab")) { |
| 1636 | 1664 | if (self.gcc_except_tab_section_index == null) { |
| 1637 | | self.gcc_except_tab_section_index = try self.allocateSection( |
| 1665 | self.gcc_except_tab_section_index = try self.initSection( |
| 1638 | 1666 | self.text_segment_cmd_index.?, |
| 1639 | 1667 | "__gcc_except_tab", |
| 1640 | 1668 | sect.size, |
| ... | ... | @@ -1649,7 +1677,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1649 | 1677 | }; |
| 1650 | 1678 | } else if (mem.eql(u8, sectname, "__objc_methlist")) { |
| 1651 | 1679 | if (self.objc_methlist_section_index == null) { |
| 1652 | | self.objc_methlist_section_index = try self.allocateSection( |
| 1680 | self.objc_methlist_section_index = try self.initSection( |
| 1653 | 1681 | self.text_segment_cmd_index.?, |
| 1654 | 1682 | "__objc_methlist", |
| 1655 | 1683 | sect.size, |
| ... | ... | @@ -1669,7 +1697,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1669 | 1697 | mem.eql(u8, sectname, "__gopclntab")) |
| 1670 | 1698 | { |
| 1671 | 1699 | if (self.data_const_section_index == null) { |
| 1672 | | self.data_const_section_index = try self.allocateSection( |
| 1700 | self.data_const_section_index = try self.initSection( |
| 1673 | 1701 | self.data_const_segment_cmd_index.?, |
| 1674 | 1702 | "__const", |
| 1675 | 1703 | sect.size, |
| ... | ... | @@ -1684,7 +1712,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1684 | 1712 | }; |
| 1685 | 1713 | } else { |
| 1686 | 1714 | if (self.text_const_section_index == null) { |
| 1687 | | self.text_const_section_index = try self.allocateSection( |
| 1715 | self.text_const_section_index = try self.initSection( |
| 1688 | 1716 | self.text_segment_cmd_index.?, |
| 1689 | 1717 | "__const", |
| 1690 | 1718 | sect.size, |
| ... | ... | @@ -1702,7 +1730,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1702 | 1730 | |
| 1703 | 1731 | if (mem.eql(u8, segname, "__DATA_CONST")) { |
| 1704 | 1732 | if (self.data_const_section_index == null) { |
| 1705 | | self.data_const_section_index = try self.allocateSection( |
| 1733 | self.data_const_section_index = try self.initSection( |
| 1706 | 1734 | self.data_const_segment_cmd_index.?, |
| 1707 | 1735 | "__const", |
| 1708 | 1736 | sect.size, |
| ... | ... | @@ -1720,7 +1748,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1720 | 1748 | if (mem.eql(u8, segname, "__DATA")) { |
| 1721 | 1749 | if (mem.eql(u8, sectname, "__const")) { |
| 1722 | 1750 | if (self.data_const_section_index == null) { |
| 1723 | | self.data_const_section_index = try self.allocateSection( |
| 1751 | self.data_const_section_index = try self.initSection( |
| 1724 | 1752 | self.data_const_segment_cmd_index.?, |
| 1725 | 1753 | "__const", |
| 1726 | 1754 | sect.size, |
| ... | ... | @@ -1735,7 +1763,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1735 | 1763 | }; |
| 1736 | 1764 | } else if (mem.eql(u8, sectname, "__cfstring")) { |
| 1737 | 1765 | if (self.objc_cfstring_section_index == null) { |
| 1738 | | self.objc_cfstring_section_index = try self.allocateSection( |
| 1766 | self.objc_cfstring_section_index = try self.initSection( |
| 1739 | 1767 | self.data_const_segment_cmd_index.?, |
| 1740 | 1768 | "__cfstring", |
| 1741 | 1769 | sect.size, |
| ... | ... | @@ -1750,7 +1778,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1750 | 1778 | }; |
| 1751 | 1779 | } else if (mem.eql(u8, sectname, "__objc_classlist")) { |
| 1752 | 1780 | if (self.objc_classlist_section_index == null) { |
| 1753 | | self.objc_classlist_section_index = try self.allocateSection( |
| 1781 | self.objc_classlist_section_index = try self.initSection( |
| 1754 | 1782 | self.data_const_segment_cmd_index.?, |
| 1755 | 1783 | "__objc_classlist", |
| 1756 | 1784 | sect.size, |
| ... | ... | @@ -1765,7 +1793,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1765 | 1793 | }; |
| 1766 | 1794 | } else if (mem.eql(u8, sectname, "__objc_imageinfo")) { |
| 1767 | 1795 | if (self.objc_imageinfo_section_index == null) { |
| 1768 | | self.objc_imageinfo_section_index = try self.allocateSection( |
| 1796 | self.objc_imageinfo_section_index = try self.initSection( |
| 1769 | 1797 | self.data_const_segment_cmd_index.?, |
| 1770 | 1798 | "__objc_imageinfo", |
| 1771 | 1799 | sect.size, |
| ... | ... | @@ -1780,7 +1808,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1780 | 1808 | }; |
| 1781 | 1809 | } else if (mem.eql(u8, sectname, "__objc_const")) { |
| 1782 | 1810 | if (self.objc_const_section_index == null) { |
| 1783 | | self.objc_const_section_index = try self.allocateSection( |
| 1811 | self.objc_const_section_index = try self.initSection( |
| 1784 | 1812 | self.data_segment_cmd_index.?, |
| 1785 | 1813 | "__objc_const", |
| 1786 | 1814 | sect.size, |
| ... | ... | @@ -1795,7 +1823,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1795 | 1823 | }; |
| 1796 | 1824 | } else if (mem.eql(u8, sectname, "__objc_classrefs")) { |
| 1797 | 1825 | if (self.objc_classrefs_section_index == null) { |
| 1798 | | self.objc_classrefs_section_index = try self.allocateSection( |
| 1826 | self.objc_classrefs_section_index = try self.initSection( |
| 1799 | 1827 | self.data_segment_cmd_index.?, |
| 1800 | 1828 | "__objc_classrefs", |
| 1801 | 1829 | sect.size, |
| ... | ... | @@ -1810,7 +1838,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1810 | 1838 | }; |
| 1811 | 1839 | } else if (mem.eql(u8, sectname, "__objc_data")) { |
| 1812 | 1840 | if (self.objc_data_section_index == null) { |
| 1813 | | self.objc_data_section_index = try self.allocateSection( |
| 1841 | self.objc_data_section_index = try self.initSection( |
| 1814 | 1842 | self.data_segment_cmd_index.?, |
| 1815 | 1843 | "__objc_data", |
| 1816 | 1844 | sect.size, |
| ... | ... | @@ -1825,7 +1853,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1825 | 1853 | }; |
| 1826 | 1854 | } else { |
| 1827 | 1855 | if (self.data_section_index == null) { |
| 1828 | | self.data_section_index = try self.allocateSection( |
| 1856 | self.data_section_index = try self.initSection( |
| 1829 | 1857 | self.data_segment_cmd_index.?, |
| 1830 | 1858 | "__data", |
| 1831 | 1859 | sect.size, |
| ... | ... | @@ -1881,6 +1909,63 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 1881 | 1909 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); |
| 1882 | 1910 | } |
| 1883 | 1911 | |
| 1912 | fn allocLocalSymbols(self: *MachO) !void { |
| 1913 | var it = self.atoms.iterator(); |
| 1914 | while (it.next()) |entry| { |
| 1915 | const match = entry.key_ptr.*; |
| 1916 | var atom = entry.value_ptr.*; |
| 1917 | |
| 1918 | while (atom.prev) |prev| { |
| 1919 | atom = prev; |
| 1920 | } |
| 1921 | |
| 1922 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 1923 | const seg = self.load_commands.items[match.seg].Segment; |
| 1924 | const sect = seg.sections.items[match.sect]; |
| 1925 | var base_vaddr = sect.addr; |
| 1926 | |
| 1927 | log.debug("allocating local symbols in {s},{s}", .{ |
| 1928 | commands.segmentName(sect), |
| 1929 | commands.sectionName(sect), |
| 1930 | }); |
| 1931 | |
| 1932 | while (true) { |
| 1933 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 1934 | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); |
| 1935 | |
| 1936 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1937 | sym.n_value = base_vaddr; |
| 1938 | sym.n_sect = n_sect; |
| 1939 | |
| 1940 | log.debug(" {d}: {s} @0x{x}", .{ |
| 1941 | atom.local_sym_index, |
| 1942 | self.getString(sym.n_strx), |
| 1943 | base_vaddr, |
| 1944 | }); |
| 1945 | |
| 1946 | // Update each alias (if any) |
| 1947 | for (atom.aliases.items) |index| { |
| 1948 | const alias_sym = &self.locals.items[index]; |
| 1949 | alias_sym.n_value = base_vaddr; |
| 1950 | alias_sym.n_sect = n_sect; |
| 1951 | } |
| 1952 | |
| 1953 | // Update each symbol contained within the atom |
| 1954 | for (atom.contained.items) |sym_at_off| { |
| 1955 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| 1956 | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| 1957 | contained_sym.n_sect = n_sect; |
| 1958 | } |
| 1959 | |
| 1960 | base_vaddr += atom.size; |
| 1961 | |
| 1962 | if (atom.next) |next| { |
| 1963 | atom = next; |
| 1964 | } else break; |
| 1965 | } |
| 1966 | } |
| 1967 | } |
| 1968 | |
| 1884 | 1969 | fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void { |
| 1885 | 1970 | var atom = self.atoms.get(match) orelse return; |
| 1886 | 1971 | |
| ... | ... | @@ -1971,7 +2056,15 @@ fn writeAtoms(self: *MachO) !void { |
| 1971 | 2056 | if (atom.next) |next| { |
| 1972 | 2057 | atom = next; |
| 1973 | 2058 | } else { |
| 2059 | if (buffer.items.len != sect.size) { |
| 2060 | log.warn("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| 2061 | log.warn(" alignment: 0x{x}", .{sect.@"align"}); |
| 2062 | log.warn(" expected: 0x{x}", .{sect.size}); |
| 2063 | log.warn(" given: 0x{x}", .{buffer.items.len}); |
| 2064 | } |
| 2065 | assert(buffer.items.len == sect.size); |
| 1974 | 2066 | if (file_offset) |off| { |
| 2067 | log.debug(" (writing at file offset 0x{x})", .{off}); |
| 1975 | 2068 | try self.base.file.?.pwriteAll(buffer.items, off); |
| 1976 | 2069 | } |
| 1977 | 2070 | file_offset = null; |
| ... | ... | @@ -2036,10 +2129,13 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 2036 | 2129 | .seg = self.data_segment_cmd_index.?, |
| 2037 | 2130 | .sect = self.data_section_index.?, |
| 2038 | 2131 | }; |
| 2039 | | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2040 | | sym.n_value = vaddr; |
| 2132 | if (self.needs_prealloc) { |
| 2133 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2134 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2135 | sym.n_value = vaddr; |
| 2136 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2137 | |
| 2041 | 2138 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2042 | | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2043 | 2139 | } |
| 2044 | 2140 | |
| 2045 | 2141 | fn createStubHelperPreambleAtom(self: *MachO) !void { |
| ... | ... | @@ -2165,11 +2261,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2165 | 2261 | .seg = self.text_segment_cmd_index.?, |
| 2166 | 2262 | .sect = self.stub_helper_section_index.?, |
| 2167 | 2263 | }; |
| 2168 | | const alignment_pow_2 = try math.powi(u32, 2, atom.alignment); |
| 2169 | | const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match); |
| 2170 | | sym.n_value = vaddr; |
| 2264 | |
| 2265 | if (self.needs_prealloc) { |
| 2266 | const alignment_pow_2 = try math.powi(u32, 2, atom.alignment); |
| 2267 | const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match); |
| 2268 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2269 | sym.n_value = vaddr; |
| 2270 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2271 | |
| 2171 | 2272 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2172 | | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2173 | 2273 | } |
| 2174 | 2274 | |
| 2175 | 2275 | pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| ... | ... | @@ -2377,10 +2477,13 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2377 | 2477 | resolv.local_sym_index = local_sym_index; |
| 2378 | 2478 | |
| 2379 | 2479 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| 2380 | | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 2381 | | const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match); |
| 2382 | | local_sym.n_value = vaddr; |
| 2383 | | global_sym.n_value = vaddr; |
| 2480 | |
| 2481 | if (self.needs_prealloc) { |
| 2482 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 2483 | const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match); |
| 2484 | local_sym.n_value = vaddr; |
| 2485 | global_sym.n_value = vaddr; |
| 2486 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2384 | 2487 | } |
| 2385 | 2488 | } |
| 2386 | 2489 | |
| ... | ... | @@ -2429,9 +2532,12 @@ fn createDsoHandleAtom(self: *MachO) !void { |
| 2429 | 2532 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2430 | 2533 | // linked list of atoms? |
| 2431 | 2534 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2432 | | const sym = &self.locals.items[local_sym_index]; |
| 2433 | | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2434 | | sym.n_value = vaddr; |
| 2535 | if (self.needs_prealloc) { |
| 2536 | const sym = &self.locals.items[local_sym_index]; |
| 2537 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2538 | sym.n_value = vaddr; |
| 2539 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2540 | |
| 2435 | 2541 | atom.dirty = false; // We don't really want to write it to file. |
| 2436 | 2542 | } |
| 2437 | 2543 | } |
| ... | ... | @@ -2771,9 +2877,13 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { |
| 2771 | 2877 | }); |
| 2772 | 2878 | |
| 2773 | 2879 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2774 | | const sym = &self.locals.items[local_sym_index]; |
| 2775 | | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2776 | | sym.n_value = vaddr; |
| 2880 | |
| 2881 | if (self.needs_prealloc) { |
| 2882 | const sym = &self.locals.items[local_sym_index]; |
| 2883 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2884 | sym.n_value = vaddr; |
| 2885 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2886 | |
| 2777 | 2887 | atom.dirty = false; |
| 2778 | 2888 | self.mh_execute_header_index = local_sym_index; |
| 2779 | 2889 | } |
| ... | ... | @@ -2828,10 +2938,14 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2828 | 2938 | .sect = self.got_section_index.?, |
| 2829 | 2939 | }; |
| 2830 | 2940 | const atom_sym = &self.locals.items[atom.local_sym_index]; |
| 2831 | | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2832 | | atom_sym.n_value = vaddr; |
| 2941 | |
| 2942 | if (self.needs_prealloc) { |
| 2943 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 2944 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2945 | atom_sym.n_value = vaddr; |
| 2946 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2947 | |
| 2833 | 2948 | atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2834 | | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 2835 | 2949 | } |
| 2836 | 2950 | |
| 2837 | 2951 | fn parseObjectsIntoAtoms(self: *MachO) !void { |
| ... | ... | @@ -2858,20 +2972,31 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2858 | 2972 | var it = object.end_atoms.iterator(); |
| 2859 | 2973 | while (it.next()) |entry| { |
| 2860 | 2974 | const match = entry.key_ptr.*; |
| 2861 | | const last_atom = entry.value_ptr.*; |
| 2862 | | var atom = last_atom; |
| 2975 | var atom = entry.value_ptr.*; |
| 2976 | |
| 2977 | while (atom.prev) |prev| { |
| 2978 | atom = prev; |
| 2979 | } |
| 2863 | 2980 | |
| 2981 | const first_atom = atom; |
| 2982 | |
| 2983 | const seg = self.load_commands.items[match.seg].Segment; |
| 2984 | const sect = seg.sections.items[match.sect]; |
| 2864 | 2985 | const metadata = try section_metadata.getOrPut(match); |
| 2865 | 2986 | if (!metadata.found_existing) { |
| 2866 | 2987 | metadata.value_ptr.* = .{ |
| 2867 | | .size = 0, |
| 2868 | | .alignment = 0, |
| 2988 | .size = sect.size, |
| 2989 | .alignment = sect.@"align", |
| 2869 | 2990 | }; |
| 2870 | 2991 | } |
| 2871 | 2992 | |
| 2993 | log.debug("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| 2994 | |
| 2872 | 2995 | while (true) { |
| 2873 | 2996 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 2874 | | metadata.value_ptr.size += mem.alignForwardGeneric(u64, atom.size, alignment); |
| 2997 | const curr_size = metadata.value_ptr.size; |
| 2998 | const curr_size_aligned = mem.alignForwardGeneric(u64, curr_size, alignment); |
| 2999 | metadata.value_ptr.size = curr_size_aligned + atom.size; |
| 2875 | 3000 | metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment); |
| 2876 | 3001 | |
| 2877 | 3002 | const sym = self.locals.items[atom.local_sym_index]; |
| ... | ... | @@ -2882,20 +3007,20 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2882 | 3007 | atom.alignment, |
| 2883 | 3008 | }); |
| 2884 | 3009 | |
| 2885 | | if (atom.prev) |prev| { |
| 2886 | | atom = prev; |
| 3010 | if (atom.next) |next| { |
| 3011 | atom = next; |
| 2887 | 3012 | } else break; |
| 2888 | 3013 | } |
| 2889 | 3014 | |
| 2890 | 3015 | if (parsed_atoms.getPtr(match)) |last| { |
| 2891 | | last.*.next = atom; |
| 2892 | | atom.prev = last.*; |
| 2893 | | last.* = atom; |
| 3016 | last.*.next = first_atom; |
| 3017 | first_atom.prev = last.*; |
| 3018 | last.* = first_atom; |
| 2894 | 3019 | } |
| 2895 | | _ = try parsed_atoms.put(match, last_atom); |
| 3020 | _ = try parsed_atoms.put(match, atom); |
| 2896 | 3021 | |
| 2897 | 3022 | if (!first_atoms.contains(match)) { |
| 2898 | | try first_atoms.putNoClobber(match, atom); |
| 3023 | try first_atoms.putNoClobber(match, first_atom); |
| 2899 | 3024 | } |
| 2900 | 3025 | } |
| 2901 | 3026 | |
| ... | ... | @@ -2915,67 +3040,84 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2915 | 3040 | metadata.alignment, |
| 2916 | 3041 | }); |
| 2917 | 3042 | |
| 2918 | | const sect_size = if (self.atoms.get(match)) |last| blk: { |
| 2919 | | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 2920 | | break :blk last_atom_sym.n_value + last.size - sect.addr; |
| 2921 | | } else 0; |
| 2922 | | |
| 2923 | 3043 | sect.@"align" = math.max(sect.@"align", metadata.alignment); |
| 2924 | | const needed_size = @intCast(u32, metadata.size + sect_size); |
| 2925 | | try self.growSection(match, needed_size); |
| 3044 | const needed_size = @intCast(u32, metadata.size); |
| 3045 | |
| 3046 | if (self.needs_prealloc) { |
| 3047 | try self.growSection(match, needed_size); |
| 3048 | } |
| 2926 | 3049 | sect.size = needed_size; |
| 3050 | } |
| 2927 | 3051 | |
| 2928 | | var base_vaddr = if (self.atoms.get(match)) |last| blk: { |
| 2929 | | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 2930 | | break :blk last_atom_sym.n_value + last.size; |
| 2931 | | } else sect.addr; |
| 2932 | | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 3052 | for (&[_]?u16{ |
| 3053 | self.text_segment_cmd_index, |
| 3054 | self.data_const_segment_cmd_index, |
| 3055 | self.data_segment_cmd_index, |
| 3056 | }) |maybe_seg_id| { |
| 3057 | const seg_id = maybe_seg_id orelse continue; |
| 3058 | const seg = self.load_commands.items[seg_id].Segment; |
| 2933 | 3059 | |
| 2934 | | var atom = first_atoms.get(match).?; |
| 2935 | | while (true) { |
| 2936 | | const alignment = try math.powi(u32, 2, atom.alignment); |
| 2937 | | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); |
| 3060 | for (seg.sections.items) |sect, sect_id| { |
| 3061 | const match = MatchingSection{ |
| 3062 | .seg = seg_id, |
| 3063 | .sect = @intCast(u16, sect_id), |
| 3064 | }; |
| 3065 | if (!section_metadata.contains(match)) continue; |
| 2938 | 3066 | |
| 2939 | | const sym = &self.locals.items[atom.local_sym_index]; |
| 2940 | | sym.n_value = base_vaddr; |
| 2941 | | sym.n_sect = n_sect; |
| 3067 | if (self.atoms.getPtr(match)) |last| { |
| 3068 | const first_atom = first_atoms.get(match).?; |
| 3069 | last.*.next = first_atom; |
| 3070 | first_atom.prev = last.*; |
| 3071 | last.* = first_atom; |
| 3072 | } |
| 3073 | _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?); |
| 2942 | 3074 | |
| 2943 | | log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{ |
| 2944 | | self.getString(sym.n_strx), |
| 2945 | | base_vaddr, |
| 2946 | | base_vaddr + atom.size, |
| 2947 | | atom.size, |
| 2948 | | atom.alignment, |
| 2949 | | }); |
| 3075 | if (!self.needs_prealloc) continue; |
| 2950 | 3076 | |
| 2951 | | // Update each alias (if any) |
| 2952 | | for (atom.aliases.items) |index| { |
| 2953 | | const alias_sym = &self.locals.items[index]; |
| 2954 | | alias_sym.n_value = base_vaddr; |
| 2955 | | alias_sym.n_sect = n_sect; |
| 2956 | | } |
| 3077 | var base_vaddr = if (self.atoms.get(match)) |last| blk: { |
| 3078 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 3079 | break :blk last_atom_sym.n_value + last.size; |
| 3080 | } else sect.addr; |
| 3081 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2957 | 3082 | |
| 2958 | | // Update each symbol contained within the atom |
| 2959 | | for (atom.contained.items) |sym_at_off| { |
| 2960 | | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| 2961 | | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| 2962 | | contained_sym.n_sect = n_sect; |
| 2963 | | } |
| 3083 | var atom = first_atoms.get(match).?; |
| 3084 | while (true) { |
| 3085 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 3086 | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); |
| 2964 | 3087 | |
| 2965 | | base_vaddr += atom.size; |
| 3088 | const sym = &self.locals.items[atom.local_sym_index]; |
| 3089 | sym.n_value = base_vaddr; |
| 3090 | sym.n_sect = n_sect; |
| 2966 | 3091 | |
| 2967 | | if (atom.next) |next| { |
| 2968 | | atom = next; |
| 2969 | | } else break; |
| 2970 | | } |
| 3092 | log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{ |
| 3093 | self.getString(sym.n_strx), |
| 3094 | base_vaddr, |
| 3095 | base_vaddr + atom.size, |
| 3096 | atom.size, |
| 3097 | atom.alignment, |
| 3098 | }); |
| 3099 | |
| 3100 | // Update each alias (if any) |
| 3101 | for (atom.aliases.items) |index| { |
| 3102 | const alias_sym = &self.locals.items[index]; |
| 3103 | alias_sym.n_value = base_vaddr; |
| 3104 | alias_sym.n_sect = n_sect; |
| 3105 | } |
| 3106 | |
| 3107 | // Update each symbol contained within the atom |
| 3108 | for (atom.contained.items) |sym_at_off| { |
| 3109 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| 3110 | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| 3111 | contained_sym.n_sect = n_sect; |
| 3112 | } |
| 2971 | 3113 | |
| 2972 | | if (self.atoms.getPtr(match)) |last| { |
| 2973 | | const first_atom = first_atoms.get(match).?; |
| 2974 | | last.*.next = first_atom; |
| 2975 | | first_atom.prev = last.*; |
| 2976 | | last.* = first_atom; |
| 3114 | base_vaddr += atom.size; |
| 3115 | |
| 3116 | if (atom.next) |next| { |
| 3117 | atom = next; |
| 3118 | } else break; |
| 3119 | } |
| 2977 | 3120 | } |
| 2978 | | _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?); |
| 2979 | 3121 | } |
| 2980 | 3122 | } |
| 2981 | 3123 | |
| ... | ... | @@ -3714,7 +3856,9 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { |
| 3714 | 3856 | return self.locals.items[decl.link.macho.local_sym_index].n_value; |
| 3715 | 3857 | } |
| 3716 | 3858 | |
| 3717 | | pub fn populateMissingMetadata(self: *MachO) !void { |
| 3859 | fn populateMissingMetadata(self: *MachO) !void { |
| 3860 | const cpu_arch = self.base.options.target.cpu.arch; |
| 3861 | |
| 3718 | 3862 | if (self.pagezero_segment_cmd_index == null) { |
| 3719 | 3863 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3720 | 3864 | try self.load_commands.append(self.base.allocator, .{ |
| ... | ... | @@ -3730,13 +3874,14 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3730 | 3874 | |
| 3731 | 3875 | if (self.text_segment_cmd_index == null) { |
| 3732 | 3876 | self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3733 | | const program_code_size_hint = self.base.options.program_code_size_hint; |
| 3734 | | const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3735 | | const ideal_size = self.header_pad + program_code_size_hint + got_size_hint; |
| 3736 | | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 3737 | | |
| 3738 | | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| 3739 | | |
| 3877 | const needed_size = if (self.needs_prealloc) blk: { |
| 3878 | const program_code_size_hint = self.base.options.program_code_size_hint; |
| 3879 | const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3880 | const ideal_size = self.header_pad + program_code_size_hint + got_size_hint; |
| 3881 | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 3882 | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| 3883 | break :blk needed_size; |
| 3884 | } else 0; |
| 3740 | 3885 | try self.load_commands.append(self.base.allocator, .{ |
| 3741 | 3886 | .Segment = .{ |
| 3742 | 3887 | .inner = .{ |
| ... | ... | @@ -3753,13 +3898,13 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3753 | 3898 | } |
| 3754 | 3899 | |
| 3755 | 3900 | if (self.text_section_index == null) { |
| 3756 | | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3901 | const alignment: u2 = switch (cpu_arch) { |
| 3757 | 3902 | .x86_64 => 0, |
| 3758 | 3903 | .aarch64 => 2, |
| 3759 | 3904 | else => unreachable, // unhandled architecture type |
| 3760 | 3905 | }; |
| 3761 | | const needed_size = self.base.options.program_code_size_hint; |
| 3762 | | self.text_section_index = try self.allocateSection( |
| 3906 | const needed_size = if (self.needs_prealloc) self.base.options.program_code_size_hint else 0; |
| 3907 | self.text_section_index = try self.initSection( |
| 3763 | 3908 | self.text_segment_cmd_index.?, |
| 3764 | 3909 | "__text", |
| 3765 | 3910 | needed_size, |
| ... | ... | @@ -3771,18 +3916,18 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3771 | 3916 | } |
| 3772 | 3917 | |
| 3773 | 3918 | if (self.stubs_section_index == null) { |
| 3774 | | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3919 | const alignment: u2 = switch (cpu_arch) { |
| 3775 | 3920 | .x86_64 => 0, |
| 3776 | 3921 | .aarch64 => 2, |
| 3777 | 3922 | else => unreachable, // unhandled architecture type |
| 3778 | 3923 | }; |
| 3779 | | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { |
| 3924 | const stub_size: u4 = switch (cpu_arch) { |
| 3780 | 3925 | .x86_64 => 6, |
| 3781 | 3926 | .aarch64 => 3 * @sizeOf(u32), |
| 3782 | 3927 | else => unreachable, // unhandled architecture type |
| 3783 | 3928 | }; |
| 3784 | | const needed_size = stub_size * self.base.options.symbol_count_hint; |
| 3785 | | self.stubs_section_index = try self.allocateSection( |
| 3929 | const needed_size = if (self.needs_prealloc) stub_size * self.base.options.symbol_count_hint else 0; |
| 3930 | self.stubs_section_index = try self.initSection( |
| 3786 | 3931 | self.text_segment_cmd_index.?, |
| 3787 | 3932 | "__stubs", |
| 3788 | 3933 | needed_size, |
| ... | ... | @@ -3795,23 +3940,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3795 | 3940 | } |
| 3796 | 3941 | |
| 3797 | 3942 | if (self.stub_helper_section_index == null) { |
| 3798 | | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3943 | const alignment: u2 = switch (cpu_arch) { |
| 3799 | 3944 | .x86_64 => 0, |
| 3800 | 3945 | .aarch64 => 2, |
| 3801 | 3946 | else => unreachable, // unhandled architecture type |
| 3802 | 3947 | }; |
| 3803 | | const preamble_size: u6 = switch (self.base.options.target.cpu.arch) { |
| 3948 | const preamble_size: u6 = switch (cpu_arch) { |
| 3804 | 3949 | .x86_64 => 15, |
| 3805 | 3950 | .aarch64 => 6 * @sizeOf(u32), |
| 3806 | 3951 | else => unreachable, |
| 3807 | 3952 | }; |
| 3808 | | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { |
| 3953 | const stub_size: u4 = switch (cpu_arch) { |
| 3809 | 3954 | .x86_64 => 10, |
| 3810 | 3955 | .aarch64 => 3 * @sizeOf(u32), |
| 3811 | 3956 | else => unreachable, |
| 3812 | 3957 | }; |
| 3813 | | const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size; |
| 3814 | | self.stub_helper_section_index = try self.allocateSection( |
| 3958 | const needed_size = if (self.needs_prealloc) |
| 3959 | stub_size * self.base.options.symbol_count_hint + preamble_size |
| 3960 | else |
| 3961 | 0; |
| 3962 | self.stub_helper_section_index = try self.initSection( |
| 3815 | 3963 | self.text_segment_cmd_index.?, |
| 3816 | 3964 | "__stub_helper", |
| 3817 | 3965 | needed_size, |
| ... | ... | @@ -3824,22 +3972,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3824 | 3972 | |
| 3825 | 3973 | if (self.data_const_segment_cmd_index == null) { |
| 3826 | 3974 | self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3827 | | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3828 | | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3829 | | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 3830 | | |
| 3831 | | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ |
| 3832 | | address_and_offset.offset, |
| 3833 | | address_and_offset.offset + needed_size, |
| 3834 | | }); |
| 3835 | | |
| 3975 | var vmaddr: u64 = 0; |
| 3976 | var fileoff: u64 = 0; |
| 3977 | var needed_size: u64 = 0; |
| 3978 | if (self.needs_prealloc) { |
| 3979 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3980 | vmaddr = address_and_offset.address; |
| 3981 | fileoff = address_and_offset.offset; |
| 3982 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3983 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 3984 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ |
| 3985 | fileoff, |
| 3986 | fileoff + needed_size, |
| 3987 | }); |
| 3988 | } |
| 3836 | 3989 | try self.load_commands.append(self.base.allocator, .{ |
| 3837 | 3990 | .Segment = .{ |
| 3838 | 3991 | .inner = .{ |
| 3839 | 3992 | .segname = makeStaticString("__DATA_CONST"), |
| 3840 | | .vmaddr = address_and_offset.address, |
| 3993 | .vmaddr = vmaddr, |
| 3841 | 3994 | .vmsize = needed_size, |
| 3842 | | .fileoff = address_and_offset.offset, |
| 3995 | .fileoff = fileoff, |
| 3843 | 3996 | .filesize = needed_size, |
| 3844 | 3997 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 3845 | 3998 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| ... | ... | @@ -3850,9 +4003,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3850 | 4003 | } |
| 3851 | 4004 | |
| 3852 | 4005 | if (self.got_section_index == null) { |
| 3853 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4006 | const needed_size = if (self.needs_prealloc) |
| 4007 | @sizeOf(u64) * self.base.options.symbol_count_hint |
| 4008 | else |
| 4009 | 0; |
| 3854 | 4010 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3855 | | self.got_section_index = try self.allocateSection( |
| 4011 | self.got_section_index = try self.initSection( |
| 3856 | 4012 | self.data_const_segment_cmd_index.?, |
| 3857 | 4013 | "__got", |
| 3858 | 4014 | needed_size, |
| ... | ... | @@ -3865,19 +4021,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3865 | 4021 | |
| 3866 | 4022 | if (self.data_segment_cmd_index == null) { |
| 3867 | 4023 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3868 | | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3869 | | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3870 | | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 3871 | | |
| 3872 | | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| 3873 | | |
| 4024 | var vmaddr: u64 = 0; |
| 4025 | var fileoff: u64 = 0; |
| 4026 | var needed_size: u64 = 0; |
| 4027 | if (self.needs_prealloc) { |
| 4028 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 4029 | vmaddr = address_and_offset.address; |
| 4030 | fileoff = address_and_offset.offset; |
| 4031 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4032 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 4033 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ |
| 4034 | fileoff, |
| 4035 | fileoff + needed_size, |
| 4036 | }); |
| 4037 | } |
| 3874 | 4038 | try self.load_commands.append(self.base.allocator, .{ |
| 3875 | 4039 | .Segment = .{ |
| 3876 | 4040 | .inner = .{ |
| 3877 | 4041 | .segname = makeStaticString("__DATA"), |
| 3878 | | .vmaddr = address_and_offset.address, |
| 4042 | .vmaddr = vmaddr, |
| 3879 | 4043 | .vmsize = needed_size, |
| 3880 | | .fileoff = address_and_offset.offset, |
| 4044 | .fileoff = fileoff, |
| 3881 | 4045 | .filesize = needed_size, |
| 3882 | 4046 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 3883 | 4047 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| ... | ... | @@ -3888,9 +4052,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3888 | 4052 | } |
| 3889 | 4053 | |
| 3890 | 4054 | if (self.la_symbol_ptr_section_index == null) { |
| 3891 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4055 | const needed_size = if (self.needs_prealloc) |
| 4056 | @sizeOf(u64) * self.base.options.symbol_count_hint |
| 4057 | else |
| 4058 | 0; |
| 3892 | 4059 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3893 | | self.la_symbol_ptr_section_index = try self.allocateSection( |
| 4060 | self.la_symbol_ptr_section_index = try self.initSection( |
| 3894 | 4061 | self.data_segment_cmd_index.?, |
| 3895 | 4062 | "__la_symbol_ptr", |
| 3896 | 4063 | needed_size, |
| ... | ... | @@ -3902,9 +4069,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3902 | 4069 | } |
| 3903 | 4070 | |
| 3904 | 4071 | if (self.data_section_index == null) { |
| 3905 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4072 | const needed_size = if (self.needs_prealloc) @sizeOf(u64) * self.base.options.symbol_count_hint else 0; |
| 3906 | 4073 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3907 | | self.data_section_index = try self.allocateSection( |
| 4074 | self.data_section_index = try self.initSection( |
| 3908 | 4075 | self.data_segment_cmd_index.?, |
| 3909 | 4076 | "__data", |
| 3910 | 4077 | needed_size, |
| ... | ... | @@ -3914,9 +4081,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3914 | 4081 | } |
| 3915 | 4082 | |
| 3916 | 4083 | if (self.tlv_section_index == null) { |
| 3917 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4084 | const needed_size = if (self.needs_prealloc) @sizeOf(u64) * self.base.options.symbol_count_hint else 0; |
| 3918 | 4085 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3919 | | self.tlv_section_index = try self.allocateSection( |
| 4086 | self.tlv_section_index = try self.initSection( |
| 3920 | 4087 | self.data_segment_cmd_index.?, |
| 3921 | 4088 | "__thread_vars", |
| 3922 | 4089 | needed_size, |
| ... | ... | @@ -3928,9 +4095,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3928 | 4095 | } |
| 3929 | 4096 | |
| 3930 | 4097 | if (self.tlv_data_section_index == null) { |
| 3931 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4098 | const needed_size = if (self.needs_prealloc) @sizeOf(u64) * self.base.options.symbol_count_hint else 0; |
| 3932 | 4099 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3933 | | self.tlv_data_section_index = try self.allocateSection( |
| 4100 | self.tlv_data_section_index = try self.initSection( |
| 3934 | 4101 | self.data_segment_cmd_index.?, |
| 3935 | 4102 | "__thread_data", |
| 3936 | 4103 | needed_size, |
| ... | ... | @@ -3942,9 +4109,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3942 | 4109 | } |
| 3943 | 4110 | |
| 3944 | 4111 | if (self.tlv_bss_section_index == null) { |
| 3945 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4112 | const needed_size = if (self.needs_prealloc) @sizeOf(u64) * self.base.options.symbol_count_hint else 0; |
| 3946 | 4113 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3947 | | self.tlv_bss_section_index = try self.allocateSection( |
| 4114 | self.tlv_bss_section_index = try self.initSection( |
| 3948 | 4115 | self.data_segment_cmd_index.?, |
| 3949 | 4116 | "__thread_bss", |
| 3950 | 4117 | needed_size, |
| ... | ... | @@ -3959,9 +4126,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3959 | 4126 | } |
| 3960 | 4127 | |
| 3961 | 4128 | if (self.bss_section_index == null) { |
| 3962 | | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4129 | const needed_size = if (self.needs_prealloc) @sizeOf(u64) * self.base.options.symbol_count_hint else 0; |
| 3963 | 4130 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3964 | | self.bss_section_index = try self.allocateSection( |
| 4131 | self.bss_section_index = try self.initSection( |
| 3965 | 4132 | self.data_segment_cmd_index.?, |
| 3966 | 4133 | "__bss", |
| 3967 | 4134 | needed_size, |
| ... | ... | @@ -3977,16 +4144,20 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3977 | 4144 | |
| 3978 | 4145 | if (self.linkedit_segment_cmd_index == null) { |
| 3979 | 4146 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3980 | | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3981 | | |
| 3982 | | log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset}); |
| 3983 | | |
| 4147 | var vmaddr: u64 = 0; |
| 4148 | var fileoff: u64 = 0; |
| 4149 | if (self.needs_prealloc) { |
| 4150 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 4151 | vmaddr = address_and_offset.address; |
| 4152 | fileoff = address_and_offset.offset; |
| 4153 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff}); |
| 4154 | } |
| 3984 | 4155 | try self.load_commands.append(self.base.allocator, .{ |
| 3985 | 4156 | .Segment = .{ |
| 3986 | 4157 | .inner = .{ |
| 3987 | 4158 | .segname = makeStaticString("__LINKEDIT"), |
| 3988 | | .vmaddr = address_and_offset.address, |
| 3989 | | .fileoff = address_and_offset.offset, |
| 4159 | .vmaddr = vmaddr, |
| 4160 | .fileoff = fileoff, |
| 3990 | 4161 | .maxprot = macho.VM_PROT_READ, |
| 3991 | 4162 | .initprot = macho.VM_PROT_READ, |
| 3992 | 4163 | }, |
| ... | ... | @@ -4198,44 +4369,123 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4198 | 4369 | self.cold_start = true; |
| 4199 | 4370 | } |
| 4200 | 4371 | |
| 4201 | | const AllocateSectionOpts = struct { |
| 4372 | fn allocateTextSegment(self: *MachO) !void { |
| 4373 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 4374 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; |
| 4375 | seg.inner.fileoff = 0; |
| 4376 | seg.inner.vmaddr = base_vmaddr; |
| 4377 | |
| 4378 | var sizeofcmds: u64 = 0; |
| 4379 | for (self.load_commands.items) |lc| { |
| 4380 | sizeofcmds += lc.cmdsize(); |
| 4381 | } |
| 4382 | |
| 4383 | try self.allocateSegment(self.text_segment_cmd_index.?, @sizeOf(macho.mach_header_64) + sizeofcmds); |
| 4384 | |
| 4385 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. |
| 4386 | var min_alignment: u32 = 0; |
| 4387 | for (seg.sections.items) |sect| { |
| 4388 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| 4389 | min_alignment = math.max(min_alignment, alignment); |
| 4390 | } |
| 4391 | |
| 4392 | assert(min_alignment > 0); |
| 4393 | const last_sect_idx = seg.sections.items.len - 1; |
| 4394 | const last_sect = seg.sections.items[last_sect_idx]; |
| 4395 | const shift: u32 = blk: { |
| 4396 | const diff = seg.inner.filesize - last_sect.offset - last_sect.size; |
| 4397 | const factor = @divTrunc(diff, min_alignment); |
| 4398 | break :blk @intCast(u32, factor * min_alignment); |
| 4399 | }; |
| 4400 | |
| 4401 | if (shift > 0) { |
| 4402 | for (seg.sections.items) |*sect| { |
| 4403 | sect.offset += shift; |
| 4404 | sect.addr += shift; |
| 4405 | } |
| 4406 | } |
| 4407 | } |
| 4408 | |
| 4409 | fn allocateDataConstSegment(self: *MachO) !void { |
| 4410 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 4411 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 4412 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| 4413 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; |
| 4414 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); |
| 4415 | } |
| 4416 | |
| 4417 | fn allocateDataSegment(self: *MachO) !void { |
| 4418 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4419 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 4420 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; |
| 4421 | seg.inner.vmaddr = data_const_seg.inner.vmaddr + data_const_seg.inner.vmsize; |
| 4422 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); |
| 4423 | } |
| 4424 | |
| 4425 | fn allocateLinkeditSegment(self: *MachO) void { |
| 4426 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 4427 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4428 | seg.inner.fileoff = data_seg.inner.fileoff + data_seg.inner.filesize; |
| 4429 | seg.inner.vmaddr = data_seg.inner.vmaddr + data_seg.inner.vmsize; |
| 4430 | } |
| 4431 | |
| 4432 | fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { |
| 4433 | const seg = &self.load_commands.items[index].Segment; |
| 4434 | |
| 4435 | // Allocate the sections according to their alignment at the beginning of the segment. |
| 4436 | var start: u64 = offset; |
| 4437 | for (seg.sections.items) |*sect| { |
| 4438 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| 4439 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); |
| 4440 | const end = start_aligned + sect.size; |
| 4441 | sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned); |
| 4442 | sect.addr = seg.inner.vmaddr + start_aligned; |
| 4443 | start = end; |
| 4444 | } |
| 4445 | |
| 4446 | const seg_size_aligned = mem.alignForwardGeneric(u64, start, self.page_size); |
| 4447 | seg.inner.filesize = seg_size_aligned; |
| 4448 | seg.inner.vmsize = seg_size_aligned; |
| 4449 | } |
| 4450 | |
| 4451 | const InitSectionOpts = struct { |
| 4202 | 4452 | flags: u32 = macho.S_REGULAR, |
| 4203 | 4453 | reserved1: u32 = 0, |
| 4204 | 4454 | reserved2: u32 = 0, |
| 4205 | 4455 | }; |
| 4206 | 4456 | |
| 4207 | | fn allocateSection( |
| 4457 | fn initSection( |
| 4208 | 4458 | self: *MachO, |
| 4209 | 4459 | segment_id: u16, |
| 4210 | 4460 | sectname: []const u8, |
| 4211 | 4461 | size: u64, |
| 4212 | 4462 | alignment: u32, |
| 4213 | | opts: AllocateSectionOpts, |
| 4463 | opts: InitSectionOpts, |
| 4214 | 4464 | ) !u16 { |
| 4215 | 4465 | const seg = &self.load_commands.items[segment_id].Segment; |
| 4216 | 4466 | var sect = macho.section_64{ |
| 4217 | 4467 | .sectname = makeStaticString(sectname), |
| 4218 | 4468 | .segname = seg.inner.segname, |
| 4219 | | .size = @intCast(u32, size), |
| 4469 | .size = if (self.needs_prealloc) @intCast(u32, size) else 0, |
| 4220 | 4470 | .@"align" = alignment, |
| 4221 | 4471 | .flags = opts.flags, |
| 4222 | 4472 | .reserved1 = opts.reserved1, |
| 4223 | 4473 | .reserved2 = opts.reserved2, |
| 4224 | 4474 | }; |
| 4225 | 4475 | |
| 4226 | | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4227 | | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4228 | | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); |
| 4229 | | |
| 4230 | | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ |
| 4231 | | commands.segmentName(sect), |
| 4232 | | commands.sectionName(sect), |
| 4233 | | off, |
| 4234 | | off + size, |
| 4235 | | }); |
| 4236 | | |
| 4237 | | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| 4238 | | sect.offset = @intCast(u32, off); |
| 4476 | if (self.needs_prealloc) { |
| 4477 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4478 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4479 | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); |
| 4480 | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ |
| 4481 | commands.segmentName(sect), |
| 4482 | commands.sectionName(sect), |
| 4483 | off, |
| 4484 | off + size, |
| 4485 | }); |
| 4486 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| 4487 | sect.offset = @intCast(u32, off); |
| 4488 | } |
| 4239 | 4489 | |
| 4240 | 4490 | const index = @intCast(u16, seg.sections.items.len); |
| 4241 | 4491 | try seg.sections.append(self.base.allocator, sect); |
| ... | ... | @@ -4270,7 +4520,11 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { |
| 4270 | 4520 | const new_seg_size = mem.alignForwardGeneric(u64, new_size, self.page_size); |
| 4271 | 4521 | assert(new_seg_size > seg.inner.filesize); |
| 4272 | 4522 | const offset_amt = new_seg_size - seg.inner.filesize; |
| 4273 | | log.debug("growing segment {s} from 0x{x} to 0x{x}", .{ seg.inner.segname, seg.inner.filesize, new_seg_size }); |
| 4523 | log.debug("growing segment {s} from 0x{x} to 0x{x}", .{ |
| 4524 | seg.inner.segname, |
| 4525 | seg.inner.filesize, |
| 4526 | new_seg_size, |
| 4527 | }); |
| 4274 | 4528 | seg.inner.filesize = new_seg_size; |
| 4275 | 4529 | seg.inner.vmsize = new_seg_size; |
| 4276 | 4530 | |
| ... | ... | @@ -4534,6 +4788,21 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m |
| 4534 | 4788 | return vaddr; |
| 4535 | 4789 | } |
| 4536 | 4790 | |
| 4791 | fn addAtomAndBumpSectionSize(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 4792 | const seg = &self.load_commands.items[match.seg].Segment; |
| 4793 | const sect = &seg.sections.items[match.sect]; |
| 4794 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 4795 | sect.size = mem.alignForwardGeneric(u64, sect.size, alignment) + atom.size; |
| 4796 | |
| 4797 | if (self.atoms.getPtr(match)) |last| { |
| 4798 | last.*.next = atom; |
| 4799 | atom.prev = last.*; |
| 4800 | last.* = atom; |
| 4801 | } else { |
| 4802 | try self.atoms.putNoClobber(self.base.allocator, match, atom); |
| 4803 | } |
| 4804 | } |
| 4805 | |
| 4537 | 4806 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4538 | 4807 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); |
| 4539 | 4808 | defer self.base.allocator.free(sym_name); |