| author | |
| committer | |
| log | f023cdad7ca676977d9b5abd3d38677779aab211 |
| tree | e9f6005480147c3daa1766e37ce1715d31877bc9 |
| parent | 06396ddd7d632704681bbd6278f18dcc2b6bf20c |
instead, transfer ownership directly to MachO struct.3 files changed, 56 insertions(+), 71 deletions(-)
src/link/MachO.zig+21-7| ... | ... | @@ -62,7 +62,7 @@ header_pad: u16 = 0x1000, |
| 62 | 62 | entry_addr: ?u64 = null, |
| 63 | 63 | |
| 64 | 64 | objects: std.ArrayListUnmanaged(Object) = .{}, |
| 65 | archives: std.ArrayListUnmanaged(*Archive) = .{}, | |
| 65 | archives: std.ArrayListUnmanaged(Archive) = .{}, | |
| 66 | 66 | dylibs: std.ArrayListUnmanaged(*Dylib) = .{}, |
| 67 | 67 | |
| 68 | 68 | next_dylib_ordinal: u16 = 1, |
| ... | ... | @@ -1006,8 +1006,13 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1006 | 1006 | continue; |
| 1007 | 1007 | } |
| 1008 | 1008 | |
| 1009 | if (try Archive.createAndParseFromPath(self.base.allocator, arch, full_path)) |archive| { | |
| 1010 | try self.archives.append(self.base.allocator, archive); | |
| 1009 | if (try Archive.isArchive(file, arch)) { | |
| 1010 | const archive = try self.archives.addOne(self.base.allocator); | |
| 1011 | archive.* = .{ | |
| 1012 | .name = full_path, | |
| 1013 | .file = file, | |
| 1014 | }; | |
| 1015 | try archive.parse(self.base.allocator, arch); | |
| 1011 | 1016 | continue; |
| 1012 | 1017 | } |
| 1013 | 1018 | |
| ... | ... | @@ -1019,6 +1024,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1019 | 1024 | continue; |
| 1020 | 1025 | } |
| 1021 | 1026 | |
| 1027 | self.base.allocator.free(full_path); | |
| 1028 | file.close(); | |
| 1022 | 1029 | log.warn("unknown filetype for positional input file: '{s}'", .{file_name}); |
| 1023 | 1030 | } |
| 1024 | 1031 | } |
| ... | ... | @@ -1026,6 +1033,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1026 | 1033 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void { |
| 1027 | 1034 | const arch = self.base.options.target.cpu.arch; |
| 1028 | 1035 | for (libs) |lib| { |
| 1036 | const file = try fs.cwd().openFile(lib, .{}); | |
| 1037 | ||
| 1029 | 1038 | if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{ |
| 1030 | 1039 | .syslibroot = syslibroot, |
| 1031 | 1040 | })) |dylibs| { |
| ... | ... | @@ -1034,11 +1043,17 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v |
| 1034 | 1043 | continue; |
| 1035 | 1044 | } |
| 1036 | 1045 | |
| 1037 | if (try Archive.createAndParseFromPath(self.base.allocator, arch, lib)) |archive| { | |
| 1038 | try self.archives.append(self.base.allocator, archive); | |
| 1046 | if (try Archive.isArchive(file, arch)) { | |
| 1047 | const archive = try self.archives.addOne(self.base.allocator); | |
| 1048 | archive.* = .{ | |
| 1049 | .name = try self.base.allocator.dupe(u8, lib), | |
| 1050 | .file = file, | |
| 1051 | }; | |
| 1052 | try archive.parse(self.base.allocator, arch); | |
| 1039 | 1053 | continue; |
| 1040 | 1054 | } |
| 1041 | 1055 | |
| 1056 | file.close(); | |
| 1042 | 1057 | log.warn("unknown filetype for a library: '{s}'", .{lib}); |
| 1043 | 1058 | } |
| 1044 | 1059 | } |
| ... | ... | @@ -3345,9 +3360,8 @@ pub fn deinit(self: *MachO) void { |
| 3345 | 3360 | } |
| 3346 | 3361 | self.objects.deinit(self.base.allocator); |
| 3347 | 3362 | |
| 3348 | for (self.archives.items) |archive| { | |
| 3363 | for (self.archives.items) |*archive| { | |
| 3349 | 3364 | archive.deinit(self.base.allocator); |
| 3350 | self.base.allocator.destroy(archive); | |
| 3351 | 3365 | } |
| 3352 | 3366 | self.archives.deinit(self.base.allocator); |
| 3353 | 3367 |
src/link/MachO/Archive.zig+25-47| ... | ... | @@ -93,36 +93,6 @@ const ar_hdr = extern struct { |
| 93 | 93 | } |
| 94 | 94 | }; |
| 95 | 95 | |
| 96 | pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8) !?*Archive { | |
| 97 | const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) { | |
| 98 | error.FileNotFound => return null, | |
| 99 | else => |e| return e, | |
| 100 | }; | |
| 101 | errdefer file.close(); | |
| 102 | ||
| 103 | const archive = try allocator.create(Archive); | |
| 104 | errdefer allocator.destroy(archive); | |
| 105 | ||
| 106 | const name = try allocator.dupe(u8, path); | |
| 107 | errdefer allocator.free(name); | |
| 108 | ||
| 109 | archive.* = .{ | |
| 110 | .name = name, | |
| 111 | .file = file, | |
| 112 | }; | |
| 113 | ||
| 114 | archive.parse(allocator, arch) catch |err| switch (err) { | |
| 115 | error.EndOfStream, error.NotArchive => { | |
| 116 | archive.deinit(allocator); | |
| 117 | allocator.destroy(archive); | |
| 118 | return null; | |
| 119 | }, | |
| 120 | else => |e| return e, | |
| 121 | }; | |
| 122 | ||
| 123 | return archive; | |
| 124 | } | |
| 125 | ||
| 126 | 96 | pub fn deinit(self: *Archive, allocator: *Allocator) void { |
| 127 | 97 | for (self.toc.keys()) |*key| { |
| 128 | 98 | allocator.free(key.*); |
| ... | ... | @@ -134,32 +104,40 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void { |
| 134 | 104 | allocator.free(self.name); |
| 135 | 105 | } |
| 136 | 106 | |
| 107 | pub fn isArchive(file: fs.File, arch: Arch) !bool { | |
| 108 | const Internal = struct { | |
| 109 | fn isArchive(reader: anytype, a: Arch) !bool { | |
| 110 | const offset = try fat.getLibraryOffset(reader, a); | |
| 111 | try reader.context.seekTo(offset); | |
| 112 | const magic = try reader.readBytesNoEof(SARMAG); | |
| 113 | if (!mem.eql(u8, &magic, ARMAG)) return false; | |
| 114 | const header = try reader.readStruct(ar_hdr); | |
| 115 | return mem.eql(u8, &header.ar_fmag, ARFMAG); | |
| 116 | } | |
| 117 | }; | |
| 118 | const is_archive = if (Internal.isArchive(file.reader(), arch)) |res| | |
| 119 | res | |
| 120 | else |err| switch (err) { | |
| 121 | error.EndOfStream => false, | |
| 122 | error.MismatchedCpuArchitecture => true, // TODO maybe this check should be done differently? | |
| 123 | else => |e| return e, | |
| 124 | }; | |
| 125 | try file.seekTo(0); | |
| 126 | return is_archive; | |
| 127 | } | |
| 128 | ||
| 137 | 129 | pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void { |
| 138 | 130 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch); |
| 139 | ||
| 140 | 131 | try self.file.seekTo(self.library_offset); |
| 141 | ||
| 142 | var reader = self.file.reader(); | |
| 132 | const reader = self.file.reader(); | |
| 143 | 133 | const magic = try reader.readBytesNoEof(SARMAG); |
| 144 | ||
| 145 | if (!mem.eql(u8, &magic, ARMAG)) { | |
| 146 | log.debug("invalid magic: expected '{s}', found '{s}'", .{ ARMAG, magic }); | |
| 147 | return error.NotArchive; | |
| 148 | } | |
| 149 | ||
| 150 | 134 | self.header = try reader.readStruct(ar_hdr); |
| 151 | ||
| 152 | if (!mem.eql(u8, &self.header.?.ar_fmag, ARFMAG)) { | |
| 153 | log.debug("invalid header delimiter: expected '{s}', found '{s}'", .{ ARFMAG, self.header.?.ar_fmag }); | |
| 154 | return error.NotArchive; | |
| 155 | } | |
| 156 | ||
| 157 | 135 | var embedded_name = try parseName(allocator, self.header.?, reader); |
| 158 | log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name }); | |
| 159 | 136 | defer allocator.free(embedded_name); |
| 160 | 137 | |
| 161 | try self.parseTableOfContents(allocator, reader); | |
| 138 | log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name }); | |
| 162 | 139 | |
| 140 | try self.parseTableOfContents(allocator, reader); | |
| 163 | 141 | try reader.context.seekTo(0); |
| 164 | 142 | } |
| 165 | 143 |
src/link/MachO/Object.zig+10-17| ... | ... | @@ -155,17 +155,18 @@ pub fn deinit(self: *Object, allocator: *Allocator) void { |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | pub fn isObject(file: fs.File) !bool { |
| 158 | const reader = file.reader(); | |
| 159 | const is_object = blk: { | |
| 160 | if (reader.readStruct(macho.mach_header_64)) |header| { | |
| 161 | break :blk header.filetype == macho.MH_OBJECT; | |
| 162 | } else |err| { | |
| 163 | switch (err) { | |
| 164 | error.EndOfStream => break :blk false, | |
| 165 | else => |e| return e, | |
| 166 | } | |
| 158 | const Internal = struct { | |
| 159 | fn isObject(reader: anytype) !bool { | |
| 160 | const header = try reader.readStruct(macho.mach_header_64); | |
| 161 | return header.filetype == macho.MH_OBJECT; | |
| 167 | 162 | } |
| 168 | 163 | }; |
| 164 | const is_object = if (Internal.isObject(file.reader())) |res| | |
| 165 | res | |
| 166 | else |err| switch (err) { | |
| 167 | error.EndOfStream => false, | |
| 168 | else => |e| return e, | |
| 169 | }; | |
| 169 | 170 | try file.seekTo(0); |
| 170 | 171 | return is_object; |
| 171 | 172 | } |
| ... | ... | @@ -175,14 +176,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { |
| 175 | 176 | if (self.file_offset) |offset| { |
| 176 | 177 | try reader.context.seekTo(offset); |
| 177 | 178 | } |
| 178 | ||
| 179 | 179 | const header = try reader.readStruct(macho.mach_header_64); |
| 180 | ||
| 181 | if (header.filetype != macho.MH_OBJECT) { | |
| 182 | log.debug("invalid filetype: expected 0x{x}, found 0x{x}", .{ macho.MH_OBJECT, header.filetype }); | |
| 183 | return error.NotObject; | |
| 184 | } | |
| 185 | ||
| 186 | 180 | const this_arch: Arch = switch (header.cputype) { |
| 187 | 181 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 188 | 182 | macho.CPU_TYPE_X86_64 => .x86_64, |
| ... | ... | @@ -195,7 +189,6 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { |
| 195 | 189 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch }); |
| 196 | 190 | return error.MismatchedCpuArchitecture; |
| 197 | 191 | } |
| 198 | ||
| 199 | 192 | self.header = header; |
| 200 | 193 | |
| 201 | 194 | try self.readLoadCommands(allocator, reader); |