| 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,7 +62,7 @@ header_pad: u16 = 0x1000, |
| 62 | entry_addr: ?u64 = null, | 62 | entry_addr: ?u64 = null, |
| 63 | 63 | ||
| 64 | objects: std.ArrayListUnmanaged(Object) = .{}, | 64 | objects: std.ArrayListUnmanaged(Object) = .{}, |
| 65 | archives: std.ArrayListUnmanaged(*Archive) = .{}, | 65 | archives: std.ArrayListUnmanaged(Archive) = .{}, |
| 66 | dylibs: std.ArrayListUnmanaged(*Dylib) = .{}, | 66 | dylibs: std.ArrayListUnmanaged(*Dylib) = .{}, |
| 67 | 67 | ||
| 68 | next_dylib_ordinal: u16 = 1, | 68 | next_dylib_ordinal: u16 = 1, |
| ... | @@ -1006,8 +1006,13 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const | ... | @@ -1006,8 +1006,13 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1006 | continue; | 1006 | continue; |
| 1007 | } | 1007 | } |
| 1008 | 1008 | ||
| 1009 | if (try Archive.createAndParseFromPath(self.base.allocator, arch, full_path)) |archive| { | 1009 | if (try Archive.isArchive(file, arch)) { |
| 1010 | try self.archives.append(self.base.allocator, archive); | 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 | continue; | 1016 | continue; |
| 1012 | } | 1017 | } |
| 1013 | 1018 | ||
| ... | @@ -1019,6 +1024,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const | ... | @@ -1019,6 +1024,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1019 | continue; | 1024 | continue; |
| 1020 | } | 1025 | } |
| 1021 | 1026 | ||
| 1027 | self.base.allocator.free(full_path); | ||
| 1028 | file.close(); | ||
| 1022 | log.warn("unknown filetype for positional input file: '{s}'", .{file_name}); | 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,6 +1033,8 @@ fn parseInputFiles(self: *MachO, files: []const []const u8, syslibroot: ?[]const |
| 1026 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void { | 1033 | fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !void { |
| 1027 | const arch = self.base.options.target.cpu.arch; | 1034 | const arch = self.base.options.target.cpu.arch; |
| 1028 | for (libs) |lib| { | 1035 | for (libs) |lib| { |
| 1036 | const file = try fs.cwd().openFile(lib, .{}); | ||
| 1037 | |||
| 1029 | if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{ | 1038 | if (try Dylib.createAndParseFromPath(self.base.allocator, arch, lib, .{ |
| 1030 | .syslibroot = syslibroot, | 1039 | .syslibroot = syslibroot, |
| 1031 | })) |dylibs| { | 1040 | })) |dylibs| { |
| ... | @@ -1034,11 +1043,17 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v | ... | @@ -1034,11 +1043,17 @@ fn parseLibs(self: *MachO, libs: []const []const u8, syslibroot: ?[]const u8) !v |
| 1034 | continue; | 1043 | continue; |
| 1035 | } | 1044 | } |
| 1036 | 1045 | ||
| 1037 | if (try Archive.createAndParseFromPath(self.base.allocator, arch, lib)) |archive| { | 1046 | if (try Archive.isArchive(file, arch)) { |
| 1038 | try self.archives.append(self.base.allocator, archive); | 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 | continue; | 1053 | continue; |
| 1040 | } | 1054 | } |
| 1041 | 1055 | ||
| 1056 | file.close(); | ||
| 1042 | log.warn("unknown filetype for a library: '{s}'", .{lib}); | 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,9 +3360,8 @@ pub fn deinit(self: *MachO) void { |
| 3345 | } | 3360 | } |
| 3346 | self.objects.deinit(self.base.allocator); | 3361 | self.objects.deinit(self.base.allocator); |
| 3347 | 3362 | ||
| 3348 | for (self.archives.items) |archive| { | 3363 | for (self.archives.items) |*archive| { |
| 3349 | archive.deinit(self.base.allocator); | 3364 | archive.deinit(self.base.allocator); |
| 3350 | self.base.allocator.destroy(archive); | ||
| 3351 | } | 3365 | } |
| 3352 | self.archives.deinit(self.base.allocator); | 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,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 | pub fn deinit(self: *Archive, allocator: *Allocator) void { | 96 | pub fn deinit(self: *Archive, allocator: *Allocator) void { |
| 127 | for (self.toc.keys()) |*key| { | 97 | for (self.toc.keys()) |*key| { |
| 128 | allocator.free(key.*); | 98 | allocator.free(key.*); |
| ... | @@ -134,32 +104,40 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void { | ... | @@ -134,32 +104,40 @@ pub fn deinit(self: *Archive, allocator: *Allocator) void { |
| 134 | allocator.free(self.name); | 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 | pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void { | 129 | pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void { |
| 138 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch); | 130 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch); |
| 139 | |||
| 140 | try self.file.seekTo(self.library_offset); | 131 | try self.file.seekTo(self.library_offset); |
| 141 | 132 | const reader = self.file.reader(); | |
| 142 | var reader = self.file.reader(); | ||
| 143 | const magic = try reader.readBytesNoEof(SARMAG); | 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 | self.header = try reader.readStruct(ar_hdr); | 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 | var embedded_name = try parseName(allocator, self.header.?, reader); | 135 | var embedded_name = try parseName(allocator, self.header.?, reader); |
| 158 | log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name }); | ||
| 159 | defer allocator.free(embedded_name); | 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 | try reader.context.seekTo(0); | 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,17 +155,18 @@ pub fn deinit(self: *Object, allocator: *Allocator) void { |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | pub fn isObject(file: fs.File) !bool { | 157 | pub fn isObject(file: fs.File) !bool { |
| 158 | const reader = file.reader(); | 158 | const Internal = struct { |
| 159 | const is_object = blk: { | 159 | fn isObject(reader: anytype) !bool { |
| 160 | if (reader.readStruct(macho.mach_header_64)) |header| { | 160 | const header = try reader.readStruct(macho.mach_header_64); |
| 161 | break :blk header.filetype == macho.MH_OBJECT; | 161 | return header.filetype == macho.MH_OBJECT; |
| 162 | } else |err| { | ||
| 163 | switch (err) { | ||
| 164 | error.EndOfStream => break :blk false, | ||
| 165 | else => |e| return e, | ||
| 166 | } | ||
| 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 | try file.seekTo(0); | 170 | try file.seekTo(0); |
| 170 | return is_object; | 171 | return is_object; |
| 171 | } | 172 | } |
| ... | @@ -175,14 +176,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { | ... | @@ -175,14 +176,7 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { |
| 175 | if (self.file_offset) |offset| { | 176 | if (self.file_offset) |offset| { |
| 176 | try reader.context.seekTo(offset); | 177 | try reader.context.seekTo(offset); |
| 177 | } | 178 | } |
| 178 | |||
| 179 | const header = try reader.readStruct(macho.mach_header_64); | 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 | const this_arch: Arch = switch (header.cputype) { | 180 | const this_arch: Arch = switch (header.cputype) { |
| 187 | macho.CPU_TYPE_ARM64 => .aarch64, | 181 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 188 | macho.CPU_TYPE_X86_64 => .x86_64, | 182 | macho.CPU_TYPE_X86_64 => .x86_64, |
| ... | @@ -195,7 +189,6 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { | ... | @@ -195,7 +189,6 @@ pub fn parse(self: *Object, allocator: *Allocator, arch: Arch) !void { |
| 195 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch }); | 189 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ arch, this_arch }); |
| 196 | return error.MismatchedCpuArchitecture; | 190 | return error.MismatchedCpuArchitecture; |
| 197 | } | 191 | } |
| 198 | |||
| 199 | self.header = header; | 192 | self.header = header; |
| 200 | 193 | ||
| 201 | try self.readLoadCommands(allocator, reader); | 194 | try self.readLoadCommands(allocator, reader); |