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 {
33503350 self.archives.deinit(self.base.allocator);
33513351
33523352 for (self.dylibs.items) |dylib| {
3353 dylib.deinit();
3353 dylib.deinit(self.base.allocator);
33543354 self.base.allocator.destroy(dylib);
33553355 }
33563356 self.dylibs.deinit(self.base.allocator);
......@@ -3381,6 +3381,9 @@ pub fn closeFiles(self: MachO) void {
33813381 for (self.archives.items) |archive| {
33823382 archive.file.close();
33833383 }
3384 for (self.dylibs.items) |dylib| {
3385 dylib.file.close();
3386 }
33843387}
33853388
33863389fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
src/link/MachO/Dylib.zig+77-85
......@@ -9,20 +9,18 @@ const macho = std.macho;
99const math = std.math;
1010const mem = std.mem;
1111const fat = @import("fat.zig");
12const commands = @import("commands.zig");
1213
1314const Allocator = mem.Allocator;
1415const Arch = std.Target.Cpu.Arch;
1516const LibStub = @import("../tapi.zig").LibStub;
17const LoadCommand = commands.LoadCommand;
1618const MachO = @import("../MachO.zig");
1719
18usingnamespace @import("commands.zig");
20file: fs.File,
21name: []const u8,
1922
20allocator: *Allocator,
21arch: ?Arch = null,
2223header: ?macho.mach_header_64 = null,
23file: ?fs.File = null,
24name: ?[]const u8 = null,
25syslibroot: ?[]const u8 = null,
2624
2725ordinal: ?u16 = null,
2826
......@@ -61,7 +59,7 @@ pub const Id = struct {
6159 };
6260 }
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 {
6563 const dylib = lc.inner.dylib;
6664 const dylib_name = @ptrCast([*:0]const u8, lc.data[dylib.name - @sizeOf(macho.dylib_command) ..]);
6765 const name = try allocator.dupe(u8, mem.spanZ(dylib_name));
......@@ -164,25 +162,22 @@ pub fn createAndParseFromPath(
164162 errdefer allocator.free(name);
165163
166164 dylib.* = .{
167 .allocator = allocator,
168 .arch = arch,
169165 .name = name,
170166 .file = file,
171 .syslibroot = opts.syslibroot,
172167 };
173168
174 dylib.parse() catch |err| switch (err) {
169 dylib.parse(allocator, arch) catch |err| switch (err) {
175170 error.EndOfStream, error.NotDylib => {
176171 try file.seekTo(0);
177172
178173 var lib_stub = LibStub.loadFromFile(allocator, file) catch {
179 dylib.deinit();
174 dylib.deinit(allocator);
180175 allocator.destroy(dylib);
181176 return null;
182177 };
183178 defer lib_stub.deinit();
184179
185 try dylib.parseFromStub(lib_stub);
180 try dylib.parseFromStub(allocator, arch, lib_stub);
186181 },
187182 else => |e| return e,
188183 };
......@@ -195,7 +190,7 @@ pub fn createAndParseFromPath(
195190 log.warn(" | dylib version: {}", .{dylib.id.?.current_version});
196191
197192 // TODO maybe this should be an error and facilitate auto-cleanup?
198 dylib.deinit();
193 dylib.deinit(allocator);
199194 allocator.destroy(dylib);
200195 return null;
201196 }
......@@ -205,50 +200,41 @@ pub fn createAndParseFromPath(
205200 defer dylibs.deinit();
206201
207202 try dylibs.append(dylib);
208 try dylib.parseDependentLibs(&dylibs);
203 try dylib.parseDependentLibs(allocator, arch, &dylibs, opts.syslibroot);
209204
210205 return dylibs.toOwnedSlice();
211206}
212207
213pub fn deinit(self: *Dylib) void {
208pub fn deinit(self: *Dylib, allocator: *Allocator) void {
214209 for (self.load_commands.items) |*lc| {
215 lc.deinit(self.allocator);
210 lc.deinit(allocator);
216211 }
217 self.load_commands.deinit(self.allocator);
212 self.load_commands.deinit(allocator);
218213
219214 for (self.symbols.keys()) |key| {
220 self.allocator.free(key);
215 allocator.free(key);
221216 }
222 self.symbols.deinit(self.allocator);
217 self.symbols.deinit(allocator);
223218
224219 for (self.dependent_libs.items) |*id| {
225 id.deinit(self.allocator);
226 }
227 self.dependent_libs.deinit(self.allocator);
228
229 if (self.name) |name| {
230 self.allocator.free(name);
220 id.deinit(allocator);
231221 }
222 self.dependent_libs.deinit(allocator);
223 allocator.free(self.name);
232224
233225 if (self.id) |*id| {
234 id.deinit(self.allocator);
226 id.deinit(allocator);
235227 }
236228}
237229
238pub fn closeFile(self: Dylib) void {
239 if (self.file) |file| {
240 file.close();
241 }
242}
230pub fn parse(self: *Dylib, allocator: *Allocator, arch: Arch) !void {
231 log.debug("parsing shared library '{s}'", .{self.name});
243232
244pub fn parse(self: *Dylib) !void {
245 log.debug("parsing shared library '{s}'", .{self.name.?});
233 self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch);
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);
250
251 var reader = self.file.?.reader();
237 var reader = self.file.reader();
252238 self.header = try reader.readStruct(macho.mach_header_64);
253239
254240 if (self.header.?.filetype != macho.MH_DYLIB) {
......@@ -258,24 +244,24 @@ pub fn parse(self: *Dylib) !void {
258244
259245 const this_arch: Arch = try fat.decodeArch(self.header.?.cputype, true);
260246
261 if (this_arch != self.arch.?) {
262 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ self.arch.?, this_arch });
247 if (this_arch != arch) {
248 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch });
263249 return error.MismatchedCpuArchitecture;
264250 }
265251
266 try self.readLoadCommands(reader);
267 try self.parseId();
268 try self.parseSymbols();
252 try self.readLoadCommands(allocator, reader);
253 try self.parseId(allocator);
254 try self.parseSymbols(allocator);
269255}
270256
271fn readLoadCommands(self: *Dylib, reader: anytype) !void {
257fn readLoadCommands(self: *Dylib, allocator: *Allocator, reader: anytype) !void {
272258 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
276262 var i: u16 = 0;
277263 while (i < self.header.?.ncmds) : (i += 1) {
278 var cmd = try LoadCommand.read(self.allocator, reader);
264 var cmd = try LoadCommand.read(allocator, reader);
279265 switch (cmd.cmd()) {
280266 macho.LC_SYMTAB => {
281267 self.symtab_cmd_index = i;
......@@ -289,8 +275,8 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
289275 macho.LC_REEXPORT_DYLIB => {
290276 if (should_lookup_reexports) {
291277 // Parse install_name to dependent dylib.
292 const id = try Id.fromLoadCommand(self.allocator, cmd.Dylib);
293 try self.dependent_libs.append(self.allocator, id);
278 const id = try Id.fromLoadCommand(allocator, cmd.Dylib);
279 try self.dependent_libs.append(allocator, id);
294280 }
295281 },
296282 else => {
......@@ -301,27 +287,27 @@ fn readLoadCommands(self: *Dylib, reader: anytype) !void {
301287 }
302288}
303289
304fn parseId(self: *Dylib) !void {
290fn parseId(self: *Dylib, allocator: *Allocator) !void {
305291 const index = self.id_cmd_index orelse {
306292 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);
308294 return;
309295 };
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);
311297}
312298
313fn parseSymbols(self: *Dylib) !void {
299fn parseSymbols(self: *Dylib, allocator: *Allocator) !void {
314300 const index = self.symtab_cmd_index orelse return;
315301 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);
318 defer self.allocator.free(symtab);
319 _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff + self.library_offset);
303 var symtab = try allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
304 defer allocator.free(symtab);
305 _ = try self.file.preadAll(symtab, symtab_cmd.symoff + self.library_offset);
320306 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);
323 defer self.allocator.free(strtab);
324 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
308 var strtab = try allocator.alloc(u8, symtab_cmd.strsize);
309 defer allocator.free(strtab);
310 _ = try self.file.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
325311
326312 for (slice) |sym| {
327313 const add_to_symtab = MachO.symbolIsExt(sym) and (MachO.symbolIsSect(sym) or MachO.symbolIsIndr(sym));
......@@ -329,8 +315,8 @@ fn parseSymbols(self: *Dylib) !void {
329315 if (!add_to_symtab) continue;
330316
331317 const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
332 const name = try self.allocator.dupe(u8, sym_name);
333 try self.symbols.putNoClobber(self.allocator, name, {});
318 const name = try allocator.dupe(u8, sym_name);
319 try self.symbols.putNoClobber(allocator, name, {});
334320 }
335321}
336322
......@@ -341,26 +327,26 @@ fn hasTarget(targets: []const []const u8, target: []const u8) bool {
341327 return false;
342328}
343329
344fn addObjCClassSymbols(self: *Dylib, sym_name: []const u8) !void {
330fn addObjCClassSymbols(self: *Dylib, allocator: *Allocator, sym_name: []const u8) !void {
345331 const expanded = &[_][]const u8{
346 try std.fmt.allocPrint(self.allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
347 try std.fmt.allocPrint(self.allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
332 try std.fmt.allocPrint(allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
333 try std.fmt.allocPrint(allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
348334 };
349335
350336 for (expanded) |sym| {
351337 if (self.symbols.contains(sym)) continue;
352 try self.symbols.putNoClobber(self.allocator, sym, .{});
338 try self.symbols.putNoClobber(allocator, sym, .{});
353339 }
354340}
355341
356pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
342pub fn parseFromStub(self: *Dylib, allocator: *Allocator, arch: Arch, lib_stub: LibStub) !void {
357343 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
361347 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);
364350 if (umbrella_lib.current_version) |version| {
365351 try id.parseCurrentVersion(version);
366352 }
......@@ -369,13 +355,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
369355 }
370356 self.id = id;
371357
372 const target_string: []const u8 = switch (self.arch.?) {
358 const target_string: []const u8 = switch (arch) {
373359 .aarch64 => "arm64-macos",
374360 .x86_64 => "x86_64-macos",
375361 else => unreachable,
376362 };
377363
378 var umbrella_libs = std.StringHashMap(void).init(self.allocator);
364 var umbrella_libs = std.StringHashMap(void).init(allocator);
379365 defer umbrella_libs.deinit();
380366
381367 for (lib_stub.inner) |stub, stub_index| {
......@@ -395,13 +381,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
395381 if (exp.symbols) |symbols| {
396382 for (symbols) |sym_name| {
397383 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), {});
399385 }
400386 }
401387
402388 if (exp.objc_classes) |classes| {
403389 for (classes) |sym_name| {
404 try self.addObjCClassSymbols(sym_name);
390 try self.addObjCClassSymbols(allocator, sym_name);
405391 }
406392 }
407393 }
......@@ -414,13 +400,13 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
414400 if (reexp.symbols) |symbols| {
415401 for (symbols) |sym_name| {
416402 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), {});
418404 }
419405 }
420406
421407 if (reexp.objc_classes) |classes| {
422408 for (classes) |sym_name| {
423 try self.addObjCClassSymbols(sym_name);
409 try self.addObjCClassSymbols(allocator, sym_name);
424410 }
425411 }
426412 }
......@@ -428,7 +414,7 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
428414
429415 if (stub.objc_classes) |classes| {
430416 for (classes) |sym_name| {
431 try self.addObjCClassSymbols(sym_name);
417 try self.addObjCClassSymbols(allocator, sym_name);
432418 }
433419 }
434420 }
......@@ -451,15 +437,21 @@ pub fn parseFromStub(self: *Dylib, lib_stub: LibStub) !void {
451437
452438 log.debug(" | {s}", .{lib});
453439
454 const dep_id = try Id.default(self.allocator, lib);
455 try self.dependent_libs.append(self.allocator, dep_id);
440 const dep_id = try Id.default(allocator, lib);
441 try self.dependent_libs.append(allocator, dep_id);
456442 }
457443 }
458444 }
459445 }
460446}
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 {
463455 outer: for (self.dependent_libs.items) |id| {
464456 const has_ext = blk: {
465457 const basename = fs.path.basename(id.name);
......@@ -472,27 +464,27 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
472464 } else id.name;
473465
474466 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}", .{
476468 without_ext,
477469 ext,
478470 });
479 defer self.allocator.free(with_ext);
471 defer allocator.free(with_ext);
480472
481 const full_path = if (self.syslibroot) |syslibroot|
482 try fs.path.join(self.allocator, &.{ syslibroot, with_ext })
473 const full_path = if (syslibroot) |root|
474 try fs.path.join(allocator, &.{ root, with_ext })
483475 else
484476 with_ext;
485 defer if (self.syslibroot) |_| self.allocator.free(full_path);
477 defer if (syslibroot) |_| allocator.free(full_path);
486478
487479 log.debug("trying dependency at fully resolved path {s}", .{full_path});
488480
489481 const dylibs = (try createAndParseFromPath(
490 self.allocator,
491 self.arch.?,
482 allocator,
483 arch,
492484 full_path,
493485 .{
494486 .id = id,
495 .syslibroot = self.syslibroot,
487 .syslibroot = syslibroot,
496488 },
497489 )) orelse {
498490 continue;