authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-04 13:53:57+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-05 22:46:46+01:00
logc86f2402d077077489154a14af73ff5616722036
tree03ad1942f65c292ee2469f143ffd6fc52a3dce60
parent9e03cf948948ea25feb3f413f234e98e71d55786

macho: don't prealloc sections when stage1


3 files changed, 461 insertions(+), 189 deletions(-)

src/link/MachO.zig+456-187
...@@ -63,6 +63,11 @@ page_size: u16,...@@ -63,6 +63,11 @@ page_size: u16,
63/// https://github.com/ziglang/zig/issues/956763/// https://github.com/ziglang/zig/issues/9567
64requires_adhoc_codesig: bool,64requires_adhoc_codesig: bool,
6565
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.
69needs_prealloc: bool = true,
70
66/// We commit 0x1000 = 4096 bytes of space to the header and71/// We commit 0x1000 = 4096 bytes of space to the header and
67/// the table of load commands. This should be plenty for any72/// the table of load commands. This should be plenty for any
68/// potential future extensions.73/// potential future extensions.
...@@ -375,6 +380,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -375,6 +380,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
375 // Adhoc code signature is required when targeting aarch64-macos either directly or indirectly via the simulator380 // Adhoc code signature is required when targeting aarch64-macos either directly or indirectly via the simulator
376 // ABI such as aarch64-ios-simulator, etc.381 // ABI such as aarch64-ios-simulator, etc.
377 const requires_adhoc_codesig = cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator);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);
378384
379 self.* = .{385 self.* = .{
380 .base = .{386 .base = .{
...@@ -385,6 +391,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {...@@ -385,6 +391,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*MachO {
385 },391 },
386 .page_size = page_size,392 .page_size = page_size,
387 .requires_adhoc_codesig = requires_adhoc_codesig,393 .requires_adhoc_codesig = requires_adhoc_codesig,
394 .needs_prealloc = needs_prealloc,
388 };395 };
389396
390 return self;397 return self;
...@@ -911,6 +918,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -911,6 +918,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
911918
912 try self.createTentativeDefAtoms();919 try self.createTentativeDefAtoms();
913 try self.parseObjectsIntoAtoms();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 try self.allocateGlobalSymbols();930 try self.allocateGlobalSymbols();
915931
916 log.debug("locals:", .{});932 log.debug("locals:", .{});
...@@ -946,6 +962,18 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -946,6 +962,18 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
946 log.debug(" {} => {s}", .{ key, self.getString(key) });962 log.debug(" {} => {s}", .{ key, self.getString(key) });
947 }963 }
948964
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 try self.writeAtoms();977 try self.writeAtoms();
950978
951 if (self.bss_section_index) |idx| {979 if (self.bss_section_index) |idx| {
...@@ -1337,7 +1365,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1337,7 +1365,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1337 switch (commands.sectionType(sect)) {1365 switch (commands.sectionType(sect)) {
1338 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {1366 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
1339 if (self.text_const_section_index == null) {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 self.text_segment_cmd_index.?,1369 self.text_segment_cmd_index.?,
1342 "__const",1370 "__const",
1343 sect.size,1371 sect.size,
...@@ -1356,7 +1384,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1356,7 +1384,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1356 // TODO it seems the common values within the sections in objects are deduplicated/merged1384 // TODO it seems the common values within the sections in objects are deduplicated/merged
1357 // on merging the sections' contents.1385 // on merging the sections' contents.
1358 if (self.objc_methname_section_index == null) {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 self.text_segment_cmd_index.?,1388 self.text_segment_cmd_index.?,
1361 "__objc_methname",1389 "__objc_methname",
1362 sect.size,1390 sect.size,
...@@ -1371,7 +1399,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1371,7 +1399,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1371 };1399 };
1372 } else if (mem.eql(u8, sectname, "__objc_methtype")) {1400 } else if (mem.eql(u8, sectname, "__objc_methtype")) {
1373 if (self.objc_methtype_section_index == null) {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 self.text_segment_cmd_index.?,1403 self.text_segment_cmd_index.?,
1376 "__objc_methtype",1404 "__objc_methtype",
1377 sect.size,1405 sect.size,
...@@ -1386,7 +1414,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1386,7 +1414,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1386 };1414 };
1387 } else if (mem.eql(u8, sectname, "__objc_classname")) {1415 } else if (mem.eql(u8, sectname, "__objc_classname")) {
1388 if (self.objc_classname_section_index == null) {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 self.text_segment_cmd_index.?,1418 self.text_segment_cmd_index.?,
1391 "__objc_classname",1419 "__objc_classname",
1392 sect.size,1420 sect.size,
...@@ -1402,7 +1430,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1402,7 +1430,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1402 }1430 }
14031431
1404 if (self.cstring_section_index == null) {1432 if (self.cstring_section_index == null) {
1405 self.cstring_section_index = try self.allocateSection(1433 self.cstring_section_index = try self.initSection(
1406 self.text_segment_cmd_index.?,1434 self.text_segment_cmd_index.?,
1407 "__cstring",1435 "__cstring",
1408 sect.size,1436 sect.size,
...@@ -1421,7 +1449,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1421,7 +1449,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1421 macho.S_LITERAL_POINTERS => {1449 macho.S_LITERAL_POINTERS => {
1422 if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) {1450 if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) {
1423 if (self.objc_selrefs_section_index == null) {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 self.data_segment_cmd_index.?,1453 self.data_segment_cmd_index.?,
1426 "__objc_selrefs",1454 "__objc_selrefs",
1427 sect.size,1455 sect.size,
...@@ -1443,7 +1471,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1443,7 +1471,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1443 },1471 },
1444 macho.S_MOD_INIT_FUNC_POINTERS => {1472 macho.S_MOD_INIT_FUNC_POINTERS => {
1445 if (self.mod_init_func_section_index == null) {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 self.data_const_segment_cmd_index.?,1475 self.data_const_segment_cmd_index.?,
1448 "__mod_init_func",1476 "__mod_init_func",
1449 sect.size,1477 sect.size,
...@@ -1461,7 +1489,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1461,7 +1489,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1461 },1489 },
1462 macho.S_MOD_TERM_FUNC_POINTERS => {1490 macho.S_MOD_TERM_FUNC_POINTERS => {
1463 if (self.mod_term_func_section_index == null) {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 self.data_const_segment_cmd_index.?,1493 self.data_const_segment_cmd_index.?,
1466 "__mod_term_func",1494 "__mod_term_func",
1467 sect.size,1495 sect.size,
...@@ -1479,7 +1507,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1479,7 +1507,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1479 },1507 },
1480 macho.S_ZEROFILL => {1508 macho.S_ZEROFILL => {
1481 if (self.bss_section_index == null) {1509 if (self.bss_section_index == null) {
1482 self.bss_section_index = try self.allocateSection(1510 self.bss_section_index = try self.initSection(
1483 self.data_segment_cmd_index.?,1511 self.data_segment_cmd_index.?,
1484 "__bss",1512 "__bss",
1485 sect.size,1513 sect.size,
...@@ -1497,7 +1525,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1497,7 +1525,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1497 },1525 },
1498 macho.S_THREAD_LOCAL_VARIABLES => {1526 macho.S_THREAD_LOCAL_VARIABLES => {
1499 if (self.tlv_section_index == null) {1527 if (self.tlv_section_index == null) {
1500 self.tlv_section_index = try self.allocateSection(1528 self.tlv_section_index = try self.initSection(
1501 self.data_segment_cmd_index.?,1529 self.data_segment_cmd_index.?,
1502 "__thread_vars",1530 "__thread_vars",
1503 sect.size,1531 sect.size,
...@@ -1515,7 +1543,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1515,7 +1543,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1515 },1543 },
1516 macho.S_THREAD_LOCAL_REGULAR => {1544 macho.S_THREAD_LOCAL_REGULAR => {
1517 if (self.tlv_data_section_index == null) {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 self.data_segment_cmd_index.?,1547 self.data_segment_cmd_index.?,
1520 "__thread_data",1548 "__thread_data",
1521 sect.size,1549 sect.size,
...@@ -1533,7 +1561,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1533,7 +1561,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1533 },1561 },
1534 macho.S_THREAD_LOCAL_ZEROFILL => {1562 macho.S_THREAD_LOCAL_ZEROFILL => {
1535 if (self.tlv_bss_section_index == null) {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 self.data_segment_cmd_index.?,1565 self.data_segment_cmd_index.?,
1538 "__thread_bss",1566 "__thread_bss",
1539 sect.size,1567 sect.size,
...@@ -1554,7 +1582,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1554,7 +1582,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1554 // TODO I believe __eh_frame is currently part of __unwind_info section1582 // TODO I believe __eh_frame is currently part of __unwind_info section
1555 // in the latest ld64 output.1583 // in the latest ld64 output.
1556 if (self.eh_frame_section_index == null) {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 self.text_segment_cmd_index.?,1586 self.text_segment_cmd_index.?,
1559 "__eh_frame",1587 "__eh_frame",
1560 sect.size,1588 sect.size,
...@@ -1571,7 +1599,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1571,7 +1599,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
15711599
1572 // TODO audit this: is this the right mapping?1600 // TODO audit this: is this the right mapping?
1573 if (self.data_const_section_index == null) {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 self.data_const_segment_cmd_index.?,1603 self.data_const_segment_cmd_index.?,
1576 "__const",1604 "__const",
1577 sect.size,1605 sect.size,
...@@ -1588,7 +1616,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1588,7 +1616,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1588 macho.S_REGULAR => {1616 macho.S_REGULAR => {
1589 if (commands.sectionIsCode(sect)) {1617 if (commands.sectionIsCode(sect)) {
1590 if (self.text_section_index == null) {1618 if (self.text_section_index == null) {
1591 self.text_section_index = try self.allocateSection(1619 self.text_section_index = try self.initSection(
1592 self.text_segment_cmd_index.?,1620 self.text_segment_cmd_index.?,
1593 "__text",1621 "__text",
1594 sect.size,1622 sect.size,
...@@ -1619,7 +1647,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1619,7 +1647,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1619 if (mem.eql(u8, segname, "__TEXT")) {1647 if (mem.eql(u8, segname, "__TEXT")) {
1620 if (mem.eql(u8, sectname, "__ustring")) {1648 if (mem.eql(u8, sectname, "__ustring")) {
1621 if (self.ustring_section_index == null) {1649 if (self.ustring_section_index == null) {
1622 self.ustring_section_index = try self.allocateSection(1650 self.ustring_section_index = try self.initSection(
1623 self.text_segment_cmd_index.?,1651 self.text_segment_cmd_index.?,
1624 "__ustring",1652 "__ustring",
1625 sect.size,1653 sect.size,
...@@ -1634,7 +1662,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1634,7 +1662,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1634 };1662 };
1635 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {1663 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
1636 if (self.gcc_except_tab_section_index == null) {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 self.text_segment_cmd_index.?,1666 self.text_segment_cmd_index.?,
1639 "__gcc_except_tab",1667 "__gcc_except_tab",
1640 sect.size,1668 sect.size,
...@@ -1649,7 +1677,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1649,7 +1677,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1649 };1677 };
1650 } else if (mem.eql(u8, sectname, "__objc_methlist")) {1678 } else if (mem.eql(u8, sectname, "__objc_methlist")) {
1651 if (self.objc_methlist_section_index == null) {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 self.text_segment_cmd_index.?,1681 self.text_segment_cmd_index.?,
1654 "__objc_methlist",1682 "__objc_methlist",
1655 sect.size,1683 sect.size,
...@@ -1669,7 +1697,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1669,7 +1697,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1669 mem.eql(u8, sectname, "__gopclntab"))1697 mem.eql(u8, sectname, "__gopclntab"))
1670 {1698 {
1671 if (self.data_const_section_index == null) {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 self.data_const_segment_cmd_index.?,1701 self.data_const_segment_cmd_index.?,
1674 "__const",1702 "__const",
1675 sect.size,1703 sect.size,
...@@ -1684,7 +1712,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1684,7 +1712,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1684 };1712 };
1685 } else {1713 } else {
1686 if (self.text_const_section_index == null) {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 self.text_segment_cmd_index.?,1716 self.text_segment_cmd_index.?,
1689 "__const",1717 "__const",
1690 sect.size,1718 sect.size,
...@@ -1702,7 +1730,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1702,7 +1730,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
17021730
1703 if (mem.eql(u8, segname, "__DATA_CONST")) {1731 if (mem.eql(u8, segname, "__DATA_CONST")) {
1704 if (self.data_const_section_index == null) {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 self.data_const_segment_cmd_index.?,1734 self.data_const_segment_cmd_index.?,
1707 "__const",1735 "__const",
1708 sect.size,1736 sect.size,
...@@ -1720,7 +1748,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1720,7 +1748,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1720 if (mem.eql(u8, segname, "__DATA")) {1748 if (mem.eql(u8, segname, "__DATA")) {
1721 if (mem.eql(u8, sectname, "__const")) {1749 if (mem.eql(u8, sectname, "__const")) {
1722 if (self.data_const_section_index == null) {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 self.data_const_segment_cmd_index.?,1752 self.data_const_segment_cmd_index.?,
1725 "__const",1753 "__const",
1726 sect.size,1754 sect.size,
...@@ -1735,7 +1763,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1735,7 +1763,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1735 };1763 };
1736 } else if (mem.eql(u8, sectname, "__cfstring")) {1764 } else if (mem.eql(u8, sectname, "__cfstring")) {
1737 if (self.objc_cfstring_section_index == null) {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 self.data_const_segment_cmd_index.?,1767 self.data_const_segment_cmd_index.?,
1740 "__cfstring",1768 "__cfstring",
1741 sect.size,1769 sect.size,
...@@ -1750,7 +1778,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1750,7 +1778,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1750 };1778 };
1751 } else if (mem.eql(u8, sectname, "__objc_classlist")) {1779 } else if (mem.eql(u8, sectname, "__objc_classlist")) {
1752 if (self.objc_classlist_section_index == null) {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 self.data_const_segment_cmd_index.?,1782 self.data_const_segment_cmd_index.?,
1755 "__objc_classlist",1783 "__objc_classlist",
1756 sect.size,1784 sect.size,
...@@ -1765,7 +1793,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1765,7 +1793,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1765 };1793 };
1766 } else if (mem.eql(u8, sectname, "__objc_imageinfo")) {1794 } else if (mem.eql(u8, sectname, "__objc_imageinfo")) {
1767 if (self.objc_imageinfo_section_index == null) {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 self.data_const_segment_cmd_index.?,1797 self.data_const_segment_cmd_index.?,
1770 "__objc_imageinfo",1798 "__objc_imageinfo",
1771 sect.size,1799 sect.size,
...@@ -1780,7 +1808,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1780,7 +1808,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1780 };1808 };
1781 } else if (mem.eql(u8, sectname, "__objc_const")) {1809 } else if (mem.eql(u8, sectname, "__objc_const")) {
1782 if (self.objc_const_section_index == null) {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 self.data_segment_cmd_index.?,1812 self.data_segment_cmd_index.?,
1785 "__objc_const",1813 "__objc_const",
1786 sect.size,1814 sect.size,
...@@ -1795,7 +1823,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1795,7 +1823,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1795 };1823 };
1796 } else if (mem.eql(u8, sectname, "__objc_classrefs")) {1824 } else if (mem.eql(u8, sectname, "__objc_classrefs")) {
1797 if (self.objc_classrefs_section_index == null) {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 self.data_segment_cmd_index.?,1827 self.data_segment_cmd_index.?,
1800 "__objc_classrefs",1828 "__objc_classrefs",
1801 sect.size,1829 sect.size,
...@@ -1810,7 +1838,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1810,7 +1838,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1810 };1838 };
1811 } else if (mem.eql(u8, sectname, "__objc_data")) {1839 } else if (mem.eql(u8, sectname, "__objc_data")) {
1812 if (self.objc_data_section_index == null) {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 self.data_segment_cmd_index.?,1842 self.data_segment_cmd_index.?,
1815 "__objc_data",1843 "__objc_data",
1816 sect.size,1844 sect.size,
...@@ -1825,7 +1853,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1825,7 +1853,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1825 };1853 };
1826 } else {1854 } else {
1827 if (self.data_section_index == null) {1855 if (self.data_section_index == null) {
1828 self.data_section_index = try self.allocateSection(1856 self.data_section_index = try self.initSection(
1829 self.data_segment_cmd_index.?,1857 self.data_segment_cmd_index.?,
1830 "__data",1858 "__data",
1831 sect.size,1859 sect.size,
...@@ -1881,6 +1909,63 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void {...@@ -1881,6 +1909,63 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void {
1881 try self.base.file.?.pwriteAll(atom.code.items, file_offset);1909 try self.base.file.?.pwriteAll(atom.code.items, file_offset);
1882}1910}
18831911
1912fn 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
1884fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void {1969fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void {
1885 var atom = self.atoms.get(match) orelse return;1970 var atom = self.atoms.get(match) orelse return;
18861971
...@@ -1971,7 +2056,15 @@ fn writeAtoms(self: *MachO) !void {...@@ -1971,7 +2056,15 @@ fn writeAtoms(self: *MachO) !void {
1971 if (atom.next) |next| {2056 if (atom.next) |next| {
1972 atom = next;2057 atom = next;
1973 } else {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 if (file_offset) |off| {2066 if (file_offset) |off| {
2067 log.debug(" (writing at file offset 0x{x})", .{off});
1975 try self.base.file.?.pwriteAll(buffer.items, off);2068 try self.base.file.?.pwriteAll(buffer.items, off);
1976 }2069 }
1977 file_offset = null;2070 file_offset = null;
...@@ -2036,10 +2129,13 @@ fn createDyldPrivateAtom(self: *MachO) !void {...@@ -2036,10 +2129,13 @@ fn createDyldPrivateAtom(self: *MachO) !void {
2036 .seg = self.data_segment_cmd_index.?,2129 .seg = self.data_segment_cmd_index.?,
2037 .sect = self.data_section_index.?,2130 .sect = self.data_section_index.?,
2038 };2131 };
2039 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);2132 if (self.needs_prealloc) {
2040 sym.n_value = vaddr;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 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);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}
20442140
2045fn createStubHelperPreambleAtom(self: *MachO) !void {2141fn createStubHelperPreambleAtom(self: *MachO) !void {
...@@ -2165,11 +2261,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -2165,11 +2261,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
2165 .seg = self.text_segment_cmd_index.?,2261 .seg = self.text_segment_cmd_index.?,
2166 .sect = self.stub_helper_section_index.?,2262 .sect = self.stub_helper_section_index.?,
2167 };2263 };
2168 const alignment_pow_2 = try math.powi(u32, 2, atom.alignment);2264
2169 const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match);2265 if (self.needs_prealloc) {
2170 sym.n_value = vaddr;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 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);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}
21742274
2175pub fn createStubHelperAtom(self: *MachO) !*Atom {2275pub fn createStubHelperAtom(self: *MachO) !*Atom {
...@@ -2377,10 +2477,13 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2377,10 +2477,13 @@ fn createTentativeDefAtoms(self: *MachO) !void {
2377 resolv.local_sym_index = local_sym_index;2477 resolv.local_sym_index = local_sym_index;
23782478
2379 const atom = try self.createEmptyAtom(local_sym_index, size, alignment);2479 const atom = try self.createEmptyAtom(local_sym_index, size, alignment);
2380 const alignment_pow_2 = try math.powi(u32, 2, alignment);2480
2381 const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match);2481 if (self.needs_prealloc) {
2382 local_sym.n_value = vaddr;2482 const alignment_pow_2 = try math.powi(u32, 2, alignment);
2383 global_sym.n_value = vaddr;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}
23862489
...@@ -2429,9 +2532,12 @@ fn createDsoHandleAtom(self: *MachO) !void {...@@ -2429,9 +2532,12 @@ fn createDsoHandleAtom(self: *MachO) !void {
2429 // TODO perhaps we should special-case special symbols? Create a separate2532 // TODO perhaps we should special-case special symbols? Create a separate
2430 // linked list of atoms?2533 // linked list of atoms?
2431 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);2534 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);
2432 const sym = &self.locals.items[local_sym_index];2535 if (self.needs_prealloc) {
2433 const vaddr = try self.allocateAtom(atom, 0, 1, match);2536 const sym = &self.locals.items[local_sym_index];
2434 sym.n_value = vaddr;2537 const vaddr = try self.allocateAtom(atom, 0, 1, match);
2538 sym.n_value = vaddr;
2539 } else try self.addAtomAndBumpSectionSize(atom, match);
2540
2435 atom.dirty = false; // We don't really want to write it to file.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,9 +2877,13 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void {
2771 });2877 });
27722878
2773 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);2879 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);
2774 const sym = &self.locals.items[local_sym_index];2880
2775 const vaddr = try self.allocateAtom(atom, 0, 1, match);2881 if (self.needs_prealloc) {
2776 sym.n_value = vaddr;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 atom.dirty = false;2887 atom.dirty = false;
2778 self.mh_execute_header_index = local_sym_index;2888 self.mh_execute_header_index = local_sym_index;
2779}2889}
...@@ -2828,10 +2938,14 @@ fn resolveDyldStubBinder(self: *MachO) !void {...@@ -2828,10 +2938,14 @@ fn resolveDyldStubBinder(self: *MachO) !void {
2828 .sect = self.got_section_index.?,2938 .sect = self.got_section_index.?,
2829 };2939 };
2830 const atom_sym = &self.locals.items[atom.local_sym_index];2940 const atom_sym = &self.locals.items[atom.local_sym_index];
2831 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);2941
2832 atom_sym.n_value = vaddr;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 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);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}
28362950
2837fn parseObjectsIntoAtoms(self: *MachO) !void {2951fn parseObjectsIntoAtoms(self: *MachO) !void {
...@@ -2858,20 +2972,31 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {...@@ -2858,20 +2972,31 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
2858 var it = object.end_atoms.iterator();2972 var it = object.end_atoms.iterator();
2859 while (it.next()) |entry| {2973 while (it.next()) |entry| {
2860 const match = entry.key_ptr.*;2974 const match = entry.key_ptr.*;
2861 const last_atom = entry.value_ptr.*;2975 var atom = entry.value_ptr.*;
2862 var atom = last_atom;2976
2977 while (atom.prev) |prev| {
2978 atom = prev;
2979 }
28632980
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 const metadata = try section_metadata.getOrPut(match);2985 const metadata = try section_metadata.getOrPut(match);
2865 if (!metadata.found_existing) {2986 if (!metadata.found_existing) {
2866 metadata.value_ptr.* = .{2987 metadata.value_ptr.* = .{
2867 .size = 0,2988 .size = sect.size,
2868 .alignment = 0,2989 .alignment = sect.@"align",
2869 };2990 };
2870 }2991 }
28712992
2993 log.debug("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
2994
2872 while (true) {2995 while (true) {
2873 const alignment = try math.powi(u32, 2, atom.alignment);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 metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment);3000 metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment);
28763001
2877 const sym = self.locals.items[atom.local_sym_index];3002 const sym = self.locals.items[atom.local_sym_index];
...@@ -2882,20 +3007,20 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {...@@ -2882,20 +3007,20 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
2882 atom.alignment,3007 atom.alignment,
2883 });3008 });
28843009
2885 if (atom.prev) |prev| {3010 if (atom.next) |next| {
2886 atom = prev;3011 atom = next;
2887 } else break;3012 } else break;
2888 }3013 }
28893014
2890 if (parsed_atoms.getPtr(match)) |last| {3015 if (parsed_atoms.getPtr(match)) |last| {
2891 last.*.next = atom;3016 last.*.next = first_atom;
2892 atom.prev = last.*;3017 first_atom.prev = last.*;
2893 last.* = atom;3018 last.* = first_atom;
2894 }3019 }
2895 _ = try parsed_atoms.put(match, last_atom);3020 _ = try parsed_atoms.put(match, atom);
28963021
2897 if (!first_atoms.contains(match)) {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 }
29013026
...@@ -2915,67 +3040,84 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {...@@ -2915,67 +3040,84 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
2915 metadata.alignment,3040 metadata.alignment,
2916 });3041 });
29173042
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 sect.@"align" = math.max(sect.@"align", metadata.alignment);3043 sect.@"align" = math.max(sect.@"align", metadata.alignment);
2924 const needed_size = @intCast(u32, metadata.size + sect_size);3044 const needed_size = @intCast(u32, metadata.size);
2925 try self.growSection(match, needed_size);3045
3046 if (self.needs_prealloc) {
3047 try self.growSection(match, needed_size);
3048 }
2926 sect.size = needed_size;3049 sect.size = needed_size;
3050 }
29273051
2928 var base_vaddr = if (self.atoms.get(match)) |last| blk: {3052 for (&[_]?u16{
2929 const last_atom_sym = self.locals.items[last.local_sym_index];3053 self.text_segment_cmd_index,
2930 break :blk last_atom_sym.n_value + last.size;3054 self.data_const_segment_cmd_index,
2931 } else sect.addr;3055 self.data_segment_cmd_index,
2932 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);3056 }) |maybe_seg_id| {
3057 const seg_id = maybe_seg_id orelse continue;
3058 const seg = self.load_commands.items[seg_id].Segment;
29333059
2934 var atom = first_atoms.get(match).?;3060 for (seg.sections.items) |sect, sect_id| {
2935 while (true) {3061 const match = MatchingSection{
2936 const alignment = try math.powi(u32, 2, atom.alignment);3062 .seg = seg_id,
2937 base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment);3063 .sect = @intCast(u16, sect_id),
3064 };
3065 if (!section_metadata.contains(match)) continue;
29383066
2939 const sym = &self.locals.items[atom.local_sym_index];3067 if (self.atoms.getPtr(match)) |last| {
2940 sym.n_value = base_vaddr;3068 const first_atom = first_atoms.get(match).?;
2941 sym.n_sect = n_sect;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).?);
29423074
2943 log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{3075 if (!self.needs_prealloc) continue;
2944 self.getString(sym.n_strx),
2945 base_vaddr,
2946 base_vaddr + atom.size,
2947 atom.size,
2948 atom.alignment,
2949 });
29503076
2951 // Update each alias (if any)3077 var base_vaddr = if (self.atoms.get(match)) |last| blk: {
2952 for (atom.aliases.items) |index| {3078 const last_atom_sym = self.locals.items[last.local_sym_index];
2953 const alias_sym = &self.locals.items[index];3079 break :blk last_atom_sym.n_value + last.size;
2954 alias_sym.n_value = base_vaddr;3080 } else sect.addr;
2955 alias_sym.n_sect = n_sect;3081 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2956 }
29573082
2958 // Update each symbol contained within the atom3083 var atom = first_atoms.get(match).?;
2959 for (atom.contained.items) |sym_at_off| {3084 while (true) {
2960 const contained_sym = &self.locals.items[sym_at_off.local_sym_index];3085 const alignment = try math.powi(u32, 2, atom.alignment);
2961 contained_sym.n_value = base_vaddr + sym_at_off.offset;3086 base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment);
2962 contained_sym.n_sect = n_sect;
2963 }
29643087
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;
29663091
2967 if (atom.next) |next| {3092 log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{
2968 atom = next;3093 self.getString(sym.n_strx),
2969 } else break;3094 base_vaddr,
2970 }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 }
29713113
2972 if (self.atoms.getPtr(match)) |last| {3114 base_vaddr += atom.size;
2973 const first_atom = first_atoms.get(match).?;3115
2974 last.*.next = first_atom;3116 if (atom.next) |next| {
2975 first_atom.prev = last.*;3117 atom = next;
2976 last.* = first_atom;3118 } else break;
3119 }
2977 }3120 }
2978 _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?);
2979 }3121 }
2980}3122}
29813123
...@@ -3714,7 +3856,9 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {...@@ -3714,7 +3856,9 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {
3714 return self.locals.items[decl.link.macho.local_sym_index].n_value;3856 return self.locals.items[decl.link.macho.local_sym_index].n_value;
3715}3857}
37163858
3717pub fn populateMissingMetadata(self: *MachO) !void {3859fn populateMissingMetadata(self: *MachO) !void {
3860 const cpu_arch = self.base.options.target.cpu.arch;
3861
3718 if (self.pagezero_segment_cmd_index == null) {3862 if (self.pagezero_segment_cmd_index == null) {
3719 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);3863 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
3720 try self.load_commands.append(self.base.allocator, .{3864 try self.load_commands.append(self.base.allocator, .{
...@@ -3730,13 +3874,14 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3730,13 +3874,14 @@ pub fn populateMissingMetadata(self: *MachO) !void {
37303874
3731 if (self.text_segment_cmd_index == null) {3875 if (self.text_segment_cmd_index == null) {
3732 self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len);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;3877 const needed_size = if (self.needs_prealloc) blk: {
3734 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;3878 const program_code_size_hint = self.base.options.program_code_size_hint;
3735 const ideal_size = self.header_pad + program_code_size_hint + got_size_hint;3879 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;
3736 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);3880 const ideal_size = self.header_pad + program_code_size_hint + got_size_hint;
37373881 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3738 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });3882 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
37393883 break :blk needed_size;
3884 } else 0;
3740 try self.load_commands.append(self.base.allocator, .{3885 try self.load_commands.append(self.base.allocator, .{
3741 .Segment = .{3886 .Segment = .{
3742 .inner = .{3887 .inner = .{
...@@ -3753,13 +3898,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3753,13 +3898,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3753 }3898 }
37543899
3755 if (self.text_section_index == null) {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 .x86_64 => 0,3902 .x86_64 => 0,
3758 .aarch64 => 2,3903 .aarch64 => 2,
3759 else => unreachable, // unhandled architecture type3904 else => unreachable, // unhandled architecture type
3760 };3905 };
3761 const needed_size = self.base.options.program_code_size_hint;3906 const needed_size = if (self.needs_prealloc) self.base.options.program_code_size_hint else 0;
3762 self.text_section_index = try self.allocateSection(3907 self.text_section_index = try self.initSection(
3763 self.text_segment_cmd_index.?,3908 self.text_segment_cmd_index.?,
3764 "__text",3909 "__text",
3765 needed_size,3910 needed_size,
...@@ -3771,18 +3916,18 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3771,18 +3916,18 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3771 }3916 }
37723917
3773 if (self.stubs_section_index == null) {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 .x86_64 => 0,3920 .x86_64 => 0,
3776 .aarch64 => 2,3921 .aarch64 => 2,
3777 else => unreachable, // unhandled architecture type3922 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 .x86_64 => 6,3925 .x86_64 => 6,
3781 .aarch64 => 3 * @sizeOf(u32),3926 .aarch64 => 3 * @sizeOf(u32),
3782 else => unreachable, // unhandled architecture type3927 else => unreachable, // unhandled architecture type
3783 };3928 };
3784 const needed_size = stub_size * self.base.options.symbol_count_hint;3929 const needed_size = if (self.needs_prealloc) stub_size * self.base.options.symbol_count_hint else 0;
3785 self.stubs_section_index = try self.allocateSection(3930 self.stubs_section_index = try self.initSection(
3786 self.text_segment_cmd_index.?,3931 self.text_segment_cmd_index.?,
3787 "__stubs",3932 "__stubs",
3788 needed_size,3933 needed_size,
...@@ -3795,23 +3940,26 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3795,23 +3940,26 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3795 }3940 }
37963941
3797 if (self.stub_helper_section_index == null) {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 .x86_64 => 0,3944 .x86_64 => 0,
3800 .aarch64 => 2,3945 .aarch64 => 2,
3801 else => unreachable, // unhandled architecture type3946 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 .x86_64 => 15,3949 .x86_64 => 15,
3805 .aarch64 => 6 * @sizeOf(u32),3950 .aarch64 => 6 * @sizeOf(u32),
3806 else => unreachable,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 .x86_64 => 10,3954 .x86_64 => 10,
3810 .aarch64 => 3 * @sizeOf(u32),3955 .aarch64 => 3 * @sizeOf(u32),
3811 else => unreachable,3956 else => unreachable,
3812 };3957 };
3813 const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size;3958 const needed_size = if (self.needs_prealloc)
3814 self.stub_helper_section_index = try self.allocateSection(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 self.text_segment_cmd_index.?,3963 self.text_segment_cmd_index.?,
3816 "__stub_helper",3964 "__stub_helper",
3817 needed_size,3965 needed_size,
...@@ -3824,22 +3972,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3824,22 +3972,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {
38243972
3825 if (self.data_const_segment_cmd_index == null) {3973 if (self.data_const_segment_cmd_index == null) {
3826 self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);3974 self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
3827 const address_and_offset = self.nextSegmentAddressAndOffset();3975 var vmaddr: u64 = 0;
3828 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;3976 var fileoff: u64 = 0;
3829 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);3977 var needed_size: u64 = 0;
38303978 if (self.needs_prealloc) {
3831 log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{3979 const address_and_offset = self.nextSegmentAddressAndOffset();
3832 address_and_offset.offset,3980 vmaddr = address_and_offset.address;
3833 address_and_offset.offset + needed_size,3981 fileoff = address_and_offset.offset;
3834 });3982 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
38353983 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 try self.load_commands.append(self.base.allocator, .{3989 try self.load_commands.append(self.base.allocator, .{
3837 .Segment = .{3990 .Segment = .{
3838 .inner = .{3991 .inner = .{
3839 .segname = makeStaticString("__DATA_CONST"),3992 .segname = makeStaticString("__DATA_CONST"),
3840 .vmaddr = address_and_offset.address,3993 .vmaddr = vmaddr,
3841 .vmsize = needed_size,3994 .vmsize = needed_size,
3842 .fileoff = address_and_offset.offset,3995 .fileoff = fileoff,
3843 .filesize = needed_size,3996 .filesize = needed_size,
3844 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,3997 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
3845 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,3998 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
...@@ -3850,9 +4003,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3850,9 +4003,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3850 }4003 }
38514004
3852 if (self.got_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_const_segment_cmd_index.?,4012 self.data_const_segment_cmd_index.?,
3857 "__got",4013 "__got",
3858 needed_size,4014 needed_size,
...@@ -3865,19 +4021,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3865,19 +4021,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {
38654021
3866 if (self.data_segment_cmd_index == null) {4022 if (self.data_segment_cmd_index == null) {
3867 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);4023 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
3868 const address_and_offset = self.nextSegmentAddressAndOffset();4024 var vmaddr: u64 = 0;
3869 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;4025 var fileoff: u64 = 0;
3870 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);4026 var needed_size: u64 = 0;
38714027 if (self.needs_prealloc) {
3872 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });4028 const address_and_offset = self.nextSegmentAddressAndOffset();
38734029 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 try self.load_commands.append(self.base.allocator, .{4038 try self.load_commands.append(self.base.allocator, .{
3875 .Segment = .{4039 .Segment = .{
3876 .inner = .{4040 .inner = .{
3877 .segname = makeStaticString("__DATA"),4041 .segname = makeStaticString("__DATA"),
3878 .vmaddr = address_and_offset.address,4042 .vmaddr = vmaddr,
3879 .vmsize = needed_size,4043 .vmsize = needed_size,
3880 .fileoff = address_and_offset.offset,4044 .fileoff = fileoff,
3881 .filesize = needed_size,4045 .filesize = needed_size,
3882 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,4046 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
3883 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,4047 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
...@@ -3888,9 +4052,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3888,9 +4052,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3888 }4052 }
38894053
3890 if (self.la_symbol_ptr_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4061 self.data_segment_cmd_index.?,
3895 "__la_symbol_ptr",4062 "__la_symbol_ptr",
3896 needed_size,4063 needed_size,
...@@ -3902,9 +4069,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3902,9 +4069,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3902 }4069 }
39034070
3904 if (self.data_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4075 self.data_segment_cmd_index.?,
3909 "__data",4076 "__data",
3910 needed_size,4077 needed_size,
...@@ -3914,9 +4081,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3914,9 +4081,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3914 }4081 }
39154082
3916 if (self.tlv_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4087 self.data_segment_cmd_index.?,
3921 "__thread_vars",4088 "__thread_vars",
3922 needed_size,4089 needed_size,
...@@ -3928,9 +4095,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3928,9 +4095,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3928 }4095 }
39294096
3930 if (self.tlv_data_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4101 self.data_segment_cmd_index.?,
3935 "__thread_data",4102 "__thread_data",
3936 needed_size,4103 needed_size,
...@@ -3942,9 +4109,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3942,9 +4109,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3942 }4109 }
39434110
3944 if (self.tlv_bss_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4115 self.data_segment_cmd_index.?,
3949 "__thread_bss",4116 "__thread_bss",
3950 needed_size,4117 needed_size,
...@@ -3959,9 +4126,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3959,9 +4126,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3959 }4126 }
39604127
3961 if (self.bss_section_index == null) {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 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)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 self.data_segment_cmd_index.?,4132 self.data_segment_cmd_index.?,
3966 "__bss",4133 "__bss",
3967 needed_size,4134 needed_size,
...@@ -3977,16 +4144,20 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3977,16 +4144,20 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39774144
3978 if (self.linkedit_segment_cmd_index == null) {4145 if (self.linkedit_segment_cmd_index == null) {
3979 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);4146 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
3980 const address_and_offset = self.nextSegmentAddressAndOffset();4147 var vmaddr: u64 = 0;
39814148 var fileoff: u64 = 0;
3982 log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset});4149 if (self.needs_prealloc) {
39834150 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 try self.load_commands.append(self.base.allocator, .{4155 try self.load_commands.append(self.base.allocator, .{
3985 .Segment = .{4156 .Segment = .{
3986 .inner = .{4157 .inner = .{
3987 .segname = makeStaticString("__LINKEDIT"),4158 .segname = makeStaticString("__LINKEDIT"),
3988 .vmaddr = address_and_offset.address,4159 .vmaddr = vmaddr,
3989 .fileoff = address_and_offset.offset,4160 .fileoff = fileoff,
3990 .maxprot = macho.VM_PROT_READ,4161 .maxprot = macho.VM_PROT_READ,
3991 .initprot = macho.VM_PROT_READ,4162 .initprot = macho.VM_PROT_READ,
3992 },4163 },
...@@ -4198,44 +4369,123 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4198,44 +4369,123 @@ pub fn populateMissingMetadata(self: *MachO) !void {
4198 self.cold_start = true;4369 self.cold_start = true;
4199}4370}
42004371
4201const AllocateSectionOpts = struct {4372fn 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
4409fn 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
4417fn 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
4425fn 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
4432fn 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
4451const InitSectionOpts = struct {
4202 flags: u32 = macho.S_REGULAR,4452 flags: u32 = macho.S_REGULAR,
4203 reserved1: u32 = 0,4453 reserved1: u32 = 0,
4204 reserved2: u32 = 0,4454 reserved2: u32 = 0,
4205};4455};
42064456
4207fn allocateSection(4457fn initSection(
4208 self: *MachO,4458 self: *MachO,
4209 segment_id: u16,4459 segment_id: u16,
4210 sectname: []const u8,4460 sectname: []const u8,
4211 size: u64,4461 size: u64,
4212 alignment: u32,4462 alignment: u32,
4213 opts: AllocateSectionOpts,4463 opts: InitSectionOpts,
4214) !u16 {4464) !u16 {
4215 const seg = &self.load_commands.items[segment_id].Segment;4465 const seg = &self.load_commands.items[segment_id].Segment;
4216 var sect = macho.section_64{4466 var sect = macho.section_64{
4217 .sectname = makeStaticString(sectname),4467 .sectname = makeStaticString(sectname),
4218 .segname = seg.inner.segname,4468 .segname = seg.inner.segname,
4219 .size = @intCast(u32, size),4469 .size = if (self.needs_prealloc) @intCast(u32, size) else 0,
4220 .@"align" = alignment,4470 .@"align" = alignment,
4221 .flags = opts.flags,4471 .flags = opts.flags,
4222 .reserved1 = opts.reserved1,4472 .reserved1 = opts.reserved1,
4223 .reserved2 = opts.reserved2,4473 .reserved2 = opts.reserved2,
4224 };4474 };
42254475
4226 const alignment_pow_2 = try math.powi(u32, 2, alignment);4476 if (self.needs_prealloc) {
4227 const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;4477 const alignment_pow_2 = try math.powi(u32, 2, alignment);
4228 const off = self.findFreeSpace(segment_id, alignment_pow_2, padding);4478 const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null;
42294479 const off = self.findFreeSpace(segment_id, alignment_pow_2, padding);
4230 log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{4480 log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{
4231 commands.segmentName(sect),4481 commands.segmentName(sect),
4232 commands.sectionName(sect),4482 commands.sectionName(sect),
4233 off,4483 off,
4234 off + size,4484 off + size,
4235 });4485 });
42364486 sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff;
4237 sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff;4487 sect.offset = @intCast(u32, off);
4238 sect.offset = @intCast(u32, off);4488 }
42394489
4240 const index = @intCast(u16, seg.sections.items.len);4490 const index = @intCast(u16, seg.sections.items.len);
4241 try seg.sections.append(self.base.allocator, sect);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,7 +4520,11 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void {
4270 const new_seg_size = mem.alignForwardGeneric(u64, new_size, self.page_size);4520 const new_seg_size = mem.alignForwardGeneric(u64, new_size, self.page_size);
4271 assert(new_seg_size > seg.inner.filesize);4521 assert(new_seg_size > seg.inner.filesize);
4272 const offset_amt = new_seg_size - seg.inner.filesize;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 seg.inner.filesize = new_seg_size;4528 seg.inner.filesize = new_seg_size;
4275 seg.inner.vmsize = new_seg_size;4529 seg.inner.vmsize = new_seg_size;
42764530
...@@ -4534,6 +4788,21 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m...@@ -4534,6 +4788,21 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m
4534 return vaddr;4788 return vaddr;
4535}4789}
45364790
4791fn 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
4537pub fn addExternFn(self: *MachO, name: []const u8) !u32 {4806pub fn addExternFn(self: *MachO, name: []const u8) !u32 {
4538 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});4807 const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name});
4539 defer self.base.allocator.free(sym_name);4808 defer self.base.allocator.free(sym_name);
src/link/MachO/Atom.zig+2-1
...@@ -344,7 +344,8 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC...@@ -344,7 +344,8 @@ pub fn parseRelocs(self: *Atom, relocs: []macho.relocation_info, context: RelocC
344 const local_sym_index = context.object.sections_as_symbols.get(sect_id) orelse blk: {344 const local_sym_index = context.object.sections_as_symbols.get(sect_id) orelse blk: {
345 const seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;345 const seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
346 const sect = seg.sections.items[sect_id];346 const sect = seg.sections.items[sect_id];
347 const match = (try context.macho_file.getMatchingSection(sect)) orelse unreachable;347 const match = (try context.macho_file.getMatchingSection(sect)) orelse
348 unreachable;
348 const local_sym_index = @intCast(u32, context.macho_file.locals.items.len);349 const local_sym_index = @intCast(u32, context.macho_file.locals.items.len);
349 try context.macho_file.locals.append(context.allocator, .{350 try context.macho_file.locals.append(context.allocator, .{
350 .n_strx = 0,351 .n_strx = 0,
src/link/MachO/Object.zig+3-1
...@@ -474,7 +474,9 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !...@@ -474,7 +474,9 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !
474 try self.sections_as_symbols.putNoClobber(allocator, sect_id, atom_local_sym_index);474 try self.sections_as_symbols.putNoClobber(allocator, sect_id, atom_local_sym_index);
475 break :blk atom_local_sym_index;475 break :blk atom_local_sym_index;
476 };476 };
477 const atom = try macho_file.createEmptyAtom(atom_local_sym_index, sect.size, sect.@"align");477 const alignment = try math.powi(u32, 2, sect.@"align");
478 const aligned_size = mem.alignForwardGeneric(u64, sect.size, alignment);
479 const atom = try macho_file.createEmptyAtom(atom_local_sym_index, aligned_size, sect.@"align");
478480
479 const is_zerofill = blk: {481 const is_zerofill = blk: {
480 const section_type = commands.sectionType(sect);482 const section_type = commands.sectionType(sect);