authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-11 16:32:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-11 16:32:58+02:00
log3df58a95835fe2f9ba16e9ff9e0d03c39d263bf3
tree52911b8431d396fd304e0fcb5e064c3f36ffeaa8
parent65b9597c07ddc6328c9725e0731ae838666d9e20

elf: add basic error reporting for positional parsing


1 files changed, 83 insertions(+), 0 deletions(-)

src/link/Elf.zig+83
...@@ -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;
982982
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, but994 // 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}
12481258
1259const 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
1270fn 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
1249fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {1289fn 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}
34533493
3494const ParseErrorCtx = struct {
3495 detected_cpu_arch: std.Target.Cpu.Arch,
3496};
3497
3498fn 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
3520fn 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
3454fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {3537fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {
3455 return .{ .data = self };3538 return .{ .data = self };
3456}3539}