diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3ebfd6132b..7ef0bd558c 100644 --- a/src/link/Elf.zig +++ b/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 }; }