| ... | @@ -980,6 +980,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -980,6 +980,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 980 | }; | 980 | }; |
| 981 | _ = compiler_rt_path; | 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 | if (self.lazy_syms.getPtr(.none)) |metadata| { | 993 | if (self.lazy_syms.getPtr(.none)) |metadata| { |
| 984 | // Most lazy symbols can be updated on first use, but | 994 | // Most lazy symbols can be updated on first use, but |
| 985 | // anyerror needs to wait for everything to be flushed. | 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,6 +1256,36 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1246 | assert(!self.got.dirty); | 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 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1289 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 1250 | const tracy = trace(@src()); | 1290 | const tracy = trace(@src()); |
| 1251 | defer tracy.end(); | 1291 | defer tracy.end(); |
| ... | @@ -3451,6 +3491,49 @@ fn reportUndefined(self: *Elf) !void { | ... | @@ -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 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { | 3537 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 3455 | return .{ .data = self }; | 3538 | return .{ .data = self }; |
| 3456 | } | 3539 | } |