aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-09-03 17:12:39 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-09-03 17:12:39 +0200
commit80e1c244b6c9d5f3e855878d92ecc09dc8eb970a (patch)
treeef93e21cde0713b0749e29951b2d54bfe000575d /src
parent1d2199b71c06e97be407c2bd0b05c07c8bd6cd2c (diff)
downloadzig-80e1c244b6c9d5f3e855878d92ecc09dc8eb970a.tar.gz
zig-80e1c244b6c9d5f3e855878d92ecc09dc8eb970a.zip
macho: dyld info subsections need to follow in strict order
MachO, why are doing this to me?
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig362
-rw-r--r--src/link/MachO/TextBlock.zig4
2 files changed, 115 insertions, 251 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index cd5a0218d1..c1fb6977c5 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -162,10 +162,7 @@ stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{},
error_flags: File.ErrorFlags = File.ErrorFlags{},
load_commands_dirty: bool = false,
-rebase_info_dirty: bool = false,
-binding_info_dirty: bool = false,
-lazy_binding_info_dirty: bool = false,
-export_info_dirty: bool = false,
+dyld_info_dirty: bool = false,
strtab_dirty: bool = false,
strtab_needs_relocation: bool = false,
@@ -814,10 +811,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
defer tracy.end();
try self.setEntryPoint();
- try self.writeRebaseInfoTable();
- try self.writeBindInfoTable();
- try self.writeLazyBindInfoTable();
- try self.writeExportInfo();
+ try self.writeDyldInfoData();
try self.writeAllGlobalAndUndefSymbols();
try self.writeIndirectSymbolTable();
try self.writeStringTable();
@@ -849,10 +843,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
}
assert(!self.load_commands_dirty);
- assert(!self.rebase_info_dirty);
- assert(!self.binding_info_dirty);
- assert(!self.lazy_binding_info_dirty);
- assert(!self.export_info_dirty);
+ assert(!self.dyld_info_dirty);
assert(!self.strtab_dirty);
assert(!self.strtab_needs_relocation);
@@ -2111,7 +2102,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym
.local_sym_index = lazy_binding_sym_index,
.offset = 0,
});
- self.lazy_binding_info_dirty = true;
+ self.dyld_info_dirty = true;
return atom;
}
@@ -2312,7 +2303,7 @@ fn resolveSymbolsInObject(
.local_sym_index = local_sym_index,
.file = object_id,
};
- self.export_info_dirty = true;
+ self.dyld_info_dirty = true;
} else if (symbolIsTentative(sym)) {
// Symbol is a tentative definition.
const resolv = self.symbol_resolver.getPtr(n_strx) orelse {
@@ -2647,7 +2638,7 @@ fn resolveDyldStubBinder(self: *MachO) !void {
.sect = self.got_section_index.?,
};
_ = try self.allocateAtom(atom, match);
- self.binding_info_dirty = true;
+ self.dyld_info_dirty = true;
}
fn parseTextBlocks(self: *MachO) !void {
@@ -2946,7 +2937,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
};
const got_atom = try self.createGotAtom(key);
try self.got_entries_map.put(self.base.allocator, key, got_atom);
- self.rebase_info_dirty = true;
+ self.dyld_info_dirty = true;
}
pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
@@ -3266,7 +3257,7 @@ pub fn updateDeclExports(
const name_str_index = try self.makeString(exp_name);
const i = if (self.globals_free_list.popOrNull()) |i| i else blk: {
_ = self.globals.addOneAssumeCapacity();
- self.export_info_dirty = true;
+ self.dyld_info_dirty = true;
break :blk @intCast(u32, self.globals.items.len - 1);
};
self.globals.items[i] = .{
@@ -3648,29 +3639,34 @@ pub fn populateMissingMetadata(self: *MachO) !void {
},
});
+ // Preallocate rebase, binding, lazy binding info, and export info.
const dyld = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
+ const subsection_size = 128; // TODO this is totally random
+ const needed_size = 4 * subsection_size;
+ const offset = self.findFreeSpaceLinkedit(needed_size, 1, null);
+
+ const rebase_off = @intCast(u32, offset);
+ log.debug("found rebase info free space 0x{x} to 0x{x}", .{ rebase_off, rebase_off + subsection_size });
+ dyld.rebase_off = rebase_off;
+ dyld.rebase_size = subsection_size;
+
+ const bind_off = rebase_off + subsection_size;
+ log.debug("found binding info free space 0x{x} to 0x{x}", .{ bind_off, bind_off + subsection_size });
+ dyld.bind_off = bind_off;
+ dyld.bind_size = subsection_size;
+
+ const lazy_bind_off = bind_off + subsection_size;
+ log.debug("found lazy binding info free space 0x{x} to 0x{x}", .{
+ lazy_bind_off,
+ lazy_bind_off + subsection_size,
+ });
+ dyld.lazy_bind_off = lazy_bind_off;
+ dyld.lazy_bind_size = subsection_size;
- // Preallocate rebase, binding, lazy binding info, and export info.
- const expected_size = 48; // TODO This is totally random.
- const rebase_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
- log.debug("found rebase info free space 0x{x} to 0x{x}", .{ rebase_off, rebase_off + expected_size });
- dyld.rebase_off = @intCast(u32, rebase_off);
- dyld.rebase_size = expected_size;
-
- const bind_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
- log.debug("found binding info free space 0x{x} to 0x{x}", .{ bind_off, bind_off + expected_size });
- dyld.bind_off = @intCast(u32, bind_off);
- dyld.bind_size = expected_size;
-
- const lazy_bind_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
- log.debug("found lazy binding info free space 0x{x} to 0x{x}", .{ lazy_bind_off, lazy_bind_off + expected_size });
- dyld.lazy_bind_off = @intCast(u32, lazy_bind_off);
- dyld.lazy_bind_size = expected_size;
-
- const export_off = self.findFreeSpaceLinkedit(expected_size, 1, null);
- log.debug("found export info free space 0x{x} to 0x{x}", .{ export_off, export_off + expected_size });
- dyld.export_off = @intCast(u32, export_off);
- dyld.export_size = expected_size;
+ const export_off = lazy_bind_off + subsection_size;
+ log.debug("found export info free space 0x{x} to 0x{x}", .{ export_off, export_off + subsection_size });
+ dyld.export_off = export_off;
+ dyld.export_size = subsection_size;
self.load_commands_dirty = true;
}
@@ -4097,10 +4093,6 @@ fn allocatedSizeLinkedit(self: *MachO, start: u64) u64 {
if (self.dyld_info_cmd_index) |idx| {
const dyld_info = self.load_commands.items[idx].DyldInfoOnly;
if (dyld_info.rebase_off > start and dyld_info.rebase_off < min_pos) min_pos = dyld_info.rebase_off;
- if (dyld_info.bind_off > start and dyld_info.bind_off < min_pos) min_pos = dyld_info.bind_off;
- if (dyld_info.weak_bind_off > start and dyld_info.weak_bind_off < min_pos) min_pos = dyld_info.weak_bind_off;
- if (dyld_info.lazy_bind_off > start and dyld_info.lazy_bind_off < min_pos) min_pos = dyld_info.lazy_bind_off;
- if (dyld_info.export_off > start and dyld_info.export_off < min_pos) min_pos = dyld_info.export_off;
}
if (self.function_starts_cmd_index) |idx| {
@@ -4141,27 +4133,14 @@ fn detectAllocCollisionLinkedit(self: *MachO, start: u64, size: u64) ?u64 {
// __LINKEDIT is a weird segment where sections get their own load commands so we
// special-case it.
- if (self.dyld_info_cmd_index) |idx| outer: {
- if (self.load_commands.items.len == idx) break :outer;
+ if (self.dyld_info_cmd_index) |idx| {
const dyld_info = self.load_commands.items[idx].DyldInfoOnly;
- if (checkForCollision(start, end, dyld_info.rebase_off, dyld_info.rebase_size)) |pos| {
- return pos;
- }
- // Binding info
- if (checkForCollision(start, end, dyld_info.bind_off, dyld_info.bind_size)) |pos| {
- return pos;
- }
- // Weak binding info
- if (checkForCollision(start, end, dyld_info.weak_bind_off, dyld_info.weak_bind_size)) |pos| {
- return pos;
- }
- // Lazy binding info
- if (checkForCollision(start, end, dyld_info.lazy_bind_off, dyld_info.lazy_bind_size)) |pos| {
- return pos;
- }
- // Export info
- if (checkForCollision(start, end, dyld_info.export_off, dyld_info.export_size)) |pos| {
- return pos;
+ const offset = dyld_info.rebase_off;
+ const actual_size = dyld_info.export_off + dyld_info.export_size - offset;
+ const increased_size = padToIdeal(actual_size);
+ const test_end = offset + increased_size;
+ if (end > offset and start < test_end) {
+ return test_end;
}
}
@@ -4483,145 +4462,53 @@ fn writeCodeSignature(self: *MachO) !void {
try self.base.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
}
-fn writeExportInfo(self: *MachO) !void {
- if (!self.export_info_dirty) return;
- if (self.globals.items.len == 0) return;
-
- const tracy = trace(@src());
- defer tracy.end();
-
- var trie: Trie = .{};
- defer trie.deinit(self.base.allocator);
-
- const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
- const base_address = text_segment.inner.vmaddr;
-
- // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
- log.debug("writing export trie", .{});
-
- for (self.globals.items) |sym| {
- const sym_name = self.getString(sym.n_strx);
- log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value });
-
- try trie.put(self.base.allocator, .{
- .name = sym_name,
- .vmaddr_offset = sym.n_value - base_address,
- .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
- });
- }
- try trie.finalize(self.base.allocator);
-
- var buffer = try self.base.allocator.alloc(u8, @intCast(usize, trie.size));
- defer self.base.allocator.free(buffer);
- var stream = std.io.fixedBufferStream(buffer);
- const nwritten = try trie.write(stream.writer());
- assert(nwritten == trie.size);
-
- const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
- const allocated_size = self.allocatedSizeLinkedit(dyld_info.export_off);
- const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
-
- if (needed_size > allocated_size) {
- dyld_info.export_off = 0;
- dyld_info.export_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
- // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
- }
- dyld_info.export_size = @intCast(u32, needed_size);
- log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
-
- try self.base.file.?.pwriteAll(buffer, dyld_info.export_off);
- self.load_commands_dirty = true;
- self.export_info_dirty = false;
-}
-
-fn writeRebaseInfoTable(self: *MachO) !void {
- if (!self.rebase_info_dirty) return;
+fn writeDyldInfoData(self: *MachO) !void {
+ if (!self.dyld_info_dirty) return;
const tracy = trace(@src());
defer tracy.end();
- var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
- defer pointers.deinit();
+ var rebase_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
+ defer rebase_pointers.deinit();
+ var bind_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
+ defer bind_pointers.deinit();
+ var lazy_bind_pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
+ defer lazy_bind_pointers.deinit();
{
var it = self.blocks.iterator();
while (it.next()) |entry| {
const match = entry.key_ptr.*;
- var block: *TextBlock = entry.value_ptr.*;
+ var atom: *TextBlock = entry.value_ptr.*;
if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
const seg = self.load_commands.items[match.seg].Segment;
while (true) {
- const sym = self.locals.items[block.local_sym_index];
+ const sym = self.locals.items[atom.local_sym_index];
const base_offset = sym.n_value - seg.inner.vmaddr;
- for (block.rebases.items) |offset| {
- try pointers.append(.{
+ for (atom.rebases.items) |offset| {
+ try rebase_pointers.append(.{
.offset = base_offset + offset,
.segment_id = match.seg,
});
}
- if (block.prev) |prev| {
- block = prev;
- } else break;
- }
- }
- }
-
- const size = try bind.rebaseInfoSize(pointers.items);
- var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
- defer self.base.allocator.free(buffer);
-
- var stream = std.io.fixedBufferStream(buffer);
- try bind.writeRebaseInfo(pointers.items, stream.writer());
-
- const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
- const allocated_size = self.allocatedSizeLinkedit(dyld_info.rebase_off);
- const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
-
- if (needed_size > allocated_size) {
- dyld_info.rebase_off = 0;
- dyld_info.rebase_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
- // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
- }
-
- dyld_info.rebase_size = @intCast(u32, needed_size);
- log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
-
- try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off);
- self.load_commands_dirty = true;
- self.rebase_info_dirty = false;
-}
-
-fn writeBindInfoTable(self: *MachO) !void {
- if (!self.binding_info_dirty) return;
-
- const tracy = trace(@src());
- defer tracy.end();
-
- var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
- defer pointers.deinit();
-
- {
- var it = self.blocks.iterator();
- while (it.next()) |entry| {
- const match = entry.key_ptr.*;
- var block: *TextBlock = entry.value_ptr.*;
-
- if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
-
- const seg = self.load_commands.items[match.seg].Segment;
-
- while (true) {
- const sym = self.locals.items[block.local_sym_index];
- const base_offset = sym.n_value - seg.inner.vmaddr;
+ for (atom.bindings.items) |binding| {
+ const bind_sym = self.undefs.items[binding.local_sym_index];
+ try bind_pointers.append(.{
+ .offset = binding.offset + base_offset,
+ .segment_id = match.seg,
+ .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
+ .name = self.getString(bind_sym.n_strx),
+ });
+ }
- for (block.bindings.items) |binding| {
+ for (atom.lazy_bindings.items) |binding| {
const bind_sym = self.undefs.items[binding.local_sym_index];
- try pointers.append(.{
+ try lazy_bind_pointers.append(.{
.offset = binding.offset + base_offset,
.segment_id = match.seg,
.dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
@@ -4629,97 +4516,76 @@ fn writeBindInfoTable(self: *MachO) !void {
});
}
- if (block.prev) |prev| {
- block = prev;
+ if (atom.prev) |prev| {
+ atom = prev;
} else break;
}
}
}
- const size = try bind.bindInfoSize(pointers.items);
- var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
- defer self.base.allocator.free(buffer);
+ var trie: Trie = .{};
+ defer trie.deinit(self.base.allocator);
- var stream = std.io.fixedBufferStream(buffer);
- try bind.writeBindInfo(pointers.items, stream.writer());
+ {
+ // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
+ log.debug("writing export trie", .{});
+ const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
+ const base_address = text_segment.inner.vmaddr;
+
+ for (self.globals.items) |sym| {
+ const sym_name = self.getString(sym.n_strx);
+ log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value });
+
+ try trie.put(self.base.allocator, .{
+ .name = sym_name,
+ .vmaddr_offset = sym.n_value - base_address,
+ .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
+ });
+ }
+
+ try trie.finalize(self.base.allocator);
+ }
const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
- const allocated_size = self.allocatedSizeLinkedit(dyld_info.bind_off);
- const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
+ const allocated_size = self.allocatedSizeLinkedit(dyld_info.rebase_off);
+ const rebase_size = @intCast(u32, try bind.rebaseInfoSize(rebase_pointers.items));
+ const bind_size = @intCast(u32, try bind.bindInfoSize(bind_pointers.items));
+ const lazy_bind_size = @intCast(u32, try bind.lazyBindInfoSize(lazy_bind_pointers.items));
+ const export_size = @intCast(u32, trie.size);
+ const total_size = rebase_size + bind_size + lazy_bind_size + export_size;
+ const needed_size = mem.alignForwardGeneric(u64, total_size, @alignOf(u64));
if (needed_size > allocated_size) {
- dyld_info.bind_off = 0;
- dyld_info.bind_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
- // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
+ dyld_info.rebase_off = 0;
+ dyld_info.rebase_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
}
- dyld_info.bind_size = @intCast(u32, needed_size);
- log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
+ dyld_info.rebase_size = rebase_size;
+ dyld_info.bind_off = dyld_info.rebase_off + dyld_info.rebase_size;
+ dyld_info.bind_size = bind_size;
+ dyld_info.lazy_bind_off = dyld_info.bind_off + dyld_info.bind_size;
+ dyld_info.lazy_bind_size = lazy_bind_size;
+ dyld_info.export_off = dyld_info.lazy_bind_off + dyld_info.lazy_bind_size;
+ dyld_info.export_size = export_size;
- try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
- self.load_commands_dirty = true;
- self.binding_info_dirty = false;
-}
-
-fn writeLazyBindInfoTable(self: *MachO) !void {
- if (!self.lazy_binding_info_dirty) return;
-
- const tracy = trace(@src());
- defer tracy.end();
-
- var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
- defer pointers.deinit();
-
- if (self.la_symbol_ptr_section_index) |sect| blk: {
- var atom = self.blocks.get(.{
- .seg = self.data_segment_cmd_index.?,
- .sect = sect,
- }) orelse break :blk;
- const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
-
- while (true) {
- const sym = self.locals.items[atom.local_sym_index];
- const base_offset = sym.n_value - seg.inner.vmaddr;
-
- for (atom.lazy_bindings.items) |binding| {
- const bind_sym = self.undefs.items[binding.local_sym_index];
- try pointers.append(.{
- .offset = binding.offset + base_offset,
- .segment_id = self.data_segment_cmd_index.?,
- .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER),
- .name = self.getString(bind_sym.n_strx),
- });
- }
- if (atom.prev) |prev| {
- atom = prev;
- } else break;
- }
- }
-
- const size = try bind.lazyBindInfoSize(pointers.items);
- var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
+ var buffer = try self.base.allocator.alloc(u8, needed_size);
defer self.base.allocator.free(buffer);
+ mem.set(u8, buffer, 0);
var stream = std.io.fixedBufferStream(buffer);
- try bind.writeLazyBindInfo(pointers.items, stream.writer());
+ const writer = stream.writer();
- const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
- const allocated_size = self.allocatedSizeLinkedit(dyld_info.lazy_bind_off);
- const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
+ try bind.writeRebaseInfo(rebase_pointers.items, writer);
+ try bind.writeBindInfo(bind_pointers.items, writer);
+ try bind.writeLazyBindInfo(lazy_bind_pointers.items, writer);
+ _ = try trie.write(writer);
- if (needed_size > allocated_size) {
- dyld_info.lazy_bind_off = 0;
- dyld_info.lazy_bind_off = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1, null));
- // TODO this might require relocating all following LC_DYLD_INFO_ONLY sections too.
- }
-
- dyld_info.lazy_bind_size = @intCast(u32, needed_size);
- 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 });
+ log.debug("writing dyld info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + needed_size });
- try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
- try self.populateLazyBindOffsetsInStubHelper(buffer);
+ try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off);
+ try self.populateLazyBindOffsetsInStubHelper(buffer[rebase_size + bind_size ..][0..lazy_bind_size]);
self.load_commands_dirty = true;
- self.lazy_binding_info_dirty = false;
+ self.dyld_info_dirty = false;
}
fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
diff --git a/src/link/MachO/TextBlock.zig b/src/link/MachO/TextBlock.zig
index af9bf5b3eb..e6ceed9c55 100644
--- a/src/link/MachO/TextBlock.zig
+++ b/src/link/MachO/TextBlock.zig
@@ -844,9 +844,7 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
.sect = context.macho_file.got_section_index.?,
};
_ = try context.macho_file.allocateAtom(atom, match);
- // TODO don't need both at once
- context.macho_file.rebase_info_dirty = true;
- context.macho_file.binding_info_dirty = true;
+ context.macho_file.dyld_info_dirty = true;
} else if (parsed_rel.payload == .unsigned) {
switch (parsed_rel.where) {
.undef => {