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 {
14151415 .mtime = mtime,
14161416 };
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) {
14191419 error.EndOfStream, error.NotObject => {
14201420 object.deinit(self.base.allocator);
14211421 return false;
......@@ -1443,7 +1443,7 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
14431443 .file = file,
14441444 };
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) {
14471447 error.EndOfStream, error.NotArchive => {
14481448 archive.deinit(self.base.allocator);
14491449 return false;
......@@ -1463,7 +1463,11 @@ fn parseArchive(self: *MachO, path: []const u8, force_load: bool) !bool {
14631463 }
14641464 for (offsets.keys()) |off| {
14651465 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 );
14671471 }
14681472 } else {
14691473 try self.archives.append(self.base.allocator, archive);
......@@ -1511,7 +1515,7 @@ pub fn parseDylib(
15111515
15121516 dylib.parse(
15131517 self.base.allocator,
1514 self.base.options.target,
1518 self.base.options.target.cpu.arch,
15151519 dylib_id,
15161520 dependent_libs,
15171521 ) catch |err| switch (err) {
......@@ -3126,7 +3130,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void {
31263130
31273131 const object_id = @intCast(u16, self.objects.items.len);
31283132 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 );
31303138 try self.resolveSymbolsInObject(object, object_id);
31313139
31323140 continue :loop;
src/link/MachO/Archive.zig+4-4
......@@ -103,9 +103,9 @@ pub fn deinit(self: *Archive, allocator: Allocator) void {
103103 allocator.free(self.name);
104104}
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 {
107107 const reader = self.file.reader();
108 self.library_offset = try fat.getLibraryOffset(reader, target);
108 self.library_offset = try fat.getLibraryOffset(reader, cpu_arch);
109109 try self.file.seekTo(self.library_offset);
110110
111111 const magic = try reader.readBytesNoEof(SARMAG);
......@@ -187,7 +187,7 @@ fn parseTableOfContents(self: *Archive, allocator: Allocator, reader: anytype) !
187187 }
188188}
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 {
191191 const reader = self.file.reader();
192192 try reader.context.seekTo(offset + self.library_offset);
193193
......@@ -216,7 +216,7 @@ pub fn parseObject(self: Archive, allocator: Allocator, target: std.Target, offs
216216 .mtime = try self.header.?.date(),
217217 };
218218
219 try object.parse(allocator, target);
219 try object.parse(allocator, cpu_arch);
220220 try reader.context.seekTo(0);
221221
222222 return object;
src/link/MachO/Dylib.zig+25-18
......@@ -11,6 +11,7 @@ const mem = std.mem;
1111const fat = @import("fat.zig");
1212
1313const Allocator = mem.Allocator;
14const CrossTarget = std.zig.CrossTarget;
1415const LibStub = @import("../tapi.zig").LibStub;
1516const MachO = @import("../MachO.zig");
1617
......@@ -145,13 +146,13 @@ pub fn deinit(self: *Dylib, allocator: Allocator) void {
145146pub fn parse(
146147 self: *Dylib,
147148 allocator: Allocator,
148 target: std.Target,
149 cpu_arch: std.Target.Cpu.Arch,
149150 dylib_id: u16,
150151 dependent_libs: anytype,
151152) !void {
152153 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
156157 try self.file.seekTo(self.library_offset);
157158
......@@ -165,8 +166,8 @@ pub fn parse(
165166
166167 const this_arch: std.Target.Cpu.Arch = try fat.decodeArch(self.header.?.cputype, true);
167168
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 });
170171 return error.MismatchedCpuArchitecture;
171172 }
172173
......@@ -278,23 +279,24 @@ fn addSymbol(self: *Dylib, allocator: Allocator, sym_name: []const u8) !void {
278279
279280const TargetMatcher = struct {
280281 allocator: Allocator,
281 target: std.Target,
282 target: CrossTarget,
282283 target_strings: std.ArrayListUnmanaged([]const u8) = .{},
283284
284 fn init(allocator: Allocator, target: std.Target) !TargetMatcher {
285 fn init(allocator: Allocator, target: CrossTarget) !TargetMatcher {
285286 var self = TargetMatcher{
286287 .allocator = allocator,
287288 .target = target,
288289 };
289290 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) {
292294 // For Apple simulator targets, linking gets tricky as we need to link against the simulator
293295 // 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.?,
296298 .os_tag = .macos,
297 }).toTarget());
299 });
298300 try self.target_strings.append(allocator, host_target);
299301 }
300302
......@@ -308,23 +310,24 @@ const TargetMatcher = struct {
308310 self.target_strings.deinit(self.allocator);
309311 }
310312
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.?) {
313315 .aarch64 => "arm64",
314316 .x86_64 => "x86_64",
315317 else => unreachable,
316318 };
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) {
319322 .none => null,
320323 .simulator => "simulator",
321324 .macabi => "maccatalyst",
322325 else => unreachable,
323326 };
324327 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 });
326329 }
327 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, os });
330 return std.fmt.allocPrint(allocator, "{s}-{s}", .{ cpu_arch, os_tag });
328331 }
329332
330333 fn hasValue(stack: []const []const u8, needle: []const u8) bool {
......@@ -342,7 +345,7 @@ const TargetMatcher = struct {
342345 }
343346
344347 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.?));
346349 }
347350};
348351
......@@ -376,7 +379,11 @@ pub fn parseFromStub(
376379
377380 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 });
380387 defer matcher.deinit();
381388
382389 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 {
6666 }
6767 self.load_commands.deinit(gpa);
6868 gpa.free(self.contents);
69 self.symtab.deinit(gpa);
6970 self.sections_as_symbols.deinit(gpa);
7071 self.atom_by_index_table.deinit(gpa);
7172
......@@ -78,7 +79,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
7879 gpa.free(self.name);
7980}
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 {
8283 const file_stat = try self.file.stat();
8384 const file_size = math.cast(usize, file_stat.size) orelse return error.Overflow;
8485 self.contents = try self.file.readToEndAlloc(allocator, file_size);
......@@ -108,8 +109,8 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void {
108109 return error.UnsupportedCpuArchitecture;
109110 },
110111 };
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 });
113114 return error.MismatchedCpuArchitecture;
114115 }
115116
......@@ -351,7 +352,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
351352 macho_file.getSection(match).sectName(),
352353 });
353354
354 const arch = macho_file.base.options.target.cpu.arch;
355 const cpu_arch = macho_file.base.options.target.cpu.arch;
355356 const is_zerofill = blk: {
356357 const section_type = sect.type_();
357358 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)
466467 sect,
467468 );
468469
469 if (arch == .x86_64 and addr == sect.addr) {
470 if (cpu_arch == .x86_64 and addr == sect.addr) {
470471 // In x86_64 relocs, it can so happen that the compiler refers to the same
471472 // atom by both the actual assigned symbol and the start of the section. In this
472473 // 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;
66const native_endian = builtin.target.cpu.arch.endian();
77
88pub 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) {
1010 macho.CPU_TYPE_ARM64 => .aarch64,
1111 macho.CPU_TYPE_X86_64 => .x86_64,
1212 else => {
......@@ -16,7 +16,7 @@ pub fn decodeArch(cputype: macho.cpu_type_t, comptime logError: bool) !std.Targe
1616 return error.UnsupportedCpuArchitecture;
1717 },
1818 };
19 return arch;
19 return cpu_arch;
2020}
2121
2222fn readFatStruct(reader: anytype, comptime T: type) !T {
......@@ -29,7 +29,7 @@ fn readFatStruct(reader: anytype, comptime T: type) !T {
2929 return res;
3030}
3131
32pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {
32pub fn getLibraryOffset(reader: anytype, cpu_arch: std.Target.Cpu.Arch) !u64 {
3333 const fat_header = try readFatStruct(reader, macho.fat_header);
3434 if (fat_header.magic != macho.FAT_MAGIC) return 0;
3535
......@@ -41,12 +41,12 @@ pub fn getLibraryOffset(reader: anytype, target: std.Target) !u64 {
4141 const lib_arch = decodeArch(fat_arch.cputype, false) catch |err| switch (err) {
4242 error.UnsupportedCpuArchitecture => continue,
4343 };
44 if (lib_arch == target.cpu.arch) {
44 if (lib_arch == cpu_arch) {
4545 // We have found a matching architecture!
4646 return fat_arch.offset;
4747 }
4848 } 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});
5050 return error.MismatchedCpuArchitecture;
5151 }
5252}