From c023b762cd2898e6d2f5cb3c1f6f188ebeb00069 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 11 Jan 2024 18:15:36 +0100 Subject: [PATCH] macho: parse tbds --- src/link/MachO.zig | 48 +++++++++++++++++++++++++++++----------- src/link/MachO/Dylib.zig | 10 ++++----- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 6a5e26d24c..7834dbae16 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -385,8 +385,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node error.MalformedDylib, error.InvalidCpuArch, error.InvalidTarget, - error.UnknownFileType, => continue, // already reported + error.UnknownFileType => try self.reportParseError(obj.path, "unknown file type for an object file", .{}), else => |e| try self.reportParseError( obj.path, "unexpected error: parsing input file failed with error {s}", @@ -436,8 +436,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node error.MalformedArchive, error.MalformedDylib, error.InvalidCpuArch, - error.UnknownFileType, => continue, // already reported + error.UnknownFileType => try self.reportParseError(lib.path, "unknown file type for a library", .{}), else => |e| try self.reportParseError( lib.path, "unexpected error: parsing library failed with error {s}", @@ -458,8 +458,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node error.MalformedArchive, error.InvalidCpuArch, error.InvalidTarget, - error.UnknownFileType, => {}, // already reported + error.UnknownFileType => try self.reportParseError(path, "unknown file type for a library", .{}), else => |e| try self.reportParseError( path, "unexpected error: parsing input file failed with error {s}", @@ -762,6 +762,7 @@ const ParseError = error{ MalformedObject, MalformedArchive, MalformedDylib, + MalformedTbd, NotLibStub, InvalidCpuArch, InvalidTarget, @@ -796,16 +797,16 @@ fn parseLibrary(self: *MachO, lib: SystemLib, must_link: bool) ParseError!void { try self.parseArchive(lib, must_link, fat_arch); } else if (try Dylib.isDylib(lib.path, fat_arch)) { _ = try self.parseDylib(lib, true, fat_arch); - } else { - try self.reportParseError(lib.path, "unknown file type for a library", .{}); - return error.UnknownFileType; - } + } else return error.UnknownFileType; } else if (try Archive.isArchive(lib.path, null)) { try self.parseArchive(lib, must_link, null); } else if (try Dylib.isDylib(lib.path, null)) { _ = try self.parseDylib(lib, true, null); } else { - try self.parseTbd(lib, true); + _ = self.parseTbd(lib, true) catch |err| switch (err) { + error.MalformedTbd => return error.UnknownFileType, + else => |e| return e, + }; } } @@ -925,11 +926,32 @@ fn parseDylib(self: *MachO, lib: SystemLib, explicit: bool, fat_arch: ?fat.Arch) return index; } -fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!void { - _ = self; - _ = lib; - _ = explicit; - return error.Unhandled; +fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!File.Index { + const tracy = trace(@src()); + defer tracy.end(); + + const gpa = self.base.comp.gpa; + const file = try std.fs.cwd().openFile(lib.path, .{}); + defer file.close(); + + var lib_stub = LibStub.loadFromFile(gpa, file) catch return error.MalformedTbd; // TODO actually handle different errors + defer lib_stub.deinit(); + + const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); + self.files.set(index, .{ .dylib = .{ + .path = try gpa.dupe(u8, lib.path), + .data = &[0]u8{}, + .index = index, + .needed = lib.needed, + .weak = lib.weak, + .reexport = lib.reexport, + .explicit = explicit, + } }); + const dylib = &self.files.items(.data)[index].dylib; + try dylib.parseTbd(self.getTarget().cpu.arch, self.platform, lib_stub, self); + try self.dylibs.append(gpa, index); + + return index; } fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 50eb8971c3..694f2214b7 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -230,12 +230,13 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void { pub fn parseTbd( self: *Dylib, cpu_arch: std.Target.Cpu.Arch, - platform: ?MachO.Options.Platform, + platform: MachO.Platform, lib_stub: LibStub, macho_file: *MachO, ) !void { const tracy = trace(@src()); defer tracy.end(); + const gpa = macho_file.base.comp.gpa; log.debug("parsing dylib from stub", .{}); @@ -258,12 +259,9 @@ pub fn parseTbd( log.debug(" (install_name '{s}')", .{umbrella_lib.installName()}); - self.platform = platform orelse .{ - .platform = .MACOS, - .version = .{ .value = 0 }, - }; + self.platform = platform; - var matcher = try TargetMatcher.init(gpa, cpu_arch, self.platform.?.platform); + var matcher = try TargetMatcher.init(gpa, cpu_arch, self.platform.?.toApplePlatform()); defer matcher.deinit(); for (lib_stub.inner, 0..) |elem, stub_index| {