authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-25 08:45:00+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
logb2af2dc8b751e3a784b10f67314303b4e6514bdc
treebede8e08d0ef6abe2f523355ff11492c573e601e
parent19afd794d08bfbebc57ee1f0cb8ddfb8e5601cdd

macho: move symbol resolver into zld driver's state


3 files changed, 54 insertions(+), 63 deletions(-)

src/link/MachO.zig+3-9
...@@ -297,12 +297,6 @@ pub const SymbolWithLoc = extern struct {...@@ -297,12 +297,6 @@ pub const SymbolWithLoc = extern struct {
297 }297 }
298};298};
299299
300pub const SymbolResolver = struct {
301 arena: Allocator,
302 table: std.StringHashMap(u32),
303 unresolved: std.AutoArrayHashMap(u32, void),
304};
305
306const HotUpdateState = struct {300const HotUpdateState = struct {
307 mach_task: ?std.os.darwin.MachTask = null,301 mach_task: ?std.os.darwin.MachTask = null,
308};302};
...@@ -4092,15 +4086,15 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 {...@@ -4092,15 +4086,15 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 {
4092 return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence;4086 return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence;
4093}4087}
40944088
4095pub fn reportUndefined(self: *MachO, ctx: anytype, resolver: *const SymbolResolver) !void {4089pub fn reportUndefined(self: *MachO, ctx: anytype) !void {
4096 const count = resolver.unresolved.count();4090 const count = ctx.unresolved.count();
4097 if (count == 0) return;4091 if (count == 0) return;
40984092
4099 const gpa = self.base.allocator;4093 const gpa = self.base.allocator;
41004094
4101 try self.misc_errors.ensureUnusedCapacity(gpa, count);4095 try self.misc_errors.ensureUnusedCapacity(gpa, count);
41024096
4103 for (resolver.unresolved.keys()) |global_index| {4097 for (ctx.unresolved.keys()) |global_index| {
4104 const global = ctx.globals.items[global_index];4098 const global = ctx.globals.items[global_index];
4105 const sym_name = ctx.getSymbolName(global);4099 const sym_name = ctx.getSymbolName(global);
41064100
src/link/MachO/dead_strip.zig+4-5
...@@ -12,13 +12,12 @@ const Allocator = mem.Allocator;...@@ -12,13 +12,12 @@ const Allocator = mem.Allocator;
12const Atom = @import("Atom.zig");12const Atom = @import("Atom.zig");
13const MachO = @import("../MachO.zig");13const MachO = @import("../MachO.zig");
14const SymbolWithLoc = MachO.SymbolWithLoc;14const SymbolWithLoc = MachO.SymbolWithLoc;
15const SymbolResolver = MachO.SymbolResolver;
16const UnwindInfo = @import("UnwindInfo.zig");15const UnwindInfo = @import("UnwindInfo.zig");
17const Zld = @import("zld.zig").Zld;16const Zld = @import("zld.zig").Zld;
1817
19const AtomTable = std.AutoHashMap(Atom.Index, void);18const AtomTable = std.AutoHashMap(Atom.Index, void);
2019
21pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void {20pub fn gcAtoms(zld: *Zld) !void {
22 const gpa = zld.gpa;21 const gpa = zld.gpa;
2322
24 var arena = std.heap.ArenaAllocator.init(gpa);23 var arena = std.heap.ArenaAllocator.init(gpa);
...@@ -30,7 +29,7 @@ pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void {...@@ -30,7 +29,7 @@ pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void {
30 var alive = AtomTable.init(arena.allocator());29 var alive = AtomTable.init(arena.allocator());
31 try alive.ensureTotalCapacity(@as(u32, @intCast(zld.atoms.items.len)));30 try alive.ensureTotalCapacity(@as(u32, @intCast(zld.atoms.items.len)));
3231
33 try collectRoots(zld, &roots, resolver);32 try collectRoots(zld, &roots);
34 try mark(zld, roots, &alive);33 try mark(zld, roots, &alive);
35 prune(zld, alive);34 prune(zld, alive);
36}35}
...@@ -48,7 +47,7 @@ fn addRoot(zld: *Zld, roots: *AtomTable, file: u32, sym_loc: SymbolWithLoc) !voi...@@ -48,7 +47,7 @@ fn addRoot(zld: *Zld, roots: *AtomTable, file: u32, sym_loc: SymbolWithLoc) !voi
48 _ = try roots.getOrPut(atom_index);47 _ = try roots.getOrPut(atom_index);
49}48}
5049
51fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) !void {50fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
52 log.debug("collecting roots", .{});51 log.debug("collecting roots", .{});
5352
54 switch (zld.options.output_mode) {53 switch (zld.options.output_mode) {
...@@ -77,7 +76,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) !...@@ -77,7 +76,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) !
7776
78 // Add all symbols force-defined by the user.77 // Add all symbols force-defined by the user.
79 for (zld.options.force_undefined_symbols.keys()) |sym_name| {78 for (zld.options.force_undefined_symbols.keys()) |sym_name| {
80 const global_index = resolver.table.get(sym_name).?;79 const global_index = zld.resolver.get(sym_name).?;
81 const global = zld.globals.items[global_index];80 const global = zld.globals.items[global_index];
82 const sym = zld.getSymbol(global);81 const sym = zld.getSymbol(global);
83 assert(!sym.undf());82 assert(!sym.undf());
src/link/MachO/zld.zig+47-49
...@@ -34,7 +34,6 @@ const Object = @import("Object.zig");...@@ -34,7 +34,6 @@ const Object = @import("Object.zig");
34const Section = MachO.Section;34const Section = MachO.Section;
35const StringTable = @import("../strtab.zig").StringTable;35const StringTable = @import("../strtab.zig").StringTable;
36const SymbolWithLoc = MachO.SymbolWithLoc;36const SymbolWithLoc = MachO.SymbolWithLoc;
37const SymbolResolver = MachO.SymbolResolver;
38const TableSection = @import("../table_section.zig").TableSection;37const TableSection = @import("../table_section.zig").TableSection;
39const Trie = @import("Trie.zig");38const Trie = @import("Trie.zig");
40const UnwindInfo = @import("UnwindInfo.zig");39const UnwindInfo = @import("UnwindInfo.zig");
...@@ -76,6 +75,8 @@ pub const Zld = struct {...@@ -76,6 +75,8 @@ pub const Zld = struct {
7675
77 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},76 locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
78 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},77 globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
78 resolver: std.StringHashMapUnmanaged(u32) = .{},
79 unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
7980
80 entry_index: ?u32 = null,81 entry_index: ?u32 = null,
81 mh_execute_header_index: ?u32 = null,82 mh_execute_header_index: ?u32 = null,
...@@ -327,53 +328,53 @@ pub const Zld = struct {...@@ -327,53 +328,53 @@ pub const Zld = struct {
327 }328 }
328 }329 }
329330
330 fn addUndefined(self: *Zld, name: []const u8, resolver: *SymbolResolver) !void {331 fn addUndefined(self: *Zld, name: []const u8) !void {
331 const sym_index = try self.allocateSymbol();332 const sym_index = try self.allocateSymbol();
332 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };333 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
333 const sym = self.getSymbolPtr(sym_loc);334 const sym = self.getSymbolPtr(sym_loc);
334 sym.n_strx = try self.strtab.insert(self.gpa, name);335 sym.n_strx = try self.strtab.insert(self.gpa, name);
335 sym.n_type = macho.N_UNDF;336 sym.n_type = macho.N_UNDF;
336 const global_index = try self.addGlobal(sym_loc);337 const global_index = try self.addGlobal(sym_loc);
337 try resolver.table.putNoClobber(name, global_index);338 try self.resolver.putNoClobber(self.gpa, name, global_index);
338 try resolver.unresolved.putNoClobber(global_index, {});339 try self.unresolved.putNoClobber(self.gpa, global_index, {});
339 }340 }
340341
341 fn resolveSymbols(self: *Zld, resolver: *SymbolResolver) !void {342 fn resolveSymbols(self: *Zld) !void {
342 // We add the specified entrypoint as the first unresolved symbols so that343 // We add the specified entrypoint as the first unresolved symbols so that
343 // we search for it in libraries should there be no object files specified344 // we search for it in libraries should there be no object files specified
344 // on the linker line.345 // on the linker line.
345 if (self.options.output_mode == .Exe) {346 if (self.options.output_mode == .Exe) {
346 const entry_name = self.options.entry orelse load_commands.default_entry_point;347 const entry_name = self.options.entry orelse load_commands.default_entry_point;
347 try self.addUndefined(entry_name, resolver);348 try self.addUndefined(entry_name);
348 }349 }
349350
350 // Force resolution of any symbols requested by the user.351 // Force resolution of any symbols requested by the user.
351 for (self.options.force_undefined_symbols.keys()) |sym_name| {352 for (self.options.force_undefined_symbols.keys()) |sym_name| {
352 try self.addUndefined(sym_name, resolver);353 try self.addUndefined(sym_name);
353 }354 }
354355
355 for (self.objects.items, 0..) |_, object_id| {356 for (self.objects.items, 0..) |_, object_id| {
356 try self.resolveSymbolsInObject(@as(u32, @intCast(object_id)), resolver);357 try self.resolveSymbolsInObject(@as(u32, @intCast(object_id)));
357 }358 }
358359
359 try self.resolveSymbolsInArchives(resolver);360 try self.resolveSymbolsInArchives();
360361
361 // Finally, force resolution of dyld_stub_binder if there are imports362 // Finally, force resolution of dyld_stub_binder if there are imports
362 // requested.363 // requested.
363 if (resolver.unresolved.count() > 0) {364 if (self.unresolved.count() > 0) {
364 try self.addUndefined("dyld_stub_binder", resolver);365 try self.addUndefined("dyld_stub_binder");
365 }366 }
366367
367 try self.resolveSymbolsInDylibs(resolver);368 try self.resolveSymbolsInDylibs();
368369
369 self.dyld_stub_binder_index = resolver.table.get("dyld_stub_binder");370 self.dyld_stub_binder_index = self.resolver.get("dyld_stub_binder");
370371
371 try self.createMhExecuteHeaderSymbol(resolver);372 try self.createMhExecuteHeaderSymbol();
372 try self.createDsoHandleSymbol(resolver);373 try self.createDsoHandleSymbol();
373 try self.resolveSymbolsAtLoading(resolver);374 try self.resolveSymbolsAtLoading();
374 }375 }
375376
376 fn resolveSymbolsInObject(self: *Zld, object_id: u32, resolver: *SymbolResolver) !void {377 fn resolveSymbolsInObject(self: *Zld, object_id: u32) !void {
377 const object = &self.objects.items[object_id];378 const object = &self.objects.items[object_id];
378 const in_symtab = object.in_symtab orelse return;379 const in_symtab = object.in_symtab orelse return;
379380
...@@ -415,11 +416,11 @@ pub const Zld = struct {...@@ -415,11 +416,11 @@ pub const Zld = struct {
415416
416 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };417 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };
417418
418 const global_index = resolver.table.get(sym_name) orelse {419 const global_index = self.resolver.get(sym_name) orelse {
419 const global_index = try self.addGlobal(sym_loc);420 const global_index = try self.addGlobal(sym_loc);
420 try resolver.table.putNoClobber(sym_name, global_index);421 try self.resolver.putNoClobber(self.gpa, sym_name, global_index);
421 if (sym.undf() and !sym.tentative()) {422 if (sym.undf() and !sym.tentative()) {
422 try resolver.unresolved.putNoClobber(global_index, {});423 try self.unresolved.putNoClobber(self.gpa, global_index, {});
423 }424 }
424 continue;425 continue;
425 };426 };
...@@ -477,7 +478,7 @@ pub const Zld = struct {...@@ -477,7 +478,7 @@ pub const Zld = struct {
477 const global_object = &self.objects.items[file];478 const global_object = &self.objects.items[file];
478 global_object.globals_lookup[global.sym_index] = global_index;479 global_object.globals_lookup[global.sym_index] = global_index;
479 }480 }
480 _ = resolver.unresolved.swapRemove(resolver.table.get(sym_name).?);481 _ = self.unresolved.swapRemove(self.resolver.get(sym_name).?);
481 global.* = sym_loc;482 global.* = sym_loc;
482 } else {483 } else {
483 object.globals_lookup[sym_index] = global_index;484 object.globals_lookup[sym_index] = global_index;
...@@ -485,14 +486,14 @@ pub const Zld = struct {...@@ -485,14 +486,14 @@ pub const Zld = struct {
485 }486 }
486 }487 }
487488
488 fn resolveSymbolsInArchives(self: *Zld, resolver: *SymbolResolver) !void {489 fn resolveSymbolsInArchives(self: *Zld) !void {
489 if (self.archives.items.len == 0) return;490 if (self.archives.items.len == 0) return;
490491
491 const gpa = self.gpa;492 const gpa = self.gpa;
492493
493 var next_sym: usize = 0;494 var next_sym: usize = 0;
494 loop: while (next_sym < resolver.unresolved.count()) {495 loop: while (next_sym < self.unresolved.count()) {
495 const global = self.globals.items[resolver.unresolved.keys()[next_sym]];496 const global = self.globals.items[self.unresolved.keys()[next_sym]];
496 const sym_name = self.getSymbolName(global);497 const sym_name = self.getSymbolName(global);
497498
498 for (self.archives.items) |archive| {499 for (self.archives.items) |archive| {
...@@ -506,7 +507,7 @@ pub const Zld = struct {...@@ -506,7 +507,7 @@ pub const Zld = struct {
506 const object_id = @as(u16, @intCast(self.objects.items.len));507 const object_id = @as(u16, @intCast(self.objects.items.len));
507 const object = try archive.parseObject(gpa, offsets.items[0]);508 const object = try archive.parseObject(gpa, offsets.items[0]);
508 try self.objects.append(gpa, object);509 try self.objects.append(gpa, object);
509 try self.resolveSymbolsInObject(object_id, resolver);510 try self.resolveSymbolsInObject(object_id);
510511
511 continue :loop;512 continue :loop;
512 }513 }
...@@ -515,12 +516,12 @@ pub const Zld = struct {...@@ -515,12 +516,12 @@ pub const Zld = struct {
515 }516 }
516 }517 }
517518
518 fn resolveSymbolsInDylibs(self: *Zld, resolver: *SymbolResolver) !void {519 fn resolveSymbolsInDylibs(self: *Zld) !void {
519 if (self.dylibs.items.len == 0) return;520 if (self.dylibs.items.len == 0) return;
520521
521 var next_sym: usize = 0;522 var next_sym: usize = 0;
522 loop: while (next_sym < resolver.unresolved.count()) {523 loop: while (next_sym < self.unresolved.count()) {
523 const global_index = resolver.unresolved.keys()[next_sym];524 const global_index = self.unresolved.keys()[next_sym];
524 const global = self.globals.items[global_index];525 const global = self.globals.items[global_index];
525 const sym = self.getSymbolPtr(global);526 const sym = self.getSymbolPtr(global);
526 const sym_name = self.getSymbolName(global);527 const sym_name = self.getSymbolName(global);
...@@ -541,7 +542,7 @@ pub const Zld = struct {...@@ -541,7 +542,7 @@ pub const Zld = struct {
541 sym.n_desc |= macho.N_WEAK_REF;542 sym.n_desc |= macho.N_WEAK_REF;
542 }543 }
543544
544 assert(resolver.unresolved.swapRemove(global_index));545 assert(self.unresolved.swapRemove(global_index));
545 continue :loop;546 continue :loop;
546 }547 }
547548
...@@ -549,14 +550,14 @@ pub const Zld = struct {...@@ -549,14 +550,14 @@ pub const Zld = struct {
549 }550 }
550 }551 }
551552
552 fn resolveSymbolsAtLoading(self: *Zld, resolver: *SymbolResolver) !void {553 fn resolveSymbolsAtLoading(self: *Zld) !void {
553 const is_lib = self.options.output_mode == .Lib;554 const is_lib = self.options.output_mode == .Lib;
554 const is_dyn_lib = self.options.link_mode == .Dynamic and is_lib;555 const is_dyn_lib = self.options.link_mode == .Dynamic and is_lib;
555 const allow_undef = is_dyn_lib and (self.options.allow_shlib_undefined orelse false);556 const allow_undef = is_dyn_lib and (self.options.allow_shlib_undefined orelse false);
556557
557 var next_sym: usize = 0;558 var next_sym: usize = 0;
558 while (next_sym < resolver.unresolved.count()) {559 while (next_sym < self.unresolved.count()) {
559 const global_index = resolver.unresolved.keys()[next_sym];560 const global_index = self.unresolved.keys()[next_sym];
560 const global = self.globals.items[global_index];561 const global = self.globals.items[global_index];
561 const sym = self.getSymbolPtr(global);562 const sym = self.getSymbolPtr(global);
562563
...@@ -568,7 +569,7 @@ pub const Zld = struct {...@@ -568,7 +569,7 @@ pub const Zld = struct {
568 .n_desc = 0,569 .n_desc = 0,
569 .n_value = 0,570 .n_value = 0,
570 };571 };
571 _ = resolver.unresolved.swapRemove(global_index);572 _ = self.unresolved.swapRemove(global_index);
572 continue;573 continue;
573 } else if (allow_undef) {574 } else if (allow_undef) {
574 const n_desc = @as(575 const n_desc = @as(
...@@ -577,7 +578,7 @@ pub const Zld = struct {...@@ -577,7 +578,7 @@ pub const Zld = struct {
577 );578 );
578 sym.n_type = macho.N_EXT;579 sym.n_type = macho.N_EXT;
579 sym.n_desc = n_desc;580 sym.n_desc = n_desc;
580 _ = resolver.unresolved.swapRemove(global_index);581 _ = self.unresolved.swapRemove(global_index);
581 continue;582 continue;
582 }583 }
583584
...@@ -585,9 +586,9 @@ pub const Zld = struct {...@@ -585,9 +586,9 @@ pub const Zld = struct {
585 }586 }
586 }587 }
587588
588 fn createMhExecuteHeaderSymbol(self: *Zld, resolver: *SymbolResolver) !void {589 fn createMhExecuteHeaderSymbol(self: *Zld) !void {
589 if (self.options.output_mode != .Exe) return;590 if (self.options.output_mode != .Exe) return;
590 if (resolver.table.get("__mh_execute_header")) |global_index| {591 if (self.resolver.get("__mh_execute_header")) |global_index| {
591 const global = self.globals.items[global_index];592 const global = self.globals.items[global_index];
592 const sym = self.getSymbol(global);593 const sym = self.getSymbol(global);
593 self.mh_execute_header_index = global_index;594 self.mh_execute_header_index = global_index;
...@@ -602,7 +603,7 @@ pub const Zld = struct {...@@ -602,7 +603,7 @@ pub const Zld = struct {
602 sym.n_type = macho.N_SECT | macho.N_EXT;603 sym.n_type = macho.N_SECT | macho.N_EXT;
603 sym.n_desc = macho.REFERENCED_DYNAMICALLY;604 sym.n_desc = macho.REFERENCED_DYNAMICALLY;
604605
605 if (resolver.table.get("__mh_execute_header")) |global_index| {606 if (self.resolver.get("__mh_execute_header")) |global_index| {
606 const global = &self.globals.items[global_index];607 const global = &self.globals.items[global_index];
607 const global_object = &self.objects.items[global.getFile().?];608 const global_object = &self.objects.items[global.getFile().?];
608 global_object.globals_lookup[global.sym_index] = global_index;609 global_object.globals_lookup[global.sym_index] = global_index;
...@@ -613,8 +614,8 @@ pub const Zld = struct {...@@ -613,8 +614,8 @@ pub const Zld = struct {
613 }614 }
614 }615 }
615616
616 fn createDsoHandleSymbol(self: *Zld, resolver: *SymbolResolver) !void {617 fn createDsoHandleSymbol(self: *Zld) !void {
617 const global_index = resolver.table.get("___dso_handle") orelse return;618 const global_index = self.resolver.get("___dso_handle") orelse return;
618 const global = &self.globals.items[global_index];619 const global = &self.globals.items[global_index];
619 self.dso_handle_index = global_index;620 self.dso_handle_index = global_index;
620 if (!self.getSymbol(global.*).undf()) return;621 if (!self.getSymbol(global.*).undf()) return;
...@@ -629,7 +630,7 @@ pub const Zld = struct {...@@ -629,7 +630,7 @@ pub const Zld = struct {
629630
630 const global_object = &self.objects.items[global.getFile().?];631 const global_object = &self.objects.items[global.getFile().?];
631 global_object.globals_lookup[global.sym_index] = global_index;632 global_object.globals_lookup[global.sym_index] = global_index;
632 _ = resolver.unresolved.swapRemove(resolver.table.get("___dso_handle").?);633 _ = self.unresolved.swapRemove(self.resolver.get("___dso_handle").?);
633 global.* = sym_loc;634 global.* = sym_loc;
634 }635 }
635636
...@@ -649,6 +650,8 @@ pub const Zld = struct {...@@ -649,6 +650,8 @@ pub const Zld = struct {
649 self.strtab.deinit(gpa);650 self.strtab.deinit(gpa);
650 self.locals.deinit(gpa);651 self.locals.deinit(gpa);
651 self.globals.deinit(gpa);652 self.globals.deinit(gpa);
653 self.resolver.deinit(gpa);
654 self.unresolved.deinit(gpa);
652655
653 for (self.objects.items) |*object| {656 for (self.objects.items) |*object| {
654 object.deinit(gpa);657 object.deinit(gpa);
...@@ -3066,17 +3069,12 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -3066,17 +3069,12 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
3066 log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)});3069 log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)});
3067 };3070 };
30683071
3069 var resolver = SymbolResolver{3072 try zld.resolveSymbols();
3070 .arena = arena,3073 try macho_file.reportUndefined(&zld);
3071 .table = std.StringHashMap(u32).init(arena),
3072 .unresolved = std.AutoArrayHashMap(u32, void).init(arena),
3073 };
3074 try zld.resolveSymbols(&resolver);
3075 try macho_file.reportUndefined(&zld, &resolver);
30763074
3077 if (options.output_mode == .Exe) {3075 if (options.output_mode == .Exe) {
3078 const entry_name = options.entry orelse load_commands.default_entry_point;3076 const entry_name = options.entry orelse load_commands.default_entry_point;
3079 const global_index = resolver.table.get(entry_name).?; // Error was flagged earlier3077 const global_index = zld.resolver.get(entry_name).?; // Error was flagged earlier
3080 zld.entry_index = global_index;3078 zld.entry_index = global_index;
3081 }3079 }
30823080
...@@ -3085,7 +3083,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -3085,7 +3083,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
3085 }3083 }
30863084
3087 if (gc_sections) {3085 if (gc_sections) {
3088 try dead_strip.gcAtoms(&zld, &resolver);3086 try dead_strip.gcAtoms(&zld);
3089 }3087 }
30903088
3091 try zld.createDyldPrivateAtom();3089 try zld.createDyldPrivateAtom();