Skip to content

Commit 1650b29

Browse files
committed
macho: improve error reporting for CPU inferrence errors
1 parent feba7b0 commit 1650b29

File tree

2 files changed

+67
-34
lines changed

2 files changed

+67
-34
lines changed

src/MachO.zig

+66-34
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,35 @@ pub fn flush(self: *MachO) !void {
247247
}
248248

249249
if (self.options.cpu_arch == null) {
250-
try self.inferCpuArchAndPlatform(resolved_objects.items);
250+
var has_parse_error = false;
251+
var platforms = std.ArrayList(struct { std.Target.Cpu.Arch, ?Options.Platform }).init(self.base.allocator);
252+
defer platforms.deinit();
253+
try platforms.ensureUnusedCapacity(resolved_objects.items.len);
254+
255+
for (resolved_objects.items) |obj| {
256+
self.inferCpuArchAndPlatform(obj, &platforms) catch |err| {
257+
has_parse_error = true;
258+
switch (err) {
259+
error.UnhandledCpuArch => {}, // already reported
260+
else => |e| {
261+
self.base.fatal("{s}: unexpected error occurred while parsing input file: {s}", .{
262+
obj.path, @errorName(e),
263+
});
264+
return e;
265+
},
266+
}
267+
};
268+
}
269+
if (has_parse_error) return error.ParseFailed;
270+
if (platforms.items.len == 0) {
271+
self.base.fatal("could not infer CPU architecture", .{});
272+
return error.InferCpuFailed;
273+
}
274+
275+
self.options.cpu_arch = platforms.items[0][0];
276+
self.options.platform = for (platforms.items) |platform| {
277+
if (platform[1]) |p| break p;
278+
} else null;
251279
}
252280

253281
if (self.options.platform == null) {
@@ -498,44 +526,48 @@ fn resolveFramework(
498526
}
499527
}
500528

501-
fn inferCpuArchAndPlatform(self: *MachO, objs: []const LinkObject) !void {
529+
fn inferCpuArchAndPlatform(self: *MachO, obj: LinkObject, platforms: anytype) !void {
502530
const gpa = self.base.allocator;
503-
for (objs) |obj| {
504-
const file = try std.fs.cwd().openFile(obj.path, .{});
505-
defer file.close();
506531

507-
const header = file.reader().readStruct(macho.mach_header_64) catch continue;
508-
if (header.filetype != macho.MH_OBJECT) continue;
532+
const file = try std.fs.cwd().openFile(obj.path, .{});
533+
defer file.close();
509534

510-
const cpu_arch: std.Target.Cpu.Arch = switch (header.cputype) {
511-
macho.CPU_TYPE_ARM64 => .aarch64,
512-
macho.CPU_TYPE_X86_64 => .x86_64,
513-
else => @panic("unhandled CPU arch"), // TODO error
514-
};
535+
const header = file.reader().readStruct(macho.mach_header_64) catch return;
536+
if (header.filetype != macho.MH_OBJECT) return;
537+
538+
const cpu_arch: std.Target.Cpu.Arch = switch (header.cputype) {
539+
macho.CPU_TYPE_ARM64 => .aarch64,
540+
macho.CPU_TYPE_X86_64 => .x86_64,
541+
else => {
542+
self.base.fatal("{s}: unhandled CPU architecture: {d}", .{
543+
obj.path,
544+
header.cputype,
545+
});
546+
return error.UnhandledCpuArch;
547+
},
548+
};
515549

516-
const cmds_buffer = try gpa.alloc(u8, header.sizeofcmds);
517-
defer gpa.free(cmds_buffer);
518-
const amt = file.reader().readAll(cmds_buffer) catch continue;
519-
if (amt != header.sizeofcmds) continue;
550+
const out = platforms.addOneAssumeCapacity();
551+
out.* = .{ cpu_arch, null };
520552

521-
var it = macho.LoadCommandIterator{
522-
.ncmds = header.ncmds,
523-
.buffer = cmds_buffer,
524-
};
525-
const platform: Options.Platform = while (it.next()) |cmd| switch (cmd.cmd()) {
526-
.BUILD_VERSION,
527-
.VERSION_MIN_MACOSX,
528-
.VERSION_MIN_IPHONEOS,
529-
.VERSION_MIN_TVOS,
530-
.VERSION_MIN_WATCHOS,
531-
=> break Options.Platform.fromLoadCommand(cmd),
532-
else => {},
533-
} else continue;
534-
535-
self.options.cpu_arch = cpu_arch;
536-
self.options.platform = platform;
537-
break;
538-
}
553+
const cmds_buffer = try gpa.alloc(u8, header.sizeofcmds);
554+
defer gpa.free(cmds_buffer);
555+
const amt = file.reader().readAll(cmds_buffer) catch return;
556+
if (amt != header.sizeofcmds) return;
557+
558+
var it = macho.LoadCommandIterator{
559+
.ncmds = header.ncmds,
560+
.buffer = cmds_buffer,
561+
};
562+
out[1] = while (it.next()) |cmd| switch (cmd.cmd()) {
563+
.BUILD_VERSION,
564+
.VERSION_MIN_MACOSX,
565+
.VERSION_MIN_IPHONEOS,
566+
.VERSION_MIN_TVOS,
567+
.VERSION_MIN_WATCHOS,
568+
=> break Options.Platform.fromLoadCommand(cmd),
569+
else => {},
570+
} else null;
539571
}
540572

541573
fn validateCpuArch(self: *MachO, index: File.Index) void {

src/main.zig

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ pub fn main() !void {
106106

107107
const zld = try Zld.openPath(gpa, tag, opts, &thread_pool);
108108
zld.flush() catch |err| switch (err) {
109+
error.InferCpuFailed,
109110
error.ParseFailed,
110111
error.MultipleSymbolDefinition,
111112
error.UndefinedSymbols,

0 commit comments

Comments
 (0)