| ... | @@ -104,8 +104,19 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? | ... | @@ -104,8 +104,19 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 104 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 104 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 105 | | 105 | |
| 106 | for (positionals.items) |obj| { | 106 | for (positionals.items) |obj| { |
| 107 | // TODO: parse for archive meaning don't unpack objects | 107 | parsePositional(macho_file, obj.path) catch |err| switch (err) { |
| 108 | _ = obj; | 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 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 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,6 +252,75 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 241 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 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 | fn markExports(macho_file: *MachO) void { | 324 | fn markExports(macho_file: *MachO) void { |
| 245 | if (macho_file.getZigObject()) |zo| { | 325 | if (macho_file.getZigObject()) |zo| { |
| 246 | zo.asFile().markExportsRelocatable(macho_file); | 326 | zo.asFile().markExportsRelocatable(macho_file); |
| ... | @@ -733,6 +813,7 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { | ... | @@ -733,6 +813,7 @@ fn writeHeader(macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { |
| 733 | const assert = std.debug.assert; | 813 | const assert = std.debug.assert; |
| 734 | const build_options = @import("build_options"); | 814 | const build_options = @import("build_options"); |
| 735 | const eh_frame = @import("eh_frame.zig"); | 815 | const eh_frame = @import("eh_frame.zig"); |
| | 816 | const fat = @import("fat.zig"); |
| 736 | const link = @import("../../link.zig"); | 817 | const link = @import("../../link.zig"); |
| 737 | const load_commands = @import("load_commands.zig"); | 818 | const load_commands = @import("load_commands.zig"); |
| 738 | const log = std.log.scoped(.link); | 819 | const log = std.log.scoped(.link); |
| ... | @@ -748,4 +829,5 @@ const Atom = @import("Atom.zig"); | ... | @@ -748,4 +829,5 @@ const Atom = @import("Atom.zig"); |
| 748 | const Compilation = @import("../../Compilation.zig"); | 829 | const Compilation = @import("../../Compilation.zig"); |
| 749 | const File = @import("file.zig").File; | 830 | const File = @import("file.zig").File; |
| 750 | const MachO = @import("../MachO.zig"); | 831 | const MachO = @import("../MachO.zig"); |
| | 832 | const Object = @import("Object.zig"); |
| 751 | const Symbol = @import("Symbol.zig"); | 833 | const Symbol = @import("Symbol.zig"); |