diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 7af13ca8d2da7668a61b33a32d52ca38ef3212b7..6763d21fdf97a811087ac796f54f282c2b761176 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -564,7 +564,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node }, }; - self.markImportsAndExports(); + try self.markImportsAndExports(); self.deadStripDylibs(); for (self.dylibs.items, 1..) |index, ord| { @@ -1533,6 +1533,10 @@ fn checkDuplicates(self: *MachO) !void { dupes.deinit(); } + if (self.getZigObject()) |zo| { + try zo.checkDuplicates(&dupes, self); + } + for (self.objects.items) |index| { try self.getFile(index).?.object.checkDuplicates(&dupes, self); } @@ -1540,8 +1544,14 @@ fn checkDuplicates(self: *MachO) !void { try self.reportDuplicates(dupes); } -fn markImportsAndExports(self: *MachO) void { - for (self.objects.items) |index| { +fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void { + const gpa = self.base.comp.gpa; + var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); + defer objects.deinit(); + if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); + objects.appendSliceAssumeCapacity(self.objects.items); + + for (objects.items) |index| { for (self.getFile(index).?.getSymbols()) |sym_index| { const sym = self.getSymbol(sym_index); const file = sym.getFile(self) orelse continue; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index aa29dc59e1243bc353dbe3752d4aab6867370959..b6a8f5448bc59773a8dfb253ded232a2bc4d4cd5 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -137,9 +137,60 @@ pub fn freeAtomRelocs(self: *ZigObject, atom: Atom) void { } pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void { - _ = self; - _ = macho_file; - @panic("TODO resolveSymbols"); + const tracy = trace(@src()); + defer tracy.end(); + + for (self.symbols.items, 0..) |index, i| { + const nlist_idx = @as(Symbol.Index, @intCast(i)); + const nlist = self.symtab.items(.nlist)[nlist_idx]; + const atom_index = self.symtab.items(.atom)[nlist_idx]; + + if (!nlist.ext()) continue; + if (nlist.undf() and !nlist.tentative()) continue; + if (nlist.sect()) { + const atom = macho_file.getAtom(atom_index).?; + if (!atom.flags.alive) continue; + } + + const symbol = macho_file.getSymbol(index); + if (self.asFile().getSymbolRank(.{ + .archive = false, + .weak = nlist.weakDef(), + .tentative = nlist.tentative(), + }) < symbol.getSymbolRank(macho_file)) { + const value = if (nlist.sect()) blk: { + const atom = macho_file.getAtom(atom_index).?; + break :blk nlist.n_value - atom.getInputAddress(macho_file); + } else nlist.n_value; + symbol.value = value; + symbol.atom = atom_index; + symbol.nlist_idx = nlist_idx; + symbol.file = self.index; + symbol.flags.weak = nlist.weakDef(); + symbol.flags.abs = nlist.abs(); + symbol.flags.tentative = nlist.tentative(); + symbol.flags.weak_ref = false; + symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0; + symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip(); + // TODO: symbol.flags.interposable = macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext(); + symbol.flags.interposable = false; + + if (nlist.sect() and + macho_file.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES) + { + symbol.flags.tlv = true; + } + } + + // Regardless of who the winner is, we still merge symbol visibility here. + if (nlist.pext() or (nlist.weakDef() and nlist.weakRef())) { + if (symbol.visibility != .global) { + symbol.visibility = .hidden; + } + } else { + symbol.visibility = .global; + } + } } pub fn resetGlobals(self: *ZigObject, macho_file: *MachO) void { @@ -170,6 +221,13 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void { } } +pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void { + _ = self; + _ = dupes; + _ = macho_file; + @panic("TODO checkDuplicates"); +} + pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end();