Commit 52959bba7c

Jakub Konka <kubkon@jakubkonka.com>
2023-12-05 14:08:01
elf: re-instate basic error reporting for LD script parser
1 parent 2e1dd1e
Changed files (4)
src/link/Elf/LdScript.zig
@@ -1,3 +1,4 @@
+path: []const u8,
 cpu_arch: ?std.Target.Cpu.Arch = null,
 args: std.ArrayListUnmanaged(Elf.SystemLib) = .{},
 
@@ -6,7 +7,7 @@ pub fn deinit(scr: *LdScript, allocator: Allocator) void {
 }
 
 pub const Error = error{
-    InvalidScript,
+    InvalidLdScript,
     UnexpectedToken,
     UnknownCpuArch,
     OutOfMemory,
@@ -30,13 +31,12 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void {
         try line_col.append(.{ .line = line, .column = column });
         switch (tok.id) {
             .invalid => {
-                // TODO errors
-                // elf_file.base.fatal("invalid token in ld script: '{s}' ({d}:{d})", .{
-                //     tok.get(data),
-                //     line,
-                //     column,
-                // });
-                return error.InvalidScript;
+                try elf_file.reportParseError(scr.path, "invalid token in LD script: '{s}' ({d}:{d})", .{
+                    tok.get(data),
+                    line,
+                    column,
+                });
+                return error.InvalidLdScript;
             },
             .new_line => {
                 line += 1;
@@ -55,17 +55,16 @@ pub fn parse(scr: *LdScript, data: []const u8, elf_file: *Elf) Error!void {
         .args = &args,
     }) catch |err| switch (err) {
         error.UnexpectedToken => {
-            // const last_token_id = parser.it.pos - 1;
-            // const last_token = parser.it.get(last_token_id);
-            // const lcol = line_col.items[last_token_id];
-            // TODO errors
-            // elf_file.base.fatal("unexpected token in ld script: {s} : '{s}' ({d}:{d})", .{
-            //     @tagName(last_token.id),
-            //     last_token.get(data),
-            //     lcol.line,
-            //     lcol.column,
-            // });
-            return error.InvalidScript;
+            const last_token_id = parser.it.pos - 1;
+            const last_token = parser.it.get(last_token_id);
+            const lcol = line_col.items[last_token_id];
+            try elf_file.reportParseError(scr.path, "unexpected token in LD script: {s}: '{s}' ({d}:{d})", .{
+                @tagName(last_token.id),
+                last_token.get(data),
+                lcol.line,
+                lcol.column,
+            });
+            return error.InvalidLdScript;
         },
         else => |e| return e,
     };
src/link/Elf/Object.zig
@@ -75,7 +75,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
             "corrupted header: section header table extends past the end of file",
             .{},
         );
-        return error.LinkFail;
+        return error.MalformedObject;
     }
 
     const shoff = math.cast(usize, self.header.?.e_shoff) orelse return error.Overflow;
@@ -88,7 +88,7 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
     for (shdrs) |shdr| {
         if (self.data.len < shdr.sh_offset or self.data.len < shdr.sh_offset + shdr.sh_size) {
             try elf_file.reportParseError2(self.index, "corrupted section header", .{});
-            return error.LinkFail;
+            return error.MalformedObject;
         }
         self.shdrs.appendAssumeCapacity(try ElfShdr.fromElf64Shdr(shdr));
     }
src/link/Elf/SharedObject.zig
@@ -70,7 +70,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf) !void {
             "corrupted header: section header table extends past the end of file",
             .{},
         );
-        return error.LinkFail;
+        return error.MalformedObject;
     }
 
     const shoff = std.math.cast(usize, self.header.?.e_shoff) orelse return error.Overflow;
@@ -84,7 +84,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf) !void {
     for (shdrs, 0..) |shdr, i| {
         if (self.data.len < shdr.sh_offset or self.data.len < shdr.sh_offset + shdr.sh_size) {
             try elf_file.reportParseError2(self.index, "corrupted section header", .{});
-            return error.LinkFail;
+            return error.MalformedObject;
         }
         self.shdrs.appendAssumeCapacity(try ElfShdr.fromElf64Shdr(shdr));
         switch (shdr.sh_type) {
src/link/Elf.zig
@@ -1042,7 +1042,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
 
     for (positionals.items) |obj| {
         self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 obj.path,
                 "unexpected error: parsing input file failed with error {s}",
@@ -1128,7 +1128,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
 
     for (system_libs.items) |lib| {
         self.parseLibrary(lib, false) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 lib.path,
                 "unexpected error: parsing library failed with error {s}",
@@ -1151,7 +1151,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
 
     for (positionals.items) |obj| {
         self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 obj.path,
                 "unexpected error: parsing input file failed with error {s}",
@@ -1316,7 +1316,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const
 
     for (positionals.items) |obj| {
         self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 obj.path,
                 "unexpected error: parsing input file failed with error {s}",
@@ -1453,7 +1453,7 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)
 
     for (positionals.items) |obj| {
         self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 obj.path,
                 "unexpected error: parsing input file failed with error {s}",
@@ -1785,8 +1785,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
 }
 
 const ParseError = error{
-    LinkFail,
-    UnknownFileType,
+    MalformedObject,
+    MalformedArchive,
     InvalidCpuArch,
     OutOfMemory,
     Overflow,
@@ -1816,11 +1816,7 @@ fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void {
     } else if (try SharedObject.isSharedObject(lib.path)) {
         try self.parseSharedObject(lib);
     } else {
-        // TODO if the script has a top-level comment identifying it as GNU ld script,
-        // then report parse errors. Otherwise return UnknownFileType.
-        self.parseLdScript(lib) catch |err| switch (err) {
-            else => return error.UnknownFileType,
-        };
+        try self.parseLdScript(lib);
     }
 }
 
@@ -1902,7 +1898,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
     const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
     defer gpa.free(data);
 
-    var script = LdScript{};
+    var script = LdScript{ .path = lib.path };
     defer script.deinit(gpa);
     try script.parse(data, self);
 
@@ -1963,7 +1959,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
             .needed = scr_obj.needed,
             .path = full_path,
         }, false) catch |err| switch (err) {
-            error.LinkFail, error.InvalidCpuArch => {}, // already reported
+            error.MalformedObject, error.InvalidCpuArch => {}, // already reported
             else => |e| try self.reportParseError(
                 full_path,
                 "unexpected error: parsing library failed with error {s}",
@@ -2195,7 +2191,7 @@ fn scanRelocs(self: *Elf) !void {
         try object.scanRelocs(self, &undefs);
     }
 
-    try self.reportUndefined(&undefs);
+    try self.reportUndefinedSymbols(&undefs);
 
     for (self.symbols.items, 0..) |*sym, i| {
         const index = @as(u32, @intCast(i));
@@ -4760,7 +4756,7 @@ fn writeAtoms(self: *Elf) !void {
         try self.base.file.?.pwriteAll(buffer, sh_offset);
     }
 
-    try self.reportUndefined(&undefs);
+    try self.reportUndefinedSymbols(&undefs);
 }
 
 fn writeAtomsObject(self: *Elf) !void {
@@ -6023,7 +6019,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
     return off;
 }
 
-fn reportUndefined(self: *Elf, undefs: anytype) !void {
+fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
     const gpa = self.base.allocator;
     const max_notes = 4;
 
@@ -6065,7 +6061,7 @@ fn reportMissingLibraryError(
     }
 }
 
-fn reportParseError(
+pub fn reportParseError(
     self: *Elf,
     path: []const u8,
     comptime format: []const u8,