| author | |
| committer | |
| log | c5e509595a267ddec7d49a9d89ab2bc4f86a9d35 |
| tree | e0af57085dd439d7642a9b6920e9dd32187c2517 |
| parent | d05e9c379267e9a68522eca3fe8800803c6a5c70 |
3 files changed, 59 insertions(+), 15 deletions(-)
src/link/MachO.zig+42-5| ... | ... | @@ -845,11 +845,48 @@ fn parseFatLibrary(self: *MachO, path: []const u8) !fat.Arch { |
| 845 | 845 | } |
| 846 | 846 | |
| 847 | 847 | fn parseArchive(self: *MachO, lib: SystemLib, must_link: bool, fat_arch: ?fat.Arch) ParseError!void { |
| 848 | _ = self; | |
| 849 | _ = lib; | |
| 850 | _ = must_link; | |
| 851 | _ = fat_arch; | |
| 852 | return error.Unhandled; | |
| 848 | const tracy = trace(@src()); | |
| 849 | defer tracy.end(); | |
| 850 | ||
| 851 | const gpa = self.base.comp.gpa; | |
| 852 | ||
| 853 | const file = try std.fs.cwd().openFile(lib.path, .{}); | |
| 854 | defer file.close(); | |
| 855 | ||
| 856 | const data = if (fat_arch) |arch| blk: { | |
| 857 | try file.seekTo(arch.offset); | |
| 858 | const data = try gpa.alloc(u8, arch.size); | |
| 859 | const nread = try file.readAll(data); | |
| 860 | if (nread != arch.size) return error.InputOutput; | |
| 861 | break :blk data; | |
| 862 | } else try file.readToEndAlloc(gpa, std.math.maxInt(u32)); | |
| 863 | ||
| 864 | var archive = Archive{ .path = try gpa.dupe(u8, lib.path), .data = data }; | |
| 865 | defer archive.deinit(gpa); | |
| 866 | try archive.parse(self); | |
| 867 | ||
| 868 | var has_parse_error = false; | |
| 869 | for (archive.objects.items) |extracted| { | |
| 870 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | |
| 871 | self.files.set(index, .{ .object = extracted }); | |
| 872 | const object = &self.files.items(.data)[index].object; | |
| 873 | object.index = index; | |
| 874 | object.alive = must_link or lib.needed; // TODO: or self.options.all_load; | |
| 875 | object.hidden = lib.hidden; | |
| 876 | object.parse(self) catch |err| switch (err) { | |
| 877 | error.MalformedObject, | |
| 878 | error.InvalidCpuArch, | |
| 879 | error.InvalidTarget, | |
| 880 | => has_parse_error = true, | |
| 881 | else => |e| return e, | |
| 882 | }; | |
| 883 | try self.objects.append(gpa, index); | |
| 884 | ||
| 885 | // Finally, we do a post-parse check for -ObjC to see if we need to force load this member | |
| 886 | // anyhow. | |
| 887 | // TODO: object.alive = object.alive or (self.options.force_load_objc and object.hasObjc()); | |
| 888 | } | |
| 889 | if (has_parse_error) return error.MalformedArchive; | |
| 853 | 890 | } |
| 854 | 891 | |
| 855 | 892 | fn parseDylib(self: *MachO, lib: SystemLib, explicit: bool, fat_arch: ?fat.Arch) ParseError!void { |
src/link/MachO/Archive.zig+16-10| ... | ... | @@ -73,14 +73,20 @@ pub fn isArchive(path: []const u8, fat_arch: ?fat.Arch) !bool { |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | 75 | pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 76 | allocator.free(self.data); | |
| 77 | allocator.free(self.path); | |
| 76 | 78 | self.objects.deinit(allocator); |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void { | |
| 80 | const gpa = macho_file.base.allocator; | |
| 81 | pub fn parse(self: *Archive, macho_file: *MachO) !void { | |
| 82 | const gpa = macho_file.base.comp.gpa; | |
| 83 | ||
| 84 | var arena = std.heap.ArenaAllocator.init(gpa); | |
| 85 | defer arena.deinit(); | |
| 81 | 86 | |
| 82 | 87 | var stream = std.io.fixedBufferStream(self.data); |
| 83 | 88 | const reader = stream.reader(); |
| 89 | _ = try reader.readBytesNoEof(SARMAG); | |
| 84 | 90 | |
| 85 | 91 | while (true) { |
| 86 | 92 | if (stream.pos >= self.data.len) break; |
| ... | ... | @@ -89,18 +95,18 @@ pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void { |
| 89 | 95 | const hdr = try reader.readStruct(ar_hdr); |
| 90 | 96 | |
| 91 | 97 | if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) { |
| 92 | macho_file.base.fatal("{s}: invalid header delimiter: expected '{s}', found '{s}'", .{ | |
| 93 | self.path, std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), | |
| 98 | try macho_file.reportParseError(self.path, "invalid header delimiter: expected '{s}', found '{s}'", .{ | |
| 99 | std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag), | |
| 94 | 100 | }); |
| 95 | return error.ParseFailed; | |
| 101 | return error.MalformedArchive; | |
| 96 | 102 | } |
| 97 | 103 | |
| 98 | 104 | var size = try hdr.size(); |
| 99 | 105 | const name = name: { |
| 100 | if (hdr.name()) |n| break :name try arena.dupe(u8, n); | |
| 106 | if (hdr.name()) |n| break :name n; | |
| 101 | 107 | if (try hdr.nameLength()) |len| { |
| 102 | 108 | size -= len; |
| 103 | const buf = try arena.alloc(u8, len); | |
| 109 | const buf = try arena.allocator().alloc(u8, len); | |
| 104 | 110 | try reader.readNoEof(buf); |
| 105 | 111 | const actual_len = mem.indexOfScalar(u8, buf, @as(u8, 0)) orelse len; |
| 106 | 112 | break :name buf[0..actual_len]; |
| ... | ... | @@ -114,9 +120,9 @@ pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void { |
| 114 | 120 | if (mem.eql(u8, name, "__.SYMDEF") or mem.eql(u8, name, "__.SYMDEF SORTED")) continue; |
| 115 | 121 | |
| 116 | 122 | const object = Object{ |
| 117 | .archive = self.path, | |
| 118 | .path = name, | |
| 119 | .data = self.data[stream.pos..][0..size], | |
| 123 | .archive = try gpa.dupe(u8, self.path), | |
| 124 | .path = try gpa.dupe(u8, name), | |
| 125 | .data = try gpa.dupe(u8, self.data[stream.pos..][0..size]), | |
| 120 | 126 | .index = undefined, |
| 121 | 127 | .alive = false, |
| 122 | 128 | .mtime = hdr.date() catch 0, |
src/link/MachO/Object.zig+1| ... | ... | @@ -56,6 +56,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 56 | 56 | sf.stabs.deinit(allocator); |
| 57 | 57 | } |
| 58 | 58 | self.stab_files.deinit(allocator); |
| 59 | allocator.free(self.data); | |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 62 | pub fn parse(self: *Object, macho_file: *MachO) !void { |