| author | |
| committer | |
| log | 20ea44ef107828d76692e610e1ca62ee231fb4a9 |
| tree | 3cdd9e3816f57c9b5e2469af238c69e2520e68cb |
| parent | cff5d9c805aa3433cc2562c3cb29bd3201817214 |
5 files changed, 53 insertions(+), 37 deletions(-)
src/link/MachO.zig+13-5| ... | ... | @@ -1415,7 +1415,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool { |
| 1415 | 1415 | .mtime = mtime, |
| 1416 | 1416 | }; |
| 1417 | 1417 | |
| 1418 | object.parse(self.base.allocator, self.base.options.target) catch |err| switch (err) { | |
| 1418 | object.parse(self.base.allocator, self.base.options.target.cpu.arch) catch |err| switch (err) { | |
| 1419 | 1419 | error.EndOfStream, error.NotObject => { |
| 1420 | 1420 | object.deinit(self.base.allocator); |
| 1421 | 1421 | return false; |
| ... | ... | @@ -1443,7 +1443,7 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool { |
| 1443 | 1443 | .file = file, |
| 1444 | 1444 | }; |
| 1445 | 1445 | |
| 1446 | archive.parse(self.base.allocator, self.base.options.target) catch |err| switch (err) { | |
| 1446 | archive.parse(self.base.allocator, self.base.options.target.cpu.arch) catch |err| switch (err) { | |
| 1447 | 1447 | error.EndOfStream, error.NotArchive => { |
| 1448 | 1448 | archive.deinit(self.base.allocator); |
| 1449 | 1449 | return false; |
| ... | ... | @@ -1463,7 +1463,11 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool { |
| 1463 | 1463 | } |
| 1464 | 1464 | for (offsets.keys()) |off| { |
| 1465 | 1465 | const object = try self.objects.addOne(self.base.allocator); |
| 1466 | object.* = try archive.parseObject(self.base.allocator, self.base.options.target, off); | |
| 1466 | object.* = try archive.parseObject( | |
| 1467 | self.base.allocator, | |
| 1468 | self.base.options.target.cpu.arch, | |
| 1469 | off, | |
| 1470 | ); | |
| 1467 | 1471 | } |
| 1468 | 1472 | } else { |
| 1469 | 1473 | try self.archives.append(self.base.allocator, archive); |
| ... | ... | @@ -1511,7 +1515,7 @@ pub fn parseDylib( |
| 1511 | 1515 | |
| 1512 | 1516 | dylib.parse( |
| 1513 | 1517 | self.base.allocator, |
| 1514 | self.base.options.target, | |
| 1518 | self.base.options.target.cpu.arch, | |
| 1515 | 1519 | dylib_id, |
| 1516 | 1520 | dependent_libs, |
| 1517 | 1521 | ) catch |err| switch (err) { |
| ... | ... | @@ -3126,7 +3130,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 3126 | 3130 | |
| 3127 | 3131 | const object_id = @intCast(u16, self.objects.items.len); |
| 3128 | 3132 | const object = try self.objects.addOne(self.base.allocator); |
| 3129 | object.* = try archive.parseObject(self.base.allocator, self.base.options.target, offsets.items[0]); | |
| 3133 | object.* = try archive.parseObject( | |
| 3134 | self.base.allocator, | |
| 3135 | self.base.options.target.cpu.arch, | |
| 3136 | offsets.items[0], | |
| 3137 | ); | |
| 3130 | 3138 | try self.resolveSymbolsInObject(object, object_id); |
| 3131 | 3139 | |
| 3132 | 3140 | continue :loop; |
src/link/MachO/Archive.zig+4-4| ... | ... | @@ -103,9 +103,9 @@ pub fn deinit(self: *Archive, allocator: Allocator) void { |
| 103 | 103 | allocator.free(self.name); |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | pub fn parse(self: *Archive, allocator: Allocator, target: std.Target) !void { | |
| 106 | pub fn parse(self: *Archive, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void { | |
| 107 | 107 | const reader = self.file.reader(); |
| 108 | self.library_offset = try fat.getLibraryOffset(reader, target); | |
| 108 | self.library_offset = try fat.getLibraryOffset(reader, cpu_arch); | |
| 109 | 109 | try self.file.seekTo(self.library_offset); |
| 110 | 110 | |
| 111 | 111 | const magic = try reader.readBytesNoEof(SARMAG); |
| ... | ... | @@ -187,7 +187,7 @@ fn parseTableOfContents(self: *Archive, allocator: Allocator, reader: anytype) ! |
| 187 | 187 | } |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offset: u32) !Object { | |
| 190 | pub fn parseObject(self: Archive, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch, offset: u32) !Object { | |
| 191 | 191 | const reader = self.file.reader(); |
| 192 | 192 | try reader.context.seekTo(offset + self.library_offset); |
| 193 | 193 | |
| ... | ... | @@ -216,7 +216,7 @@ pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offs |
| 216 | 216 | .mtime = try self.header.?.date(), |
| 217 | 217 | }; |
| 218 | 218 | |
| 219 | try object.parse(allocator, target); | |
| 219 | try object.parse(allocator, cpu_arch); | |
| 220 | 220 | try reader.context.seekTo(0); |
| 221 | 221 | |
| 222 | 222 | return object; |
src/link/MachO/Dylib.zig+25-18| ... | ... | @@ -11,6 +11,7 @@ const mem = std.mem; |
| 11 | 11 | const fat = @import("fat.zig"); |
| 12 | 12 | |
| 13 | 13 | const Allocator = mem.Allocator; |
| 14 | const CrossTarget = std.zig.CrossTarget; | |
| 14 | 15 | const LibStub = @import("../tapi.zig").LibStub; |
| 15 | 16 | const MachO = @import("../MachO.zig"); |
| 16 | 17 | |
| ... | ... | @@ -145,13 +146,13 @@ pub fn deinit(self: *Dylib, allocator: Allocator) void { |
| 145 | 146 | pub fn parse( |
| 146 | 147 | self: *Dylib, |
| 147 | 148 | allocator: Allocator, |
| 148 | target: std.Target, | |
| 149 | cpu_arch: std.Target.Cpu.Arch, | |
| 149 | 150 | dylib_id: u16, |
| 150 | 151 | dependent_libs: anytype, |
| 151 | 152 | ) !void { |
| 152 | 153 | log.debug("parsing shared library '{s}'", .{self.name}); |
| 153 | 154 | |
| 154 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), target); | |
| 155 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), cpu_arch); | |
| 155 | 156 | |
| 156 | 157 | try self.file.seekTo(self.library_offset); |
| 157 | 158 | |
| ... | ... | @@ -165,8 +166,8 @@ pub fn parse( |
| 165 | 166 | |
| 166 | 167 | const this_arch: std.Target.Cpu.Arch = try fat.decodeArch(self.header.?.cputype, true); |
| 167 | 168 | |
| 168 | if (this_arch != target.cpu.arch) { | |
| 169 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch }); | |
| 169 | if (this_arch != cpu_arch) { | |
| 170 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ cpu_arch, this_arch }); | |
| 170 | 171 | return error.MismatchedCpuArchitecture; |
| 171 | 172 | } |
| 172 | 173 | |
| ... | ... | @@ -278,23 +279,24 @@ fn addSymbol(self: *Dylib, allocator: Allocator, sym_name: []const u8) !void { |
| 278 | 279 | |
| 279 | 280 | const TargetMatcher = struct { |
| 280 | 281 | allocator: Allocator, |
| 281 | target: std.Target, | |
| 282 | target: CrossTarget, | |
| 282 | 283 | target_strings: std.ArrayListUnmanaged([]const u8) = .{}, |
| 283 | 284 | |
| 284 | fn init(allocator: Allocator, target: std.Target) !TargetMatcher { | |
| 285 | fn init(allocator: Allocator, target: CrossTarget) !TargetMatcher { | |
| 285 | 286 | var self = TargetMatcher{ |
| 286 | 287 | .allocator = allocator, |
| 287 | 288 | .target = target, |
| 288 | 289 | }; |
| 289 | 290 | try self.target_strings.append(allocator, try targetToAppleString(allocator, target)); |
| 290 | 291 | |
| 291 | if (target.abi == .simulator) { | |
| 292 | const abi = target.abi orelse .none; | |
| 293 | if (abi == .simulator) { | |
| 292 | 294 | // For Apple simulator targets, linking gets tricky as we need to link against the simulator |
| 293 | 295 | // hosts dylibs too. |
| 294 | const host_target = try targetToAppleString(allocator, (std.zig.CrossTarget{ | |
| 295 | .cpu_arch = target.cpu.arch, | |
| 296 | const host_target = try targetToAppleString(allocator, .{ | |
| 297 | .cpu_arch = target.cpu_arch.?, | |
| 296 | 298 | .os_tag = .macos, |
| 297 | }).toTarget()); | |
| 299 | }); | |
| 298 | 300 | try self.target_strings.append(allocator, host_target); |
| 299 | 301 | } |
| 300 | 302 | |
| ... | ... | @@ -308,23 +310,24 @@ const TargetMatcher = struct { |
| 308 | 310 | self.target_strings.deinit(self.allocator); |
| 309 | 311 | } |
| 310 | 312 | |
| 311 | fn targetToAppleString(allocator: Allocator, target: std.Target) ![]const u8 { | |
| 312 | const arch = switch (target.cpu.arch) { | |
| 313 | fn targetToAppleString(allocator: Allocator, target: CrossTarget) ![]const u8 { | |
| 314 | const cpu_arch = switch (target.cpu_arch.?) { | |
| 313 | 315 | .aarch64 => "arm64", |
| 314 | 316 | .x86_64 => "x86_64", |
| 315 | 317 | else => unreachable, |
| 316 | 318 | }; |
| 317 | const os = @tagName(target.os.tag); | |
| 318 | const abi: ?[]const u8 = switch (target.abi) { | |
| 319 | const os_tag = @tagName(target.os_tag.?); | |
| 320 | const target_abi = target.abi orelse .none; | |
| 321 | const abi: ?[]const u8 = switch (target_abi) { | |
| 319 | 322 | .none => null, |
| 320 | 323 | .simulator => "simulator", |
| 321 | 324 | .macabi => "maccatalyst", |
| 322 | 325 | else => unreachable, |
| 323 | 326 | }; |
| 324 | 327 | if (abi) |x| { |
| 325 | return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ arch, os, x }); | |
| 328 | return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ cpu_arch, os_tag, x }); | |
| 326 | 329 | } |
| 327 | return std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, os }); | |
| 330 | return std.fmt.allocPrint(allocator, "{s}-{s}", .{ cpu_arch, os_tag }); | |
| 328 | 331 | } |
| 329 | 332 | |
| 330 | 333 | fn hasValue(stack: []const []const u8, needle: []const u8) bool { |
| ... | ... | @@ -342,7 +345,7 @@ const TargetMatcher = struct { |
| 342 | 345 | } |
| 343 | 346 | |
| 344 | 347 | fn matchesArch(self: TargetMatcher, archs: []const []const u8) bool { |
| 345 | return hasValue(archs, @tagName(self.target.cpu.arch)); | |
| 348 | return hasValue(archs, @tagName(self.target.cpu_arch.?)); | |
| 346 | 349 | } |
| 347 | 350 | }; |
| 348 | 351 | |
| ... | ... | @@ -376,7 +379,11 @@ pub fn parseFromStub( |
| 376 | 379 | |
| 377 | 380 | log.debug(" (install_name '{s}')", .{umbrella_lib.installName()}); |
| 378 | 381 | |
| 379 | var matcher = try TargetMatcher.init(allocator, target); | |
| 382 | var matcher = try TargetMatcher.init(allocator, .{ | |
| 383 | .cpu_arch = target.cpu.arch, | |
| 384 | .os_tag = target.os.tag, | |
| 385 | .abi = target.abi, | |
| 386 | }); | |
| 380 | 387 | defer matcher.deinit(); |
| 381 | 388 | |
| 382 | 389 | for (lib_stub.inner) |elem, stub_index| { |
src/link/MachO/Object.zig+6-5| ... | ... | @@ -66,6 +66,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void { |
| 66 | 66 | } |
| 67 | 67 | self.load_commands.deinit(gpa); |
| 68 | 68 | gpa.free(self.contents); |
| 69 | self.symtab.deinit(gpa); | |
| 69 | 70 | self.sections_as_symbols.deinit(gpa); |
| 70 | 71 | self.atom_by_index_table.deinit(gpa); |
| 71 | 72 | |
| ... | ... | @@ -78,7 +79,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void { |
| 78 | 79 | gpa.free(self.name); |
| 79 | 80 | } |
| 80 | 81 | |
| 81 | pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { | |
| 82 | pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void { | |
| 82 | 83 | const file_stat = try self.file.stat(); |
| 83 | 84 | const file_size = math.cast(usize, file_stat.size) orelse return error.Overflow; |
| 84 | 85 | self.contents = try self.file.readToEndAlloc(allocator, file_size); |
| ... | ... | @@ -108,8 +109,8 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { |
| 108 | 109 | return error.UnsupportedCpuArchitecture; |
| 109 | 110 | }, |
| 110 | 111 | }; |
| 111 | if (this_arch != target.cpu.arch) { | |
| 112 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch }); | |
| 112 | if (this_arch != cpu_arch) { | |
| 113 | log.err("mismatched cpu architecture: expected {s}, found {s}", .{ cpu_arch, this_arch }); | |
| 113 | 114 | return error.MismatchedCpuArchitecture; |
| 114 | 115 | } |
| 115 | 116 | |
| ... | ... | @@ -351,7 +352,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) |
| 351 | 352 | macho_file.getSection(match).sectName(), |
| 352 | 353 | }); |
| 353 | 354 | |
| 354 | const arch = macho_file.base.options.target.cpu.arch; | |
| 355 | const cpu_arch = macho_file.base.options.target.cpu.arch; | |
| 355 | 356 | const is_zerofill = blk: { |
| 356 | 357 | const section_type = sect.type_(); |
| 357 | 358 | break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; |
| ... | ... | @@ -466,7 +467,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) |
| 466 | 467 | sect, |
| 467 | 468 | ); |
| 468 | 469 | |
| 469 | if (arch == .x86_64 and addr == sect.addr) { | |
| 470 | if (cpu_arch == .x86_64 and addr == sect.addr) { | |
| 470 | 471 | // In x86_64 relocs, it can so happen that the compiler refers to the same |
| 471 | 472 | // atom by both the actual assigned symbol and the start of the section. In this |
| 472 | 473 | // case, we need to link the two together so add an alias. |
src/link/MachO/fat.zig+5-5| ... | ... | @@ -6,7 +6,7 @@ const mem = std.mem; |
| 6 | 6 | const native_endian = builtin.target.cpu.arch.endian(); |
| 7 | 7 | |
| 8 | 8 | pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Target.Cpu.Arch { |
| 9 | const arch: std.Target.Cpu.Arch = switch (cputype) { | |
| 9 | const cpu_arch: std.Target.Cpu.Arch = switch (cputype) { | |
| 10 | 10 | macho.CPU_TYPE_ARM64 => .aarch64, |
| 11 | 11 | macho.CPU_TYPE_X86_64 => .x86_64, |
| 12 | 12 | else => { |
| ... | ... | @@ -16,7 +16,7 @@ pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Targe |
| 16 | 16 | return error.UnsupportedCpuArchitecture; |
| 17 | 17 | }, |
| 18 | 18 | }; |
| 19 | return arch; | |
| 19 | return cpu_arch; | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | fn readFatStruct(reader: anytype, comptime T: type) !T { |
| ... | ... | @@ -29,7 +29,7 @@ fn readFatStruct(reader: anytype, comptime T: type) !T { |
| 29 | 29 | return res; |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 { | |
| 32 | pub fn getLibraryOffset(reader: anytype, cpu_arch: std.Target.Cpu.Arch) !u64 { | |
| 33 | 33 | const fat_header = try readFatStruct(reader, macho.fat_header); |
| 34 | 34 | if (fat_header.magic != macho.FAT_MAGIC) return 0; |
| 35 | 35 | |
| ... | ... | @@ -41,12 +41,12 @@ pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 { |
| 41 | 41 | const lib_arch = decodeArch(fat_arch.cputype, false) catch |err| switch (err) { |
| 42 | 42 | error.UnsupportedCpuArchitecture => continue, |
| 43 | 43 | }; |
| 44 | if (lib_arch == target.cpu.arch) { | |
| 44 | if (lib_arch == cpu_arch) { | |
| 45 | 45 | // We have found a matching architecture! |
| 46 | 46 | return fat_arch.offset; |
| 47 | 47 | } |
| 48 | 48 | } else { |
| 49 | log.err("Could not find matching cpu architecture in fat library: expected {s}", .{target.cpu.arch}); | |
| 49 | log.err("Could not find matching cpu architecture in fat library: expected {s}", .{cpu_arch}); | |
| 50 | 50 | return error.MismatchedCpuArchitecture; |
| 51 | 51 | } |
| 52 | 52 | } |