authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-06 13:56:28+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-07 19:27:25+01:00
logbdbb1dbe1535b727e542c80fe1f7d62a78e527fd
treee314ac9d74ee474d12b233887aae88d8d28212e6
parent352e27c55ca32fdc31dd01e3e60893775f03a318

macho: refactor markExports, markImportsExports and claimUnresolved


4 files changed, 151 insertions(+), 110 deletions(-)

src/link/MachO.zig+18-61
...@@ -379,6 +379,10 @@ pub fn deinit(self: *MachO) void {...@@ -379,6 +379,10 @@ pub fn deinit(self: *MachO) void {
379}379}
380380
381pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {381pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void {
382 // TODO: I think this is just a temp and can be removed once we can emit static archives
383 if (self.base.isStaticLib() and build_options.have_llvm) {
384 return self.base.linkAsArchive(arena, prog_node);
385 }
382 try self.flushModule(arena, prog_node);386 try self.flushModule(arena, prog_node);
383}387}
384388
...@@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
391395
392 if (self.llvm_object) |llvm_object| {396 if (self.llvm_object) |llvm_object| {
393 try self.base.emitLlvmObject(arena, llvm_object, prog_node);397 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
398 // TODO: I think this is just a temp and can be removed once we can emit static archives
399 if (self.base.isStaticLib() and build_options.have_llvm) return;
394 }400 }
395401
396 var sub_prog_node = prog_node.start("MachO Flush", 0);402 var sub_prog_node = prog_node.start("MachO Flush", 0);
...@@ -571,7 +577,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -571,7 +577,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
571 },577 },
572 };578 };
573579
574 try self.markImportsAndExports();580 self.markImportsAndExports();
575 self.deadStripDylibs();581 self.deadStripDylibs();
576582
577 for (self.dylibs.items, 1..) |index, ord| {583 for (self.dylibs.items, 1..) |index, ord| {
...@@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void {...@@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void {
1509}1515}
15101516
1511fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {1517fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {
1512 const gpa = self.base.comp.gpa;1518 if (self.getZigObject()) |zo| {
15131519 try zo.asFile().claimUnresolved(self);
1514 var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);1520 }
1515 defer objects.deinit();1521 for (self.objects.items) |index| {
1516 if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);1522 try self.getFile(index).?.claimUnresolved(self);
1517 objects.appendSliceAssumeCapacity(self.objects.items);
1518
1519 for (objects.items) |index| {
1520 const file = self.getFile(index).?;
1521
1522 for (file.getSymbols(), 0..) |sym_index, i| {
1523 const nlist_idx = @as(Symbol.Index, @intCast(i));
1524 const nlist = switch (file) {
1525 .object => |x| x.symtab.items(.nlist)[nlist_idx],
1526 .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
1527 else => unreachable,
1528 };
1529 if (!nlist.ext()) continue;
1530 if (!nlist.undf()) continue;
1531
1532 const sym = self.getSymbol(sym_index);
1533 if (sym.getFile(self) != null) continue;
1534
1535 const is_import = switch (self.undefined_treatment) {
1536 .@"error" => false,
1537 .warn, .suppress => nlist.weakRef(),
1538 .dynamic_lookup => true,
1539 };
1540 if (is_import) {
1541 sym.value = 0;
1542 sym.atom = 0;
1543 sym.nlist_idx = 0;
1544 sym.file = self.internal_object.?;
1545 sym.flags.weak = false;
1546 sym.flags.weak_ref = nlist.weakRef();
1547 sym.flags.import = is_import;
1548 sym.visibility = .global;
1549 try self.getInternalObject().?.symbols.append(self.base.comp.gpa, sym_index);
1550 }
1551 }
1552 }1523 }
1553}1524}
15541525
...@@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void {...@@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void {
1574 try self.reportDuplicates(dupes);1545 try self.reportDuplicates(dupes);
1575}1546}
15761547
1577fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void {1548fn markImportsAndExports(self: *MachO) void {
1578 const gpa = self.base.comp.gpa;1549 if (self.getZigObject()) |zo| {
1579 var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);1550 zo.asFile().markImportsExports(self);
1580 defer objects.deinit();1551 }
1581 if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);1552 for (self.objects.items) |index| {
1582 objects.appendSliceAssumeCapacity(self.objects.items);1553 self.getFile(index).?.markImportsExports(self);
1583
1584 for (objects.items) |index| {
1585 for (self.getFile(index).?.getSymbols()) |sym_index| {
1586 const sym = self.getSymbol(sym_index);
1587 const file = sym.getFile(self) orelse continue;
1588 if (sym.visibility != .global) continue;
1589 if (file == .dylib and !sym.flags.abs) {
1590 sym.flags.import = true;
1591 continue;
1592 }
1593 if (file.getIndex() == index) {
1594 sym.flags.@"export" = true;
1595 }
1596 }
1597 }1554 }
15981555
1599 for (self.undefined_symbols.items) |index| {1556 for (self.undefined_symbols.items) |index| {
src/link/MachO/Archive.zig+27-2
...@@ -144,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index:...@@ -144,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index:
144}144}
145145
146pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {146pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
147 _ = comp;147 const gpa = comp.gpa;
148 _ = module_obj_path;148
149 var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
150 defer positionals.deinit();
151
152 try positionals.ensureUnusedCapacity(comp.objects.len);
153 positionals.appendSliceAssumeCapacity(comp.objects);
154
155 for (comp.c_object_table.keys()) |key| {
156 try positionals.append(.{ .path = key.status.success.object_path });
157 }
158
159 if (module_obj_path) |path| try positionals.append(.{ .path = path });
160
161 for (positionals.items) |obj| {
162 // TODO: parse for archive meaning don't unpack objects
163 _ = obj;
164 }
165
166 if (comp.link_errors.items.len > 0) return error.FlushFailure;
167
168 // First, we flush relocatable object file generated with our backends.
169 if (macho_file.getZigObject()) |zo| {
170 zo.resolveSymbols(macho_file);
171 zo.asFile().claimUnresolvedRelocatable(macho_file);
172 }
149173
150 var err = try macho_file.addErrorWithNotes(0);174 var err = try macho_file.addErrorWithNotes(0);
151 try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});175 try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});
...@@ -158,6 +182,7 @@ const link = @import("../../link.zig");...@@ -158,6 +182,7 @@ const link = @import("../../link.zig");
158const log = std.log.scoped(.link);182const log = std.log.scoped(.link);
159const macho = std.macho;183const macho = std.macho;
160const mem = std.mem;184const mem = std.mem;
185const relocatable = @import("relocatable.zig");
161const std = @import("std");186const std = @import("std");
162187
163const Allocator = mem.Allocator;188const Allocator = mem.Allocator;
src/link/MachO/file.zig+92
...@@ -44,6 +44,97 @@ pub const File = union(enum) {...@@ -44,6 +44,97 @@ pub const File = union(enum) {
44 }44 }
45 }45 }
4646
47 pub fn claimUnresolved(file: File, macho_file: *MachO) error{OutOfMemory}!void {
48 assert(file == .object or file == .zig_object);
49
50 for (file.getSymbols(), 0..) |sym_index, i| {
51 const nlist_idx = @as(Symbol.Index, @intCast(i));
52 const nlist = switch (file) {
53 .object => |x| x.symtab.items(.nlist)[nlist_idx],
54 .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
55 else => unreachable,
56 };
57 if (!nlist.ext()) continue;
58 if (!nlist.undf()) continue;
59
60 const sym = macho_file.getSymbol(sym_index);
61 if (sym.getFile(macho_file) != null) continue;
62
63 const is_import = switch (macho_file.undefined_treatment) {
64 .@"error" => false,
65 .warn, .suppress => nlist.weakRef(),
66 .dynamic_lookup => true,
67 };
68 if (is_import) {
69 sym.value = 0;
70 sym.atom = 0;
71 sym.nlist_idx = 0;
72 sym.file = macho_file.internal_object.?;
73 sym.flags.weak = false;
74 sym.flags.weak_ref = nlist.weakRef();
75 sym.flags.import = is_import;
76 sym.visibility = .global;
77 try macho_file.getInternalObject().?.symbols.append(macho_file.base.comp.gpa, sym_index);
78 }
79 }
80 }
81
82 pub fn claimUnresolvedRelocatable(file: File, macho_file: *MachO) void {
83 assert(file == .object or file == .zig_object);
84
85 for (file.getSymbols(), 0..) |sym_index, i| {
86 const nlist_idx = @as(Symbol.Index, @intCast(i));
87 const nlist = switch (file) {
88 .object => |x| x.symtab.items(.nlist)[nlist_idx],
89 .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
90 else => unreachable,
91 };
92 if (!nlist.ext()) continue;
93 if (!nlist.undf()) continue;
94
95 const sym = macho_file.getSymbol(sym_index);
96 if (sym.getFile(macho_file) != null) continue;
97
98 sym.value = 0;
99 sym.atom = 0;
100 sym.nlist_idx = nlist_idx;
101 sym.file = file.getIndex();
102 sym.flags.weak_ref = nlist.weakRef();
103 sym.flags.import = true;
104 sym.visibility = .global;
105 }
106 }
107
108 pub fn markImportsExports(file: File, macho_file: *MachO) void {
109 assert(file == .object or file == .zig_object);
110
111 for (file.getSymbols()) |sym_index| {
112 const sym = macho_file.getSymbol(sym_index);
113 const other_file = sym.getFile(macho_file) orelse continue;
114 if (sym.visibility != .global) continue;
115 if (other_file == .dylib and !sym.flags.abs) {
116 sym.flags.import = true;
117 continue;
118 }
119 if (other_file.getIndex() == file.getIndex()) {
120 sym.flags.@"export" = true;
121 }
122 }
123 }
124
125 pub fn markExportsRelocatable(file: File, macho_file: *MachO) void {
126 assert(file == .object or file == .zig_object);
127
128 for (file.getSymbols()) |sym_index| {
129 const sym = macho_file.getSymbol(sym_index);
130 const other_file = sym.getFile(macho_file) orelse continue;
131 if (sym.visibility != .global) continue;
132 if (other_file.getIndex() == file.getIndex()) {
133 sym.flags.@"export" = true;
134 }
135 }
136 }
137
47 /// Encodes symbol rank so that the following ordering applies:138 /// Encodes symbol rank so that the following ordering applies:
48 /// * strong in object139 /// * strong in object
49 /// * weak in object140 /// * weak in object
...@@ -110,6 +201,7 @@ pub const File = union(enum) {...@@ -110,6 +201,7 @@ pub const File = union(enum) {
110 pub const HandleIndex = Index;201 pub const HandleIndex = Index;
111};202};
112203
204const assert = std.debug.assert;
113const macho = std.macho;205const macho = std.macho;
114const std = @import("std");206const std = @import("std");
115207
src/link/MachO/relocatable.zig+14-47
...@@ -46,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u...@@ -46,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
4646
47 try macho_file.addUndefinedGlobals();47 try macho_file.addUndefinedGlobals();
48 try macho_file.resolveSymbols();48 try macho_file.resolveSymbols();
49 try markExports(macho_file);49 markExports(macho_file);
50 try claimUnresolved(macho_file);50 claimUnresolved(macho_file);
51 try initOutputSections(macho_file);51 try initOutputSections(macho_file);
52 try macho_file.sortSections();52 try macho_file.sortSections();
53 try macho_file.addAtomsToSections();53 try macho_file.addAtomsToSections();
...@@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u...@@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
86 try writeHeader(macho_file, ncmds, sizeofcmds);86 try writeHeader(macho_file, ncmds, sizeofcmds);
87}87}
8888
89fn markExports(macho_file: *MachO) error{OutOfMemory}!void {89fn markExports(macho_file: *MachO) void {
90 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);90 if (macho_file.getZigObject()) |zo| {
91 defer objects.deinit();91 zo.asFile().markExportsRelocatable(macho_file);
92 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);92 }
93 objects.appendSliceAssumeCapacity(macho_file.objects.items);93 for (macho_file.objects.items) |index| {
9494 macho_file.getFile(index).?.markExportsRelocatable(macho_file);
95 for (objects.items) |index| {
96 for (macho_file.getFile(index).?.getSymbols()) |sym_index| {
97 const sym = macho_file.getSymbol(sym_index);
98 const file = sym.getFile(macho_file) orelse continue;
99 if (sym.visibility != .global) continue;
100 if (file.getIndex() == index) {
101 sym.flags.@"export" = true;
102 }
103 }
104 }95 }
105}96}
10697
107fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void {98pub fn claimUnresolved(macho_file: *MachO) void {
108 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);99 if (macho_file.getZigObject()) |zo| {
109 defer objects.deinit();100 zo.asFile().claimUnresolvedRelocatable(macho_file);
110 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);101 }
111 objects.appendSliceAssumeCapacity(macho_file.objects.items);102 for (macho_file.objects.items) |index| {
112103 macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file);
113 for (objects.items) |index| {
114 const file = macho_file.getFile(index).?;
115
116 for (file.getSymbols(), 0..) |sym_index, i| {
117 const nlist_idx = @as(Symbol.Index, @intCast(i));
118 const nlist = switch (file) {
119 .object => |x| x.symtab.items(.nlist)[nlist_idx],
120 .zig_object => |x| x.symtab.items(.nlist)[nlist_idx],
121 else => unreachable,
122 };
123 if (!nlist.ext()) continue;
124 if (!nlist.undf()) continue;
125
126 const sym = macho_file.getSymbol(sym_index);
127 if (sym.getFile(macho_file) != null) continue;
128
129 sym.value = 0;
130 sym.atom = 0;
131 sym.nlist_idx = nlist_idx;
132 sym.file = index;
133 sym.flags.weak_ref = nlist.weakRef();
134 sym.flags.import = true;
135 sym.visibility = .global;
136 }
137 }104 }
138}105}
139106