| ... | @@ -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,42 +918,28 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -911,42 +918,28 @@ 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(); |
| 914 | try self.allocateGlobalSymbols(); | | |
| 915 | | 921 | |
| 916 | log.debug("locals:", .{}); | 922 | if (use_stage1) { |
| 917 | for (self.locals.items) |sym, id| { | 923 | try self.sortSections(); |
| 918 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); | 924 | try self.allocateTextSegment(); |
| 919 | } | 925 | try self.allocateDataConstSegment(); |
| 920 | log.debug("globals:", .{}); | 926 | try self.allocateDataSegment(); |
| 921 | for (self.globals.items) |sym, id| { | 927 | self.allocateLinkeditSegment(); |
| 922 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); | 928 | try self.allocateLocals(); |
| 923 | } | | |
| 924 | log.debug("undefs:", .{}); | | |
| 925 | for (self.undefs.items) |sym, id| { | | |
| 926 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); | | |
| 927 | } | | |
| 928 | { | | |
| 929 | log.debug("resolver:", .{}); | | |
| 930 | var it = self.symbol_resolver.iterator(); | | |
| 931 | while (it.next()) |entry| { | | |
| 932 | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); | | |
| 933 | } | | |
| 934 | } | 929 | } |
| 935 | | 930 | |
| 936 | log.debug("GOT entries:", .{}); | 931 | try self.allocateGlobals(); |
| 937 | for (self.got_entries_map.keys()) |key| { | | |
| 938 | switch (key) { | | |
| 939 | .local => |sym_index| log.debug(" {} => {d}", .{ key, sym_index }), | | |
| 940 | .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }), | | |
| 941 | } | | |
| 942 | } | | |
| 943 | | 932 | |
| 944 | log.debug("stubs:", .{}); | 933 | if (build_options.enable_logging) { |
| 945 | for (self.stubs_map.keys()) |key| { | 934 | self.logSymtab(); |
| 946 | log.debug(" {} => {s}", .{ key, self.getString(key) }); | 935 | self.logSectionOrdinals(); |
| 947 | } | 936 | } |
| 948 | | 937 | |
| 949 | try self.writeAtoms(); | 938 | if (use_stage1) { |
| | 939 | try self.writeAllAtoms(); |
| | 940 | } else { |
| | 941 | try self.writeAtoms(); |
| | 942 | } |
| 950 | | 943 | |
| 951 | if (self.bss_section_index) |idx| { | 944 | if (self.bss_section_index) |idx| { |
| 952 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 945 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| ... | @@ -1337,7 +1330,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1337,7 +1330,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1337 | switch (commands.sectionType(sect)) { | 1330 | switch (commands.sectionType(sect)) { |
| 1338 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { | 1331 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1339 | if (self.text_const_section_index == null) { | 1332 | if (self.text_const_section_index == null) { |
| 1340 | self.text_const_section_index = try self.allocateSection( | 1333 | self.text_const_section_index = try self.initSection( |
| 1341 | self.text_segment_cmd_index.?, | 1334 | self.text_segment_cmd_index.?, |
| 1342 | "__const", | 1335 | "__const", |
| 1343 | sect.size, | 1336 | sect.size, |
| ... | @@ -1356,7 +1349,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1356,7 +1349,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 | 1349 | // TODO it seems the common values within the sections in objects are deduplicated/merged |
| 1357 | // on merging the sections' contents. | 1350 | // on merging the sections' contents. |
| 1358 | if (self.objc_methname_section_index == null) { | 1351 | if (self.objc_methname_section_index == null) { |
| 1359 | self.objc_methname_section_index = try self.allocateSection( | 1352 | self.objc_methname_section_index = try self.initSection( |
| 1360 | self.text_segment_cmd_index.?, | 1353 | self.text_segment_cmd_index.?, |
| 1361 | "__objc_methname", | 1354 | "__objc_methname", |
| 1362 | sect.size, | 1355 | sect.size, |
| ... | @@ -1371,7 +1364,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1371,7 +1364,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1371 | }; | 1364 | }; |
| 1372 | } else if (mem.eql(u8, sectname, "__objc_methtype")) { | 1365 | } else if (mem.eql(u8, sectname, "__objc_methtype")) { |
| 1373 | if (self.objc_methtype_section_index == null) { | 1366 | if (self.objc_methtype_section_index == null) { |
| 1374 | self.objc_methtype_section_index = try self.allocateSection( | 1367 | self.objc_methtype_section_index = try self.initSection( |
| 1375 | self.text_segment_cmd_index.?, | 1368 | self.text_segment_cmd_index.?, |
| 1376 | "__objc_methtype", | 1369 | "__objc_methtype", |
| 1377 | sect.size, | 1370 | sect.size, |
| ... | @@ -1386,7 +1379,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1386,7 +1379,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1386 | }; | 1379 | }; |
| 1387 | } else if (mem.eql(u8, sectname, "__objc_classname")) { | 1380 | } else if (mem.eql(u8, sectname, "__objc_classname")) { |
| 1388 | if (self.objc_classname_section_index == null) { | 1381 | if (self.objc_classname_section_index == null) { |
| 1389 | self.objc_classname_section_index = try self.allocateSection( | 1382 | self.objc_classname_section_index = try self.initSection( |
| 1390 | self.text_segment_cmd_index.?, | 1383 | self.text_segment_cmd_index.?, |
| 1391 | "__objc_classname", | 1384 | "__objc_classname", |
| 1392 | sect.size, | 1385 | sect.size, |
| ... | @@ -1402,7 +1395,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1402,7 +1395,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1402 | } | 1395 | } |
| 1403 | | 1396 | |
| 1404 | if (self.cstring_section_index == null) { | 1397 | if (self.cstring_section_index == null) { |
| 1405 | self.cstring_section_index = try self.allocateSection( | 1398 | self.cstring_section_index = try self.initSection( |
| 1406 | self.text_segment_cmd_index.?, | 1399 | self.text_segment_cmd_index.?, |
| 1407 | "__cstring", | 1400 | "__cstring", |
| 1408 | sect.size, | 1401 | sect.size, |
| ... | @@ -1421,7 +1414,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1421,7 +1414,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1421 | macho.S_LITERAL_POINTERS => { | 1414 | macho.S_LITERAL_POINTERS => { |
| 1422 | if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) { | 1415 | if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) { |
| 1423 | if (self.objc_selrefs_section_index == null) { | 1416 | if (self.objc_selrefs_section_index == null) { |
| 1424 | self.objc_selrefs_section_index = try self.allocateSection( | 1417 | self.objc_selrefs_section_index = try self.initSection( |
| 1425 | self.data_segment_cmd_index.?, | 1418 | self.data_segment_cmd_index.?, |
| 1426 | "__objc_selrefs", | 1419 | "__objc_selrefs", |
| 1427 | sect.size, | 1420 | sect.size, |
| ... | @@ -1443,7 +1436,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1443,7 +1436,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1443 | }, | 1436 | }, |
| 1444 | macho.S_MOD_INIT_FUNC_POINTERS => { | 1437 | macho.S_MOD_INIT_FUNC_POINTERS => { |
| 1445 | if (self.mod_init_func_section_index == null) { | 1438 | if (self.mod_init_func_section_index == null) { |
| 1446 | self.mod_init_func_section_index = try self.allocateSection( | 1439 | self.mod_init_func_section_index = try self.initSection( |
| 1447 | self.data_const_segment_cmd_index.?, | 1440 | self.data_const_segment_cmd_index.?, |
| 1448 | "__mod_init_func", | 1441 | "__mod_init_func", |
| 1449 | sect.size, | 1442 | sect.size, |
| ... | @@ -1461,7 +1454,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1461,7 +1454,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1461 | }, | 1454 | }, |
| 1462 | macho.S_MOD_TERM_FUNC_POINTERS => { | 1455 | macho.S_MOD_TERM_FUNC_POINTERS => { |
| 1463 | if (self.mod_term_func_section_index == null) { | 1456 | if (self.mod_term_func_section_index == null) { |
| 1464 | self.mod_term_func_section_index = try self.allocateSection( | 1457 | self.mod_term_func_section_index = try self.initSection( |
| 1465 | self.data_const_segment_cmd_index.?, | 1458 | self.data_const_segment_cmd_index.?, |
| 1466 | "__mod_term_func", | 1459 | "__mod_term_func", |
| 1467 | sect.size, | 1460 | sect.size, |
| ... | @@ -1479,7 +1472,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1479,7 +1472,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1479 | }, | 1472 | }, |
| 1480 | macho.S_ZEROFILL => { | 1473 | macho.S_ZEROFILL => { |
| 1481 | if (self.bss_section_index == null) { | 1474 | if (self.bss_section_index == null) { |
| 1482 | self.bss_section_index = try self.allocateSection( | 1475 | self.bss_section_index = try self.initSection( |
| 1483 | self.data_segment_cmd_index.?, | 1476 | self.data_segment_cmd_index.?, |
| 1484 | "__bss", | 1477 | "__bss", |
| 1485 | sect.size, | 1478 | sect.size, |
| ... | @@ -1497,7 +1490,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1497,7 +1490,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1497 | }, | 1490 | }, |
| 1498 | macho.S_THREAD_LOCAL_VARIABLES => { | 1491 | macho.S_THREAD_LOCAL_VARIABLES => { |
| 1499 | if (self.tlv_section_index == null) { | 1492 | if (self.tlv_section_index == null) { |
| 1500 | self.tlv_section_index = try self.allocateSection( | 1493 | self.tlv_section_index = try self.initSection( |
| 1501 | self.data_segment_cmd_index.?, | 1494 | self.data_segment_cmd_index.?, |
| 1502 | "__thread_vars", | 1495 | "__thread_vars", |
| 1503 | sect.size, | 1496 | sect.size, |
| ... | @@ -1515,7 +1508,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1515,7 +1508,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1515 | }, | 1508 | }, |
| 1516 | macho.S_THREAD_LOCAL_REGULAR => { | 1509 | macho.S_THREAD_LOCAL_REGULAR => { |
| 1517 | if (self.tlv_data_section_index == null) { | 1510 | if (self.tlv_data_section_index == null) { |
| 1518 | self.tlv_data_section_index = try self.allocateSection( | 1511 | self.tlv_data_section_index = try self.initSection( |
| 1519 | self.data_segment_cmd_index.?, | 1512 | self.data_segment_cmd_index.?, |
| 1520 | "__thread_data", | 1513 | "__thread_data", |
| 1521 | sect.size, | 1514 | sect.size, |
| ... | @@ -1533,7 +1526,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1533,7 +1526,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1533 | }, | 1526 | }, |
| 1534 | macho.S_THREAD_LOCAL_ZEROFILL => { | 1527 | macho.S_THREAD_LOCAL_ZEROFILL => { |
| 1535 | if (self.tlv_bss_section_index == null) { | 1528 | if (self.tlv_bss_section_index == null) { |
| 1536 | self.tlv_bss_section_index = try self.allocateSection( | 1529 | self.tlv_bss_section_index = try self.initSection( |
| 1537 | self.data_segment_cmd_index.?, | 1530 | self.data_segment_cmd_index.?, |
| 1538 | "__thread_bss", | 1531 | "__thread_bss", |
| 1539 | sect.size, | 1532 | sect.size, |
| ... | @@ -1554,7 +1547,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1554,7 +1547,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1554 | // TODO I believe __eh_frame is currently part of __unwind_info section | 1547 | // TODO I believe __eh_frame is currently part of __unwind_info section |
| 1555 | // in the latest ld64 output. | 1548 | // in the latest ld64 output. |
| 1556 | if (self.eh_frame_section_index == null) { | 1549 | if (self.eh_frame_section_index == null) { |
| 1557 | self.eh_frame_section_index = try self.allocateSection( | 1550 | self.eh_frame_section_index = try self.initSection( |
| 1558 | self.text_segment_cmd_index.?, | 1551 | self.text_segment_cmd_index.?, |
| 1559 | "__eh_frame", | 1552 | "__eh_frame", |
| 1560 | sect.size, | 1553 | sect.size, |
| ... | @@ -1571,7 +1564,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1571,7 +1564,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1571 | | 1564 | |
| 1572 | // TODO audit this: is this the right mapping? | 1565 | // TODO audit this: is this the right mapping? |
| 1573 | if (self.data_const_section_index == null) { | 1566 | if (self.data_const_section_index == null) { |
| 1574 | self.data_const_section_index = try self.allocateSection( | 1567 | self.data_const_section_index = try self.initSection( |
| 1575 | self.data_const_segment_cmd_index.?, | 1568 | self.data_const_segment_cmd_index.?, |
| 1576 | "__const", | 1569 | "__const", |
| 1577 | sect.size, | 1570 | sect.size, |
| ... | @@ -1588,7 +1581,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1588,7 +1581,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1588 | macho.S_REGULAR => { | 1581 | macho.S_REGULAR => { |
| 1589 | if (commands.sectionIsCode(sect)) { | 1582 | if (commands.sectionIsCode(sect)) { |
| 1590 | if (self.text_section_index == null) { | 1583 | if (self.text_section_index == null) { |
| 1591 | self.text_section_index = try self.allocateSection( | 1584 | self.text_section_index = try self.initSection( |
| 1592 | self.text_segment_cmd_index.?, | 1585 | self.text_segment_cmd_index.?, |
| 1593 | "__text", | 1586 | "__text", |
| 1594 | sect.size, | 1587 | sect.size, |
| ... | @@ -1619,7 +1612,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1619,7 +1612,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1619 | if (mem.eql(u8, segname, "__TEXT")) { | 1612 | if (mem.eql(u8, segname, "__TEXT")) { |
| 1620 | if (mem.eql(u8, sectname, "__ustring")) { | 1613 | if (mem.eql(u8, sectname, "__ustring")) { |
| 1621 | if (self.ustring_section_index == null) { | 1614 | if (self.ustring_section_index == null) { |
| 1622 | self.ustring_section_index = try self.allocateSection( | 1615 | self.ustring_section_index = try self.initSection( |
| 1623 | self.text_segment_cmd_index.?, | 1616 | self.text_segment_cmd_index.?, |
| 1624 | "__ustring", | 1617 | "__ustring", |
| 1625 | sect.size, | 1618 | sect.size, |
| ... | @@ -1634,7 +1627,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1634,7 +1627,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1634 | }; | 1627 | }; |
| 1635 | } else if (mem.eql(u8, sectname, "__gcc_except_tab")) { | 1628 | } else if (mem.eql(u8, sectname, "__gcc_except_tab")) { |
| 1636 | if (self.gcc_except_tab_section_index == null) { | 1629 | if (self.gcc_except_tab_section_index == null) { |
| 1637 | self.gcc_except_tab_section_index = try self.allocateSection( | 1630 | self.gcc_except_tab_section_index = try self.initSection( |
| 1638 | self.text_segment_cmd_index.?, | 1631 | self.text_segment_cmd_index.?, |
| 1639 | "__gcc_except_tab", | 1632 | "__gcc_except_tab", |
| 1640 | sect.size, | 1633 | sect.size, |
| ... | @@ -1649,7 +1642,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1649,7 +1642,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1649 | }; | 1642 | }; |
| 1650 | } else if (mem.eql(u8, sectname, "__objc_methlist")) { | 1643 | } else if (mem.eql(u8, sectname, "__objc_methlist")) { |
| 1651 | if (self.objc_methlist_section_index == null) { | 1644 | if (self.objc_methlist_section_index == null) { |
| 1652 | self.objc_methlist_section_index = try self.allocateSection( | 1645 | self.objc_methlist_section_index = try self.initSection( |
| 1653 | self.text_segment_cmd_index.?, | 1646 | self.text_segment_cmd_index.?, |
| 1654 | "__objc_methlist", | 1647 | "__objc_methlist", |
| 1655 | sect.size, | 1648 | sect.size, |
| ... | @@ -1669,7 +1662,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1669,7 +1662,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1669 | mem.eql(u8, sectname, "__gopclntab")) | 1662 | mem.eql(u8, sectname, "__gopclntab")) |
| 1670 | { | 1663 | { |
| 1671 | if (self.data_const_section_index == null) { | 1664 | if (self.data_const_section_index == null) { |
| 1672 | self.data_const_section_index = try self.allocateSection( | 1665 | self.data_const_section_index = try self.initSection( |
| 1673 | self.data_const_segment_cmd_index.?, | 1666 | self.data_const_segment_cmd_index.?, |
| 1674 | "__const", | 1667 | "__const", |
| 1675 | sect.size, | 1668 | sect.size, |
| ... | @@ -1684,7 +1677,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1684,7 +1677,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1684 | }; | 1677 | }; |
| 1685 | } else { | 1678 | } else { |
| 1686 | if (self.text_const_section_index == null) { | 1679 | if (self.text_const_section_index == null) { |
| 1687 | self.text_const_section_index = try self.allocateSection( | 1680 | self.text_const_section_index = try self.initSection( |
| 1688 | self.text_segment_cmd_index.?, | 1681 | self.text_segment_cmd_index.?, |
| 1689 | "__const", | 1682 | "__const", |
| 1690 | sect.size, | 1683 | sect.size, |
| ... | @@ -1702,7 +1695,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1702,7 +1695,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1702 | | 1695 | |
| 1703 | if (mem.eql(u8, segname, "__DATA_CONST")) { | 1696 | if (mem.eql(u8, segname, "__DATA_CONST")) { |
| 1704 | if (self.data_const_section_index == null) { | 1697 | if (self.data_const_section_index == null) { |
| 1705 | self.data_const_section_index = try self.allocateSection( | 1698 | self.data_const_section_index = try self.initSection( |
| 1706 | self.data_const_segment_cmd_index.?, | 1699 | self.data_const_segment_cmd_index.?, |
| 1707 | "__const", | 1700 | "__const", |
| 1708 | sect.size, | 1701 | sect.size, |
| ... | @@ -1720,7 +1713,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1720,7 +1713,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1720 | if (mem.eql(u8, segname, "__DATA")) { | 1713 | if (mem.eql(u8, segname, "__DATA")) { |
| 1721 | if (mem.eql(u8, sectname, "__const")) { | 1714 | if (mem.eql(u8, sectname, "__const")) { |
| 1722 | if (self.data_const_section_index == null) { | 1715 | if (self.data_const_section_index == null) { |
| 1723 | self.data_const_section_index = try self.allocateSection( | 1716 | self.data_const_section_index = try self.initSection( |
| 1724 | self.data_const_segment_cmd_index.?, | 1717 | self.data_const_segment_cmd_index.?, |
| 1725 | "__const", | 1718 | "__const", |
| 1726 | sect.size, | 1719 | sect.size, |
| ... | @@ -1735,7 +1728,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1735,7 +1728,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1735 | }; | 1728 | }; |
| 1736 | } else if (mem.eql(u8, sectname, "__cfstring")) { | 1729 | } else if (mem.eql(u8, sectname, "__cfstring")) { |
| 1737 | if (self.objc_cfstring_section_index == null) { | 1730 | if (self.objc_cfstring_section_index == null) { |
| 1738 | self.objc_cfstring_section_index = try self.allocateSection( | 1731 | self.objc_cfstring_section_index = try self.initSection( |
| 1739 | self.data_const_segment_cmd_index.?, | 1732 | self.data_const_segment_cmd_index.?, |
| 1740 | "__cfstring", | 1733 | "__cfstring", |
| 1741 | sect.size, | 1734 | sect.size, |
| ... | @@ -1750,7 +1743,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1750,7 +1743,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1750 | }; | 1743 | }; |
| 1751 | } else if (mem.eql(u8, sectname, "__objc_classlist")) { | 1744 | } else if (mem.eql(u8, sectname, "__objc_classlist")) { |
| 1752 | if (self.objc_classlist_section_index == null) { | 1745 | if (self.objc_classlist_section_index == null) { |
| 1753 | self.objc_classlist_section_index = try self.allocateSection( | 1746 | self.objc_classlist_section_index = try self.initSection( |
| 1754 | self.data_const_segment_cmd_index.?, | 1747 | self.data_const_segment_cmd_index.?, |
| 1755 | "__objc_classlist", | 1748 | "__objc_classlist", |
| 1756 | sect.size, | 1749 | sect.size, |
| ... | @@ -1765,7 +1758,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1765,7 +1758,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1765 | }; | 1758 | }; |
| 1766 | } else if (mem.eql(u8, sectname, "__objc_imageinfo")) { | 1759 | } else if (mem.eql(u8, sectname, "__objc_imageinfo")) { |
| 1767 | if (self.objc_imageinfo_section_index == null) { | 1760 | if (self.objc_imageinfo_section_index == null) { |
| 1768 | self.objc_imageinfo_section_index = try self.allocateSection( | 1761 | self.objc_imageinfo_section_index = try self.initSection( |
| 1769 | self.data_const_segment_cmd_index.?, | 1762 | self.data_const_segment_cmd_index.?, |
| 1770 | "__objc_imageinfo", | 1763 | "__objc_imageinfo", |
| 1771 | sect.size, | 1764 | sect.size, |
| ... | @@ -1780,7 +1773,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1780,7 +1773,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1780 | }; | 1773 | }; |
| 1781 | } else if (mem.eql(u8, sectname, "__objc_const")) { | 1774 | } else if (mem.eql(u8, sectname, "__objc_const")) { |
| 1782 | if (self.objc_const_section_index == null) { | 1775 | if (self.objc_const_section_index == null) { |
| 1783 | self.objc_const_section_index = try self.allocateSection( | 1776 | self.objc_const_section_index = try self.initSection( |
| 1784 | self.data_segment_cmd_index.?, | 1777 | self.data_segment_cmd_index.?, |
| 1785 | "__objc_const", | 1778 | "__objc_const", |
| 1786 | sect.size, | 1779 | sect.size, |
| ... | @@ -1795,7 +1788,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1795,7 +1788,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1795 | }; | 1788 | }; |
| 1796 | } else if (mem.eql(u8, sectname, "__objc_classrefs")) { | 1789 | } else if (mem.eql(u8, sectname, "__objc_classrefs")) { |
| 1797 | if (self.objc_classrefs_section_index == null) { | 1790 | if (self.objc_classrefs_section_index == null) { |
| 1798 | self.objc_classrefs_section_index = try self.allocateSection( | 1791 | self.objc_classrefs_section_index = try self.initSection( |
| 1799 | self.data_segment_cmd_index.?, | 1792 | self.data_segment_cmd_index.?, |
| 1800 | "__objc_classrefs", | 1793 | "__objc_classrefs", |
| 1801 | sect.size, | 1794 | sect.size, |
| ... | @@ -1810,7 +1803,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1810,7 +1803,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1810 | }; | 1803 | }; |
| 1811 | } else if (mem.eql(u8, sectname, "__objc_data")) { | 1804 | } else if (mem.eql(u8, sectname, "__objc_data")) { |
| 1812 | if (self.objc_data_section_index == null) { | 1805 | if (self.objc_data_section_index == null) { |
| 1813 | self.objc_data_section_index = try self.allocateSection( | 1806 | self.objc_data_section_index = try self.initSection( |
| 1814 | self.data_segment_cmd_index.?, | 1807 | self.data_segment_cmd_index.?, |
| 1815 | "__objc_data", | 1808 | "__objc_data", |
| 1816 | sect.size, | 1809 | sect.size, |
| ... | @@ -1825,7 +1818,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1825,7 +1818,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1825 | }; | 1818 | }; |
| 1826 | } else { | 1819 | } else { |
| 1827 | if (self.data_section_index == null) { | 1820 | if (self.data_section_index == null) { |
| 1828 | self.data_section_index = try self.allocateSection( | 1821 | self.data_section_index = try self.initSection( |
| 1829 | self.data_segment_cmd_index.?, | 1822 | self.data_segment_cmd_index.?, |
| 1830 | "__data", | 1823 | "__data", |
| 1831 | sect.size, | 1824 | sect.size, |
| ... | @@ -1881,7 +1874,64 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void { | ... | @@ -1881,7 +1874,64 @@ pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 1881 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); | 1874 | try self.base.file.?.pwriteAll(atom.code.items, file_offset); |
| 1882 | } | 1875 | } |
| 1883 | | 1876 | |
| 1884 | fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void { | 1877 | fn allocateLocals(self: *MachO) !void { |
| | 1878 | var it = self.atoms.iterator(); |
| | 1879 | while (it.next()) |entry| { |
| | 1880 | const match = entry.key_ptr.*; |
| | 1881 | var atom = entry.value_ptr.*; |
| | 1882 | |
| | 1883 | while (atom.prev) |prev| { |
| | 1884 | atom = prev; |
| | 1885 | } |
| | 1886 | |
| | 1887 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| | 1888 | const seg = self.load_commands.items[match.seg].Segment; |
| | 1889 | const sect = seg.sections.items[match.sect]; |
| | 1890 | var base_vaddr = sect.addr; |
| | 1891 | |
| | 1892 | log.debug("allocating local symbols in {s},{s}", .{ |
| | 1893 | commands.segmentName(sect), |
| | 1894 | commands.sectionName(sect), |
| | 1895 | }); |
| | 1896 | |
| | 1897 | while (true) { |
| | 1898 | const alignment = try math.powi(u32, 2, atom.alignment); |
| | 1899 | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); |
| | 1900 | |
| | 1901 | const sym = &self.locals.items[atom.local_sym_index]; |
| | 1902 | sym.n_value = base_vaddr; |
| | 1903 | sym.n_sect = n_sect; |
| | 1904 | |
| | 1905 | log.debug(" {d}: {s} allocated at 0x{x}", .{ |
| | 1906 | atom.local_sym_index, |
| | 1907 | self.getString(sym.n_strx), |
| | 1908 | base_vaddr, |
| | 1909 | }); |
| | 1910 | |
| | 1911 | // Update each alias (if any) |
| | 1912 | for (atom.aliases.items) |index| { |
| | 1913 | const alias_sym = &self.locals.items[index]; |
| | 1914 | alias_sym.n_value = base_vaddr; |
| | 1915 | alias_sym.n_sect = n_sect; |
| | 1916 | } |
| | 1917 | |
| | 1918 | // Update each symbol contained within the atom |
| | 1919 | for (atom.contained.items) |sym_at_off| { |
| | 1920 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| | 1921 | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| | 1922 | contained_sym.n_sect = n_sect; |
| | 1923 | } |
| | 1924 | |
| | 1925 | base_vaddr += atom.size; |
| | 1926 | |
| | 1927 | if (atom.next) |next| { |
| | 1928 | atom = next; |
| | 1929 | } else break; |
| | 1930 | } |
| | 1931 | } |
| | 1932 | } |
| | 1933 | |
| | 1934 | fn shiftLocalsByOffset(self: *MachO, match: MatchingSection, offset: i64) !void { |
| 1885 | var atom = self.atoms.get(match) orelse return; | 1935 | var atom = self.atoms.get(match) orelse return; |
| 1886 | | 1936 | |
| 1887 | while (true) { | 1937 | while (true) { |
| ... | @@ -1904,7 +1954,9 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void | ... | @@ -1904,7 +1954,9 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void |
| 1904 | } | 1954 | } |
| 1905 | } | 1955 | } |
| 1906 | | 1956 | |
| 1907 | fn allocateGlobalSymbols(self: *MachO) !void { | 1957 | fn allocateGlobals(self: *MachO) !void { |
| | 1958 | log.debug("allocating global symbols", .{}); |
| | 1959 | |
| 1908 | var sym_it = self.symbol_resolver.valueIterator(); | 1960 | var sym_it = self.symbol_resolver.valueIterator(); |
| 1909 | while (sym_it.next()) |resolv| { | 1961 | while (sym_it.next()) |resolv| { |
| 1910 | if (resolv.where != .global) continue; | 1962 | if (resolv.where != .global) continue; |
| ... | @@ -1914,7 +1966,60 @@ fn allocateGlobalSymbols(self: *MachO) !void { | ... | @@ -1914,7 +1966,60 @@ fn allocateGlobalSymbols(self: *MachO) !void { |
| 1914 | const sym = &self.globals.items[resolv.where_index]; | 1966 | const sym = &self.globals.items[resolv.where_index]; |
| 1915 | sym.n_value = local_sym.n_value; | 1967 | sym.n_value = local_sym.n_value; |
| 1916 | sym.n_sect = local_sym.n_sect; | 1968 | sym.n_sect = local_sym.n_sect; |
| 1917 | log.debug("allocating global symbol {s} at 0x{x}", .{ self.getString(sym.n_strx), local_sym.n_value }); | 1969 | |
| | 1970 | log.debug(" {d}: {s} allocated at 0x{x}", .{ |
| | 1971 | resolv.where_index, |
| | 1972 | self.getString(sym.n_strx), |
| | 1973 | local_sym.n_value, |
| | 1974 | }); |
| | 1975 | } |
| | 1976 | } |
| | 1977 | |
| | 1978 | fn writeAllAtoms(self: *MachO) !void { |
| | 1979 | var it = self.atoms.iterator(); |
| | 1980 | while (it.next()) |entry| { |
| | 1981 | const match = entry.key_ptr.*; |
| | 1982 | const seg = self.load_commands.items[match.seg].Segment; |
| | 1983 | const sect = seg.sections.items[match.sect]; |
| | 1984 | var atom: *Atom = entry.value_ptr.*; |
| | 1985 | |
| | 1986 | var buffer = std.ArrayList(u8).init(self.base.allocator); |
| | 1987 | defer buffer.deinit(); |
| | 1988 | try buffer.ensureTotalCapacity(sect.size); |
| | 1989 | |
| | 1990 | log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| | 1991 | |
| | 1992 | while (atom.prev) |prev| { |
| | 1993 | atom = prev; |
| | 1994 | } |
| | 1995 | |
| | 1996 | while (true) { |
| | 1997 | const atom_sym = self.locals.items[atom.local_sym_index]; |
| | 1998 | const padding_size: usize = if (atom.next) |next| blk: { |
| | 1999 | const next_sym = self.locals.items[next.local_sym_index]; |
| | 2000 | const size = next_sym.n_value - (atom_sym.n_value + atom.size); |
| | 2001 | break :blk try math.cast(usize, size); |
| | 2002 | } else 0; |
| | 2003 | |
| | 2004 | log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym }); |
| | 2005 | |
| | 2006 | try atom.resolveRelocs(self); |
| | 2007 | buffer.appendSliceAssumeCapacity(atom.code.items); |
| | 2008 | |
| | 2009 | var i: usize = 0; |
| | 2010 | while (i < padding_size) : (i += 1) { |
| | 2011 | buffer.appendAssumeCapacity(0); |
| | 2012 | } |
| | 2013 | |
| | 2014 | if (atom.next) |next| { |
| | 2015 | atom = next; |
| | 2016 | } else { |
| | 2017 | assert(buffer.items.len == sect.size); |
| | 2018 | log.debug(" (writing at file offset 0x{x})", .{sect.offset}); |
| | 2019 | try self.base.file.?.pwriteAll(buffer.items, sect.offset); |
| | 2020 | break; |
| | 2021 | } |
| | 2022 | } |
| 1918 | } | 2023 | } |
| 1919 | } | 2024 | } |
| 1920 | | 2025 | |
| ... | @@ -1962,6 +2067,7 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1962,6 +2067,7 @@ fn writeAtoms(self: *MachO) !void { |
| 1962 | atom.dirty = false; | 2067 | atom.dirty = false; |
| 1963 | } else { | 2068 | } else { |
| 1964 | if (file_offset) |off| { | 2069 | if (file_offset) |off| { |
| | 2070 | log.debug(" (writing at file offset 0x{x})", .{off}); |
| 1965 | try self.base.file.?.pwriteAll(buffer.items, off); | 2071 | try self.base.file.?.pwriteAll(buffer.items, off); |
| 1966 | } | 2072 | } |
| 1967 | file_offset = null; | 2073 | file_offset = null; |
| ... | @@ -1972,6 +2078,7 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1972,6 +2078,7 @@ fn writeAtoms(self: *MachO) !void { |
| 1972 | atom = next; | 2078 | atom = next; |
| 1973 | } else { | 2079 | } else { |
| 1974 | if (file_offset) |off| { | 2080 | if (file_offset) |off| { |
| | 2081 | log.debug(" (writing at file offset 0x{x})", .{off}); |
| 1975 | try self.base.file.?.pwriteAll(buffer.items, off); | 2082 | try self.base.file.?.pwriteAll(buffer.items, off); |
| 1976 | } | 2083 | } |
| 1977 | file_offset = null; | 2084 | file_offset = null; |
| ... | @@ -2036,10 +2143,13 @@ fn createDyldPrivateAtom(self: *MachO) !void { | ... | @@ -2036,10 +2143,13 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 2036 | .seg = self.data_segment_cmd_index.?, | 2143 | .seg = self.data_segment_cmd_index.?, |
| 2037 | .sect = self.data_section_index.?, | 2144 | .sect = self.data_section_index.?, |
| 2038 | }; | 2145 | }; |
| 2039 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); | 2146 | if (self.needs_prealloc) { |
| 2040 | sym.n_value = vaddr; | 2147 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| | 2148 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| | 2149 | sym.n_value = vaddr; |
| | 2150 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| | 2151 | |
| 2041 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 2152 | 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 | } | 2153 | } |
| 2044 | | 2154 | |
| 2045 | fn createStubHelperPreambleAtom(self: *MachO) !void { | 2155 | fn createStubHelperPreambleAtom(self: *MachO) !void { |
| ... | @@ -2165,11 +2275,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { | ... | @@ -2165,11 +2275,15 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2165 | .seg = self.text_segment_cmd_index.?, | 2275 | .seg = self.text_segment_cmd_index.?, |
| 2166 | .sect = self.stub_helper_section_index.?, | 2276 | .sect = self.stub_helper_section_index.?, |
| 2167 | }; | 2277 | }; |
| 2168 | const alignment_pow_2 = try math.powi(u32, 2, atom.alignment); | 2278 | |
| 2169 | const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match); | 2279 | if (self.needs_prealloc) { |
| 2170 | sym.n_value = vaddr; | 2280 | const alignment_pow_2 = try math.powi(u32, 2, atom.alignment); |
| | 2281 | const vaddr = try self.allocateAtom(atom, atom.size, alignment_pow_2, match); |
| | 2282 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| | 2283 | sym.n_value = vaddr; |
| | 2284 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| | 2285 | |
| 2171 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 2286 | 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 | } | 2287 | } |
| 2174 | | 2288 | |
| 2175 | pub fn createStubHelperAtom(self: *MachO) !*Atom { | 2289 | pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| ... | @@ -2377,10 +2491,13 @@ fn createTentativeDefAtoms(self: *MachO) !void { | ... | @@ -2377,10 +2491,13 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2377 | resolv.local_sym_index = local_sym_index; | 2491 | resolv.local_sym_index = local_sym_index; |
| 2378 | | 2492 | |
| 2379 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); | 2493 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); |
| 2380 | const alignment_pow_2 = try math.powi(u32, 2, alignment); | 2494 | |
| 2381 | const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match); | 2495 | if (self.needs_prealloc) { |
| 2382 | local_sym.n_value = vaddr; | 2496 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 2383 | global_sym.n_value = vaddr; | 2497 | const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match); |
| | 2498 | local_sym.n_value = vaddr; |
| | 2499 | global_sym.n_value = vaddr; |
| | 2500 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2384 | } | 2501 | } |
| 2385 | } | 2502 | } |
| 2386 | | 2503 | |
| ... | @@ -2429,10 +2546,11 @@ fn createDsoHandleAtom(self: *MachO) !void { | ... | @@ -2429,10 +2546,11 @@ fn createDsoHandleAtom(self: *MachO) !void { |
| 2429 | // TODO perhaps we should special-case special symbols? Create a separate | 2546 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2430 | // linked list of atoms? | 2547 | // linked list of atoms? |
| 2431 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | 2548 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2432 | const sym = &self.locals.items[local_sym_index]; | 2549 | if (self.needs_prealloc) { |
| 2433 | const vaddr = try self.allocateAtom(atom, 0, 1, match); | 2550 | const sym = &self.locals.items[local_sym_index]; |
| 2434 | sym.n_value = vaddr; | 2551 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| 2435 | atom.dirty = false; // We don't really want to write it to file. | 2552 | sym.n_value = vaddr; |
| | 2553 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| 2436 | } | 2554 | } |
| 2437 | } | 2555 | } |
| 2438 | | 2556 | |
| ... | @@ -2466,12 +2584,11 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2466,12 +2584,11 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2466 | return error.UnhandledSymbolType; | 2584 | return error.UnhandledSymbolType; |
| 2467 | } | 2585 | } |
| 2468 | | 2586 | |
| 2469 | const n_strx = try self.makeString(sym_name); | | |
| 2470 | if (sym.sect()) { | 2587 | if (sym.sect()) { |
| 2471 | // Defined symbol regardless of scope lands in the locals symbol table. | 2588 | // Defined symbol regardless of scope lands in the locals symbol table. |
| 2472 | const local_sym_index = @intCast(u32, self.locals.items.len); | 2589 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2473 | try self.locals.append(self.base.allocator, .{ | 2590 | try self.locals.append(self.base.allocator, .{ |
| 2474 | .n_strx = n_strx, | 2591 | .n_strx = if (symbolIsTemp(sym, sym_name)) 0 else try self.makeString(sym_name), |
| 2475 | .n_type = macho.N_SECT, | 2592 | .n_type = macho.N_SECT, |
| 2476 | .n_sect = 0, | 2593 | .n_sect = 0, |
| 2477 | .n_desc = 0, | 2594 | .n_desc = 0, |
| ... | @@ -2484,6 +2601,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2484,6 +2601,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2484 | // if we should save the symbol as a global, or potentially flag the error. | 2601 | // if we should save the symbol as a global, or potentially flag the error. |
| 2485 | if (!sym.ext()) continue; | 2602 | if (!sym.ext()) continue; |
| 2486 | | 2603 | |
| | 2604 | const n_strx = try self.makeString(sym_name); |
| 2487 | const local = self.locals.items[local_sym_index]; | 2605 | const local = self.locals.items[local_sym_index]; |
| 2488 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { | 2606 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 2489 | const global_sym_index = @intCast(u32, self.globals.items.len); | 2607 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| ... | @@ -2554,6 +2672,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2554,6 +2672,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2554 | }; | 2672 | }; |
| 2555 | } else if (sym.tentative()) { | 2673 | } else if (sym.tentative()) { |
| 2556 | // Symbol is a tentative definition. | 2674 | // Symbol is a tentative definition. |
| | 2675 | const n_strx = try self.makeString(sym_name); |
| 2557 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { | 2676 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse { |
| 2558 | const global_sym_index = @intCast(u32, self.globals.items.len); | 2677 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| 2559 | try self.globals.append(self.base.allocator, .{ | 2678 | try self.globals.append(self.base.allocator, .{ |
| ... | @@ -2611,6 +2730,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | ... | @@ -2611,6 +2730,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2611 | } | 2730 | } |
| 2612 | } else { | 2731 | } else { |
| 2613 | // Symbol is undefined. | 2732 | // Symbol is undefined. |
| | 2733 | const n_strx = try self.makeString(sym_name); |
| 2614 | if (self.symbol_resolver.contains(n_strx)) continue; | 2734 | if (self.symbol_resolver.contains(n_strx)) continue; |
| 2615 | | 2735 | |
| 2616 | const undef_sym_index = @intCast(u32, self.undefs.items.len); | 2736 | const undef_sym_index = @intCast(u32, self.undefs.items.len); |
| ... | @@ -2771,10 +2891,13 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { | ... | @@ -2771,10 +2891,13 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { |
| 2771 | }); | 2891 | }); |
| 2772 | | 2892 | |
| 2773 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | 2893 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); |
| 2774 | const sym = &self.locals.items[local_sym_index]; | 2894 | |
| 2775 | const vaddr = try self.allocateAtom(atom, 0, 1, match); | 2895 | if (self.needs_prealloc) { |
| 2776 | sym.n_value = vaddr; | 2896 | const sym = &self.locals.items[local_sym_index]; |
| 2777 | atom.dirty = false; | 2897 | const vaddr = try self.allocateAtom(atom, 0, 1, match); |
| | 2898 | sym.n_value = vaddr; |
| | 2899 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| | 2900 | |
| 2778 | self.mh_execute_header_index = local_sym_index; | 2901 | self.mh_execute_header_index = local_sym_index; |
| 2779 | } | 2902 | } |
| 2780 | | 2903 | |
| ... | @@ -2828,13 +2951,19 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2828,13 +2951,19 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2828 | .sect = self.got_section_index.?, | 2951 | .sect = self.got_section_index.?, |
| 2829 | }; | 2952 | }; |
| 2830 | const atom_sym = &self.locals.items[atom.local_sym_index]; | 2953 | const atom_sym = &self.locals.items[atom.local_sym_index]; |
| 2831 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); | 2954 | |
| 2832 | atom_sym.n_value = vaddr; | 2955 | if (self.needs_prealloc) { |
| | 2956 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| | 2957 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| | 2958 | atom_sym.n_value = vaddr; |
| | 2959 | } else try self.addAtomAndBumpSectionSize(atom, match); |
| | 2960 | |
| 2833 | atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 2961 | 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 | } | 2962 | } |
| 2836 | | 2963 | |
| 2837 | fn parseObjectsIntoAtoms(self: *MachO) !void { | 2964 | fn parseObjectsIntoAtoms(self: *MachO) !void { |
| | 2965 | // TODO I need to see if I can simplify this logic, or perhaps split it into two functions: |
| | 2966 | // one for non-prealloc traditional path, and one for incremental prealloc path. |
| 2838 | const tracy = trace(@src()); | 2967 | const tracy = trace(@src()); |
| 2839 | defer tracy.end(); | 2968 | defer tracy.end(); |
| 2840 | | 2969 | |
| ... | @@ -2858,20 +2987,31 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { | ... | @@ -2858,20 +2987,31 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2858 | var it = object.end_atoms.iterator(); | 2987 | var it = object.end_atoms.iterator(); |
| 2859 | while (it.next()) |entry| { | 2988 | while (it.next()) |entry| { |
| 2860 | const match = entry.key_ptr.*; | 2989 | const match = entry.key_ptr.*; |
| 2861 | const last_atom = entry.value_ptr.*; | 2990 | var atom = entry.value_ptr.*; |
| 2862 | var atom = last_atom; | 2991 | |
| | 2992 | while (atom.prev) |prev| { |
| | 2993 | atom = prev; |
| | 2994 | } |
| | 2995 | |
| | 2996 | const first_atom = atom; |
| 2863 | | 2997 | |
| | 2998 | const seg = self.load_commands.items[match.seg].Segment; |
| | 2999 | const sect = seg.sections.items[match.sect]; |
| 2864 | const metadata = try section_metadata.getOrPut(match); | 3000 | const metadata = try section_metadata.getOrPut(match); |
| 2865 | if (!metadata.found_existing) { | 3001 | if (!metadata.found_existing) { |
| 2866 | metadata.value_ptr.* = .{ | 3002 | metadata.value_ptr.* = .{ |
| 2867 | .size = 0, | 3003 | .size = sect.size, |
| 2868 | .alignment = 0, | 3004 | .alignment = sect.@"align", |
| 2869 | }; | 3005 | }; |
| 2870 | } | 3006 | } |
| 2871 | | 3007 | |
| | 3008 | log.debug("{s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); |
| | 3009 | |
| 2872 | while (true) { | 3010 | while (true) { |
| 2873 | const alignment = try math.powi(u32, 2, atom.alignment); | 3011 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 2874 | metadata.value_ptr.size += mem.alignForwardGeneric(u64, atom.size, alignment); | 3012 | const curr_size = metadata.value_ptr.size; |
| | 3013 | const curr_size_aligned = mem.alignForwardGeneric(u64, curr_size, alignment); |
| | 3014 | metadata.value_ptr.size = curr_size_aligned + atom.size; |
| 2875 | metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment); | 3015 | metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment); |
| 2876 | | 3016 | |
| 2877 | const sym = self.locals.items[atom.local_sym_index]; | 3017 | const sym = self.locals.items[atom.local_sym_index]; |
| ... | @@ -2882,20 +3022,20 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { | ... | @@ -2882,20 +3022,20 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2882 | atom.alignment, | 3022 | atom.alignment, |
| 2883 | }); | 3023 | }); |
| 2884 | | 3024 | |
| 2885 | if (atom.prev) |prev| { | 3025 | if (atom.next) |next| { |
| 2886 | atom = prev; | 3026 | atom = next; |
| 2887 | } else break; | 3027 | } else break; |
| 2888 | } | 3028 | } |
| 2889 | | 3029 | |
| 2890 | if (parsed_atoms.getPtr(match)) |last| { | 3030 | if (parsed_atoms.getPtr(match)) |last| { |
| 2891 | last.*.next = atom; | 3031 | last.*.next = first_atom; |
| 2892 | atom.prev = last.*; | 3032 | first_atom.prev = last.*; |
| 2893 | last.* = atom; | 3033 | last.* = first_atom; |
| 2894 | } | 3034 | } |
| 2895 | _ = try parsed_atoms.put(match, last_atom); | 3035 | _ = try parsed_atoms.put(match, atom); |
| 2896 | | 3036 | |
| 2897 | if (!first_atoms.contains(match)) { | 3037 | if (!first_atoms.contains(match)) { |
| 2898 | try first_atoms.putNoClobber(match, atom); | 3038 | try first_atoms.putNoClobber(match, first_atom); |
| 2899 | } | 3039 | } |
| 2900 | } | 3040 | } |
| 2901 | | 3041 | |
| ... | @@ -2915,67 +3055,85 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { | ... | @@ -2915,67 +3055,85 @@ fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2915 | metadata.alignment, | 3055 | metadata.alignment, |
| 2916 | }); | 3056 | }); |
| 2917 | | 3057 | |
| 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); | 3058 | sect.@"align" = math.max(sect.@"align", metadata.alignment); |
| 2924 | const needed_size = @intCast(u32, metadata.size + sect_size); | 3059 | const needed_size = @intCast(u32, metadata.size); |
| 2925 | try self.growSection(match, needed_size); | 3060 | |
| | 3061 | if (self.needs_prealloc) { |
| | 3062 | try self.growSection(match, needed_size); |
| | 3063 | } |
| 2926 | sect.size = needed_size; | 3064 | sect.size = needed_size; |
| | 3065 | } |
| 2927 | | 3066 | |
| 2928 | var base_vaddr = if (self.atoms.get(match)) |last| blk: { | 3067 | for (&[_]?u16{ |
| 2929 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 3068 | self.text_segment_cmd_index, |
| 2930 | break :blk last_atom_sym.n_value + last.size; | 3069 | self.data_const_segment_cmd_index, |
| 2931 | } else sect.addr; | 3070 | self.data_segment_cmd_index, |
| 2932 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 3071 | }) |maybe_seg_id| { |
| | 3072 | const seg_id = maybe_seg_id orelse continue; |
| | 3073 | const seg = self.load_commands.items[seg_id].Segment; |
| 2933 | | 3074 | |
| 2934 | var atom = first_atoms.get(match).?; | 3075 | for (seg.sections.items) |sect, sect_id| { |
| 2935 | while (true) { | 3076 | const match = MatchingSection{ |
| 2936 | const alignment = try math.powi(u32, 2, atom.alignment); | 3077 | .seg = seg_id, |
| 2937 | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); | 3078 | .sect = @intCast(u16, sect_id), |
| | 3079 | }; |
| | 3080 | if (!section_metadata.contains(match)) continue; |
| | 3081 | |
| | 3082 | var base_vaddr = if (self.atoms.get(match)) |last| blk: { |
| | 3083 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| | 3084 | break :blk last_atom_sym.n_value + last.size; |
| | 3085 | } else sect.addr; |
| | 3086 | |
| | 3087 | if (self.atoms.getPtr(match)) |last| { |
| | 3088 | const first_atom = first_atoms.get(match).?; |
| | 3089 | last.*.next = first_atom; |
| | 3090 | first_atom.prev = last.*; |
| | 3091 | last.* = first_atom; |
| | 3092 | } |
| | 3093 | _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?); |
| 2938 | | 3094 | |
| 2939 | const sym = &self.locals.items[atom.local_sym_index]; | 3095 | if (!self.needs_prealloc) continue; |
| 2940 | sym.n_value = base_vaddr; | | |
| 2941 | sym.n_sect = n_sect; | | |
| 2942 | | 3096 | |
| 2943 | log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{ | 3097 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2944 | self.getString(sym.n_strx), | | |
| 2945 | base_vaddr, | | |
| 2946 | base_vaddr + atom.size, | | |
| 2947 | atom.size, | | |
| 2948 | atom.alignment, | | |
| 2949 | }); | | |
| 2950 | | 3098 | |
| 2951 | // Update each alias (if any) | 3099 | var atom = first_atoms.get(match).?; |
| 2952 | for (atom.aliases.items) |index| { | 3100 | while (true) { |
| 2953 | const alias_sym = &self.locals.items[index]; | 3101 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 2954 | alias_sym.n_value = base_vaddr; | 3102 | base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment); |
| 2955 | alias_sym.n_sect = n_sect; | | |
| 2956 | } | | |
| 2957 | | 3103 | |
| 2958 | // Update each symbol contained within the atom | 3104 | const sym = &self.locals.items[atom.local_sym_index]; |
| 2959 | for (atom.contained.items) |sym_at_off| { | 3105 | sym.n_value = base_vaddr; |
| 2960 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; | 3106 | sym.n_sect = n_sect; |
| 2961 | contained_sym.n_value = base_vaddr + sym_at_off.offset; | | |
| 2962 | contained_sym.n_sect = n_sect; | | |
| 2963 | } | | |
| 2964 | | 3107 | |
| 2965 | base_vaddr += atom.size; | 3108 | log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{ |
| | 3109 | self.getString(sym.n_strx), |
| | 3110 | base_vaddr, |
| | 3111 | base_vaddr + atom.size, |
| | 3112 | atom.size, |
| | 3113 | atom.alignment, |
| | 3114 | }); |
| 2966 | | 3115 | |
| 2967 | if (atom.next) |next| { | 3116 | // Update each alias (if any) |
| 2968 | atom = next; | 3117 | for (atom.aliases.items) |index| { |
| 2969 | } else break; | 3118 | const alias_sym = &self.locals.items[index]; |
| 2970 | } | 3119 | alias_sym.n_value = base_vaddr; |
| | 3120 | alias_sym.n_sect = n_sect; |
| | 3121 | } |
| | 3122 | |
| | 3123 | // Update each symbol contained within the atom |
| | 3124 | for (atom.contained.items) |sym_at_off| { |
| | 3125 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| | 3126 | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| | 3127 | contained_sym.n_sect = n_sect; |
| | 3128 | } |
| | 3129 | |
| | 3130 | base_vaddr += atom.size; |
| 2971 | | 3131 | |
| 2972 | if (self.atoms.getPtr(match)) |last| { | 3132 | if (atom.next) |next| { |
| 2973 | const first_atom = first_atoms.get(match).?; | 3133 | atom = next; |
| 2974 | last.*.next = first_atom; | 3134 | } else break; |
| 2975 | first_atom.prev = last.*; | 3135 | } |
| 2976 | last.* = first_atom; | | |
| 2977 | } | 3136 | } |
| 2978 | _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?); | | |
| 2979 | } | 3137 | } |
| 2980 | } | 3138 | } |
| 2981 | | 3139 | |
| ... | @@ -3714,7 +3872,9 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { | ... | @@ -3714,7 +3872,9 @@ pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 { |
| 3714 | return self.locals.items[decl.link.macho.local_sym_index].n_value; | 3872 | return self.locals.items[decl.link.macho.local_sym_index].n_value; |
| 3715 | } | 3873 | } |
| 3716 | | 3874 | |
| 3717 | pub fn populateMissingMetadata(self: *MachO) !void { | 3875 | fn populateMissingMetadata(self: *MachO) !void { |
| | 3876 | const cpu_arch = self.base.options.target.cpu.arch; |
| | 3877 | |
| 3718 | if (self.pagezero_segment_cmd_index == null) { | 3878 | if (self.pagezero_segment_cmd_index == null) { |
| 3719 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 3879 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3720 | try self.load_commands.append(self.base.allocator, .{ | 3880 | try self.load_commands.append(self.base.allocator, .{ |
| ... | @@ -3730,13 +3890,14 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3730,13 +3890,14 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3730 | | 3890 | |
| 3731 | if (self.text_segment_cmd_index == null) { | 3891 | if (self.text_segment_cmd_index == null) { |
| 3732 | self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 3892 | 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; | 3893 | const needed_size = if (self.needs_prealloc) blk: { |
| 3734 | const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint; | 3894 | 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; | 3895 | 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); | 3896 | const ideal_size = self.header_pad + program_code_size_hint + got_size_hint; |
| 3737 | | 3897 | 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 }); | 3898 | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| 3739 | | 3899 | break :blk needed_size; |
| | 3900 | } else 0; |
| 3740 | try self.load_commands.append(self.base.allocator, .{ | 3901 | try self.load_commands.append(self.base.allocator, .{ |
| 3741 | .Segment = .{ | 3902 | .Segment = .{ |
| 3742 | .inner = .{ | 3903 | .inner = .{ |
| ... | @@ -3753,13 +3914,13 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3753,13 +3914,13 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3753 | } | 3914 | } |
| 3754 | | 3915 | |
| 3755 | if (self.text_section_index == null) { | 3916 | if (self.text_section_index == null) { |
| 3756 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { | 3917 | const alignment: u2 = switch (cpu_arch) { |
| 3757 | .x86_64 => 0, | 3918 | .x86_64 => 0, |
| 3758 | .aarch64 => 2, | 3919 | .aarch64 => 2, |
| 3759 | else => unreachable, // unhandled architecture type | 3920 | else => unreachable, // unhandled architecture type |
| 3760 | }; | 3921 | }; |
| 3761 | const needed_size = self.base.options.program_code_size_hint; | 3922 | const needed_size = if (self.needs_prealloc) self.base.options.program_code_size_hint else 0; |
| 3762 | self.text_section_index = try self.allocateSection( | 3923 | self.text_section_index = try self.initSection( |
| 3763 | self.text_segment_cmd_index.?, | 3924 | self.text_segment_cmd_index.?, |
| 3764 | "__text", | 3925 | "__text", |
| 3765 | needed_size, | 3926 | needed_size, |
| ... | @@ -3771,18 +3932,18 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3771,18 +3932,18 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3771 | } | 3932 | } |
| 3772 | | 3933 | |
| 3773 | if (self.stubs_section_index == null) { | 3934 | if (self.stubs_section_index == null) { |
| 3774 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { | 3935 | const alignment: u2 = switch (cpu_arch) { |
| 3775 | .x86_64 => 0, | 3936 | .x86_64 => 0, |
| 3776 | .aarch64 => 2, | 3937 | .aarch64 => 2, |
| 3777 | else => unreachable, // unhandled architecture type | 3938 | else => unreachable, // unhandled architecture type |
| 3778 | }; | 3939 | }; |
| 3779 | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { | 3940 | const stub_size: u4 = switch (cpu_arch) { |
| 3780 | .x86_64 => 6, | 3941 | .x86_64 => 6, |
| 3781 | .aarch64 => 3 * @sizeOf(u32), | 3942 | .aarch64 => 3 * @sizeOf(u32), |
| 3782 | else => unreachable, // unhandled architecture type | 3943 | else => unreachable, // unhandled architecture type |
| 3783 | }; | 3944 | }; |
| 3784 | const needed_size = stub_size * self.base.options.symbol_count_hint; | 3945 | 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( | 3946 | self.stubs_section_index = try self.initSection( |
| 3786 | self.text_segment_cmd_index.?, | 3947 | self.text_segment_cmd_index.?, |
| 3787 | "__stubs", | 3948 | "__stubs", |
| 3788 | needed_size, | 3949 | needed_size, |
| ... | @@ -3795,23 +3956,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3795,23 +3956,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3795 | } | 3956 | } |
| 3796 | | 3957 | |
| 3797 | if (self.stub_helper_section_index == null) { | 3958 | if (self.stub_helper_section_index == null) { |
| 3798 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { | 3959 | const alignment: u2 = switch (cpu_arch) { |
| 3799 | .x86_64 => 0, | 3960 | .x86_64 => 0, |
| 3800 | .aarch64 => 2, | 3961 | .aarch64 => 2, |
| 3801 | else => unreachable, // unhandled architecture type | 3962 | else => unreachable, // unhandled architecture type |
| 3802 | }; | 3963 | }; |
| 3803 | const preamble_size: u6 = switch (self.base.options.target.cpu.arch) { | 3964 | const preamble_size: u6 = switch (cpu_arch) { |
| 3804 | .x86_64 => 15, | 3965 | .x86_64 => 15, |
| 3805 | .aarch64 => 6 * @sizeOf(u32), | 3966 | .aarch64 => 6 * @sizeOf(u32), |
| 3806 | else => unreachable, | 3967 | else => unreachable, |
| 3807 | }; | 3968 | }; |
| 3808 | const stub_size: u4 = switch (self.base.options.target.cpu.arch) { | 3969 | const stub_size: u4 = switch (cpu_arch) { |
| 3809 | .x86_64 => 10, | 3970 | .x86_64 => 10, |
| 3810 | .aarch64 => 3 * @sizeOf(u32), | 3971 | .aarch64 => 3 * @sizeOf(u32), |
| 3811 | else => unreachable, | 3972 | else => unreachable, |
| 3812 | }; | 3973 | }; |
| 3813 | const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size; | 3974 | const needed_size = if (self.needs_prealloc) |
| 3814 | self.stub_helper_section_index = try self.allocateSection( | 3975 | stub_size * self.base.options.symbol_count_hint + preamble_size |
| | 3976 | else |
| | 3977 | 0; |
| | 3978 | self.stub_helper_section_index = try self.initSection( |
| 3815 | self.text_segment_cmd_index.?, | 3979 | self.text_segment_cmd_index.?, |
| 3816 | "__stub_helper", | 3980 | "__stub_helper", |
| 3817 | needed_size, | 3981 | needed_size, |
| ... | @@ -3824,22 +3988,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3824,22 +3988,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3824 | | 3988 | |
| 3825 | if (self.data_const_segment_cmd_index == null) { | 3989 | if (self.data_const_segment_cmd_index == null) { |
| 3826 | self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 3990 | self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3827 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 3991 | var vmaddr: u64 = 0; |
| 3828 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 3992 | var fileoff: u64 = 0; |
| 3829 | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); | 3993 | var needed_size: u64 = 0; |
| 3830 | | 3994 | if (self.needs_prealloc) { |
| 3831 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ | 3995 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3832 | address_and_offset.offset, | 3996 | vmaddr = address_and_offset.address; |
| 3833 | address_and_offset.offset + needed_size, | 3997 | fileoff = address_and_offset.offset; |
| 3834 | }); | 3998 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 3835 | | 3999 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| | 4000 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ |
| | 4001 | fileoff, |
| | 4002 | fileoff + needed_size, |
| | 4003 | }); |
| | 4004 | } |
| 3836 | try self.load_commands.append(self.base.allocator, .{ | 4005 | try self.load_commands.append(self.base.allocator, .{ |
| 3837 | .Segment = .{ | 4006 | .Segment = .{ |
| 3838 | .inner = .{ | 4007 | .inner = .{ |
| 3839 | .segname = makeStaticString("__DATA_CONST"), | 4008 | .segname = makeStaticString("__DATA_CONST"), |
| 3840 | .vmaddr = address_and_offset.address, | 4009 | .vmaddr = vmaddr, |
| 3841 | .vmsize = needed_size, | 4010 | .vmsize = needed_size, |
| 3842 | .fileoff = address_and_offset.offset, | 4011 | .fileoff = fileoff, |
| 3843 | .filesize = needed_size, | 4012 | .filesize = needed_size, |
| 3844 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4013 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 3845 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4014 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| ... | @@ -3850,9 +4019,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3850,9 +4019,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3850 | } | 4019 | } |
| 3851 | | 4020 | |
| 3852 | if (self.got_section_index == null) { | 4021 | if (self.got_section_index == null) { |
| 3853 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4022 | const needed_size = if (self.needs_prealloc) |
| | 4023 | @sizeOf(u64) * self.base.options.symbol_count_hint |
| | 4024 | else |
| | 4025 | 0; |
| 3854 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | 4026 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3855 | self.got_section_index = try self.allocateSection( | 4027 | self.got_section_index = try self.initSection( |
| 3856 | self.data_const_segment_cmd_index.?, | 4028 | self.data_const_segment_cmd_index.?, |
| 3857 | "__got", | 4029 | "__got", |
| 3858 | needed_size, | 4030 | needed_size, |
| ... | @@ -3865,19 +4037,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3865,19 +4037,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3865 | | 4037 | |
| 3866 | if (self.data_segment_cmd_index == null) { | 4038 | if (self.data_segment_cmd_index == null) { |
| 3867 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 4039 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3868 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 4040 | var vmaddr: u64 = 0; |
| 3869 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; | 4041 | var fileoff: u64 = 0; |
| 3870 | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); | 4042 | var needed_size: u64 = 0; |
| 3871 | | 4043 | 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 }); | 4044 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| 3873 | | 4045 | vmaddr = address_and_offset.address; |
| | 4046 | fileoff = address_and_offset.offset; |
| | 4047 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; |
| | 4048 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| | 4049 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ |
| | 4050 | fileoff, |
| | 4051 | fileoff + needed_size, |
| | 4052 | }); |
| | 4053 | } |
| 3874 | try self.load_commands.append(self.base.allocator, .{ | 4054 | try self.load_commands.append(self.base.allocator, .{ |
| 3875 | .Segment = .{ | 4055 | .Segment = .{ |
| 3876 | .inner = .{ | 4056 | .inner = .{ |
| 3877 | .segname = makeStaticString("__DATA"), | 4057 | .segname = makeStaticString("__DATA"), |
| 3878 | .vmaddr = address_and_offset.address, | 4058 | .vmaddr = vmaddr, |
| 3879 | .vmsize = needed_size, | 4059 | .vmsize = needed_size, |
| 3880 | .fileoff = address_and_offset.offset, | 4060 | .fileoff = fileoff, |
| 3881 | .filesize = needed_size, | 4061 | .filesize = needed_size, |
| 3882 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4062 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 3883 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, | 4063 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| ... | @@ -3888,9 +4068,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3888,9 +4068,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3888 | } | 4068 | } |
| 3889 | | 4069 | |
| 3890 | if (self.la_symbol_ptr_section_index == null) { | 4070 | if (self.la_symbol_ptr_section_index == null) { |
| 3891 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4071 | const needed_size = if (self.needs_prealloc) |
| | 4072 | @sizeOf(u64) * self.base.options.symbol_count_hint |
| | 4073 | else |
| | 4074 | 0; |
| 3892 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) | 4075 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3893 | self.la_symbol_ptr_section_index = try self.allocateSection( | 4076 | self.la_symbol_ptr_section_index = try self.initSection( |
| 3894 | self.data_segment_cmd_index.?, | 4077 | self.data_segment_cmd_index.?, |
| 3895 | "__la_symbol_ptr", | 4078 | "__la_symbol_ptr", |
| 3896 | needed_size, | 4079 | needed_size, |
| ... | @@ -3902,9 +4085,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3902,9 +4085,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3902 | } | 4085 | } |
| 3903 | | 4086 | |
| 3904 | if (self.data_section_index == null) { | 4087 | if (self.data_section_index == null) { |
| 3905 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4088 | 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) | 4089 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3907 | self.data_section_index = try self.allocateSection( | 4090 | self.data_section_index = try self.initSection( |
| 3908 | self.data_segment_cmd_index.?, | 4091 | self.data_segment_cmd_index.?, |
| 3909 | "__data", | 4092 | "__data", |
| 3910 | needed_size, | 4093 | needed_size, |
| ... | @@ -3914,9 +4097,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3914,9 +4097,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3914 | } | 4097 | } |
| 3915 | | 4098 | |
| 3916 | if (self.tlv_section_index == null) { | 4099 | if (self.tlv_section_index == null) { |
| 3917 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4100 | 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) | 4101 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3919 | self.tlv_section_index = try self.allocateSection( | 4102 | self.tlv_section_index = try self.initSection( |
| 3920 | self.data_segment_cmd_index.?, | 4103 | self.data_segment_cmd_index.?, |
| 3921 | "__thread_vars", | 4104 | "__thread_vars", |
| 3922 | needed_size, | 4105 | needed_size, |
| ... | @@ -3928,9 +4111,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3928,9 +4111,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3928 | } | 4111 | } |
| 3929 | | 4112 | |
| 3930 | if (self.tlv_data_section_index == null) { | 4113 | if (self.tlv_data_section_index == null) { |
| 3931 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4114 | 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) | 4115 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3933 | self.tlv_data_section_index = try self.allocateSection( | 4116 | self.tlv_data_section_index = try self.initSection( |
| 3934 | self.data_segment_cmd_index.?, | 4117 | self.data_segment_cmd_index.?, |
| 3935 | "__thread_data", | 4118 | "__thread_data", |
| 3936 | needed_size, | 4119 | needed_size, |
| ... | @@ -3942,9 +4125,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3942,9 +4125,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3942 | } | 4125 | } |
| 3943 | | 4126 | |
| 3944 | if (self.tlv_bss_section_index == null) { | 4127 | if (self.tlv_bss_section_index == null) { |
| 3945 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4128 | 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) | 4129 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3947 | self.tlv_bss_section_index = try self.allocateSection( | 4130 | self.tlv_bss_section_index = try self.initSection( |
| 3948 | self.data_segment_cmd_index.?, | 4131 | self.data_segment_cmd_index.?, |
| 3949 | "__thread_bss", | 4132 | "__thread_bss", |
| 3950 | needed_size, | 4133 | needed_size, |
| ... | @@ -3959,9 +4142,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3959,9 +4142,9 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3959 | } | 4142 | } |
| 3960 | | 4143 | |
| 3961 | if (self.bss_section_index == null) { | 4144 | if (self.bss_section_index == null) { |
| 3962 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4145 | 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) | 4146 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 3964 | self.bss_section_index = try self.allocateSection( | 4147 | self.bss_section_index = try self.initSection( |
| 3965 | self.data_segment_cmd_index.?, | 4148 | self.data_segment_cmd_index.?, |
| 3966 | "__bss", | 4149 | "__bss", |
| 3967 | needed_size, | 4150 | needed_size, |
| ... | @@ -3977,16 +4160,20 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -3977,16 +4160,20 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3977 | | 4160 | |
| 3978 | if (self.linkedit_segment_cmd_index == null) { | 4161 | if (self.linkedit_segment_cmd_index == null) { |
| 3979 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 4162 | self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3980 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 4163 | var vmaddr: u64 = 0; |
| 3981 | | 4164 | var fileoff: u64 = 0; |
| 3982 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset}); | 4165 | if (self.needs_prealloc) { |
| 3983 | | 4166 | const address_and_offset = self.nextSegmentAddressAndOffset(); |
| | 4167 | vmaddr = address_and_offset.address; |
| | 4168 | fileoff = address_and_offset.offset; |
| | 4169 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff}); |
| | 4170 | } |
| 3984 | try self.load_commands.append(self.base.allocator, .{ | 4171 | try self.load_commands.append(self.base.allocator, .{ |
| 3985 | .Segment = .{ | 4172 | .Segment = .{ |
| 3986 | .inner = .{ | 4173 | .inner = .{ |
| 3987 | .segname = makeStaticString("__LINKEDIT"), | 4174 | .segname = makeStaticString("__LINKEDIT"), |
| 3988 | .vmaddr = address_and_offset.address, | 4175 | .vmaddr = vmaddr, |
| 3989 | .fileoff = address_and_offset.offset, | 4176 | .fileoff = fileoff, |
| 3990 | .maxprot = macho.VM_PROT_READ, | 4177 | .maxprot = macho.VM_PROT_READ, |
| 3991 | .initprot = macho.VM_PROT_READ, | 4178 | .initprot = macho.VM_PROT_READ, |
| 3992 | }, | 4179 | }, |
| ... | @@ -4198,44 +4385,123 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4198,44 +4385,123 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4198 | self.cold_start = true; | 4385 | self.cold_start = true; |
| 4199 | } | 4386 | } |
| 4200 | | 4387 | |
| 4201 | const AllocateSectionOpts = struct { | 4388 | fn allocateTextSegment(self: *MachO) !void { |
| | 4389 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4390 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; |
| | 4391 | seg.inner.fileoff = 0; |
| | 4392 | seg.inner.vmaddr = base_vmaddr; |
| | 4393 | |
| | 4394 | var sizeofcmds: u64 = 0; |
| | 4395 | for (self.load_commands.items) |lc| { |
| | 4396 | sizeofcmds += lc.cmdsize(); |
| | 4397 | } |
| | 4398 | |
| | 4399 | try self.allocateSegment(self.text_segment_cmd_index.?, @sizeOf(macho.mach_header_64) + sizeofcmds); |
| | 4400 | |
| | 4401 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. |
| | 4402 | var min_alignment: u32 = 0; |
| | 4403 | for (seg.sections.items) |sect| { |
| | 4404 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| | 4405 | min_alignment = math.max(min_alignment, alignment); |
| | 4406 | } |
| | 4407 | |
| | 4408 | assert(min_alignment > 0); |
| | 4409 | const last_sect_idx = seg.sections.items.len - 1; |
| | 4410 | const last_sect = seg.sections.items[last_sect_idx]; |
| | 4411 | const shift: u32 = blk: { |
| | 4412 | const diff = seg.inner.filesize - last_sect.offset - last_sect.size; |
| | 4413 | const factor = @divTrunc(diff, min_alignment); |
| | 4414 | break :blk @intCast(u32, factor * min_alignment); |
| | 4415 | }; |
| | 4416 | |
| | 4417 | if (shift > 0) { |
| | 4418 | for (seg.sections.items) |*sect| { |
| | 4419 | sect.offset += shift; |
| | 4420 | sect.addr += shift; |
| | 4421 | } |
| | 4422 | } |
| | 4423 | } |
| | 4424 | |
| | 4425 | fn allocateDataConstSegment(self: *MachO) !void { |
| | 4426 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 4427 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4428 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| | 4429 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; |
| | 4430 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); |
| | 4431 | } |
| | 4432 | |
| | 4433 | fn allocateDataSegment(self: *MachO) !void { |
| | 4434 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 4435 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 4436 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; |
| | 4437 | seg.inner.vmaddr = data_const_seg.inner.vmaddr + data_const_seg.inner.vmsize; |
| | 4438 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); |
| | 4439 | } |
| | 4440 | |
| | 4441 | fn allocateLinkeditSegment(self: *MachO) void { |
| | 4442 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 4443 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 4444 | seg.inner.fileoff = data_seg.inner.fileoff + data_seg.inner.filesize; |
| | 4445 | seg.inner.vmaddr = data_seg.inner.vmaddr + data_seg.inner.vmsize; |
| | 4446 | } |
| | 4447 | |
| | 4448 | fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { |
| | 4449 | const seg = &self.load_commands.items[index].Segment; |
| | 4450 | |
| | 4451 | // Allocate the sections according to their alignment at the beginning of the segment. |
| | 4452 | var start: u64 = offset; |
| | 4453 | for (seg.sections.items) |*sect| { |
| | 4454 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| | 4455 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); |
| | 4456 | const end = start_aligned + sect.size; |
| | 4457 | sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned); |
| | 4458 | sect.addr = seg.inner.vmaddr + start_aligned; |
| | 4459 | start = end; |
| | 4460 | } |
| | 4461 | |
| | 4462 | const seg_size_aligned = mem.alignForwardGeneric(u64, start, self.page_size); |
| | 4463 | seg.inner.filesize = seg_size_aligned; |
| | 4464 | seg.inner.vmsize = seg_size_aligned; |
| | 4465 | } |
| | 4466 | |
| | 4467 | const InitSectionOpts = struct { |
| 4202 | flags: u32 = macho.S_REGULAR, | 4468 | flags: u32 = macho.S_REGULAR, |
| 4203 | reserved1: u32 = 0, | 4469 | reserved1: u32 = 0, |
| 4204 | reserved2: u32 = 0, | 4470 | reserved2: u32 = 0, |
| 4205 | }; | 4471 | }; |
| 4206 | | 4472 | |
| 4207 | fn allocateSection( | 4473 | fn initSection( |
| 4208 | self: *MachO, | 4474 | self: *MachO, |
| 4209 | segment_id: u16, | 4475 | segment_id: u16, |
| 4210 | sectname: []const u8, | 4476 | sectname: []const u8, |
| 4211 | size: u64, | 4477 | size: u64, |
| 4212 | alignment: u32, | 4478 | alignment: u32, |
| 4213 | opts: AllocateSectionOpts, | 4479 | opts: InitSectionOpts, |
| 4214 | ) !u16 { | 4480 | ) !u16 { |
| 4215 | const seg = &self.load_commands.items[segment_id].Segment; | 4481 | const seg = &self.load_commands.items[segment_id].Segment; |
| 4216 | var sect = macho.section_64{ | 4482 | var sect = macho.section_64{ |
| 4217 | .sectname = makeStaticString(sectname), | 4483 | .sectname = makeStaticString(sectname), |
| 4218 | .segname = seg.inner.segname, | 4484 | .segname = seg.inner.segname, |
| 4219 | .size = @intCast(u32, size), | 4485 | .size = if (self.needs_prealloc) @intCast(u32, size) else 0, |
| 4220 | .@"align" = alignment, | 4486 | .@"align" = alignment, |
| 4221 | .flags = opts.flags, | 4487 | .flags = opts.flags, |
| 4222 | .reserved1 = opts.reserved1, | 4488 | .reserved1 = opts.reserved1, |
| 4223 | .reserved2 = opts.reserved2, | 4489 | .reserved2 = opts.reserved2, |
| 4224 | }; | 4490 | }; |
| 4225 | | 4491 | |
| 4226 | const alignment_pow_2 = try math.powi(u32, 2, alignment); | 4492 | if (self.needs_prealloc) { |
| 4227 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; | 4493 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4228 | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); | 4494 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4229 | | 4495 | const off = self.findFreeSpace(segment_id, alignment_pow_2, padding); |
| 4230 | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ | 4496 | log.debug("allocating {s},{s} section from 0x{x} to 0x{x}", .{ |
| 4231 | commands.segmentName(sect), | 4497 | commands.segmentName(sect), |
| 4232 | commands.sectionName(sect), | 4498 | commands.sectionName(sect), |
| 4233 | off, | 4499 | off, |
| 4234 | off + size, | 4500 | off + size, |
| 4235 | }); | 4501 | }); |
| 4236 | | 4502 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| 4237 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; | 4503 | sect.offset = @intCast(u32, off); |
| 4238 | sect.offset = @intCast(u32, off); | 4504 | } |
| 4239 | | 4505 | |
| 4240 | const index = @intCast(u16, seg.sections.items.len); | 4506 | const index = @intCast(u16, seg.sections.items.len); |
| 4241 | try seg.sections.append(self.base.allocator, sect); | 4507 | try seg.sections.append(self.base.allocator, sect); |
| ... | @@ -4270,7 +4536,11 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { | ... | @@ -4270,7 +4536,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); | 4536 | const new_seg_size = mem.alignForwardGeneric(u64, new_size, self.page_size); |
| 4271 | assert(new_seg_size > seg.inner.filesize); | 4537 | assert(new_seg_size > seg.inner.filesize); |
| 4272 | const offset_amt = new_seg_size - seg.inner.filesize; | 4538 | 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 }); | 4539 | log.debug("growing segment {s} from 0x{x} to 0x{x}", .{ |
| | 4540 | seg.inner.segname, |
| | 4541 | seg.inner.filesize, |
| | 4542 | new_seg_size, |
| | 4543 | }); |
| 4274 | seg.inner.filesize = new_seg_size; | 4544 | seg.inner.filesize = new_seg_size; |
| 4275 | seg.inner.vmsize = new_seg_size; | 4545 | seg.inner.vmsize = new_seg_size; |
| 4276 | | 4546 | |
| ... | @@ -4321,7 +4591,7 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { | ... | @@ -4321,7 +4591,7 @@ fn growSegment(self: *MachO, seg_id: u16, new_size: u64) !void { |
| 4321 | moved_sect.addr + moved_sect.size, | 4591 | moved_sect.addr + moved_sect.size, |
| 4322 | }); | 4592 | }); |
| 4323 | | 4593 | |
| 4324 | try self.allocateLocalSymbols(.{ | 4594 | try self.shiftLocalsByOffset(.{ |
| 4325 | .seg = @intCast(u16, next), | 4595 | .seg = @intCast(u16, next), |
| 4326 | .sect = @intCast(u16, moved_sect_id), | 4596 | .sect = @intCast(u16, moved_sect_id), |
| 4327 | }, @intCast(i64, offset_amt)); | 4597 | }, @intCast(i64, offset_amt)); |
| ... | @@ -4395,7 +4665,7 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void { | ... | @@ -4395,7 +4665,7 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void { |
| 4395 | moved_sect.addr + moved_sect.size, | 4665 | moved_sect.addr + moved_sect.size, |
| 4396 | }); | 4666 | }); |
| 4397 | | 4667 | |
| 4398 | try self.allocateLocalSymbols(.{ | 4668 | try self.shiftLocalsByOffset(.{ |
| 4399 | .seg = match.seg, | 4669 | .seg = match.seg, |
| 4400 | .sect = next, | 4670 | .sect = next, |
| 4401 | }, @intCast(i64, offset_amt)); | 4671 | }, @intCast(i64, offset_amt)); |
| ... | @@ -4534,6 +4804,21 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m | ... | @@ -4534,6 +4804,21 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, m |
| 4534 | return vaddr; | 4804 | return vaddr; |
| 4535 | } | 4805 | } |
| 4536 | | 4806 | |
| | 4807 | fn addAtomAndBumpSectionSize(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| | 4808 | const seg = &self.load_commands.items[match.seg].Segment; |
| | 4809 | const sect = &seg.sections.items[match.sect]; |
| | 4810 | const alignment = try math.powi(u32, 2, atom.alignment); |
| | 4811 | sect.size = mem.alignForwardGeneric(u64, sect.size, alignment) + atom.size; |
| | 4812 | |
| | 4813 | if (self.atoms.getPtr(match)) |last| { |
| | 4814 | last.*.next = atom; |
| | 4815 | atom.prev = last.*; |
| | 4816 | last.* = atom; |
| | 4817 | } else { |
| | 4818 | try self.atoms.putNoClobber(self.base.allocator, match, atom); |
| | 4819 | } |
| | 4820 | } |
| | 4821 | |
| 4537 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { | 4822 | pub fn addExternFn(self: *MachO, name: []const u8) !u32 { |
| 4538 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); | 4823 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); |
| 4539 | defer self.base.allocator.free(sym_name); | 4824 | defer self.base.allocator.free(sym_name); |
| ... | @@ -4580,6 +4865,160 @@ fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { | ... | @@ -4580,6 +4865,160 @@ fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { |
| 4580 | }; | 4865 | }; |
| 4581 | } | 4866 | } |
| 4582 | | 4867 | |
| | 4868 | fn sortSections(self: *MachO) !void { |
| | 4869 | var text_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4870 | defer text_index_mapping.deinit(); |
| | 4871 | var data_const_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4872 | defer data_const_index_mapping.deinit(); |
| | 4873 | var data_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4874 | defer data_index_mapping.deinit(); |
| | 4875 | |
| | 4876 | { |
| | 4877 | // __TEXT segment |
| | 4878 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4879 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4880 | defer self.base.allocator.free(sections); |
| | 4881 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4882 | |
| | 4883 | const indices = &[_]*?u16{ |
| | 4884 | &self.text_section_index, |
| | 4885 | &self.stubs_section_index, |
| | 4886 | &self.stub_helper_section_index, |
| | 4887 | &self.gcc_except_tab_section_index, |
| | 4888 | &self.cstring_section_index, |
| | 4889 | &self.ustring_section_index, |
| | 4890 | &self.text_const_section_index, |
| | 4891 | &self.objc_methlist_section_index, |
| | 4892 | &self.objc_methname_section_index, |
| | 4893 | &self.objc_methtype_section_index, |
| | 4894 | &self.objc_classname_section_index, |
| | 4895 | &self.eh_frame_section_index, |
| | 4896 | }; |
| | 4897 | for (indices) |maybe_index| { |
| | 4898 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4899 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4900 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4901 | try text_index_mapping.putNoClobber(index, idx); |
| | 4902 | break :blk idx; |
| | 4903 | } else continue; |
| | 4904 | maybe_index.* = new_index; |
| | 4905 | } |
| | 4906 | } |
| | 4907 | |
| | 4908 | { |
| | 4909 | // __DATA_CONST segment |
| | 4910 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 4911 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4912 | defer self.base.allocator.free(sections); |
| | 4913 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4914 | |
| | 4915 | const indices = &[_]*?u16{ |
| | 4916 | &self.got_section_index, |
| | 4917 | &self.mod_init_func_section_index, |
| | 4918 | &self.mod_term_func_section_index, |
| | 4919 | &self.data_const_section_index, |
| | 4920 | &self.objc_cfstring_section_index, |
| | 4921 | &self.objc_classlist_section_index, |
| | 4922 | &self.objc_imageinfo_section_index, |
| | 4923 | }; |
| | 4924 | for (indices) |maybe_index| { |
| | 4925 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4926 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4927 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4928 | try data_const_index_mapping.putNoClobber(index, idx); |
| | 4929 | break :blk idx; |
| | 4930 | } else continue; |
| | 4931 | maybe_index.* = new_index; |
| | 4932 | } |
| | 4933 | } |
| | 4934 | |
| | 4935 | { |
| | 4936 | // __DATA segment |
| | 4937 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 4938 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4939 | defer self.base.allocator.free(sections); |
| | 4940 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4941 | |
| | 4942 | // __DATA segment |
| | 4943 | const indices = &[_]*?u16{ |
| | 4944 | &self.la_symbol_ptr_section_index, |
| | 4945 | &self.objc_const_section_index, |
| | 4946 | &self.objc_selrefs_section_index, |
| | 4947 | &self.objc_classrefs_section_index, |
| | 4948 | &self.objc_data_section_index, |
| | 4949 | &self.data_section_index, |
| | 4950 | &self.tlv_section_index, |
| | 4951 | &self.tlv_data_section_index, |
| | 4952 | &self.tlv_bss_section_index, |
| | 4953 | &self.bss_section_index, |
| | 4954 | }; |
| | 4955 | for (indices) |maybe_index| { |
| | 4956 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4957 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4958 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4959 | try data_index_mapping.putNoClobber(index, idx); |
| | 4960 | break :blk idx; |
| | 4961 | } else continue; |
| | 4962 | maybe_index.* = new_index; |
| | 4963 | } |
| | 4964 | } |
| | 4965 | |
| | 4966 | { |
| | 4967 | var transient: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{}; |
| | 4968 | try transient.ensureTotalCapacity(self.base.allocator, self.atoms.count()); |
| | 4969 | |
| | 4970 | var it = self.atoms.iterator(); |
| | 4971 | while (it.next()) |entry| { |
| | 4972 | const old = entry.key_ptr.*; |
| | 4973 | const sect = if (old.seg == self.text_segment_cmd_index.?) |
| | 4974 | text_index_mapping.get(old.sect).? |
| | 4975 | else if (old.seg == self.data_const_segment_cmd_index.?) |
| | 4976 | data_const_index_mapping.get(old.sect).? |
| | 4977 | else |
| | 4978 | data_index_mapping.get(old.sect).?; |
| | 4979 | transient.putAssumeCapacityNoClobber(.{ |
| | 4980 | .seg = old.seg, |
| | 4981 | .sect = sect, |
| | 4982 | }, entry.value_ptr.*); |
| | 4983 | } |
| | 4984 | |
| | 4985 | self.atoms.clearAndFree(self.base.allocator); |
| | 4986 | self.atoms.deinit(self.base.allocator); |
| | 4987 | self.atoms = transient; |
| | 4988 | } |
| | 4989 | |
| | 4990 | { |
| | 4991 | // Create new section ordinals. |
| | 4992 | self.section_ordinals.clearRetainingCapacity(); |
| | 4993 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4994 | for (text_seg.sections.items) |_, sect_id| { |
| | 4995 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 4996 | .seg = self.text_segment_cmd_index.?, |
| | 4997 | .sect = @intCast(u16, sect_id), |
| | 4998 | }); |
| | 4999 | assert(!res.found_existing); |
| | 5000 | } |
| | 5001 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 5002 | for (data_const_seg.sections.items) |_, sect_id| { |
| | 5003 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 5004 | .seg = self.data_const_segment_cmd_index.?, |
| | 5005 | .sect = @intCast(u16, sect_id), |
| | 5006 | }); |
| | 5007 | assert(!res.found_existing); |
| | 5008 | } |
| | 5009 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 5010 | for (data_seg.sections.items) |_, sect_id| { |
| | 5011 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 5012 | .seg = self.data_segment_cmd_index.?, |
| | 5013 | .sect = @intCast(u16, sect_id), |
| | 5014 | }); |
| | 5015 | assert(!res.found_existing); |
| | 5016 | } |
| | 5017 | } |
| | 5018 | |
| | 5019 | self.sections_order_dirty = false; |
| | 5020 | } |
| | 5021 | |
| 4583 | fn updateSectionOrdinals(self: *MachO) !void { | 5022 | fn updateSectionOrdinals(self: *MachO) !void { |
| 4584 | if (!self.sections_order_dirty) return; | 5023 | if (!self.sections_order_dirty) return; |
| 4585 | | 5024 | |
| ... | @@ -4957,7 +5396,7 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -4957,7 +5396,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 4957 | | 5396 | |
| 4958 | for (self.locals.items) |sym| { | 5397 | for (self.locals.items) |sym| { |
| 4959 | if (sym.n_strx == 0) continue; | 5398 | if (sym.n_strx == 0) continue; |
| 4960 | if (symbolIsTemp(sym, self.getString(sym.n_strx))) continue; | 5399 | if (self.symbol_resolver.get(sym.n_strx)) |_| continue; |
| 4961 | try locals.append(sym); | 5400 | try locals.append(sym); |
| 4962 | } | 5401 | } |
| 4963 | | 5402 | |
| ... | @@ -5309,7 +5748,7 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 { | ... | @@ -5309,7 +5748,7 @@ pub fn makeString(self: *MachO, string: []const u8) !u32 { |
| 5309 | return new_off; | 5748 | return new_off; |
| 5310 | } | 5749 | } |
| 5311 | | 5750 | |
| 5312 | pub fn getString(self: *MachO, off: u32) []const u8 { | 5751 | pub fn getString(self: MachO, off: u32) []const u8 { |
| 5313 | assert(off < self.strtab.items.len); | 5752 | assert(off < self.strtab.items.len); |
| 5314 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.items.ptr + off), 0); | 5753 | return mem.sliceTo(@ptrCast([*:0]const u8, self.strtab.items.ptr + off), 0); |
| 5315 | } | 5754 | } |
| ... | @@ -5602,3 +6041,55 @@ fn snapshotState(self: *MachO) !void { | ... | @@ -5602,3 +6041,55 @@ fn snapshotState(self: *MachO) !void { |
| 5602 | try std.json.stringify(snapshot, .{}, writer); | 6041 | try std.json.stringify(snapshot, .{}, writer); |
| 5603 | try writer.writeByte(']'); | 6042 | try writer.writeByte(']'); |
| 5604 | } | 6043 | } |
| | 6044 | |
| | 6045 | fn logSymtab(self: MachO) void { |
| | 6046 | log.debug("locals:", .{}); |
| | 6047 | for (self.locals.items) |sym, id| { |
| | 6048 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| | 6049 | } |
| | 6050 | |
| | 6051 | log.debug("globals:", .{}); |
| | 6052 | for (self.globals.items) |sym, id| { |
| | 6053 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| | 6054 | } |
| | 6055 | |
| | 6056 | log.debug("undefs:", .{}); |
| | 6057 | for (self.undefs.items) |sym, id| { |
| | 6058 | log.debug(" {d}: {s}: {}", .{ id, self.getString(sym.n_strx), sym }); |
| | 6059 | } |
| | 6060 | |
| | 6061 | { |
| | 6062 | log.debug("resolver:", .{}); |
| | 6063 | var it = self.symbol_resolver.iterator(); |
| | 6064 | while (it.next()) |entry| { |
| | 6065 | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); |
| | 6066 | } |
| | 6067 | } |
| | 6068 | |
| | 6069 | log.debug("GOT entries:", .{}); |
| | 6070 | for (self.got_entries_map.keys()) |key| { |
| | 6071 | switch (key) { |
| | 6072 | .local => |sym_index| log.debug(" {} => {d}", .{ key, sym_index }), |
| | 6073 | .global => |n_strx| log.debug(" {} => {s}", .{ key, self.getString(n_strx) }), |
| | 6074 | } |
| | 6075 | } |
| | 6076 | |
| | 6077 | log.debug("stubs:", .{}); |
| | 6078 | for (self.stubs_map.keys()) |key| { |
| | 6079 | log.debug(" {} => {s}", .{ key, self.getString(key) }); |
| | 6080 | } |
| | 6081 | } |
| | 6082 | |
| | 6083 | fn logSectionOrdinals(self: MachO) void { |
| | 6084 | for (self.section_ordinals.keys()) |match, i| { |
| | 6085 | const seg = self.load_commands.items[match.seg].Segment; |
| | 6086 | const sect = seg.sections.items[match.sect]; |
| | 6087 | log.debug("ord {d}: {d},{d} => {s},{s}", .{ |
| | 6088 | i + 1, |
| | 6089 | match.seg, |
| | 6090 | match.sect, |
| | 6091 | commands.segmentName(sect), |
| | 6092 | commands.sectionName(sect), |
| | 6093 | }); |
| | 6094 | } |
| | 6095 | } |