authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-30 15:43:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-30 15:43:20+02:00
log2831d6e9b8b29c21bc7417c5e370674e3130f6ae
tree81a3f7bc619b03efb15aee12c88ad1aa50c59c3c
parenta14e98fcaceed92be8b1859d7ae331176d4e4d84

macho: add first pass at allocating parsed atoms in objects

This commit makes it possible to combine self-hosted with a pre-compiled C object file, e.g.: ``` zig-out/bin/zig build-exe hello.zig add.o ``` where `add.o` is a pre-compiled C object file.

4 files changed, 164 insertions(+), 46 deletions(-)

src/link/MachO.zig+140-31
......@@ -789,6 +789,31 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
789789 try self.allocateTextBlocks();
790790 try self.flushZld();
791791 } else {
792 try self.parseTextBlocks();
793 try self.allocateGlobalSymbols();
794 {
795 log.debug("locals:", .{});
796 for (self.locals.items) |sym| {
797 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
798 }
799 log.debug("globals:", .{});
800 for (self.globals.items) |sym| {
801 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
802 }
803 log.debug("undefs:", .{});
804 for (self.undefs.items) |sym| {
805 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
806 }
807 log.debug("unresolved:", .{});
808 for (self.unresolved.keys()) |key| {
809 log.debug(" {d} => {s}", .{ key, self.unresolved.get(key).? });
810 }
811 log.debug("resolved:", .{});
812 var it = self.symbol_resolver.iterator();
813 while (it.next()) |entry| {
814 log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* });
815 }
816 }
792817 try self.writeAtoms();
793818 try self.flushModule(comp);
794819 }
......@@ -1114,12 +1139,14 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11141139 const segname = commands.segmentName(sect);
11151140 const sectname = commands.sectionName(sect);
11161141
1142 var needs_allocation = false;
11171143 const res: ?MatchingSection = blk: {
11181144 switch (commands.sectionType(sect)) {
11191145 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
11201146 if (self.text_const_section_index == null) {
11211147 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
11221148 try text_seg.addSection(self.base.allocator, "__const", .{});
1149 needs_allocation = true;
11231150 }
11241151
11251152 break :blk .{
......@@ -1136,6 +1163,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11361163 try text_seg.addSection(self.base.allocator, "__objc_methname", .{
11371164 .flags = macho.S_CSTRING_LITERALS,
11381165 });
1166 needs_allocation = true;
11391167 }
11401168
11411169 break :blk .{
......@@ -1148,6 +1176,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11481176 try text_seg.addSection(self.base.allocator, "__objc_methtype", .{
11491177 .flags = macho.S_CSTRING_LITERALS,
11501178 });
1179 needs_allocation = true;
11511180 }
11521181
11531182 break :blk .{
......@@ -1158,6 +1187,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11581187 if (self.objc_classname_section_index == null) {
11591188 self.objc_classname_section_index = @intCast(u16, text_seg.sections.items.len);
11601189 try text_seg.addSection(self.base.allocator, "__objc_classname", .{});
1190 needs_allocation = true;
11611191 }
11621192
11631193 break :blk .{
......@@ -1171,6 +1201,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11711201 try text_seg.addSection(self.base.allocator, "__cstring", .{
11721202 .flags = macho.S_CSTRING_LITERALS,
11731203 });
1204 needs_allocation = true;
11741205 }
11751206
11761207 break :blk .{
......@@ -1185,6 +1216,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11851216 try data_seg.addSection(self.base.allocator, "__objc_selrefs", .{
11861217 .flags = macho.S_LITERAL_POINTERS,
11871218 });
1219 needs_allocation = true;
11881220 }
11891221
11901222 break :blk .{
......@@ -1202,6 +1234,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12021234 try data_const_seg.addSection(self.base.allocator, "__mod_init_func", .{
12031235 .flags = macho.S_MOD_INIT_FUNC_POINTERS,
12041236 });
1237 needs_allocation = true;
12051238 }
12061239
12071240 break :blk .{
......@@ -1215,6 +1248,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12151248 try data_const_seg.addSection(self.base.allocator, "__mod_term_func", .{
12161249 .flags = macho.S_MOD_TERM_FUNC_POINTERS,
12171250 });
1251 needs_allocation = true;
12181252 }
12191253
12201254 break :blk .{
......@@ -1228,6 +1262,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12281262 try data_seg.addSection(self.base.allocator, "__bss", .{
12291263 .flags = macho.S_ZEROFILL,
12301264 });
1265 needs_allocation = true;
12311266 }
12321267
12331268 break :blk .{
......@@ -1241,6 +1276,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12411276 try data_seg.addSection(self.base.allocator, "__thread_vars", .{
12421277 .flags = macho.S_THREAD_LOCAL_VARIABLES,
12431278 });
1279 needs_allocation = true;
12441280 }
12451281
12461282 break :blk .{
......@@ -1254,6 +1290,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12541290 try data_seg.addSection(self.base.allocator, "__thread_data", .{
12551291 .flags = macho.S_THREAD_LOCAL_REGULAR,
12561292 });
1293 needs_allocation = true;
12571294 }
12581295
12591296 break :blk .{
......@@ -1267,6 +1304,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12671304 try data_seg.addSection(self.base.allocator, "__thread_bss", .{
12681305 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
12691306 });
1307 needs_allocation = true;
12701308 }
12711309
12721310 break :blk .{
......@@ -1281,6 +1319,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12811319 if (self.eh_frame_section_index == null) {
12821320 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
12831321 try text_seg.addSection(self.base.allocator, "__eh_frame", .{});
1322 needs_allocation = true;
12841323 }
12851324
12861325 break :blk .{
......@@ -1293,6 +1332,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12931332 if (self.data_const_section_index == null) {
12941333 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
12951334 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1335 needs_allocation = true;
12961336 }
12971337
12981338 break :blk .{
......@@ -1307,6 +1347,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13071347 try text_seg.addSection(self.base.allocator, "__text", .{
13081348 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
13091349 });
1350 needs_allocation = true;
13101351 }
13111352
13121353 break :blk .{
......@@ -1329,6 +1370,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13291370 if (self.ustring_section_index == null) {
13301371 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
13311372 try text_seg.addSection(self.base.allocator, "__ustring", .{});
1373 needs_allocation = true;
13321374 }
13331375
13341376 break :blk .{
......@@ -1339,6 +1381,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13391381 if (self.gcc_except_tab_section_index == null) {
13401382 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
13411383 try text_seg.addSection(self.base.allocator, "__gcc_except_tab", .{});
1384 needs_allocation = true;
13421385 }
13431386
13441387 break :blk .{
......@@ -1349,6 +1392,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13491392 if (self.objc_methlist_section_index == null) {
13501393 self.objc_methlist_section_index = @intCast(u16, text_seg.sections.items.len);
13511394 try text_seg.addSection(self.base.allocator, "__objc_methlist", .{});
1395 needs_allocation = true;
13521396 }
13531397
13541398 break :blk .{
......@@ -1364,6 +1408,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13641408 if (self.data_const_section_index == null) {
13651409 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
13661410 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1411 needs_allocation = true;
13671412 }
13681413
13691414 break :blk .{
......@@ -1374,6 +1419,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13741419 if (self.text_const_section_index == null) {
13751420 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
13761421 try text_seg.addSection(self.base.allocator, "__const", .{});
1422 needs_allocation = true;
13771423 }
13781424
13791425 break :blk .{
......@@ -1387,6 +1433,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13871433 if (self.data_const_section_index == null) {
13881434 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
13891435 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1436 needs_allocation = true;
13901437 }
13911438
13921439 break :blk .{
......@@ -1400,6 +1447,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14001447 if (self.data_const_section_index == null) {
14011448 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
14021449 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1450 needs_allocation = true;
14031451 }
14041452
14051453 break :blk .{
......@@ -1410,6 +1458,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14101458 if (self.objc_cfstring_section_index == null) {
14111459 self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
14121460 try data_const_seg.addSection(self.base.allocator, "__cfstring", .{});
1461 needs_allocation = true;
14131462 }
14141463
14151464 break :blk .{
......@@ -1420,6 +1469,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14201469 if (self.objc_classlist_section_index == null) {
14211470 self.objc_classlist_section_index = @intCast(u16, data_const_seg.sections.items.len);
14221471 try data_const_seg.addSection(self.base.allocator, "__objc_classlist", .{});
1472 needs_allocation = true;
14231473 }
14241474
14251475 break :blk .{
......@@ -1430,6 +1480,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14301480 if (self.objc_imageinfo_section_index == null) {
14311481 self.objc_imageinfo_section_index = @intCast(u16, data_const_seg.sections.items.len);
14321482 try data_const_seg.addSection(self.base.allocator, "__objc_imageinfo", .{});
1483 needs_allocation = true;
14331484 }
14341485
14351486 break :blk .{
......@@ -1440,6 +1491,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14401491 if (self.objc_const_section_index == null) {
14411492 self.objc_const_section_index = @intCast(u16, data_seg.sections.items.len);
14421493 try data_seg.addSection(self.base.allocator, "__objc_const", .{});
1494 needs_allocation = true;
14431495 }
14441496
14451497 break :blk .{
......@@ -1450,6 +1502,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14501502 if (self.objc_classrefs_section_index == null) {
14511503 self.objc_classrefs_section_index = @intCast(u16, data_seg.sections.items.len);
14521504 try data_seg.addSection(self.base.allocator, "__objc_classrefs", .{});
1505 needs_allocation = true;
14531506 }
14541507
14551508 break :blk .{
......@@ -1460,6 +1513,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14601513 if (self.objc_data_section_index == null) {
14611514 self.objc_data_section_index = @intCast(u16, data_seg.sections.items.len);
14621515 try data_seg.addSection(self.base.allocator, "__objc_data", .{});
1516 needs_allocation = true;
14631517 }
14641518
14651519 break :blk .{
......@@ -1470,6 +1524,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14701524 if (self.data_section_index == null) {
14711525 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
14721526 try data_seg.addSection(self.base.allocator, "__data", .{});
1527 needs_allocation = true;
14731528 }
14741529
14751530 break :blk .{
......@@ -1494,6 +1549,36 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14941549 if (res) |match| {
14951550 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
14961551 _ = try self.block_free_lists.getOrPutValue(self.base.allocator, match, .{});
1552
1553 const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1;
1554 if (!use_stage1) {
1555 const target_seg = &self.load_commands.items[match.seg].Segment;
1556 const target_sect = &target_seg.sections.items[match.sect];
1557
1558 // Update section's alignment
1559 // TODO if sect.@"align" > target_sect.@"align", should we move the entire
1560 // section to match the required alignment?
1561 target_sect.@"align" = math.max(target_sect.@"align", sect.@"align");
1562
1563 if (needs_allocation) {
1564 const alignment = try math.powi(u32, 2, target_sect.@"align");
1565 const needed_size = sect.size;
1566 const off = target_seg.findFreeSpace(needed_size, alignment, self.header_pad);
1567 assert(off + needed_size <= target_seg.inner.fileoff + target_seg.inner.filesize); // TODO expand
1568
1569 log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
1570 segname,
1571 sectname,
1572 off,
1573 off + needed_size,
1574 });
1575
1576 target_sect.addr = target_seg.inner.vmaddr + off;
1577 target_sect.size = needed_size;
1578 target_sect.offset = @intCast(u32, off);
1579 self.load_commands_dirty = true;
1580 }
1581 }
14971582 }
14981583
14991584 return res;
......@@ -1759,23 +1844,41 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment:
17591844}
17601845
17611846pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 {
1762 // TODO converge with `allocateTextBlock`
1763 const seg = self.load_commands.items[match.seg].Segment;
1764 const sect = seg.sections.items[match.sect];
1847 const seg = &self.load_commands.items[match.seg].Segment;
1848 const sect = &seg.sections.items[match.sect];
17651849 const sym = &self.locals.items[atom.local_sym_index];
1766 const base_addr = if (self.blocks.get(match)) |last| blk: {
1850
1851 var atom_placement: ?*TextBlock = null;
1852
1853 // TODO converge with `allocateTextBlock` and handle free list
1854 const vaddr = if (self.blocks.get(match)) |last| blk: {
17671855 const last_atom_sym = self.locals.items[last.local_sym_index];
1768 break :blk last_atom_sym.n_value + last.size;
1856 const ideal_capacity = padToIdeal(last.size);
1857 const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity;
1858 const last_atom_alignment = try math.powi(u32, 2, atom.alignment);
1859 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment);
1860 atom_placement = last;
1861 break :blk new_start_vaddr;
17691862 } else sect.addr;
1770 const atom_alignment = try math.powi(u32, 2, atom.alignment);
1771 const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment);
1863
17721864 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });
17731865
1774 const expand_section = true;
1866 const expand_section = atom_placement == null or atom_placement.?.next == null;
17751867 if (expand_section) {
1776 // Expand the section, possibly shifting all the atoms for the sections following it.
1777 // It might also be needed to shift entire segments too if there is not enough
1778 // padding left.
1868 const needed_size = (vaddr + atom.size) - sect.addr;
1869 const end_addr = blk: {
1870 const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with.
1871 const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: {
1872 const next_match = self.section_ordinals.keys()[next_ordinal];
1873 const next_seg = self.load_commands.items[next_match.seg].Segment;
1874 const next_sect = next_seg.sections.items[next_match.sect];
1875 break :inner next_sect.addr;
1876 } else seg.inner.filesize;
1877 break :blk end_addr;
1878 };
1879 assert(needed_size <= end_addr); // TODO must expand the section
1880 sect.size = needed_size;
1881 self.load_commands_dirty = true;
17791882 }
17801883 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
17811884 sym.n_value = vaddr;
......@@ -1828,6 +1931,21 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
18281931 try self.writeLocalSymbol(atom.local_sym_index);
18291932}
18301933
1934fn allocateGlobalSymbols(self: *MachO) !void {
1935 // TODO should we do this in `allocateAtom` (or similar)? Then, we would need to
1936 // store the link atom -> globals somewhere.
1937 var sym_it = self.symbol_resolver.valueIterator();
1938 while (sym_it.next()) |resolv| {
1939 if (resolv.where != .global) continue;
1940
1941 assert(resolv.local_sym_index != 0);
1942 const local_sym = self.locals.items[resolv.local_sym_index];
1943 const sym = &self.globals.items[resolv.where_index];
1944 sym.n_value = local_sym.n_value;
1945 sym.n_sect = local_sym.n_sect;
1946 }
1947}
1948
18311949pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
18321950 // Update target section's metadata
18331951 // TODO should we update segment's size here too?
......@@ -2313,14 +2431,14 @@ fn resolveSymbolsInObject(
23132431 continue;
23142432 },
23152433 .undef => {
2316 const undef = &self.undefs.items[resolv.where_index];
2317 undef.* = .{
2318 .n_strx = 0,
2319 .n_type = macho.N_UNDF,
2320 .n_sect = 0,
2321 .n_desc = 0,
2322 .n_value = 0,
2323 };
2434 // const undef = &self.undefs.items[resolv.where_index];
2435 // undef.* = .{
2436 // .n_strx = 0,
2437 // .n_type = macho.N_UNDF,
2438 // .n_sect = 0,
2439 // .n_desc = 0,
2440 // .n_value = 0,
2441 // };
23242442 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
23252443 },
23262444 }
......@@ -2457,18 +2575,9 @@ fn resolveSymbols(self: *MachO) !void {
24572575 // text blocks for each tentative defintion.
24582576 while (tentatives.popOrNull()) |entry| {
24592577 const sym = &self.globals.items[entry.key];
2460 const match: MatchingSection = blk: {
2461 if (self.bss_section_index == null) {
2462 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2463 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
2464 try data_seg.addSection(self.base.allocator, "__bss", .{
2465 .flags = macho.S_ZEROFILL,
2466 });
2467 }
2468 break :blk .{
2469 .seg = self.data_segment_cmd_index.?,
2470 .sect = self.bss_section_index.?,
2471 };
2578 const match = MatchingSection{
2579 .seg = self.data_segment_cmd_index.?,
2580 .sect = self.bss_section_index.?,
24722581 };
24732582 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
24742583
src/link/MachO/Object.zig+10-14
......@@ -504,7 +504,6 @@ pub fn parseTextBlocks(
504504 log.debug("unhandled section", .{});
505505 continue;
506506 };
507 // TODO allocate section here.
508507
509508 // Read section's code
510509 var code = try allocator.alloc(u8, @intCast(usize, sect.size));
......@@ -569,12 +568,6 @@ pub fn parseTextBlocks(
569568 const block_size = block_code.len;
570569 const block = try macho_file.createEmptyAtom(block_local_sym_index, block_size, sect.@"align");
571570
572 if (use_stage1) {
573 try macho_file.allocateAtomStage1(block, match);
574 } else {
575 _ = try macho_file.allocateAtom(block, match);
576 }
577
578571 mem.copy(u8, block.code.items, block_code);
579572
580573 try block.parseRelocs(relocs, .{
......@@ -597,6 +590,11 @@ pub fn parseTextBlocks(
597590 }
598591 }
599592
593 if (use_stage1) {
594 try macho_file.allocateAtomStage1(block, match);
595 } else {
596 _ = try macho_file.allocateAtom(block, match);
597 }
600598 try self.text_blocks.append(allocator, block);
601599 }
602600
......@@ -648,7 +646,6 @@ pub fn parseTextBlocks(
648646 } else {
649647 _ = try macho_file.allocateAtom(block, match);
650648 }
651
652649 try self.text_blocks.append(allocator, block);
653650 }
654651
......@@ -679,12 +676,6 @@ pub fn parseTextBlocks(
679676 };
680677 const block = try macho_file.createEmptyAtom(block_local_sym_index, sect.size, sect.@"align");
681678
682 if (use_stage1) {
683 try macho_file.allocateAtomStage1(block, match);
684 } else {
685 _ = try macho_file.allocateAtom(block, match);
686 }
687
688679 mem.copy(u8, block.code.items, code);
689680
690681 try block.parseRelocs(relocs, .{
......@@ -743,6 +734,11 @@ pub fn parseTextBlocks(
743734 });
744735 }
745736
737 if (use_stage1) {
738 try macho_file.allocateAtomStage1(block, match);
739 } else {
740 _ = try macho_file.allocateAtom(block, match);
741 }
746742 try self.text_blocks.append(allocator, block);
747743 }
748744 }
src/link/MachO/TextBlock.zig+13
......@@ -1183,9 +1183,22 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
11831183 },
11841184 .undef => {
11851185 const atom = macho_file.stubs_map.get(rel.where_index) orelse {
1186 // TODO this is required for incremental when we don't have every symbol
1187 // resolved when creating relocations. In this case, we will insert a branch
1188 // reloc to an undef symbol which may happen to be defined within the binary.
1189 // Then, the undef we point at will be a null symbol (free symbol) which we
1190 // should remove/repurpose. To circumvent this (for now), we check if the symbol
1191 // we point to is garbage, and if so we fall back to symbol resolver to find by name.
1192 const n_strx = macho_file.undefs.items[rel.where_index].n_strx;
1193 if (macho_file.symbol_resolver.get(n_strx)) |resolv| inner: {
1194 if (resolv.where != .global) break :inner;
1195 break :blk macho_file.globals.items[resolv.where_index].n_value;
1196 }
1197
11861198 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
11871199 break :blk 0; // Dynamically bound by dyld.
11881200 };
1201
11891202 break :blk macho_file.locals.items[atom.local_sym_index].n_value;
11901203 },
11911204 }
src/link/MachO/commands.zig+1-1
......@@ -337,7 +337,7 @@ pub const SegmentCommand = struct {
337337 return null;
338338 }
339339
340 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u16, start: ?u64) u64 {
340 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u32, start: ?u64) u64 {
341341 var st: u64 = if (start) |v| v else self.inner.fileoff;
342342 while (self.detectAllocCollision(st, object_size)) |item_end| {
343343 st = mem.alignForwardGeneric(u64, item_end, min_alignment);