authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-05 13:49:55+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-05 13:49:55+01:00
log3f42ed3ca25d6ef32c92a8ed43129b789cf846c5
treefacf0de891161731d209fa865a96996c784b15bf
parentaf8621db2d2de4675240dad0ff885f23dc33f518

elf: do not write ELF header if there were errors


2 files changed, 70 insertions(+), 70 deletions(-)

src/link/Elf.zig+61-70
......@@ -1041,9 +1041,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10411041 }
10421042
10431043 for (positionals.items) |obj| {
1044 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1045 self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err|
1046 try self.handleAndReportParseError(obj.path, err, &parse_ctx);
1044 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1045 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1046 else => |e| try self.reportParseError(
1047 obj.path,
1048 "unexpected error: parsing input file failed with error {s}",
1049 .{@errorName(e)},
1050 ),
1051 };
10471052 }
10481053
10491054 var system_libs = std.ArrayList(SystemLib).init(arena);
......@@ -1122,9 +1127,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11221127 }
11231128
11241129 for (system_libs.items) |lib| {
1125 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1126 self.parseLibrary(lib, false, &parse_ctx) catch |err|
1127 try self.handleAndReportParseError(lib.path, err, &parse_ctx);
1130 self.parseLibrary(lib, false) catch |err| switch (err) {
1131 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1132 else => |e| try self.reportParseError(
1133 lib.path,
1134 "unexpected error: parsing library failed with error {s}",
1135 .{@errorName(e)},
1136 ),
1137 };
11281138 }
11291139
11301140 // Finally, as the last input objects we add compiler_rt and CSU postlude (if any).
......@@ -1140,9 +1150,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11401150 if (csu.crtn) |v| try positionals.append(.{ .path = v });
11411151
11421152 for (positionals.items) |obj| {
1143 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1144 self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err|
1145 try self.handleAndReportParseError(obj.path, err, &parse_ctx);
1153 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1154 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1155 else => |e| try self.reportParseError(
1156 obj.path,
1157 "unexpected error: parsing input file failed with error {s}",
1158 .{@errorName(e)},
1159 ),
1160 };
11461161 }
11471162
11481163 // Init all objects
......@@ -1300,9 +1315,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const
13001315 if (module_obj_path) |path| try positionals.append(.{ .path = path });
13011316
13021317 for (positionals.items) |obj| {
1303 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1304 self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err|
1305 try self.handleAndReportParseError(obj.path, err, &parse_ctx);
1318 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1319 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1320 else => |e| try self.reportParseError(
1321 obj.path,
1322 "unexpected error: parsing input file failed with error {s}",
1323 .{@errorName(e)},
1324 ),
1325 };
13061326 }
13071327
13081328 // First, we flush relocatable object file generated with our backends.
......@@ -1432,9 +1452,14 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)
14321452 if (module_obj_path) |path| try positionals.append(.{ .path = path });
14331453
14341454 for (positionals.items) |obj| {
1435 var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
1436 self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err|
1437 try self.handleAndReportParseError(obj.path, err, &parse_ctx);
1455 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1456 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1457 else => |e| try self.reportParseError(
1458 obj.path,
1459 "unexpected error: parsing input file failed with error {s}",
1460 .{@errorName(e)},
1461 ),
1462 };
14381463 }
14391464
14401465 // Init all objects
......@@ -1770,37 +1795,36 @@ const ParseError = error{
17701795 FileSystem,
17711796 NotSupported,
17721797 InvalidCharacter,
1773 MalformedObject,
17741798} || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError;
17751799
1776fn parsePositional(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void {
1800fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void {
17771801 const tracy = trace(@src());
17781802 defer tracy.end();
17791803 if (try Object.isObject(path)) {
1780 try self.parseObject(path, ctx);
1804 try self.parseObject(path);
17811805 } else {
1782 try self.parseLibrary(.{ .path = path }, must_link, ctx);
1806 try self.parseLibrary(.{ .path = path }, must_link);
17831807 }
17841808}
17851809
1786fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool, ctx: *ParseErrorCtx) ParseError!void {
1810fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void {
17871811 const tracy = trace(@src());
17881812 defer tracy.end();
17891813
17901814 if (try Archive.isArchive(lib.path)) {
1791 try self.parseArchive(lib.path, must_link, ctx);
1815 try self.parseArchive(lib.path, must_link);
17921816 } else if (try SharedObject.isSharedObject(lib.path)) {
1793 try self.parseSharedObject(lib, ctx);
1817 try self.parseSharedObject(lib);
17941818 } else {
17951819 // TODO if the script has a top-level comment identifying it as GNU ld script,
17961820 // then report parse errors. Otherwise return UnknownFileType.
1797 self.parseLdScript(lib, ctx) catch |err| switch (err) {
1821 self.parseLdScript(lib) catch |err| switch (err) {
17981822 else => return error.UnknownFileType,
17991823 };
18001824 }
18011825}
18021826
1803fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!void {
1827fn parseObject(self: *Elf, path: []const u8) ParseError!void {
18041828 const tracy = trace(@src());
18051829 defer tracy.end();
18061830
......@@ -1818,12 +1842,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi
18181842
18191843 const object = self.file(index).?.object;
18201844 try object.parse(self);
1821
1822 ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?;
1823 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
18241845}
18251846
1826fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void {
1847fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void {
18271848 const tracy = trace(@src());
18281849 defer tracy.end();
18291850
......@@ -1846,13 +1867,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC
18461867 object.alive = must_link;
18471868 try object.parse(self);
18481869 try self.objects.append(gpa, index);
1849
1850 ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?;
1851 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
18521870 }
18531871}
18541872
1855fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void {
1873fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void {
18561874 const tracy = trace(@src());
18571875 defer tracy.end();
18581876
......@@ -1872,12 +1890,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError
18721890
18731891 const shared_object = self.file(index).?.shared_object;
18741892 try shared_object.parse(self);
1875
1876 ctx.detected_cpu_arch = shared_object.header.?.e_machine.toTargetCpuArch().?;
1877 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
18781893}
18791894
1880fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void {
1895fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
18811896 const tracy = trace(@src());
18821897 defer tracy.end();
18831898
......@@ -1891,11 +1906,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi
18911906 defer script.deinit(gpa);
18921907 try script.parse(data, self);
18931908
1894 if (script.cpu_arch) |cpu_arch| {
1895 ctx.detected_cpu_arch = cpu_arch;
1896 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
1897 }
1898
18991909 const lib_dirs = self.base.options.lib_dirs;
19001910
19011911 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
......@@ -1949,11 +1959,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi
19491959 }
19501960
19511961 const full_path = test_path.items;
1952 var scr_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined };
19531962 self.parseLibrary(.{
19541963 .needed = scr_obj.needed,
19551964 .path = full_path,
1956 }, false, &scr_ctx) catch |err| try self.handleAndReportParseError(full_path, err, &scr_ctx);
1965 }, false) catch |err| switch (err) {
1966 error.LinkFail, error.InvalidCpuArch => {}, // already reported
1967 else => |e| try self.reportParseError(
1968 full_path,
1969 "unexpected error: parsing library failed with error {s}",
1970 .{@errorName(e)},
1971 ),
1972 };
19571973 }
19581974}
19591975
......@@ -3009,6 +3025,8 @@ fn writePhdrTable(self: *Elf) !void {
30093025}
30103026
30113027fn writeElfHeader(self: *Elf) !void {
3028 if (self.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable
3029
30123030 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined;
30133031
30143032 var index: usize = 0;
......@@ -6047,33 +6065,6 @@ fn reportMissingLibraryError(
60476065 }
60486066}
60496067
6050const ParseErrorCtx = struct {
6051 detected_cpu_arch: std.Target.Cpu.Arch,
6052};
6053
6054fn handleAndReportParseError(
6055 self: *Elf,
6056 path: []const u8,
6057 err: ParseError,
6058 ctx: *const ParseErrorCtx,
6059) error{OutOfMemory}!void {
6060 const cpu_arch = self.base.options.target.cpu.arch;
6061 switch (err) {
6062 error.LinkFail => {}, // already reported
6063 error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}),
6064 error.InvalidCpuArch => try self.reportParseError(
6065 path,
6066 "invalid cpu architecture: expected '{s}', but found '{s}'",
6067 .{ @tagName(cpu_arch), @tagName(ctx.detected_cpu_arch) },
6068 ),
6069 else => |e| try self.reportParseError(
6070 path,
6071 "unexpected error: parsing object failed with error {s}",
6072 .{@errorName(e)},
6073 ),
6074 }
6075}
6076
60776068fn reportParseError(
60786069 self: *Elf,
60796070 path: []const u8,
src/link/Elf/Object.zig+9
......@@ -54,6 +54,15 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
5454
5555 self.header = try reader.readStruct(elf.Elf64_Ehdr);
5656
57 if (elf_file.base.options.target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) {
58 try elf_file.reportParseError2(
59 self.index,
60 "invalid cpu architecture: {s}",
61 .{@tagName(self.header.?.e_machine.toTargetCpuArch().?)},
62 );
63 return error.InvalidCpuArch;
64 }
65
5766 if (self.header.?.e_shnum == 0) return;
5867
5968 const gpa = elf_file.base.allocator;