elf: add basic error reporting for positional parsing

This commit is contained in:
Jakub Konka
2023-09-11 16:32:58 +02:00
parent 65b9597c07
commit 3df58a9583

View File

@@ -980,6 +980,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
};
_ = compiler_rt_path;
// Parse input files
for (self.base.options.objects) |obj| {
const in_file = try std.fs.cwd().openFile(obj.path, .{});
defer in_file.close();
var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
self.parsePositional(in_file, obj.path, obj.must_link, &parse_ctx) catch |err|
try self.handleAndReportParseError(obj.path, err, &parse_ctx);
}
if (self.lazy_syms.getPtr(.none)) |metadata| {
// Most lazy symbols can be updated on first use, but
// anyerror needs to wait for everything to be flushed.
@@ -1246,6 +1256,36 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
assert(!self.got.dirty);
}
const ParseError = error{
UnknownFileType,
InvalidCpuArch,
OutOfMemory,
Overflow,
InputOutput,
EndOfStream,
FileSystem,
NotSupported,
} || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError;
fn parsePositional(
self: *Elf,
in_file: std.fs.File,
path: []const u8,
must_link: bool,
ctx: *ParseErrorCtx,
) ParseError!void {
const tracy = trace(@src());
defer tracy.end();
_ = self;
_ = in_file;
_ = path;
_ = must_link;
_ = ctx;
return error.UnknownFileType;
}
fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -3451,6 +3491,49 @@ fn reportUndefined(self: *Elf) !void {
}
}
const ParseErrorCtx = struct {
detected_cpu_arch: std.Target.Cpu.Arch,
};
fn handleAndReportParseError(
self: *Elf,
path: []const u8,
err: ParseError,
ctx: *const ParseErrorCtx,
) error{OutOfMemory}!void {
const cpu_arch = self.base.options.target.cpu.arch;
switch (err) {
error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),
error.InvalidCpuArch => try self.reportParseError(
path,
"invalid cpu architecture: expected '{s}', but found '{s}'",
.{ @tagName(cpu_arch), @tagName(ctx.detected_cpu_arch) },
),
else => |e| try self.reportParseError(
path,
"unexpected error: parsing object failed with error {s}",
.{@errorName(e)},
),
}
}
fn reportParseError(
self: *Elf,
path: []const u8,
comptime format: []const u8,
args: anytype,
) error{OutOfMemory}!void {
const gpa = self.base.allocator;
try self.misc_errors.ensureUnusedCapacity(gpa, 1);
var notes = try gpa.alloc(link.File.ErrorMsg, 1);
errdefer gpa.free(notes);
notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) };
self.misc_errors.appendAssumeCapacity(.{
.msg = try std.fmt.allocPrint(gpa, format, args),
.notes = notes,
});
}
fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {
return .{ .data = self };
}