Commit 30b7d3e45f

Jakub Konka <kubkon@jakubkonka.com>
2024-01-18 21:23:00
macho: implement resolveSymbols in ZigObject
1 parent 5ef63e3
Changed files (2)
src
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();
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;