Commit 3df58a9583

Jakub Konka <kubkon@jakubkonka.com>
2023-09-11 16:32:58
elf: add basic error reporting for positional parsing
1 parent 65b9597
Changed files (1)
src
link
src/link/Elf.zig
@@ -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 };
 }