From b2af2dc8b751e3a784b10f67314303b4e6514bdc Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 25 Aug 2023 08:45:00 +0200 Subject: [PATCH] macho: move symbol resolver into zld driver's state --- src/link/MachO.zig | 12 ++--- src/link/MachO/dead_strip.zig | 9 ++-- src/link/MachO/zld.zig | 96 +++++++++++++++++------------------ 3 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index cee5324ac3..412a8ab0e4 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -297,12 +297,6 @@ pub const SymbolWithLoc = extern struct { } }; -pub const SymbolResolver = struct { - arena: Allocator, - table: std.StringHashMap(u32), - unresolved: std.AutoArrayHashMap(u32, void), -}; - const HotUpdateState = struct { mach_task: ?std.os.darwin.MachTask = null, }; @@ -4092,15 +4086,15 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 { return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; } -pub fn reportUndefined(self: *MachO, ctx: anytype, resolver: *const SymbolResolver) !void { - const count = resolver.unresolved.count(); +pub fn reportUndefined(self: *MachO, ctx: anytype) !void { + const count = ctx.unresolved.count(); if (count == 0) return; const gpa = self.base.allocator; try self.misc_errors.ensureUnusedCapacity(gpa, count); - for (resolver.unresolved.keys()) |global_index| { + for (ctx.unresolved.keys()) |global_index| { const global = ctx.globals.items[global_index]; const sym_name = ctx.getSymbolName(global); diff --git a/src/link/MachO/dead_strip.zig b/src/link/MachO/dead_strip.zig index f79b3c6184..42a2e0cbd8 100644 --- a/src/link/MachO/dead_strip.zig +++ b/src/link/MachO/dead_strip.zig @@ -12,13 +12,12 @@ const Allocator = mem.Allocator; const Atom = @import("Atom.zig"); const MachO = @import("../MachO.zig"); const SymbolWithLoc = MachO.SymbolWithLoc; -const SymbolResolver = MachO.SymbolResolver; const UnwindInfo = @import("UnwindInfo.zig"); const Zld = @import("zld.zig").Zld; const AtomTable = std.AutoHashMap(Atom.Index, void); -pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void { +pub fn gcAtoms(zld: *Zld) !void { const gpa = zld.gpa; var arena = std.heap.ArenaAllocator.init(gpa); @@ -30,7 +29,7 @@ pub fn gcAtoms(zld: *Zld, resolver: *const SymbolResolver) !void { var alive = AtomTable.init(arena.allocator()); try alive.ensureTotalCapacity(@as(u32, @intCast(zld.atoms.items.len))); - try collectRoots(zld, &roots, resolver); + try collectRoots(zld, &roots); try mark(zld, roots, &alive); prune(zld, alive); } @@ -48,7 +47,7 @@ fn addRoot(zld: *Zld, roots: *AtomTable, file: u32, sym_loc: SymbolWithLoc) !voi _ = try roots.getOrPut(atom_index); } -fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) !void { +fn collectRoots(zld: *Zld, roots: *AtomTable) !void { log.debug("collecting roots", .{}); switch (zld.options.output_mode) { @@ -77,7 +76,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable, resolver: *const SymbolResolver) ! // Add all symbols force-defined by the user. for (zld.options.force_undefined_symbols.keys()) |sym_name| { - const global_index = resolver.table.get(sym_name).?; + const global_index = zld.resolver.get(sym_name).?; const global = zld.globals.items[global_index]; const sym = zld.getSymbol(global); assert(!sym.undf()); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index c86a7221fc..7fa506ce0e 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -34,7 +34,6 @@ const Object = @import("Object.zig"); const Section = MachO.Section; const StringTable = @import("../strtab.zig").StringTable; const SymbolWithLoc = MachO.SymbolWithLoc; -const SymbolResolver = MachO.SymbolResolver; const TableSection = @import("../table_section.zig").TableSection; const Trie = @import("Trie.zig"); const UnwindInfo = @import("UnwindInfo.zig"); @@ -76,6 +75,8 @@ pub const Zld = struct { locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, + resolver: std.StringHashMapUnmanaged(u32) = .{}, + unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, entry_index: ?u32 = null, mh_execute_header_index: ?u32 = null, @@ -327,53 +328,53 @@ pub const Zld = struct { } } - fn addUndefined(self: *Zld, name: []const u8, resolver: *SymbolResolver) !void { + fn addUndefined(self: *Zld, name: []const u8) !void { const sym_index = try self.allocateSymbol(); const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; const sym = self.getSymbolPtr(sym_loc); sym.n_strx = try self.strtab.insert(self.gpa, name); sym.n_type = macho.N_UNDF; const global_index = try self.addGlobal(sym_loc); - try resolver.table.putNoClobber(name, global_index); - try resolver.unresolved.putNoClobber(global_index, {}); + try self.resolver.putNoClobber(self.gpa, name, global_index); + try self.unresolved.putNoClobber(self.gpa, global_index, {}); } - fn resolveSymbols(self: *Zld, resolver: *SymbolResolver) !void { + fn resolveSymbols(self: *Zld) !void { // We add the specified entrypoint as the first unresolved symbols so that // we search for it in libraries should there be no object files specified // on the linker line. if (self.options.output_mode == .Exe) { const entry_name = self.options.entry orelse load_commands.default_entry_point; - try self.addUndefined(entry_name, resolver); + try self.addUndefined(entry_name); } // Force resolution of any symbols requested by the user. for (self.options.force_undefined_symbols.keys()) |sym_name| { - try self.addUndefined(sym_name, resolver); + try self.addUndefined(sym_name); } for (self.objects.items, 0..) |_, object_id| { - try self.resolveSymbolsInObject(@as(u32, @intCast(object_id)), resolver); + try self.resolveSymbolsInObject(@as(u32, @intCast(object_id))); } - try self.resolveSymbolsInArchives(resolver); + try self.resolveSymbolsInArchives(); // Finally, force resolution of dyld_stub_binder if there are imports // requested. - if (resolver.unresolved.count() > 0) { - try self.addUndefined("dyld_stub_binder", resolver); + if (self.unresolved.count() > 0) { + try self.addUndefined("dyld_stub_binder"); } - try self.resolveSymbolsInDylibs(resolver); + try self.resolveSymbolsInDylibs(); - self.dyld_stub_binder_index = resolver.table.get("dyld_stub_binder"); + self.dyld_stub_binder_index = self.resolver.get("dyld_stub_binder"); - try self.createMhExecuteHeaderSymbol(resolver); - try self.createDsoHandleSymbol(resolver); - try self.resolveSymbolsAtLoading(resolver); + try self.createMhExecuteHeaderSymbol(); + try self.createDsoHandleSymbol(); + try self.resolveSymbolsAtLoading(); } - fn resolveSymbolsInObject(self: *Zld, object_id: u32, resolver: *SymbolResolver) !void { + fn resolveSymbolsInObject(self: *Zld, object_id: u32) !void { const object = &self.objects.items[object_id]; const in_symtab = object.in_symtab orelse return; @@ -415,11 +416,11 @@ pub const Zld = struct { const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 }; - const global_index = resolver.table.get(sym_name) orelse { + const global_index = self.resolver.get(sym_name) orelse { const global_index = try self.addGlobal(sym_loc); - try resolver.table.putNoClobber(sym_name, global_index); + try self.resolver.putNoClobber(self.gpa, sym_name, global_index); if (sym.undf() and !sym.tentative()) { - try resolver.unresolved.putNoClobber(global_index, {}); + try self.unresolved.putNoClobber(self.gpa, global_index, {}); } continue; }; @@ -477,7 +478,7 @@ pub const Zld = struct { const global_object = &self.objects.items[file]; global_object.globals_lookup[global.sym_index] = global_index; } - _ = resolver.unresolved.swapRemove(resolver.table.get(sym_name).?); + _ = self.unresolved.swapRemove(self.resolver.get(sym_name).?); global.* = sym_loc; } else { object.globals_lookup[sym_index] = global_index; @@ -485,14 +486,14 @@ pub const Zld = struct { } } - fn resolveSymbolsInArchives(self: *Zld, resolver: *SymbolResolver) !void { + fn resolveSymbolsInArchives(self: *Zld) !void { if (self.archives.items.len == 0) return; const gpa = self.gpa; var next_sym: usize = 0; - loop: while (next_sym < resolver.unresolved.count()) { - const global = self.globals.items[resolver.unresolved.keys()[next_sym]]; + loop: while (next_sym < self.unresolved.count()) { + const global = self.globals.items[self.unresolved.keys()[next_sym]]; const sym_name = self.getSymbolName(global); for (self.archives.items) |archive| { @@ -506,7 +507,7 @@ pub const Zld = struct { const object_id = @as(u16, @intCast(self.objects.items.len)); const object = try archive.parseObject(gpa, offsets.items[0]); try self.objects.append(gpa, object); - try self.resolveSymbolsInObject(object_id, resolver); + try self.resolveSymbolsInObject(object_id); continue :loop; } @@ -515,12 +516,12 @@ pub const Zld = struct { } } - fn resolveSymbolsInDylibs(self: *Zld, resolver: *SymbolResolver) !void { + fn resolveSymbolsInDylibs(self: *Zld) !void { if (self.dylibs.items.len == 0) return; var next_sym: usize = 0; - loop: while (next_sym < resolver.unresolved.count()) { - const global_index = resolver.unresolved.keys()[next_sym]; + loop: while (next_sym < self.unresolved.count()) { + const global_index = self.unresolved.keys()[next_sym]; const global = self.globals.items[global_index]; const sym = self.getSymbolPtr(global); const sym_name = self.getSymbolName(global); @@ -541,7 +542,7 @@ pub const Zld = struct { sym.n_desc |= macho.N_WEAK_REF; } - assert(resolver.unresolved.swapRemove(global_index)); + assert(self.unresolved.swapRemove(global_index)); continue :loop; } @@ -549,14 +550,14 @@ pub const Zld = struct { } } - fn resolveSymbolsAtLoading(self: *Zld, resolver: *SymbolResolver) !void { + fn resolveSymbolsAtLoading(self: *Zld) !void { const is_lib = self.options.output_mode == .Lib; const is_dyn_lib = self.options.link_mode == .Dynamic and is_lib; const allow_undef = is_dyn_lib and (self.options.allow_shlib_undefined orelse false); var next_sym: usize = 0; - while (next_sym < resolver.unresolved.count()) { - const global_index = resolver.unresolved.keys()[next_sym]; + while (next_sym < self.unresolved.count()) { + const global_index = self.unresolved.keys()[next_sym]; const global = self.globals.items[global_index]; const sym = self.getSymbolPtr(global); @@ -568,7 +569,7 @@ pub const Zld = struct { .n_desc = 0, .n_value = 0, }; - _ = resolver.unresolved.swapRemove(global_index); + _ = self.unresolved.swapRemove(global_index); continue; } else if (allow_undef) { const n_desc = @as( @@ -577,7 +578,7 @@ pub const Zld = struct { ); sym.n_type = macho.N_EXT; sym.n_desc = n_desc; - _ = resolver.unresolved.swapRemove(global_index); + _ = self.unresolved.swapRemove(global_index); continue; } @@ -585,9 +586,9 @@ pub const Zld = struct { } } - fn createMhExecuteHeaderSymbol(self: *Zld, resolver: *SymbolResolver) !void { + fn createMhExecuteHeaderSymbol(self: *Zld) !void { if (self.options.output_mode != .Exe) return; - if (resolver.table.get("__mh_execute_header")) |global_index| { + if (self.resolver.get("__mh_execute_header")) |global_index| { const global = self.globals.items[global_index]; const sym = self.getSymbol(global); self.mh_execute_header_index = global_index; @@ -602,7 +603,7 @@ pub const Zld = struct { sym.n_type = macho.N_SECT | macho.N_EXT; sym.n_desc = macho.REFERENCED_DYNAMICALLY; - if (resolver.table.get("__mh_execute_header")) |global_index| { + if (self.resolver.get("__mh_execute_header")) |global_index| { const global = &self.globals.items[global_index]; const global_object = &self.objects.items[global.getFile().?]; global_object.globals_lookup[global.sym_index] = global_index; @@ -613,8 +614,8 @@ pub const Zld = struct { } } - fn createDsoHandleSymbol(self: *Zld, resolver: *SymbolResolver) !void { - const global_index = resolver.table.get("___dso_handle") orelse return; + fn createDsoHandleSymbol(self: *Zld) !void { + const global_index = self.resolver.get("___dso_handle") orelse return; const global = &self.globals.items[global_index]; self.dso_handle_index = global_index; if (!self.getSymbol(global.*).undf()) return; @@ -629,7 +630,7 @@ pub const Zld = struct { const global_object = &self.objects.items[global.getFile().?]; global_object.globals_lookup[global.sym_index] = global_index; - _ = resolver.unresolved.swapRemove(resolver.table.get("___dso_handle").?); + _ = self.unresolved.swapRemove(self.resolver.get("___dso_handle").?); global.* = sym_loc; } @@ -649,6 +650,8 @@ pub const Zld = struct { self.strtab.deinit(gpa); self.locals.deinit(gpa); self.globals.deinit(gpa); + self.resolver.deinit(gpa); + self.unresolved.deinit(gpa); for (self.objects.items) |*object| { object.deinit(gpa); @@ -3066,17 +3069,12 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)}); }; - var resolver = SymbolResolver{ - .arena = arena, - .table = std.StringHashMap(u32).init(arena), - .unresolved = std.AutoArrayHashMap(u32, void).init(arena), - }; - try zld.resolveSymbols(&resolver); - try macho_file.reportUndefined(&zld, &resolver); + try zld.resolveSymbols(); + try macho_file.reportUndefined(&zld); if (options.output_mode == .Exe) { const entry_name = options.entry orelse load_commands.default_entry_point; - const global_index = resolver.table.get(entry_name).?; // Error was flagged earlier + const global_index = zld.resolver.get(entry_name).?; // Error was flagged earlier zld.entry_index = global_index; } @@ -3085,7 +3083,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr } if (gc_sections) { - try dead_strip.gcAtoms(&zld, &resolver); + try dead_strip.gcAtoms(&zld); } try zld.createDyldPrivateAtom();