macho: create an explicit error set for parse functions

This commit is contained in:
Jakub Konka 2023-08-28 17:34:10 +02:00
parent 1820aed786
commit 2473ccc335
4 changed files with 43 additions and 23 deletions

View File

@ -419,6 +419,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
&dependent_libs,
&parse_error_ctx,
) catch |err| switch (err) {
error.DylibAlreadyExists => {},
error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),
error.MissingArchFatLib => try self.reportParseError(
path,
@ -723,6 +724,22 @@ fn resolveLib(
return full_path;
}
const ParseError = error{
UnknownFileType,
MissingArchFatLib,
InvalidArch,
DylibAlreadyExists,
IncompatibleDylibVersion,
OutOfMemory,
Overflow,
InputOutput,
MalformedArchive,
NotLibStub,
EndOfStream,
FileSystem,
NotSupported,
} || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError;
pub fn parsePositional(
self: *MachO,
file: std.fs.File,
@ -730,7 +747,7 @@ pub fn parsePositional(
must_link: bool,
dependent_libs: anytype,
error_ctx: anytype,
) !void {
) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
@ -750,7 +767,7 @@ fn parseObject(
file: std.fs.File,
path: []const u8,
error_ctx: anytype,
) !void {
) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
@ -793,7 +810,7 @@ pub fn parseLibrary(
must_link: bool,
dependent_libs: anytype,
error_ctx: anytype,
) !void {
) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
@ -829,7 +846,7 @@ pub fn parseLibrary(
}
}
pub fn parseFatLibrary(self: *MachO, file: std.fs.File, cpu_arch: std.Target.Cpu.Arch) !u64 {
pub fn parseFatLibrary(self: *MachO, file: std.fs.File, cpu_arch: std.Target.Cpu.Arch) ParseError!u64 {
_ = self;
var buffer: [2]fat.Arch = undefined;
const fat_archs = try fat.parseArchs(file, &buffer);
@ -846,7 +863,7 @@ fn parseArchive(
must_link: bool,
cpu_arch: std.Target.Cpu.Arch,
error_ctx: anytype,
) !void {
) ParseError!void {
const gpa = self.base.allocator;
// We take ownership of the file so that we can store it for the duration of symbol resolution.
@ -915,7 +932,7 @@ fn parseDylib(
dependent_libs: anytype,
dylib_options: DylibOpts,
error_ctx: anytype,
) !void {
) ParseError!void {
const gpa = self.base.allocator;
const self_cpu_arch = self.base.options.target.cpu.arch;
@ -948,13 +965,10 @@ fn parseDylib(
// TODO verify platform
self.addDylib(dylib, .{
try self.addDylib(dylib, .{
.needed = dylib_options.needed,
.weak = dylib_options.weak,
}) catch |err| switch (err) {
error.DylibAlreadyExists => dylib.deinit(gpa),
else => |e| return e,
};
});
}
fn parseLibStub(
@ -963,7 +977,7 @@ fn parseLibStub(
path: []const u8,
dependent_libs: anytype,
dylib_options: DylibOpts,
) !void {
) ParseError!void {
const gpa = self.base.allocator;
var lib_stub = try LibStub.loadFromFile(gpa, file);
defer lib_stub.deinit();
@ -984,16 +998,13 @@ fn parseLibStub(
path,
);
self.addDylib(dylib, .{
try self.addDylib(dylib, .{
.needed = dylib_options.needed,
.weak = dylib_options.weak,
}) catch |err| switch (err) {
error.DylibAlreadyExists => dylib.deinit(gpa),
else => |e| return e,
};
});
}
fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts) !void {
fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts) ParseError!void {
if (dylib_options.id) |id| {
if (dylib.id.?.current_version < id.compatibility_version) {
// TODO convert into an error
@ -1022,7 +1033,7 @@ fn addDylib(self: *MachO, dylib: Dylib, dylib_options: DylibOpts) !void {
}
}
pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anytype) !void {
pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype, error_ctx: anytype) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
@ -5145,6 +5156,7 @@ const link = @import("../link.zig");
const llvm_backend = @import("../codegen/llvm.zig");
const load_commands = @import("MachO/load_commands.zig");
const stubs = @import("MachO/stubs.zig");
const tapi = @import("tapi.zig");
const target_util = @import("../target.zig");
const thunks = @import("MachO/thunks.zig");
const trace = @import("../tracy.zig").trace;
@ -5162,7 +5174,7 @@ const DwarfInfo = @import("MachO/DwarfInfo.zig");
const Dylib = @import("MachO/Dylib.zig");
const File = link.File;
const Object = @import("MachO/Object.zig");
const LibStub = @import("tapi.zig").LibStub;
const LibStub = tapi.LibStub;
const Liveness = @import("../Liveness.zig");
const LlvmObject = @import("../codegen/llvm.zig").Object;
const Md5 = std.crypto.hash.Md5;

View File

@ -320,7 +320,7 @@ pub fn parseFromStub(
dependent_libs: anytype,
name: []const u8,
) !void {
if (lib_stub.inner.len == 0) return error.EmptyStubFile;
if (lib_stub.inner.len == 0) return error.NotLibStub;
log.debug("parsing shared library from stub '{s}'", .{name});

View File

@ -361,6 +361,7 @@ pub fn linkWithZld(
&dependent_libs,
&parse_error_ctx,
) catch |err| switch (err) {
error.DylibAlreadyExists => {},
error.UnknownFileType => try macho_file.reportParseError(obj.path, "unknown file type", .{}),
error.MissingArchFatLib => try macho_file.reportParseError(
obj.path,
@ -392,6 +393,7 @@ pub fn linkWithZld(
&dependent_libs,
&parse_error_ctx,
) catch |err| switch (err) {
error.DylibAlreadyExists => {},
error.UnknownFileType => try macho_file.reportParseError(path, "unknown file type", .{}),
error.MissingArchFatLib => try macho_file.reportParseError(
path,

View File

@ -2,9 +2,10 @@ const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const log = std.log.scoped(.tapi);
const yaml = @import("tapi/yaml.zig");
const Allocator = mem.Allocator;
const Yaml = @import("tapi/yaml.zig").Yaml;
const Yaml = yaml.Yaml;
const VersionField = union(enum) {
string: []const u8,
@ -102,6 +103,11 @@ pub const Tbd = union(enum) {
}
};
pub const TapiError = error{
NotLibStub,
FileTooBig,
} || yaml.YamlError || std.fs.File.ReadError;
pub const LibStub = struct {
/// Underlying memory for stub's contents.
yaml: Yaml,
@ -109,7 +115,7 @@ pub const LibStub = struct {
/// Typed contents of the tbd file.
inner: []Tbd,
pub fn loadFromFile(allocator: Allocator, file: fs.File) !LibStub {
pub fn loadFromFile(allocator: Allocator, file: fs.File) TapiError!LibStub {
const source = try file.readToEndAlloc(allocator, std.math.maxInt(u32));
defer allocator.free(source);