| ... | ... | @@ -980,6 +980,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 980 | 980 | }; |
| 981 | 981 | _ = compiler_rt_path; |
| 982 | 982 | |
| 983 | // Parse input files |
| 984 | for (self.base.options.objects) |obj| { |
| 985 | const in_file = try std.fs.cwd().openFile(obj.path, .{}); |
| 986 | defer in_file.close(); |
| 987 | |
| 988 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| 989 | self.parsePositional(in_file, obj.path, obj.must_link, &parse_ctx) catch |err| |
| 990 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| 991 | } |
| 992 | |
| 983 | 993 | if (self.lazy_syms.getPtr(.none)) |metadata| { |
| 984 | 994 | // Most lazy symbols can be updated on first use, but |
| 985 | 995 | // 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 |
| 1246 | 1256 | assert(!self.got.dirty); |
| 1247 | 1257 | } |
| 1248 | 1258 | |
| 1259 | const ParseError = error{ |
| 1260 | UnknownFileType, |
| 1261 | InvalidCpuArch, |
| 1262 | OutOfMemory, |
| 1263 | Overflow, |
| 1264 | InputOutput, |
| 1265 | EndOfStream, |
| 1266 | FileSystem, |
| 1267 | NotSupported, |
| 1268 | } || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; |
| 1269 | |
| 1270 | fn parsePositional( |
| 1271 | self: *Elf, |
| 1272 | in_file: std.fs.File, |
| 1273 | path: []const u8, |
| 1274 | must_link: bool, |
| 1275 | ctx: *ParseErrorCtx, |
| 1276 | ) ParseError!void { |
| 1277 | const tracy = trace(@src()); |
| 1278 | defer tracy.end(); |
| 1279 | |
| 1280 | _ = self; |
| 1281 | _ = in_file; |
| 1282 | _ = path; |
| 1283 | _ = must_link; |
| 1284 | _ = ctx; |
| 1285 | |
| 1286 | return error.UnknownFileType; |
| 1287 | } |
| 1288 | |
| 1249 | 1289 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 1250 | 1290 | const tracy = trace(@src()); |
| 1251 | 1291 | defer tracy.end(); |
| ... | ... | @@ -3451,6 +3491,49 @@ fn reportUndefined(self: *Elf) !void { |
| 3451 | 3491 | } |
| 3452 | 3492 | } |
| 3453 | 3493 | |
| 3494 | const ParseErrorCtx = struct { |
| 3495 | detected_cpu_arch: std.Target.Cpu.Arch, |
| 3496 | }; |
| 3497 | |
| 3498 | fn handleAndReportParseError( |
| 3499 | self: *Elf, |
| 3500 | path: []const u8, |
| 3501 | err: ParseError, |
| 3502 | ctx: *const ParseErrorCtx, |
| 3503 | ) error{OutOfMemory}!void { |
| 3504 | const cpu_arch = self.base.options.target.cpu.arch; |
| 3505 | switch (err) { |
| 3506 | error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), |
| 3507 | error.InvalidCpuArch => try self.reportParseError( |
| 3508 | path, |
| 3509 | "invalid cpu architecture: expected '{s}', but found '{s}'", |
| 3510 | .{ @tagName(cpu_arch), @tagName(ctx.detected_cpu_arch) }, |
| 3511 | ), |
| 3512 | else => |e| try self.reportParseError( |
| 3513 | path, |
| 3514 | "unexpected error: parsing object failed with error {s}", |
| 3515 | .{@errorName(e)}, |
| 3516 | ), |
| 3517 | } |
| 3518 | } |
| 3519 | |
| 3520 | fn reportParseError( |
| 3521 | self: *Elf, |
| 3522 | path: []const u8, |
| 3523 | comptime format: []const u8, |
| 3524 | args: anytype, |
| 3525 | ) error{OutOfMemory}!void { |
| 3526 | const gpa = self.base.allocator; |
| 3527 | try self.misc_errors.ensureUnusedCapacity(gpa, 1); |
| 3528 | var notes = try gpa.alloc(link.File.ErrorMsg, 1); |
| 3529 | errdefer gpa.free(notes); |
| 3530 | notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) }; |
| 3531 | self.misc_errors.appendAssumeCapacity(.{ |
| 3532 | .msg = try std.fmt.allocPrint(gpa, format, args), |
| 3533 | .notes = notes, |
| 3534 | }); |
| 3535 | } |
| 3536 | |
| 3454 | 3537 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 3455 | 3538 | return .{ .data = self }; |
| 3456 | 3539 | } |