authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-09 19:42:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log58997363d3c94aaa66960f0e87b40d5f98f0471b
tree0afb5d55e60ed601a390c852f76944fea1166886
parentf86a38564f5d8eb903b940ddf9b9f5685a3ca932

macho: migrate MachO.File abstraction


1 files changed, 126 insertions(+), 109 deletions(-)

src/link/MachO/file.zig+126-109
......@@ -32,106 +32,15 @@ pub const File = union(enum) {
3232
3333 pub fn resolveSymbols(file: File, macho_file: *MachO) void {
3434 switch (file) {
35 .internal => unreachable,
3635 inline else => |x| x.resolveSymbols(macho_file),
3736 }
3837 }
3938
40 pub fn resetGlobals(file: File, macho_file: *MachO) void {
39 pub fn scanRelocs(file: File, macho_file: *MachO) !void {
4140 switch (file) {
42 .internal => unreachable,
43 inline else => |x| x.resetGlobals(macho_file),
44 }
45 }
46
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 }
41 .dylib => unreachable,
42 .internal => |x| x.scanRelocs(macho_file),
43 inline else => |x| x.scanRelocs(macho_file),
13544 }
13645 }
13746
......@@ -162,39 +71,122 @@ pub const File = union(enum) {
16271 return base + (file.getIndex() << 24);
16372 }
16473
165 pub fn getSymbols(file: File) []const Symbol.Index {
74 pub fn getAtom(file: File, atom_index: Atom.Index) ?*Atom {
16675 return switch (file) {
167 inline else => |x| x.symbols.items,
76 .dylib => unreachable,
77 inline else => |x| x.getAtom(atom_index),
16878 };
16979 }
17080
17181 pub fn getAtoms(file: File) []const Atom.Index {
17282 return switch (file) {
17383 .dylib => unreachable,
174 inline else => |x| x.atoms.items,
84 inline else => |x| x.getAtoms(),
17585 };
17686 }
17787
178 pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void {
88 pub fn addAtomExtra(file: File, allocator: Allocator, extra: Atom.Extra) !u32 {
17989 return switch (file) {
180 .dylib, .internal => unreachable,
181 inline else => |x| x.updateArSymtab(ar_symtab, macho_file),
90 .dylib => unreachable,
91 inline else => |x| x.addAtomExtra(allocator, extra),
18292 };
18393 }
18494
185 pub fn updateArSize(file: File, macho_file: *MachO) !void {
95 pub fn getAtomExtra(file: File, index: u32) Atom.Extra {
18696 return switch (file) {
187 .dylib, .internal => unreachable,
188 .zig_object => |x| x.updateArSize(),
189 .object => |x| x.updateArSize(macho_file),
97 .dylib => unreachable,
98 inline else => |x| x.getAtomExtra(index),
19099 };
191100 }
192101
193 pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {
102 pub fn setAtomExtra(file: File, index: u32, extra: Atom.Extra) void {
194103 return switch (file) {
195 .dylib, .internal => unreachable,
196 .zig_object => |x| x.writeAr(ar_format, writer),
197 .object => |x| x.writeAr(ar_format, macho_file, writer),
104 .dylib => unreachable,
105 inline else => |x| x.setAtomExtra(index, extra),
106 };
107 }
108
109 pub fn getSymbols(file: File) []Symbol {
110 return switch (file) {
111 inline else => |x| x.symbols.items,
112 };
113 }
114
115 pub fn getSymbolRef(file: File, sym_index: Symbol.Index, macho_file: *MachO) MachO.Ref {
116 return switch (file) {
117 inline else => |x| x.getSymbolRef(sym_index, macho_file),
118 };
119 }
120
121 pub fn markImportsExports(file: File, macho_file: *MachO) void {
122 const nsyms = switch (file) {
123 .dylib => unreachable,
124 inline else => |x| x.symbols.items.len,
125 };
126 for (0..nsyms) |i| {
127 const ref = file.getSymbolRef(@intCast(i), macho_file);
128 if (ref.getFile(macho_file) == null) continue;
129 const sym = ref.getSymbol(macho_file).?;
130 if (sym.visibility != .global) continue;
131 if (sym.getFile(macho_file).? == .dylib and !sym.flags.abs) {
132 sym.flags.import = true;
133 continue;
134 }
135 if (file.getIndex() == ref.file) {
136 sym.flags.@"export" = true;
137 }
138 }
139 }
140
141 pub fn createSymbolIndirection(file: File, macho_file: *MachO) !void {
142 const nsyms = switch (file) {
143 inline else => |x| x.symbols.items.len,
144 };
145 for (0..nsyms) |i| {
146 const ref = file.getSymbolRef(@intCast(i), macho_file);
147 if (ref.getFile(macho_file) == null) continue;
148 if (ref.file != file.getIndex()) continue;
149 const sym = ref.getSymbol(macho_file).?;
150 if (sym.getSectionFlags().got) {
151 log.debug("'{s}' needs GOT", .{sym.getName(macho_file)});
152 try macho_file.got.addSymbol(ref, macho_file);
153 }
154 if (sym.getSectionFlags().stubs) {
155 log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)});
156 try macho_file.stubs.addSymbol(ref, macho_file);
157 }
158 if (sym.getSectionFlags().tlv_ptr) {
159 log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)});
160 try macho_file.tlv_ptr.addSymbol(ref, macho_file);
161 }
162 if (sym.getSectionFlags().objc_stubs) {
163 log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)});
164 try macho_file.objc_stubs.addSymbol(ref, macho_file);
165 }
166 }
167 }
168
169 pub fn initOutputSections(file: File, macho_file: *MachO) !void {
170 const tracy = trace(@src());
171 defer tracy.end();
172 for (file.getAtoms()) |atom_index| {
173 const atom = file.getAtom(atom_index) orelse continue;
174 if (!atom.alive.load(.seq_cst)) continue;
175 atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);
176 }
177 }
178
179 pub fn dedupLiterals(file: File, lp: MachO.LiteralPool, macho_file: *MachO) void {
180 return switch (file) {
181 .dylib => unreachable,
182 inline else => |x| x.dedupLiterals(lp, macho_file),
183 };
184 }
185
186 pub fn writeAtoms(file: File, macho_file: *MachO) !void {
187 return switch (file) {
188 .dylib => unreachable,
189 inline else => |x| x.writeAtoms(macho_file),
198190 };
199191 }
200192
......@@ -210,6 +202,29 @@ pub const File = union(enum) {
210202 };
211203 }
212204
205 pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void {
206 return switch (file) {
207 .dylib, .internal => unreachable,
208 inline else => |x| x.updateArSymtab(ar_symtab, macho_file),
209 };
210 }
211
212 pub fn updateArSize(file: File, macho_file: *MachO) !void {
213 return switch (file) {
214 .dylib, .internal => unreachable,
215 .zig_object => |x| x.updateArSize(),
216 .object => |x| x.updateArSize(macho_file),
217 };
218 }
219
220 pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void {
221 return switch (file) {
222 .dylib, .internal => unreachable,
223 .zig_object => |x| x.writeAr(ar_format, writer),
224 .object => |x| x.writeAr(ar_format, macho_file, writer),
225 };
226 }
227
213228 pub const Index = u32;
214229
215230 pub const Entry = union(enum) {
......@@ -225,8 +240,10 @@ pub const File = union(enum) {
225240};
226241
227242const assert = std.debug.assert;
243const log = std.log.scoped(.link);
228244const macho = std.macho;
229245const std = @import("std");
246const trace = @import("../../tracy.zig").trace;
230247
231248const Allocator = std.mem.Allocator;
232249const Archive = @import("Archive.zig");