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 {
379379}
380380
381381pub 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 }
382386 try self.flushModule(arena, prog_node);
383387}
384388
......@@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
391395
392396 if (self.llvm_object) |llvm_object| {
393397 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;
394400 }
395401
396402 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
571577 },
572578 };
573579
574 try self.markImportsAndExports();
580 self.markImportsAndExports();
575581 self.deadStripDylibs();
576582
577583 for (self.dylibs.items, 1..) |index, ord| {
......@@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void {
15091515}
15101516
15111517fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {
1512 const gpa = self.base.comp.gpa;
1513
1514 var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);
1515 defer objects.deinit();
1516 if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
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 }
1518 if (self.getZigObject()) |zo| {
1519 try zo.asFile().claimUnresolved(self);
1520 }
1521 for (self.objects.items) |index| {
1522 try self.getFile(index).?.claimUnresolved(self);
15521523 }
15531524}
15541525
......@@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void {
15741545 try self.reportDuplicates(dupes);
15751546}
15761547
1577fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void {
1578 const gpa = self.base.comp.gpa;
1579 var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);
1580 defer objects.deinit();
1581 if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
1582 objects.appendSliceAssumeCapacity(self.objects.items);
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 }
1548fn markImportsAndExports(self: *MachO) void {
1549 if (self.getZigObject()) |zo| {
1550 zo.asFile().markImportsExports(self);
1551 }
1552 for (self.objects.items) |index| {
1553 self.getFile(index).?.markImportsExports(self);
15971554 }
15981555
15991556 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:
144144}
145145
146146pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
147 _ = comp;
148 _ = module_obj_path;
147 const gpa = comp.gpa;
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
150174 var err = try macho_file.addErrorWithNotes(0);
151175 try err.addMsg(macho_file, "TODO implement flushStaticLib", .{});
......@@ -158,6 +182,7 @@ const link = @import("../../link.zig");
158182const log = std.log.scoped(.link);
159183const macho = std.macho;
160184const mem = std.mem;
185const relocatable = @import("relocatable.zig");
161186const std = @import("std");
162187
163188const Allocator = mem.Allocator;
src/link/MachO/file.zig+92
......@@ -44,6 +44,97 @@ pub const File = union(enum) {
4444 }
4545 }
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
47138 /// Encodes symbol rank so that the following ordering applies:
48139 /// * strong in object
49140 /// * weak in object
......@@ -110,6 +201,7 @@ pub const File = union(enum) {
110201 pub const HandleIndex = Index;
111202};
112203
204const assert = std.debug.assert;
113205const macho = std.macho;
114206const 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
4646
4747 try macho_file.addUndefinedGlobals();
4848 try macho_file.resolveSymbols();
49 try markExports(macho_file);
50 try claimUnresolved(macho_file);
49 markExports(macho_file);
50 claimUnresolved(macho_file);
5151 try initOutputSections(macho_file);
5252 try macho_file.sortSections();
5353 try macho_file.addAtomsToSections();
......@@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
8686 try writeHeader(macho_file, ncmds, sizeofcmds);
8787}
8888
89fn markExports(macho_file: *MachO) error{OutOfMemory}!void {
90 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
91 defer objects.deinit();
92 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
93 objects.appendSliceAssumeCapacity(macho_file.objects.items);
94
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 }
89fn markExports(macho_file: *MachO) void {
90 if (macho_file.getZigObject()) |zo| {
91 zo.asFile().markExportsRelocatable(macho_file);
92 }
93 for (macho_file.objects.items) |index| {
94 macho_file.getFile(index).?.markExportsRelocatable(macho_file);
10495 }
10596}
10697
107fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void {
108 var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1);
109 defer objects.deinit();
110 if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
111 objects.appendSliceAssumeCapacity(macho_file.objects.items);
112
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 }
98pub fn claimUnresolved(macho_file: *MachO) void {
99 if (macho_file.getZigObject()) |zo| {
100 zo.asFile().claimUnresolvedRelocatable(macho_file);
101 }
102 for (macho_file.objects.items) |index| {
103 macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file);
137104 }
138105}
139106