| ... | @@ -63,6 +63,11 @@ page_size: u16, | ... | @@ -63,6 +63,11 @@ page_size: u16, |
| 63 | /// https://github.com/ziglang/zig/issues/9567 | 63 | /// https://github.com/ziglang/zig/issues/9567 |
| 64 | requires_adhoc_codesig: bool, | 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 | /// We commit 0x1000 = 4096 bytes of space to the header and | 71 | /// We commit 0x1000 = 4096 bytes of space to the header and |
| 67 | /// the table of load commands. This should be plenty for any | 72 | /// 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 simulator | 380 | // 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); |
| 378 | | 384 | |
| 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 | }; |
| 389 | | 396 | |
| 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 { |
| 911 | | 918 | |
| 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(); |
| 915 | | 931 | |
| 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 | } |
| 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 | try self.writeAtoms(); | 977 | try self.writeAtoms(); |
| 950 | | 978 | |
| 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/merged | 1384 | // 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 | } |
| 1403 | | 1431 | |
| 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 section | 1582 | // 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 |
| 1571 | | 1599 | |
| 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 |
| 1702 | | 1730 | |
| 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 | } |
| 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 | fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void { | 1969 | fn 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; |
| 1886 | | 1971 | |
| ... | @@ -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 | } |
| 2044 | | 2140 | |
| 2045 | fn createStubHelperPreambleAtom(self: *MachO) !void { | 2141 | fn 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 | } |
| 2174 | | 2274 | |
| 2175 | pub fn createStubHelperAtom(self: *MachO) !*Atom { | 2275 | pub 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; |
| 2378 | | 2478 | |
| 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 | } |
| 2386 | | 2489 | |
| ... | @@ -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 separate | 2532 | // 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 | }); |
| 2772 | | 2878 | |
| 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 | } |
| 2836 | | 2950 | |
| 2837 | fn parseObjectsIntoAtoms(self: *MachO) !void { | 2951 | fn 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 | } |
| 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 | 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 | } |
| 2871 | | 2992 | |
| | 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); |
| 2876 | | 3001 | |
| 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 | }); |
| 2884 | | 3009 | |
| 2885 | if (atom.prev) |prev| { | 3010 | if (atom.next) |next| { |
| 2886 | atom = prev; | 3011 | atom = next; |
| 2887 | } else break; | 3012 | } else break; |
| 2888 | } | 3013 | } |
| 2889 | | 3014 | |
| 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); |
| 2896 | | 3021 | |
| 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 | } |
| 2901 | | 3026 | |
| ... | @@ -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 | }); |
| 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 | 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 | } |
| 2927 | | 3051 | |
| 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; |
| 2933 | | 3059 | |
| 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; |
| 2938 | | 3066 | |
| 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).?); |
| 2942 | | 3074 | |
| 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 | }); | | |
| 2950 | | 3076 | |
| 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 | } | | |
| 2957 | | 3082 | |
| 2958 | // Update each symbol contained within the atom | 3083 | 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 | } | | |
| 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| { | 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 | } |
| 2971 | | 3113 | |
| 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 | } |
| 2981 | | 3123 | |
| ... | @@ -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 | } |
| 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 | 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 { |
| 3730 | | 3874 | |
| 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; |
| 3737 | | 3881 | 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 }); |
| 3739 | | 3883 | 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 | } |
| 3754 | | 3899 | |
| 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 type | 3904 | 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 | } |
| 3772 | | 3917 | |
| 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 type | 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 | .x86_64 => 6, | 3925 | .x86_64 => 6, |
| 3781 | .aarch64 => 3 * @sizeOf(u32), | 3926 | .aarch64 => 3 * @sizeOf(u32), |
| 3782 | else => unreachable, // unhandled architecture type | 3927 | 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 | } |
| 3796 | | 3941 | |
| 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 type | 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 | .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 { |
| 3824 | | 3972 | |
| 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; |
| 3830 | | 3978 | 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; |
| 3835 | | 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 | 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 | } |
| 3851 | | 4004 | |
| 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 { |
| 3865 | | 4021 | |
| 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; |
| 3871 | | 4027 | 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(); |
| 3873 | | 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 | 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 | } |
| 3889 | | 4053 | |
| 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 | } |
| 3903 | | 4070 | |
| 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 | } |
| 3915 | | 4082 | |
| 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 | } |
| 3929 | | 4096 | |
| 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 | } |
| 3943 | | 4110 | |
| 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 | } |
| 3960 | | 4127 | |
| 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 { |
| 3977 | | 4144 | |
| 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; |
| 3981 | | 4148 | var fileoff: u64 = 0; |
| 3982 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset}); | 4149 | if (self.needs_prealloc) { |
| 3983 | | 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 | 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 | } |
| 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 | 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 | }; |
| 4206 | | 4456 | |
| 4207 | fn allocateSection( | 4457 | fn 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 | }; |
| 4225 | | 4475 | |
| 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; |
| 4229 | | 4479 | 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 | }); |
| 4236 | | 4486 | 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 | } |
| 4239 | | 4489 | |
| 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; |
| 4276 | | 4530 | |
| ... | @@ -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 | } |
| 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 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { | 4806 | pub 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); |