authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-03 17:12:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-03 17:12:39+02:00
log80e1c244b6c9d5f3e855878d92ecc09dc8eb970a
treeef93e21cde0713b0749e29951b2d54bfe000575d
parent1d2199b71c06e97be407c2bd0b05c07c8bd6cd2c

macho: dyld info subsections need to follow in strict order

MachO, why are doing this to me?

2 files changed, 115 insertions(+), 251 deletions(-)

src/link/MachO.zig+114-248
......@@ -162,10 +162,7 @@ stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{},
162162error_flags: File.ErrorFlags = File.ErrorFlags{},
163163
164164load_commands_dirty: bool = false,
165rebase_info_dirty: bool = false,
166binding_info_dirty: bool = false,
167lazy_binding_info_dirty: bool = false,
168export_info_dirty: bool = false,
165dyld_info_dirty: bool = false,
169166
170167strtab_dirty: bool = false,
171168strtab_needs_relocation: bool = false,
......@@ -814,10 +811,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
814811 defer tracy.end();
815812
816813 try self.setEntryPoint();
817 try self.writeRebaseInfoTable();
818 try self.writeBindInfoTable();
819 try self.writeLazyBindInfoTable();
820 try self.writeExportInfo();
814 try self.writeDyldInfoData();
821815 try self.writeAllGlobalAndUndefSymbols();
822816 try self.writeIndirectSymbolTable();
823817 try self.writeStringTable();
......@@ -849,10 +843,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
849843 }
850844
851845 assert(!self.load_commands_dirty);
852 assert(!self.rebase_info_dirty);
853 assert(!self.binding_info_dirty);
854 assert(!self.lazy_binding_info_dirty);
855 assert(!self.export_info_dirty);
846 assert(!self.dyld_info_dirty);
856847 assert(!self.strtab_dirty);
857848 assert(!self.strtab_needs_relocation);
858849
......@@ -2111,7 +2102,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym
21112102 .local_sym_index = lazy_binding_sym_index,
21122103 .offset = 0,
21132104 });
2114 self.lazy_binding_info_dirty = true;
2105 self.dyld_info_dirty = true;
21152106 return atom;
21162107}
21172108
......@@ -2312,7 +2303,7 @@ fn resolveSymbolsInObject(
23122303 .local_sym_index = local_sym_index,
23132304 .file = object_id,
23142305 };
2315 self.export_info_dirty = true;
2306 self.dyld_info_dirty = true;
23162307 } else if (symbolIsTentative(sym)) {
23172308 // Symbol is a tentative definition.
23182309 const resolv = self.symbol_resolver.getPtr(n_strx) orelse {
......@@ -2647,7 +2638,7 @@ fn resolveDyldStubBinder(self: *MachO) !void {
26472638 .sect = self.got_section_index.?,
26482639 };
26492640 _ = try self.allocateAtom(atom, match);
2650 self.binding_info_dirty = true;
2641 self.dyld_info_dirty = true;
26512642}
26522643
26532644fn parseTextBlocks(self: *MachO) !void {
......@@ -2946,7 +2937,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
29462937 };
29472938 const got_atom = try self.createGotAtom(key);
29482939 try self.got_entries_map.put(self.base.allocator, key, got_atom);
2949 self.rebase_info_dirty = true;
2940 self.dyld_info_dirty = true;
29502941}
29512942
29522943pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
......@@ -3266,7 +3257,7 @@ pub fn updateDeclExports(
32663257 const name_str_index = try self.makeString(exp_name);
32673258 const i = if (self.globals_free_list.popOrNull()) |i| i else blk: {
32683259 _ = self.globals.addOneAssumeCapacity();
3269 self.export_info_dirty = true;
3260 self.dyld_info_dirty = true;
32703261 break :blk @intCast(u32, self.globals.items.len - 1);
32713262 };
32723263 self.globals.items[i] = .{
......@@ -3648,29 +3639,34 @@ pub fn populateMissingMetadata(self: *MachO) !void {
36483639 },
36493640 });
36503641
3642 // Preallocate rebase, binding, lazy binding info, and export info.
36513643 const dyld = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
3644 const subsection_size = 128; // TODO this is totally random
3645 const needed_size = 4 * subsection_size;
3646 const offset = self.findFreeSpaceLinkedit(needed_size, 1, null);
3647
3648 const rebase_off = @intCast(u32, offset);
3649 log.debug("found rebase info free space 0x{x} to 0x{x}", .{ rebase_off, rebase_off + subsection_size });
3650 dyld.rebase_off = rebase_off;
3651 dyld.rebase_size = subsection_size;
3652
3653 const bind_off = rebase_off + subsection_size;
3654 log.debug("found binding info free space 0x{x} to 0x{x}", .{ bind_off, bind_off + subsection_size });
3655 dyld.bind_off = bind_off;
3656 dyld.bind_size = subsection_size;
3657
3658 const lazy_bind_off = bind_off + subsection_size;
3659 log.debug("found lazy binding info free space 0x{x} to 0x{x}", .{
3660 lazy_bind_off,
3661 lazy_bind_off + subsection_size,
3662 });
3663 dyld.lazy_bind_off = lazy_bind_off;
3664 dyld.lazy_bind_size = subsection_size;
36523665
3653 // Preallocate rebase, binding, lazy binding info, and export info.
3654 const expected_size = 48; // TODO This is totally random.
3655 const rebase_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
3656 log.debug("found rebase info free space 0x{x} to 0x{x}", .{ rebase_off, rebase_off + expected_size });
3657 dyld.rebase_off = @intCast(u32, rebase_off);
3658 dyld.rebase_size = expected_size;
3659
3660 const bind_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
3661 log.debug("found binding info free space 0x{x} to 0x{x}", .{ bind_off, bind_off + expected_size });
3662 dyld.bind_off = @intCast(u32, bind_off);
3663 dyld.bind_size = expected_size;
3664
3665 const lazy_bind_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
3666 log.debug("found lazy binding info free space 0x{x} to 0x{x}", .{ lazy_bind_off, lazy_bind_off + expected_size });
3667 dyld.lazy_bind_off = @intCast(u32, lazy_bind_off);
3668 dyld.lazy_bind_size = expected_size;
3669
3670 const export_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
3671 log.debug("found export info free space 0x{x} to 0x{x}", .{ export_off, export_off + expected_size });
3672 dyld.export_off = @intCast(u32, export_off);
3673 dyld.export_size = expected_size;
3666 const export_off = lazy_bind_off + subsection_size;
3667 log.debug("found export info free space 0x{x} to 0x{x}", .{ export_off, export_off + subsection_size });
3668 dyld.export_off = export_off;
3669 dyld.export_size = subsection_size;
36743670
36753671 self.load_commands_dirty = true;
36763672 }
......@@ -4097,10 +4093,6 @@ fn allocatedSizeLinkedit(self: *MachO, start: u64) u64 {
40974093 if (self.dyld_info_cmd_index) |idx| {
40984094 const dyld_info = self.load_commands.items[idx].DyldInfoOnly;
40994095 if (dyld_info.rebase_off > start and dyld_info.rebase_off < min_pos) min_pos = dyld_info.rebase_off;
4100 if (dyld_info.bind_off > start and dyld_info.bind_off < min_pos) min_pos = dyld_info.bind_off;
4101 if (dyld_info.weak_bind_off > start and dyld_info.weak_bind_off < min_pos) min_pos = dyld_info.weak_bind_off;
4102 if (dyld_info.lazy_bind_off > start and dyld_info.lazy_bind_off < min_pos) min_pos = dyld_info.lazy_bind_off;
4103 if (dyld_info.export_off > start and dyld_info.export_off < min_pos) min_pos = dyld_info.export_off;
41044096 }
41054097
41064098 if (self.function_starts_cmd_index) |idx| {
......@@ -4141,27 +4133,14 @@ fn detectAllocCollisionLinkedit(self: *MachO, start: u64, size: u64) ?u64 {
41414133
41424134 // __LINKEDIT is a weird segment where sections get their own load commands so we
41434135 // special-case it.
4144 if (self.dyld_info_cmd_index) |idx| outer: {
4145 if (self.load_commands.items.len == idx) break :outer;
4136 if (self.dyld_info_cmd_index) |idx| {
41464137 const dyld_info = self.load_commands.items[idx].DyldInfoOnly;
4147 if (checkForCollision(start, end, dyld_info.rebase_off, dyld_info.rebase_size)) |pos| {
4148 return pos;
4149 }
4150 // Binding info
4151 if (checkForCollision(start, end, dyld_info.bind_off, dyld_info.bind_size)) |pos| {
4152 return pos;
4153 }
4154 // Weak binding info
4155 if (checkForCollision(start, end, dyld_info.weak_bind_off, dyld_info.weak_bind_size)) |pos| {
4156 return pos;
4157 }
4158 // Lazy binding info
4159 if (checkForCollision(start, end, dyld_info.lazy_bind_off, dyld_info.lazy_bind_size)) |pos| {
4160 return pos;
4161 }
4162 // Export info
4163 if (checkForCollision(start, end, dyld_info.export_off, dyld_info.export_size)) |pos| {
4164 return pos;
4138 const offset = dyld_info.rebase_off;
4139 const actual_size = dyld_info.export_off + dyld_info.export_size - offset;
4140 const increased_size = padToIdeal(actual_size);
4141 const test_end = offset + increased_size;
4142 if (end > offset and start < test_end) {
4143 return test_end;
41654144 }
41664145 }
41674146
......@@ -4483,145 +4462,53 @@ fn writeCodeSignature(self: *MachO) !void {
44834462 try self.base.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
44844463}
44854464
4486fn writeExportInfo(self: *MachO) !void {
4487 if (!self.export_info_dirty) return;
4488 if (self.globals.items.len == 0) return;
4489
4490 const tracy = trace(@src());
4491 defer tracy.end();
4492
4493 var trie: Trie = .{};
4494 defer trie.deinit(self.base.allocator);
4495
4496 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
4497 const base_address = text_segment.inner.vmaddr;
4498
4499 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
4500 log.debug("writing export trie", .{});
4501
4502 for (self.globals.items) |sym| {
4503 const sym_name = self.getString(sym.n_strx);
4504 log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value });
4505
4506 try trie.put(self.base.allocator, .{
4507 .name = sym_name,
4508 .vmaddr_offset = sym.n_value - base_address,
4509 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
4510 });
4511 }
4512 try trie.finalize(self.base.allocator);
4513
4514 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, trie.size));
4515 defer self.base.allocator.free(buffer);
4516 var stream = std.io.fixedBufferStream(buffer);
4517 const nwritten = try trie.write(stream.writer());
4518 assert(nwritten == trie.size);
4519
4520 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
4521 const allocated_size = self.allocatedSizeLinkedit(dyld_info.export_off);
4522 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
4523
4524 if (needed_size > allocated_size) {
4525 dyld_info.export_off = 0;
4526 dyld_info.export_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
4527 // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
4528 }
4529 dyld_info.export_size = @intCast(u32, needed_size);
4530 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
4531
4532 try self.base.file.?.pwriteAll(buffer, dyld_info.export_off);
4533 self.load_commands_dirty = true;
4534 self.export_info_dirty = false;
4535}
4536
4537fn writeRebaseInfoTable(self: *MachO) !void {
4538 if (!self.rebase_info_dirty) return;
4465fn writeDyldInfoData(self: *MachO) !void {
4466 if (!self.dyld_info_dirty) return;
45394467
45404468 const tracy = trace(@src());
45414469 defer tracy.end();
45424470
4543 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4544 defer pointers.deinit();
4471 var rebase_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4472 defer rebase_pointers.deinit();
4473 var bind_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4474 defer bind_pointers.deinit();
4475 var lazy_bind_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4476 defer lazy_bind_pointers.deinit();
45454477
45464478 {
45474479 var it = self.blocks.iterator();
45484480 while (it.next()) |entry| {
45494481 const match = entry.key_ptr.*;
4550 var block: *TextBlock = entry.value_ptr.*;
4482 var atom: *TextBlock = entry.value_ptr.*;
45514483
45524484 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
45534485
45544486 const seg = self.load_commands.items[match.seg].Segment;
45554487
45564488 while (true) {
4557 const sym = self.locals.items[block.local_sym_index];
4489 const sym = self.locals.items[atom.local_sym_index];
45584490 const base_offset = sym.n_value - seg.inner.vmaddr;
45594491
4560 for (block.rebases.items) |offset| {
4561 try pointers.append(.{
4492 for (atom.rebases.items) |offset| {
4493 try rebase_pointers.append(.{
45624494 .offset = base_offset + offset,
45634495 .segment_id = match.seg,
45644496 });
45654497 }
45664498
4567 if (block.prev) |prev| {
4568 block = prev;
4569 } else break;
4570 }
4571 }
4572 }
4573
4574 const size = try bind.rebaseInfoSize(pointers.items);
4575 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
4576 defer self.base.allocator.free(buffer);
4577
4578 var stream = std.io.fixedBufferStream(buffer);
4579 try bind.writeRebaseInfo(pointers.items, stream.writer());
4580
4581 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
4582 const allocated_size = self.allocatedSizeLinkedit(dyld_info.rebase_off);
4583 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
4584
4585 if (needed_size > allocated_size) {
4586 dyld_info.rebase_off = 0;
4587 dyld_info.rebase_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
4588 // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
4589 }
4590
4591 dyld_info.rebase_size = @intCast(u32, needed_size);
4592 log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
4593
4594 try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off);
4595 self.load_commands_dirty = true;
4596 self.rebase_info_dirty = false;
4597}
4598
4599fn writeBindInfoTable(self: *MachO) !void {
4600 if (!self.binding_info_dirty) return;
4601
4602 const tracy = trace(@src());
4603 defer tracy.end();
4604
4605 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4606 defer pointers.deinit();
4607
4608 {
4609 var it = self.blocks.iterator();
4610 while (it.next()) |entry| {
4611 const match = entry.key_ptr.*;
4612 var block: *TextBlock = entry.value_ptr.*;
4613
4614 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
4615
4616 const seg = self.load_commands.items[match.seg].Segment;
4617
4618 while (true) {
4619 const sym = self.locals.items[block.local_sym_index];
4620 const base_offset = sym.n_value - seg.inner.vmaddr;
4499 for (atom.bindings.items) |binding| {
4500 const bind_sym = self.undefs.items[binding.local_sym_index];
4501 try bind_pointers.append(.{
4502 .offset = binding.offset + base_offset,
4503 .segment_id = match.seg,
4504 .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
4505 .name = self.getString(bind_sym.n_strx),
4506 });
4507 }
46214508
4622 for (block.bindings.items) |binding| {
4509 for (atom.lazy_bindings.items) |binding| {
46234510 const bind_sym = self.undefs.items[binding.local_sym_index];
4624 try pointers.append(.{
4511 try lazy_bind_pointers.append(.{
46254512 .offset = binding.offset + base_offset,
46264513 .segment_id = match.seg,
46274514 .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
......@@ -4629,97 +4516,76 @@ fn writeBindInfoTable(self: *MachO) !void {
46294516 });
46304517 }
46314518
4632 if (block.prev) |prev| {
4633 block = prev;
4519 if (atom.prev) |prev| {
4520 atom = prev;
46344521 } else break;
46354522 }
46364523 }
46374524 }
46384525
4639 const size = try bind.bindInfoSize(pointers.items);
4640 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
4641 defer self.base.allocator.free(buffer);
4526 var trie: Trie = .{};
4527 defer trie.deinit(self.base.allocator);
46424528
4643 var stream = std.io.fixedBufferStream(buffer);
4644 try bind.writeBindInfo(pointers.items, stream.writer());
4529 {
4530 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
4531 log.debug("writing export trie", .{});
4532 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
4533 const base_address = text_segment.inner.vmaddr;
4534
4535 for (self.globals.items) |sym| {
4536 const sym_name = self.getString(sym.n_strx);
4537 log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value });
4538
4539 try trie.put(self.base.allocator, .{
4540 .name = sym_name,
4541 .vmaddr_offset = sym.n_value - base_address,
4542 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
4543 });
4544 }
4545
4546 try trie.finalize(self.base.allocator);
4547 }
46454548
46464549 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
4647 const allocated_size = self.allocatedSizeLinkedit(dyld_info.bind_off);
4648 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
4550 const allocated_size = self.allocatedSizeLinkedit(dyld_info.rebase_off);
4551 const rebase_size = @intCast(u32, try bind.rebaseInfoSize(rebase_pointers.items));
4552 const bind_size = @intCast(u32, try bind.bindInfoSize(bind_pointers.items));
4553 const lazy_bind_size = @intCast(u32, try bind.lazyBindInfoSize(lazy_bind_pointers.items));
4554 const export_size = @intCast(u32, trie.size);
4555 const total_size = rebase_size + bind_size + lazy_bind_size + export_size;
4556 const needed_size = mem.alignForwardGeneric(u64, total_size, @alignOf(u64));
46494557
46504558 if (needed_size > allocated_size) {
4651 dyld_info.bind_off = 0;
4652 dyld_info.bind_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
4653 // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
4559 dyld_info.rebase_off = 0;
4560 dyld_info.rebase_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
46544561 }
46554562
4656 dyld_info.bind_size = @intCast(u32, needed_size);
4657 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
4563 dyld_info.rebase_size = rebase_size;
4564 dyld_info.bind_off = dyld_info.rebase_off + dyld_info.rebase_size;
4565 dyld_info.bind_size = bind_size;
4566 dyld_info.lazy_bind_off = dyld_info.bind_off + dyld_info.bind_size;
4567 dyld_info.lazy_bind_size = lazy_bind_size;
4568 dyld_info.export_off = dyld_info.lazy_bind_off + dyld_info.lazy_bind_size;
4569 dyld_info.export_size = export_size;
46584570
4659 try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
4660 self.load_commands_dirty = true;
4661 self.binding_info_dirty = false;
4662}
4663
4664fn writeLazyBindInfoTable(self: *MachO) !void {
4665 if (!self.lazy_binding_info_dirty) return;
4666
4667 const tracy = trace(@src());
4668 defer tracy.end();
4669
4670 var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
4671 defer pointers.deinit();
4672
4673 if (self.la_symbol_ptr_section_index) |sect| blk: {
4674 var atom = self.blocks.get(.{
4675 .seg = self.data_segment_cmd_index.?,
4676 .sect = sect,
4677 }) orelse break :blk;
4678 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
4679
4680 while (true) {
4681 const sym = self.locals.items[atom.local_sym_index];
4682 const base_offset = sym.n_value - seg.inner.vmaddr;
4683
4684 for (atom.lazy_bindings.items) |binding| {
4685 const bind_sym = self.undefs.items[binding.local_sym_index];
4686 try pointers.append(.{
4687 .offset = binding.offset + base_offset,
4688 .segment_id = self.data_segment_cmd_index.?,
4689 .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
4690 .name = self.getString(bind_sym.n_strx),
4691 });
4692 }
4693 if (atom.prev) |prev| {
4694 atom = prev;
4695 } else break;
4696 }
4697 }
4698
4699 const size = try bind.lazyBindInfoSize(pointers.items);
4700 var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
4571 var buffer = try self.base.allocator.alloc(u8, needed_size);
47014572 defer self.base.allocator.free(buffer);
4573 mem.set(u8, buffer, 0);
47024574
47034575 var stream = std.io.fixedBufferStream(buffer);
4704 try bind.writeLazyBindInfo(pointers.items, stream.writer());
4576 const writer = stream.writer();
47054577
4706 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
4707 const allocated_size = self.allocatedSizeLinkedit(dyld_info.lazy_bind_off);
4708 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
4578 try bind.writeRebaseInfo(rebase_pointers.items, writer);
4579 try bind.writeBindInfo(bind_pointers.items, writer);
4580 try bind.writeLazyBindInfo(lazy_bind_pointers.items, writer);
4581 _ = try trie.write(writer);
47094582
4710 if (needed_size > allocated_size) {
4711 dyld_info.lazy_bind_off = 0;
4712 dyld_info.lazy_bind_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
4713 // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
4714 }
4715
4716 dyld_info.lazy_bind_size = @intCast(u32, needed_size);
4717 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
4583 log.debug("writing dyld info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + needed_size });
47184584
4719 try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
4720 try self.populateLazyBindOffsetsInStubHelper(buffer);
4585 try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off);
4586 try self.populateLazyBindOffsetsInStubHelper(buffer[rebase_size + bind_size ..][0..lazy_bind_size]);
47214587 self.load_commands_dirty = true;
4722 self.lazy_binding_info_dirty = false;
4588 self.dyld_info_dirty = false;
47234589}
47244590
47254591fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
src/link/MachO/TextBlock.zig+1-3
......@@ -844,9 +844,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
844844 .sect = context.macho_file.got_section_index.?,
845845 };
846846 _ = try context.macho_file.allocateAtom(atom, match);
847 // TODO don't need both at once
848 context.macho_file.rebase_info_dirty = true;
849 context.macho_file.binding_info_dirty = true;
847 context.macho_file.dyld_info_dirty = true;
850848 } else if (parsed_rel.payload == .unsigned) {
851849 switch (parsed_rel.where) {
852850 .undef => {