diff options
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/MachO.zig | 42 | ||||
| -rw-r--r-- | src/link/MachO/Archive.zig | 18 | ||||
| -rw-r--r-- | src/link/MachO/Dylib.zig | 6 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 6 | ||||
| -rw-r--r-- | src/link/MachO/Zld.zig | 106 |
5 files changed, 100 insertions, 78 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index f0f25bea66..e00a4d2c2d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -698,8 +698,8 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { try positionals.append(comp.libcxx_static_lib.?.full_object_path); } - // Shared libraries. - var shared_libs = std.ArrayList([]const u8).init(arena); + // Shared and static libraries passed via `-l` flag. + var libs = std.ArrayList([]const u8).init(arena); var search_lib_names = std.ArrayList([]const u8).init(arena); const system_libs = self.base.options.system_libs.items(); @@ -708,9 +708,8 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { // By this time, we depend on these libs being dynamically linked libraries and not static libraries // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which // case we want to avoid prepending "-l". - // TODO I think they should go as an input file instead of via shared_libs. if (Compilation.classifyFileExt(link_lib) == .shared_library) { - try shared_libs.append(link_lib); + try positionals.append(link_lib); continue; } @@ -760,24 +759,29 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { } } - for (search_lib_names.items) |l_name| { - // TODO text-based API, or .tbd files. - const l_name_ext = try std.fmt.allocPrint(arena, "lib{s}.dylib", .{l_name}); + // TODO text-based API, or .tbd files. + const exts = &[_][]const u8{ "dylib", "a" }; + for (search_lib_names.items) |l_name| { var found = false; - for (search_lib_dirs.items) |lib_dir| { - const full_path = try fs.path.join(arena, &[_][]const u8{ lib_dir, l_name_ext }); - // Check if the dylib file exists. - const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { - error.FileNotFound => continue, - else => |e| return e, - }; - defer tmp.close(); + for (exts) |ext| ext: { + const l_name_ext = try std.fmt.allocPrint(arena, "lib{s}.{s}", .{ l_name, ext }); + + for (search_lib_dirs.items) |lib_dir| { + const full_path = try fs.path.join(arena, &[_][]const u8{ lib_dir, l_name_ext }); - try shared_libs.append(full_path); - found = true; - break; + // Check if the dylib file exists. + const tmp = fs.cwd().openFile(full_path, .{}) catch |err| switch (err) { + error.FileNotFound => continue, + else => |e| return e, + }; + defer tmp.close(); + + try libs.append(full_path); + found = true; + break :ext; + } } if (!found) { @@ -835,7 +839,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { } try zld.link(positionals.items, full_out_path, .{ - .shared_libs = shared_libs.items, + .libs = libs.items, .rpaths = rpaths.items, }); diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig index 702a807a4d..4c40b35938 100644 --- a/src/link/MachO/Archive.zig +++ b/src/link/MachO/Archive.zig @@ -27,14 +27,14 @@ toc: std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(u32)) = .{}, // `struct ar_hdr', and as many bytes of member file data as its `ar_size' // member indicates, for each member file. /// String that begins an archive file. -pub const ARMAG: *const [SARMAG:0]u8 = "!<arch>\n"; +const ARMAG: *const [SARMAG:0]u8 = "!<arch>\n"; /// Size of that string. -pub const SARMAG: u4 = 8; +const SARMAG: u4 = 8; /// String in ar_fmag at the end of each header. -pub const ARFMAG: *const [2:0]u8 = "`\n"; +const ARFMAG: *const [2:0]u8 = "`\n"; -pub const ar_hdr = extern struct { +const ar_hdr = extern struct { /// Member file name, sometimes / terminated. ar_name: [16]u8, @@ -60,7 +60,7 @@ pub const ar_hdr = extern struct { Name: []const u8, Length: u64, }; - pub fn nameOrLength(self: ar_hdr) !NameOrLength { + fn nameOrLength(self: ar_hdr) !NameOrLength { const value = getValue(&self.ar_name); const slash_index = mem.indexOf(u8, value, "/") orelse return error.MalformedArchive; const len = value.len; @@ -75,7 +75,7 @@ pub const ar_hdr = extern struct { } } - pub fn size(self: ar_hdr) !u64 { + fn size(self: ar_hdr) !u64 { const value = getValue(&self.ar_size); return std.fmt.parseInt(u64, value, 10); } @@ -231,3 +231,9 @@ pub fn parseObject(self: Archive, offset: u32) !*Object { return object; } + +pub fn isArchive(file: fs.File) !bool { + const magic = try file.reader().readBytesNoEof(Archive.SARMAG); + try file.seekTo(0); + return mem.eql(u8, &magic, Archive.ARMAG); +} diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 8d864454f8..d7039f7f6c 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -183,3 +183,9 @@ pub fn parseSymbols(self: *Dylib) !void { try self.symbols.putNoClobber(self.allocator, name, &proxy.base); } } + +pub fn isDylib(file: fs.File) !bool { + const header = try file.reader().readStruct(macho.mach_header_64); + try file.seekTo(0); + return header.filetype == macho.MH_DYLIB; +} diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 4d2ade7aad..4160c2d75c 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -485,3 +485,9 @@ pub fn parseDataInCode(self: *Object) !void { try self.data_in_code_entries.append(self.allocator, dice); } } + +pub fn isObject(file: fs.File) !bool { + const header = try file.reader().readStruct(macho.mach_header_64); + try file.seekTo(0); + return header.filetype == macho.MH_OBJECT; +} diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index cc39ce1047..cef6414acb 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -187,7 +187,7 @@ pub fn closeFiles(self: Zld) void { } const LinkArgs = struct { - shared_libs: []const []const u8, + libs: []const []const u8, rpaths: []const []const u8, }; @@ -229,7 +229,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L try self.populateMetadata(); try self.addRpaths(args.rpaths); try self.parseInputFiles(files); - try self.parseDylibs(args.shared_libs); + try self.parseLibs(args.libs); try self.resolveSymbols(); try self.resolveStubsAndGotEntries(); try self.updateMetadata(); @@ -265,13 +265,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { }; try_object: { - const header = try file.reader().readStruct(macho.mach_header_64); - if (header.filetype != macho.MH_OBJECT) { - try file.seekTo(0); - break :try_object; - } - - try file.seekTo(0); + if (!(try Object.isObject(file))) break :try_object; try classified.append(.{ .kind = .object, .file = file, @@ -281,13 +275,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { } try_archive: { - const magic = try file.reader().readBytesNoEof(Archive.SARMAG); - if (!mem.eql(u8, &magic, Archive.ARMAG)) { - try file.seekTo(0); - break :try_archive; - } - - try file.seekTo(0); + if (!(try Archive.isArchive(file))) break :try_archive; try classified.append(.{ .kind = .archive, .file = file, @@ -297,13 +285,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { } try_dylib: { - const header = try file.reader().readStruct(macho.mach_header_64); - if (header.filetype != macho.MH_DYLIB) { - try file.seekTo(0); - break :try_dylib; - } - - try file.seekTo(0); + if (!(try Dylib.isDylib(file))) break :try_dylib; try classified.append(.{ .kind = .dylib, .file = file, @@ -312,7 +294,8 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { continue; } - log.debug("unexpected input file of unknown type '{s}'", .{file_name}); + file.close(); + log.warn("unknown filetype for positional input file: '{s}'", .{file_name}); } // Based on our classification, proceed with parsing. @@ -373,35 +356,52 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { } } -fn parseDylibs(self: *Zld, shared_libs: []const []const u8) !void { - for (shared_libs) |lib| { - const dylib = try self.allocator.create(Dylib); - errdefer self.allocator.destroy(dylib); - - dylib.* = Dylib.init(self.allocator); - dylib.arch = self.arch.?; - dylib.name = try self.allocator.dupe(u8, lib); - dylib.file = try fs.cwd().openFile(lib, .{}); - - const ordinal = @intCast(u16, self.dylibs.items.len); - dylib.ordinal = ordinal + 2; // TODO +2 since 1 is reserved for libSystem - - // TODO Defer parsing of the dylibs until they are actually needed - try dylib.parse(); - try self.dylibs.append(self.allocator, dylib); - - // Add LC_LOAD_DYLIB command - const dylib_id = dylib.id orelse unreachable; - var dylib_cmd = try createLoadDylibCommand( - self.allocator, - dylib_id.name, - dylib_id.timestamp, - dylib_id.current_version, - dylib_id.compatibility_version, - ); - errdefer dylib_cmd.deinit(self.allocator); - - try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); +fn parseLibs(self: *Zld, libs: []const []const u8) !void { + for (libs) |lib| { + const file = try fs.cwd().openFile(lib, .{}); + + if (try Dylib.isDylib(file)) { + const dylib = try self.allocator.create(Dylib); + errdefer self.allocator.destroy(dylib); + + dylib.* = Dylib.init(self.allocator); + dylib.arch = self.arch.?; + dylib.name = try self.allocator.dupe(u8, lib); + dylib.file = file; + + const ordinal = @intCast(u16, self.dylibs.items.len); + dylib.ordinal = ordinal + 2; // TODO +2 since 1 is reserved for libSystem + + // TODO Defer parsing of the dylibs until they are actually needed + try dylib.parse(); + try self.dylibs.append(self.allocator, dylib); + + // Add LC_LOAD_DYLIB command + const dylib_id = dylib.id orelse unreachable; + var dylib_cmd = try createLoadDylibCommand( + self.allocator, + dylib_id.name, + dylib_id.timestamp, + dylib_id.current_version, + dylib_id.compatibility_version, + ); + errdefer dylib_cmd.deinit(self.allocator); + + try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); + } else if (try Archive.isArchive(file)) { + const archive = try self.allocator.create(Archive); + errdefer self.allocator.destroy(archive); + + archive.* = Archive.init(self.allocator); + archive.arch = self.arch.?; + archive.name = try self.allocator.dupe(u8, lib); + archive.file = file; + try archive.parse(); + try self.archives.append(self.allocator, archive); + } else { + file.close(); + log.warn("unknown filetype for a library: '{s}'", .{lib}); + } } } |
