authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-25 18:26:06+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-25 22:46:43-07:00
log20ea44ef107828d76692e610e1ca62ee231fb4a9
tree3cdd9e3816f57c9b5e2469af238c69e2520e68cb
parentcff5d9c805aa3433cc2562c3cb29bd3201817214

macho: fix memory leak and refactor Target usage


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,7 +1415,7 @@ fn parseObject(self: *MachO, path: []const u8) !bool {
1415 .mtime = mtime,1415 .mtime = mtime,
1416 };1416 };
14171417
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 error.EndOfStream, error.NotObject => {1419 error.EndOfStream, error.NotObject => {
1420 object.deinit(self.base.allocator);1420 object.deinit(self.base.allocator);
1421 return false;1421 return false;
...@@ -1443,7 +1443,7 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {...@@ -1443,7 +1443,7 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
1443 .file = file,1443 .file = file,
1444 };1444 };
14451445
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 error.EndOfStream, error.NotArchive => {1447 error.EndOfStream, error.NotArchive => {
1448 archive.deinit(self.base.allocator);1448 archive.deinit(self.base.allocator);
1449 return false;1449 return false;
...@@ -1463,7 +1463,11 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {...@@ -1463,7 +1463,11 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
1463 }1463 }
1464 for (offsets.keys()) |off| {1464 for (offsets.keys()) |off| {
1465 const object = try self.objects.addOne(self.base.allocator);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 } else {1472 } else {
1469 try self.archives.append(self.base.allocator, archive);1473 try self.archives.append(self.base.allocator, archive);
...@@ -1511,7 +1515,7 @@ pub fn parseDylib(...@@ -1511,7 +1515,7 @@ pub fn parseDylib(
15111515
1512 dylib.parse(1516 dylib.parse(
1513 self.base.allocator,1517 self.base.allocator,
1514 self.base.options.target,1518 self.base.options.target.cpu.arch,
1515 dylib_id,1519 dylib_id,
1516 dependent_libs,1520 dependent_libs,
1517 ) catch |err| switch (err) {1521 ) catch |err| switch (err) {
...@@ -3126,7 +3130,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {...@@ -3126,7 +3130,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
31263130
3127 const object_id = @intCast(u16, self.objects.items.len);3131 const object_id = @intCast(u16, self.objects.items.len);
3128 const object = try self.objects.addOne(self.base.allocator);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 try self.resolveSymbolsInObject(object, object_id);3138 try self.resolveSymbolsInObject(object, object_id);
31313139
3132 continue :loop;3140 continue :loop;
src/link/MachO/Archive.zig+4-4
...@@ -103,9 +103,9 @@ pub fn deinit(self: *Archive, allocator: Allocator) void {...@@ -103,9 +103,9 @@ pub fn deinit(self: *Archive, allocator: Allocator) void {
103 allocator.free(self.name);103 allocator.free(self.name);
104}104}
105105
106pub fn parse(self: *Archive, allocator: Allocator, target: std.Target) !void {106pub fn parse(self: *Archive, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void {
107 const reader = self.file.reader();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 try self.file.seekTo(self.library_offset);109 try self.file.seekTo(self.library_offset);
110110
111 const magic = try reader.readBytesNoEof(SARMAG);111 const magic = try reader.readBytesNoEof(SARMAG);
...@@ -187,7 +187,7 @@ fn parseTableOfContents(self: *Archive, allocator: Allocator, reader: anytype) !...@@ -187,7 +187,7 @@ fn parseTableOfContents(self: *Archive, allocator: Allocator, reader: anytype) !
187 }187 }
188}188}
189189
190pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offset: u32) !Object {190pub fn parseObject(self: Archive, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch, offset: u32) !Object {
191 const reader = self.file.reader();191 const reader = self.file.reader();
192 try reader.context.seekTo(offset + self.library_offset);192 try reader.context.seekTo(offset + self.library_offset);
193193
...@@ -216,7 +216,7 @@ pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offs...@@ -216,7 +216,7 @@ pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offs
216 .mtime = try self.header.?.date(),216 .mtime = try self.header.?.date(),
217 };217 };
218218
219 try object.parse(allocator, target);219 try object.parse(allocator, cpu_arch);
220 try reader.context.seekTo(0);220 try reader.context.seekTo(0);
221221
222 return object;222 return object;
src/link/MachO/Dylib.zig+25-18
...@@ -11,6 +11,7 @@ const mem = std.mem;...@@ -11,6 +11,7 @@ const mem = std.mem;
11const fat = @import("fat.zig");11const fat = @import("fat.zig");
1212
13const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
14const CrossTarget = std.zig.CrossTarget;
14const LibStub = @import("../tapi.zig").LibStub;15const LibStub = @import("../tapi.zig").LibStub;
15const MachO = @import("../MachO.zig");16const MachO = @import("../MachO.zig");
1617
...@@ -145,13 +146,13 @@ pub fn deinit(self: *Dylib, allocator: Allocator) void {...@@ -145,13 +146,13 @@ pub fn deinit(self: *Dylib, allocator: Allocator) void {
145pub fn parse(146pub fn parse(
146 self: *Dylib,147 self: *Dylib,
147 allocator: Allocator,148 allocator: Allocator,
148 target: std.Target,149 cpu_arch: std.Target.Cpu.Arch,
149 dylib_id: u16,150 dylib_id: u16,
150 dependent_libs: anytype,151 dependent_libs: anytype,
151) !void {152) !void {
152 log.debug("parsing shared library '{s}'", .{self.name});153 log.debug("parsing shared library '{s}'", .{self.name});
153154
154 self.library_offset = try fat.getLibraryOffset(self.file.reader(), target);155 self.library_offset = try fat.getLibraryOffset(self.file.reader(), cpu_arch);
155156
156 try self.file.seekTo(self.library_offset);157 try self.file.seekTo(self.library_offset);
157158
...@@ -165,8 +166,8 @@ pub fn parse(...@@ -165,8 +166,8 @@ pub fn parse(
165166
166 const this_arch: std.Target.Cpu.Arch = try fat.decodeArch(self.header.?.cputype, true);167 const this_arch: std.Target.Cpu.Arch = try fat.decodeArch(self.header.?.cputype, true);
167168
168 if (this_arch != target.cpu.arch) {169 if (this_arch != cpu_arch) {
169 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch });170 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ cpu_arch, this_arch });
170 return error.MismatchedCpuArchitecture;171 return error.MismatchedCpuArchitecture;
171 }172 }
172173
...@@ -278,23 +279,24 @@ fn addSymbol(self: *Dylib, allocator: Allocator, sym_name: []const u8) !void {...@@ -278,23 +279,24 @@ fn addSymbol(self: *Dylib, allocator: Allocator, sym_name: []const u8) !void {
278279
279const TargetMatcher = struct {280const TargetMatcher = struct {
280 allocator: Allocator,281 allocator: Allocator,
281 target: std.Target,282 target: CrossTarget,
282 target_strings: std.ArrayListUnmanaged([]const u8) = .{},283 target_strings: std.ArrayListUnmanaged([]const u8) = .{},
283284
284 fn init(allocator: Allocator, target: std.Target) !TargetMatcher {285 fn init(allocator: Allocator, target: CrossTarget) !TargetMatcher {
285 var self = TargetMatcher{286 var self = TargetMatcher{
286 .allocator = allocator,287 .allocator = allocator,
287 .target = target,288 .target = target,
288 };289 };
289 try self.target_strings.append(allocator, try targetToAppleString(allocator, target));290 try self.target_strings.append(allocator, try targetToAppleString(allocator, target));
290291
291 if (target.abi == .simulator) {292 const abi = target.abi orelse .none;
293 if (abi == .simulator) {
292 // For Apple simulator targets, linking gets tricky as we need to link against the simulator294 // For Apple simulator targets, linking gets tricky as we need to link against the simulator
293 // hosts dylibs too.295 // hosts dylibs too.
294 const host_target = try targetToAppleString(allocator, (std.zig.CrossTarget{296 const host_target = try targetToAppleString(allocator, .{
295 .cpu_arch = target.cpu.arch,297 .cpu_arch = target.cpu_arch.?,
296 .os_tag = .macos,298 .os_tag = .macos,
297 }).toTarget());299 });
298 try self.target_strings.append(allocator, host_target);300 try self.target_strings.append(allocator, host_target);
299 }301 }
300302
...@@ -308,23 +310,24 @@ const TargetMatcher = struct {...@@ -308,23 +310,24 @@ const TargetMatcher = struct {
308 self.target_strings.deinit(self.allocator);310 self.target_strings.deinit(self.allocator);
309 }311 }
310312
311 fn targetToAppleString(allocator: Allocator, target: std.Target) ![]const u8 {313 fn targetToAppleString(allocator: Allocator, target: CrossTarget) ![]const u8 {
312 const arch = switch (target.cpu.arch) {314 const cpu_arch = switch (target.cpu_arch.?) {
313 .aarch64 => "arm64",315 .aarch64 => "arm64",
314 .x86_64 => "x86_64",316 .x86_64 => "x86_64",
315 else => unreachable,317 else => unreachable,
316 };318 };
317 const os = @tagName(target.os.tag);319 const os_tag = @tagName(target.os_tag.?);
318 const abi: ?[]const u8 = switch (target.abi) {320 const target_abi = target.abi orelse .none;
321 const abi: ?[]const u8 = switch (target_abi) {
319 .none => null,322 .none => null,
320 .simulator => "simulator",323 .simulator => "simulator",
321 .macabi => "maccatalyst",324 .macabi => "maccatalyst",
322 else => unreachable,325 else => unreachable,
323 };326 };
324 if (abi) |x| {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 }
329332
330 fn hasValue(stack: []const []const u8, needle: []const u8) bool {333 fn hasValue(stack: []const []const u8, needle: []const u8) bool {
...@@ -342,7 +345,7 @@ const TargetMatcher = struct {...@@ -342,7 +345,7 @@ const TargetMatcher = struct {
342 }345 }
343346
344 fn matchesArch(self: TargetMatcher, archs: []const []const u8) bool {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};
348351
...@@ -376,7 +379,11 @@ pub fn parseFromStub(...@@ -376,7 +379,11 @@ pub fn parseFromStub(
376379
377 log.debug(" (install_name '{s}')", .{umbrella_lib.installName()});380 log.debug(" (install_name '{s}')", .{umbrella_lib.installName()});
378381
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 defer matcher.deinit();387 defer matcher.deinit();
381388
382 for (lib_stub.inner) |elem, stub_index| {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,6 +66,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
66 }66 }
67 self.load_commands.deinit(gpa);67 self.load_commands.deinit(gpa);
68 gpa.free(self.contents);68 gpa.free(self.contents);
69 self.symtab.deinit(gpa);
69 self.sections_as_symbols.deinit(gpa);70 self.sections_as_symbols.deinit(gpa);
70 self.atom_by_index_table.deinit(gpa);71 self.atom_by_index_table.deinit(gpa);
7172
...@@ -78,7 +79,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {...@@ -78,7 +79,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
78 gpa.free(self.name);79 gpa.free(self.name);
79}80}
8081
81pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {82pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void {
82 const file_stat = try self.file.stat();83 const file_stat = try self.file.stat();
83 const file_size = math.cast(usize, file_stat.size) orelse return error.Overflow;84 const file_size = math.cast(usize, file_stat.size) orelse return error.Overflow;
84 self.contents = try self.file.readToEndAlloc(allocator, file_size);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,8 +109,8 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {
108 return error.UnsupportedCpuArchitecture;109 return error.UnsupportedCpuArchitecture;
109 },110 },
110 };111 };
111 if (this_arch != target.cpu.arch) {112 if (this_arch != cpu_arch) {
112 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ target.cpu.arch, this_arch });113 log.err("mismatched cpu architecture: expected {s}, found {s}", .{ cpu_arch, this_arch });
113 return error.MismatchedCpuArchitecture;114 return error.MismatchedCpuArchitecture;
114 }115 }
115116
...@@ -351,7 +352,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)...@@ -351,7 +352,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
351 macho_file.getSection(match).sectName(),352 macho_file.getSection(match).sectName(),
352 });353 });
353354
354 const arch = macho_file.base.options.target.cpu.arch;355 const cpu_arch = macho_file.base.options.target.cpu.arch;
355 const is_zerofill = blk: {356 const is_zerofill = blk: {
356 const section_type = sect.type_();357 const section_type = sect.type_();
357 break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL;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,7 +467,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
466 sect,467 sect,
467 );468 );
468469
469 if (arch == .x86_64 and addr == sect.addr) {470 if (cpu_arch == .x86_64 and addr == sect.addr) {
470 // In x86_64 relocs, it can so happen that the compiler refers to the same471 // In x86_64 relocs, it can so happen that the compiler refers to the same
471 // atom by both the actual assigned symbol and the start of the section. In this472 // atom by both the actual assigned symbol and the start of the section. In this
472 // case, we need to link the two together so add an alias.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,7 +6,7 @@ const mem = std.mem;
6const native_endian = builtin.target.cpu.arch.endian();6const native_endian = builtin.target.cpu.arch.endian();
77
8pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Target.Cpu.Arch {8pub 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 macho.CPU_TYPE_ARM64 => .aarch64,10 macho.CPU_TYPE_ARM64 => .aarch64,
11 macho.CPU_TYPE_X86_64 => .x86_64,11 macho.CPU_TYPE_X86_64 => .x86_64,
12 else => {12 else => {
...@@ -16,7 +16,7 @@ pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Targe...@@ -16,7 +16,7 @@ pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Targe
16 return error.UnsupportedCpuArchitecture;16 return error.UnsupportedCpuArchitecture;
17 },17 },
18 };18 };
19 return arch;19 return cpu_arch;
20}20}
2121
22fn readFatStruct(reader: anytype, comptime T: type) !T {22fn readFatStruct(reader: anytype, comptime T: type) !T {
...@@ -29,7 +29,7 @@ fn readFatStruct(reader: anytype, comptime T: type) !T {...@@ -29,7 +29,7 @@ fn readFatStruct(reader: anytype, comptime T: type) !T {
29 return res;29 return res;
30}30}
3131
32pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {32pub fn getLibraryOffset(reader: anytype, cpu_arch: std.Target.Cpu.Arch) !u64 {
33 const fat_header = try readFatStruct(reader, macho.fat_header);33 const fat_header = try readFatStruct(reader, macho.fat_header);
34 if (fat_header.magic != macho.FAT_MAGIC) return 0;34 if (fat_header.magic != macho.FAT_MAGIC) return 0;
3535
...@@ -41,12 +41,12 @@ pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {...@@ -41,12 +41,12 @@ pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {
41 const lib_arch = decodeArch(fat_arch.cputype, false) catch |err| switch (err) {41 const lib_arch = decodeArch(fat_arch.cputype, false) catch |err| switch (err) {
42 error.UnsupportedCpuArchitecture => continue,42 error.UnsupportedCpuArchitecture => continue,
43 };43 };
44 if (lib_arch == target.cpu.arch) {44 if (lib_arch == cpu_arch) {
45 // We have found a matching architecture!45 // We have found a matching architecture!
46 return fat_arch.offset;46 return fat_arch.offset;
47 }47 }
48 } else {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 return error.MismatchedCpuArchitecture;50 return error.MismatchedCpuArchitecture;
51 }51 }
52}52}