elf: re-instate basic error reporting for LD script parser

This commit is contained in:
Jakub Konka 2023-12-05 14:08:01 +01:00
parent 2e1dd1e554
commit 52959bba7c
4 changed files with 36 additions and 41 deletions

View File

@ -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,

View File

@ -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,
};

View File

@ -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));
}

View File

@ -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) {