authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-31 10:59:22+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-01 09:06:56+02:00
loge73777333dd66570ddacdb7de56a390de01b33c5
tree3c66da878488a37da825764cdc2245d2d5f76004
parent586a19e3db7d462559874ce6ac877608f7e50f10

macho: don't store allocator in Dylib instance

instead pass it in as an arg to a function that requires it.

2 files changed, 81 insertions(+), 86 deletions(-)

src/link/MachO.zig+4-1
...@@ -3350,7 +3350,7 @@ pub fn deinit(self: *MachO) void {...@@ -3350,7 +3350,7 @@ pub fn deinit(self: *MachO) void {
3350 self.archives.deinit(self.base.allocator);3350 self.archives.deinit(self.base.allocator);
33513351
3352 for (self.dylibs.items) |dylib| {3352 for (self.dylibs.items) |dylib| {
3353 dylib.deinit();3353 dylib.deinit(self.base.allocator);
3354 self.base.allocator.destroy(dylib);3354 self.base.allocator.destroy(dylib);
3355 }3355 }
3356 self.dylibs.deinit(self.base.allocator);3356 self.dylibs.deinit(self.base.allocator);
...@@ -3381,6 +3381,9 @@ pub fn closeFiles(self: MachO) void {...@@ -3381,6 +3381,9 @@ pub fn closeFiles(self: MachO) void {
3381 for (self.archives.items) |archive| {3381 for (self.archives.items) |archive| {
3382 archive.file.close();3382 archive.file.close();
3383 }3383 }
3384 for (self.dylibs.items) |dylib| {
3385 dylib.file.close();
3386 }
3384}3387}
33853388
3386fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {3389fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
src/link/MachO/Dylib.zig+77-85
...@@ -9,20 +9,18 @@ const macho = std.macho;...@@ -9,20 +9,18 @@ const macho = std.macho;
9const math = std.math;9const math = std.math;
10const mem = std.mem;10const mem = std.mem;
11const fat = @import("fat.zig");11const fat = @import("fat.zig");
12const commands = @import("commands.zig");
1213
13const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
14const Arch = std.Target.Cpu.Arch;15const Arch = std.Target.Cpu.Arch;
15const LibStub = @import("../tapi.zig").LibStub;16const LibStub = @import("../tapi.zig").LibStub;
17const LoadCommand = commands.LoadCommand;
16const MachO = @import("../MachO.zig");18const MachO = @import("../MachO.zig");
1719
18usingnamespace @import("commands.zig");20file: fs.File,
21name: []const u8,
1922
20allocator: *Allocator,
21arch: ?Arch = null,
22header: ?macho.mach_header_64 = null,23header: ?macho.mach_header_64 = null,
23file: ?fs.File = null,
24name: ?[]const u8 = null,
25syslibroot: ?[]const u8 = null,
2624
27ordinal: ?u16 = null,25ordinal: ?u16 = null,
2826
...@@ -61,7 +59,7 @@ pub const Id = struct {...@@ -61,7 +59,7 @@ pub const Id = struct {
61 };59 };
62 }60 }
6361
64 pub fn fromLoadCommand(allocator: *Allocator, lc: GenericCommandWithData(macho.dylib_command)) !Id {62 pub fn fromLoadCommand(allocator: *Allocator, lc: commands.GenericCommandWithData(macho.dylib_command)) !Id {
65 const dylib = lc.inner.dylib;63 const dylib = lc.inner.dylib;
66 const dylib_name = @ptrCast([*:0]const u8, lc.data[dylib.name - @sizeOf(macho.dylib_command) ..]);64 const dylib_name = @ptrCast([*:0]const u8, lc.data[dylib.name - @sizeOf(macho.dylib_command) ..]);
67 const name = try allocator.dupe(u8, mem.spanZ(dylib_name));65 const name = try allocator.dupe(u8, mem.spanZ(dylib_name));
...@@ -164,25 +162,22 @@ pub fn createAndParseFromPath(...@@ -164,25 +162,22 @@ pub fn createAndParseFromPath(
164 errdefer allocator.free(name);162 errdefer allocator.free(name);
165163
166 dylib.* = .{164 dylib.* = .{
167 .allocator = allocator,
168 .arch = arch,
169 .name = name,165 .name = name,
170 .file = file,166 .file = file,
171 .syslibroot = opts.syslibroot,
172 };167 };
173168
174 dylib.parse() catch |err| switch (err) {169 dylib.parse(allocator, arch) catch |err| switch (err) {
175 error.EndOfStream, error.NotDylib => {170 error.EndOfStream, error.NotDylib => {
176 try file.seekTo(0);171 try file.seekTo(0);
177172
178 var lib_stub = LibStub.loadFromFile(allocator, file) catch {173 var lib_stub = LibStub.loadFromFile(allocator, file) catch {
179 dylib.deinit();174 dylib.deinit(allocator);
180 allocator.destroy(dylib);175 allocator.destroy(dylib);
181 return null;176 return null;
182 };177 };
183 defer lib_stub.deinit();178 defer lib_stub.deinit();
184179
185 try dylib.parseFromStub(lib_stub);180 try dylib.parseFromStub(allocator, arch, lib_stub);
186 },181 },
187 else => |e| return e,182 else => |e| return e,
188 };183 };
...@@ -195,7 +190,7 @@ pub fn createAndParseFromPath(...@@ -195,7 +190,7 @@ pub fn createAndParseFromPath(
195 log.warn(" | dylib version: {}", .{dylib.id.?.current_version});190 log.warn(" | dylib version: {}", .{dylib.id.?.current_version});
196191
197 // TODO maybe this should be an error and facilitate auto-cleanup?192 // TODO maybe this should be an error and facilitate auto-cleanup?
198 dylib.deinit();193 dylib.deinit(allocator);
199 allocator.destroy(dylib);194 allocator.destroy(dylib);
200 return null;195 return null;
201 }196 }
...@@ -205,50 +200,41 @@ pub fn createAndParseFromPath(...@@ -205,50 +200,41 @@ pub fn createAndParseFromPath(
205 defer dylibs.deinit();200 defer dylibs.deinit();
206201
207 try dylibs.append(dylib);202 try dylibs.append(dylib);
208 try dylib.parseDependentLibs(&dylibs);203 try dylib.parseDependentLibs(allocator, arch, &dylibs, opts.syslibroot);
209204
210 return dylibs.toOwnedSlice();205 return dylibs.toOwnedSlice();
211}206}
212207
213pub fn deinit(self: *Dylib) void {208pub fn deinit(self: *Dylib, allocator: *Allocator) void {
214 for (self.load_commands.items) |*lc| {209 for (self.load_commands.items) |*lc| {
215 lc.deinit(self.allocator);210 lc.deinit(allocator);
216 }211 }
217 self.load_commands.deinit(self.allocator);212 self.load_commands.deinit(allocator);
218213
219 for (self.symbols.keys()) |key| {214 for (self.symbols.keys()) |key| {
220 self.allocator.free(key);215 allocator.free(key);
221 }216 }
222 self.symbols.deinit(self.allocator);217 self.symbols.deinit(allocator);
223218
224 for (self.dependent_libs.items) |*id| {219 for (self.dependent_libs.items) |*id| {
225 id.deinit(self.allocator);220 id.deinit(allocator);
226 }
227 self.dependent_libs.deinit(self.allocator);
228
229 if (self.name) |name| {
230 self.allocator.free(name);
231 }221 }
222 self.dependent_libs.deinit(allocator);
223 allocator.free(self.name);
232224
233 if (self.id) |*id| {225 if (self.id) |*id| {
234 id.deinit(self.allocator);226 id.deinit(allocator);
235 }227 }
236}228}
237229
238pub fn closeFile(self: Dylib) void {230pub fn parse(self: *Dylib, allocator: *Allocator, arch: Arch) !void {
239 if (self.file) |file| {231 log.debug("parsing shared library '{s}'", .{self.name});
240 file.close();
241 }
242}
243232
244pub fn parse(self: *Dylib) !void {233 self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
245 log.debug("parsing shared library '{s}'", .{self.name.?});
246234
247 self.library_offset = try fat.getLibraryOffset(self.file.?.reader(), self.arch.?);235 try self.file.seekTo(self.library_offset);
248236
249 try self.file.?.seekTo(self.library_offset);237 var reader = self.file.reader();
250
251 var reader = self.file.?.reader();
252 self.header = try reader.readStruct(macho.mach_header_64);238 self.header = try reader.readStruct(macho.mach_header_64);
253239
254 if (self.header.?.filetype != macho.MH_DYLIB) {240 if (self.header.?.filetype != macho.MH_DYLIB) {
...@@ -258,24 +244,24 @@ pub fn parse(self: *Dylib) !void {...@@ -258,24 +244,24 @@ pub fn parse(self: *Dylib) !void {
258244
259 const this_arch: Arch = try fat.decodeArch(self.header.?.cputype, true);245 const this_arch: Arch = try fat.decodeArch(self.header.?.cputype, true);
260246
261 if (this_arch != self.arch.?) {247 if (this_arch != arch) {
262 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ self.arch.?, this_arch });248 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
263 return error.MismatchedCpuArchitecture;249 return error.MismatchedCpuArchitecture;
264 }250 }
265251
266 try self.readLoadCommands(reader);252 try self.readLoadCommands(allocator, reader);
267 try self.parseId();253 try self.parseId(allocator);
268 try self.parseSymbols();254 try self.parseSymbols(allocator);
269}255}
270256
271fn readLoadCommands(self: *Dylib, reader: anytype) !void {257fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void {
272 const should_lookup_reexports = self.header.?.flags & macho.MH_NO_REEXPORTED_DYLIBS == 0;258 const should_lookup_reexports = self.header.?.flags & macho.MH_NO_REEXPORTED_DYLIBS == 0;
273259
274 try self.load_commands.ensureCapacity(self.allocator, self.header.?.ncmds);260 try self.load_commands.ensureCapacity(allocator, self.header.?.ncmds);
275261
276 var i: u16 = 0;262 var i: u16 = 0;
277 while (i < self.header.?.ncmds) : (i += 1) {263 while (i < self.header.?.ncmds) : (i += 1) {
278 var cmd = try LoadCommand.read(self.allocator, reader);264 var cmd = try LoadCommand.read(allocator, reader);
279 switch (cmd.cmd()) {265 switch (cmd.cmd()) {
280 macho.LC_SYMTAB => {266 macho.LC_SYMTAB => {
281 self.symtab_cmd_index = i;267 self.symtab_cmd_index = i;
...@@ -289,8 +275,8 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {...@@ -289,8 +275,8 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
289 macho.LC_REEXPORT_DYLIB => {275 macho.LC_REEXPORT_DYLIB => {
290 if (should_lookup_reexports) {276 if (should_lookup_reexports) {
291 // Parse install_name to dependent dylib.277 // Parse install_name to dependent dylib.
292 const id = try Id.fromLoadCommand(self.allocator, cmd.Dylib);278 const id = try Id.fromLoadCommand(allocator, cmd.Dylib);
293 try self.dependent_libs.append(self.allocator, id);279 try self.dependent_libs.append(allocator, id);
294 }280 }
295 },281 },
296 else => {282 else => {
...@@ -301,27 +287,27 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {...@@ -301,27 +287,27 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
301 }287 }
302}288}
303289
304fn parseId(self: *Dylib) !void {290fn parseId(self: *Dylib, allocator: *Allocator) !void {
305 const index = self.id_cmd_index orelse {291 const index = self.id_cmd_index orelse {
306 log.debug("no LC_ID_DYLIB load command found; using hard-coded defaults...", .{});292 log.debug("no LC_ID_DYLIB load command found; using hard-coded defaults...", .{});
307 self.id = try Id.default(self.allocator, self.name.?);293 self.id = try Id.default(allocator, self.name);
308 return;294 return;
309 };295 };
310 self.id = try Id.fromLoadCommand(self.allocator, self.load_commands.items[index].Dylib);296 self.id = try Id.fromLoadCommand(allocator, self.load_commands.items[index].Dylib);
311}297}
312298
313fn parseSymbols(self: *Dylib) !void {299fn parseSymbols(self: *Dylib, allocator: *Allocator) !void {
314 const index = self.symtab_cmd_index orelse return;300 const index = self.symtab_cmd_index orelse return;
315 const symtab_cmd = self.load_commands.items[index].Symtab;301 const symtab_cmd = self.load_commands.items[index].Symtab;
316302
317 var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);303 var symtab = try allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
318 defer self.allocator.free(symtab);304 defer allocator.free(symtab);
319 _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff + self.library_offset);305 _ = try self.file.preadAll(symtab, symtab_cmd.symoff + self.library_offset);
320 const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));306 const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));
321307
322 var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);308 var strtab = try allocator.alloc(u8, symtab_cmd.strsize);
323 defer self.allocator.free(strtab);309 defer allocator.free(strtab);
324 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff + self.library_offset);310 _ = try self.file.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
325311
326 for (slice) |sym| {312 for (slice) |sym| {
327 const add_to_symtab = MachO.symbolIsExt(sym) and (MachO.symbolIsSect(sym) or MachO.symbolIsIndr(sym));313 const add_to_symtab = MachO.symbolIsExt(sym) and (MachO.symbolIsSect(sym) or MachO.symbolIsIndr(sym));
...@@ -329,8 +315,8 @@ fn parseSymbols(self: *Dylib) !void {...@@ -329,8 +315,8 @@ fn parseSymbols(self: *Dylib) !void {
329 if (!add_to_symtab) continue;315 if (!add_to_symtab) continue;
330316
331 const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));317 const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
332 const name = try self.allocator.dupe(u8, sym_name);318 const name = try allocator.dupe(u8, sym_name);
333 try self.symbols.putNoClobber(self.allocator, name, {});319 try self.symbols.putNoClobber(allocator, name, {});
334 }320 }
335}321}
336322
...@@ -341,26 +327,26 @@ fn hasTarget(targets: []const []const u8, target: []const u8) bool {...@@ -341,26 +327,26 @@ fn hasTarget(targets: []const []const u8, target: []const u8) bool {
341 return false;327 return false;
342}328}
343329
344fn addObjCClassSymbols(self: *Dylib, sym_name: []const u8) !void {330fn addObjCClassSymbols(self: *Dylib, allocator: *Allocator, sym_name: []const u8) !void {
345 const expanded = &[_][]const u8{331 const expanded = &[_][]const u8{
346 try std.fmt.allocPrint(self.allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),332 try std.fmt.allocPrint(allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
347 try std.fmt.allocPrint(self.allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),333 try std.fmt.allocPrint(allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
348 };334 };
349335
350 for (expanded) |sym| {336 for (expanded) |sym| {
351 if (self.symbols.contains(sym)) continue;337 if (self.symbols.contains(sym)) continue;
352 try self.symbols.putNoClobber(self.allocator, sym, .{});338 try self.symbols.putNoClobber(allocator, sym, .{});
353 }339 }
354}340}
355341
356pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {342pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub: LibStub) !void {
357 if (lib_stub.inner.len == 0) return error.EmptyStubFile;343 if (lib_stub.inner.len == 0) return error.EmptyStubFile;
358344
359 log.debug("parsing shared library from stub '{s}'", .{self.name.?});345 log.debug("parsing shared library from stub '{s}'", .{self.name});
360346
361 const umbrella_lib = lib_stub.inner[0];347 const umbrella_lib = lib_stub.inner[0];
362348
363 var id = try Id.default(self.allocator, umbrella_lib.install_name);349 var id = try Id.default(allocator, umbrella_lib.install_name);
364 if (umbrella_lib.current_version) |version| {350 if (umbrella_lib.current_version) |version| {
365 try id.parseCurrentVersion(version);351 try id.parseCurrentVersion(version);
366 }352 }
...@@ -369,13 +355,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {...@@ -369,13 +355,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
369 }355 }
370 self.id = id;356 self.id = id;
371357
372 const target_string: []const u8 = switch (self.arch.?) {358 const target_string: []const u8 = switch (arch) {
373 .aarch64 => "arm64-macos",359 .aarch64 => "arm64-macos",
374 .x86_64 => "x86_64-macos",360 .x86_64 => "x86_64-macos",
375 else => unreachable,361 else => unreachable,
376 };362 };
377363
378 var umbrella_libs = std.StringHashMap(void).init(self.allocator);364 var umbrella_libs = std.StringHashMap(void).init(allocator);
379 defer umbrella_libs.deinit();365 defer umbrella_libs.deinit();
380366
381 for (lib_stub.inner) |stub, stub_index| {367 for (lib_stub.inner) |stub, stub_index| {
...@@ -395,13 +381,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {...@@ -395,13 +381,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
395 if (exp.symbols) |symbols| {381 if (exp.symbols) |symbols| {
396 for (symbols) |sym_name| {382 for (symbols) |sym_name| {
397 if (self.symbols.contains(sym_name)) continue;383 if (self.symbols.contains(sym_name)) continue;
398 try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});384 try self.symbols.putNoClobber(allocator, try allocator.dupe(u8, sym_name), {});
399 }385 }
400 }386 }
401387
402 if (exp.objc_classes) |classes| {388 if (exp.objc_classes) |classes| {
403 for (classes) |sym_name| {389 for (classes) |sym_name| {
404 try self.addObjCClassSymbols(sym_name);390 try self.addObjCClassSymbols(allocator, sym_name);
405 }391 }
406 }392 }
407 }393 }
...@@ -414,13 +400,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {...@@ -414,13 +400,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
414 if (reexp.symbols) |symbols| {400 if (reexp.symbols) |symbols| {
415 for (symbols) |sym_name| {401 for (symbols) |sym_name| {
416 if (self.symbols.contains(sym_name)) continue;402 if (self.symbols.contains(sym_name)) continue;
417 try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});403 try self.symbols.putNoClobber(allocator, try allocator.dupe(u8, sym_name), {});
418 }404 }
419 }405 }
420406
421 if (reexp.objc_classes) |classes| {407 if (reexp.objc_classes) |classes| {
422 for (classes) |sym_name| {408 for (classes) |sym_name| {
423 try self.addObjCClassSymbols(sym_name);409 try self.addObjCClassSymbols(allocator, sym_name);
424 }410 }
425 }411 }
426 }412 }
...@@ -428,7 +414,7 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {...@@ -428,7 +414,7 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
428414
429 if (stub.objc_classes) |classes| {415 if (stub.objc_classes) |classes| {
430 for (classes) |sym_name| {416 for (classes) |sym_name| {
431 try self.addObjCClassSymbols(sym_name);417 try self.addObjCClassSymbols(allocator, sym_name);
432 }418 }
433 }419 }
434 }420 }
...@@ -451,15 +437,21 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {...@@ -451,15 +437,21 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
451437
452 log.debug(" | {s}", .{lib});438 log.debug(" | {s}", .{lib});
453439
454 const dep_id = try Id.default(self.allocator, lib);440 const dep_id = try Id.default(allocator, lib);
455 try self.dependent_libs.append(self.allocator, dep_id);441 try self.dependent_libs.append(allocator, dep_id);
456 }442 }
457 }443 }
458 }444 }
459 }445 }
460}446}
461447
462pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {448pub fn parseDependentLibs(
449 self: *Dylib,
450 allocator: *Allocator,
451 arch: Arch,
452 out: *std.ArrayList(*Dylib),
453 syslibroot: ?[]const u8,
454) !void {
463 outer: for (self.dependent_libs.items) |id| {455 outer: for (self.dependent_libs.items) |id| {
464 const has_ext = blk: {456 const has_ext = blk: {
465 const basename = fs.path.basename(id.name);457 const basename = fs.path.basename(id.name);
...@@ -472,27 +464,27 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {...@@ -472,27 +464,27 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
472 } else id.name;464 } else id.name;
473465
474 for (&[_][]const u8{ extension, ".tbd" }) |ext| {466 for (&[_][]const u8{ extension, ".tbd" }) |ext| {
475 const with_ext = try std.fmt.allocPrint(self.allocator, "{s}{s}", .{467 const with_ext = try std.fmt.allocPrint(allocator, "{s}{s}", .{
476 without_ext,468 without_ext,
477 ext,469 ext,
478 });470 });
479 defer self.allocator.free(with_ext);471 defer allocator.free(with_ext);
480472
481 const full_path = if (self.syslibroot) |syslibroot|473 const full_path = if (syslibroot) |root|
482 try fs.path.join(self.allocator, &.{ syslibroot, with_ext })474 try fs.path.join(allocator, &.{ root, with_ext })
483 else475 else
484 with_ext;476 with_ext;
485 defer if (self.syslibroot) |_| self.allocator.free(full_path);477 defer if (syslibroot) |_| allocator.free(full_path);
486478
487 log.debug("trying dependency at fully resolved path {s}", .{full_path});479 log.debug("trying dependency at fully resolved path {s}", .{full_path});
488480
489 const dylibs = (try createAndParseFromPath(481 const dylibs = (try createAndParseFromPath(
490 self.allocator,482 allocator,
491 self.arch.?,483 arch,
492 full_path,484 full_path,
493 .{485 .{
494 .id = id,486 .id = id,
495 .syslibroot = self.syslibroot,487 .syslibroot = syslibroot,
496 },488 },
497 )) orelse {489 )) orelse {
498 continue;490 continue;