| ... | ... | @@ -104,8 +104,19 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 104 | 104 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 105 | 105 | |
| 106 | 106 | for (positionals.items) |obj| { |
| 107 | | // TODO: parse for archive meaning don't unpack objects |
| 108 | | _ = obj; |
| 107 | parsePositional(macho_file, obj.path) catch |err| switch (err) { |
| 108 | error.MalformedObject, |
| 109 | error.MalformedArchive, |
| 110 | error.InvalidCpuArch, |
| 111 | error.InvalidTarget, |
| 112 | => continue, // already reported |
| 113 | error.UnknownFileType => try macho_file.reportParseError(obj.path, "unknown file type for an object file", .{}), |
| 114 | else => |e| try macho_file.reportParseError( |
| 115 | obj.path, |
| 116 | "unexpected error: parsing input file failed with error {s}", |
| 117 | .{@errorName(e)}, |
| 118 | ), |
| 119 | }; |
| 109 | 120 | } |
| 110 | 121 | |
| 111 | 122 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| ... | ... | @@ -241,6 +252,75 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 241 | 252 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 242 | 253 | } |
| 243 | 254 | |
| 255 | fn parsePositional(macho_file: *MachO, path: []const u8) MachO.ParseError!void { |
| 256 | const tracy = trace(@src()); |
| 257 | defer tracy.end(); |
| 258 | if (try Object.isObject(path)) { |
| 259 | try parseObject(macho_file, path); |
| 260 | } else if (try fat.isFatLibrary(path)) { |
| 261 | const fat_arch = try macho_file.parseFatLibrary(path); |
| 262 | if (try Archive.isArchive(path, fat_arch)) { |
| 263 | try parseArchive(macho_file, path, fat_arch); |
| 264 | } else return error.UnknownFileType; |
| 265 | } else if (try Archive.isArchive(path, null)) { |
| 266 | try parseArchive(macho_file, path, null); |
| 267 | } else return error.UnknownFileType; |
| 268 | } |
| 269 | |
| 270 | fn parseObject(macho_file: *MachO, path: []const u8) MachO.ParseError!void { |
| 271 | const tracy = trace(@src()); |
| 272 | defer tracy.end(); |
| 273 | |
| 274 | const gpa = macho_file.base.comp.gpa; |
| 275 | const file = try std.fs.cwd().openFile(path, .{}); |
| 276 | errdefer file.close(); |
| 277 | const handle = try macho_file.addFileHandle(file); |
| 278 | const mtime: u64 = mtime: { |
| 279 | const stat = file.stat() catch break :mtime 0; |
| 280 | break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000))); |
| 281 | }; |
| 282 | const index = @as(File.Index, @intCast(try macho_file.files.addOne(gpa))); |
| 283 | macho_file.files.set(index, .{ .object = .{ |
| 284 | .path = try gpa.dupe(u8, path), |
| 285 | .file_handle = handle, |
| 286 | .mtime = mtime, |
| 287 | .index = index, |
| 288 | } }); |
| 289 | try macho_file.objects.append(gpa, index); |
| 290 | |
| 291 | const object = macho_file.getFile(index).?.object; |
| 292 | try object.parseAr(macho_file); |
| 293 | } |
| 294 | |
| 295 | fn parseArchive(macho_file: *MachO, path: []const u8, fat_arch: ?fat.Arch) MachO.ParseError!void { |
| 296 | const tracy = trace(@src()); |
| 297 | defer tracy.end(); |
| 298 | |
| 299 | const gpa = macho_file.base.comp.gpa; |
| 300 | |
| 301 | const file = try std.fs.cwd().openFile(path, .{}); |
| 302 | errdefer file.close(); |
| 303 | const handle = try macho_file.addFileHandle(file); |
| 304 | |
| 305 | var archive = Archive{}; |
| 306 | defer archive.deinit(gpa); |
| 307 | try archive.parse(macho_file, path, handle, fat_arch); |
| 308 | |
| 309 | var has_parse_error = false; |
| 310 | for (archive.objects.items) |extracted| { |
| 311 | const index = @as(File.Index, @intCast(try macho_file.files.addOne(gpa))); |
| 312 | macho_file.files.set(index, .{ .object = extracted }); |
| 313 | const object = &macho_file.files.items(.data)[index].object; |
| 314 | object.index = index; |
| 315 | object.parseAr(macho_file) catch |err| switch (err) { |
| 316 | error.InvalidCpuArch => has_parse_error = true, |
| 317 | else => |e| return e, |
| 318 | }; |
| 319 | try macho_file.objects.append(gpa, index); |
| 320 | } |
| 321 | if (has_parse_error) return error.MalformedArchive; |
| 322 | } |
| 323 | |
| 244 | 324 | fn markExports(macho_file: *MachO) void { |
| 245 | 325 | if (macho_file.getZigObject()) |zo| { |
| 246 | 326 | zo.asFile().markExportsRelocatable(macho_file); |
| ... | ... | @@ -733,6 +813,7 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { |
| 733 | 813 | const assert = std.debug.assert; |
| 734 | 814 | const build_options = @import("build_options"); |
| 735 | 815 | const eh_frame = @import("eh_frame.zig"); |
| 816 | const fat = @import("fat.zig"); |
| 736 | 817 | const link = @import("../../link.zig"); |
| 737 | 818 | const load_commands = @import("load_commands.zig"); |
| 738 | 819 | const log = std.log.scoped(.link); |
| ... | ... | @@ -748,4 +829,5 @@ const Atom = @import("Atom.zig"); |
| 748 | 829 | const Compilation = @import("../../Compilation.zig"); |
| 749 | 830 | const File = @import("file.zig").File; |
| 750 | 831 | const MachO = @import("../MachO.zig"); |
| 832 | const Object = @import("Object.zig"); |
| 751 | 833 | const Symbol = @import("Symbol.zig"); |