diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-12-05 13:49:55 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-12-05 13:49:55 +0100 |
| commit | 3f42ed3ca25d6ef32c92a8ed43129b789cf846c5 (patch) | |
| tree | facf0de891161731d209fa865a96996c784b15bf /src | |
| parent | af8621db2d2de4675240dad0ff885f23dc33f518 (diff) | |
| download | zig-3f42ed3ca25d6ef32c92a8ed43129b789cf846c5.tar.gz zig-3f42ed3ca25d6ef32c92a8ed43129b789cf846c5.zip | |
elf: do not write ELF header if there were errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 131 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 9 |
2 files changed, 70 insertions, 70 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 859932e133..885af57e9e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1041,9 +1041,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } for (positionals.items) |obj| { - var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; - self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| - try self.handleAndReportParseError(obj.path, err, &parse_ctx); + self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + obj.path, + "unexpected error: parsing input file failed with error {s}", + .{@errorName(e)}, + ), + }; } var system_libs = std.ArrayList(SystemLib).init(arena); @@ -1122,9 +1127,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } for (system_libs.items) |lib| { - var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; - self.parseLibrary(lib, false, &parse_ctx) catch |err| - try self.handleAndReportParseError(lib.path, err, &parse_ctx); + self.parseLibrary(lib, false) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + lib.path, + "unexpected error: parsing library failed with error {s}", + .{@errorName(e)}, + ), + }; } // 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 if (csu.crtn) |v| try positionals.append(.{ .path = v }); for (positionals.items) |obj| { - var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; - self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| - try self.handleAndReportParseError(obj.path, err, &parse_ctx); + self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + obj.path, + "unexpected error: parsing input file failed with error {s}", + .{@errorName(e)}, + ), + }; } // Init all objects @@ -1300,9 +1315,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const if (module_obj_path) |path| try positionals.append(.{ .path = path }); for (positionals.items) |obj| { - var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; - self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| - try self.handleAndReportParseError(obj.path, err, &parse_ctx); + self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + obj.path, + "unexpected error: parsing input file failed with error {s}", + .{@errorName(e)}, + ), + }; } // 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) if (module_obj_path) |path| try positionals.append(.{ .path = path }); for (positionals.items) |obj| { - var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; - self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| - try self.handleAndReportParseError(obj.path, err, &parse_ctx); + self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + obj.path, + "unexpected error: parsing input file failed with error {s}", + .{@errorName(e)}, + ), + }; } // Init all objects @@ -1770,37 +1795,36 @@ const ParseError = error{ FileSystem, NotSupported, InvalidCharacter, - MalformedObject, } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; -fn parsePositional(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { +fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { const tracy = trace(@src()); defer tracy.end(); if (try Object.isObject(path)) { - try self.parseObject(path, ctx); + try self.parseObject(path); } else { - try self.parseLibrary(.{ .path = path }, must_link, ctx); + try self.parseLibrary(.{ .path = path }, must_link); } } -fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { +fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { const tracy = trace(@src()); defer tracy.end(); if (try Archive.isArchive(lib.path)) { - try self.parseArchive(lib.path, must_link, ctx); + try self.parseArchive(lib.path, must_link); } else if (try SharedObject.isSharedObject(lib.path)) { - try self.parseSharedObject(lib, ctx); + 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, ctx) catch |err| switch (err) { + self.parseLdScript(lib) catch |err| switch (err) { else => return error.UnknownFileType, }; } } -fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!void { +fn parseObject(self: *Elf, path: []const u8) ParseError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1818,12 +1842,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi const object = self.file(index).?.object; try object.parse(self); - - ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; - if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; } -fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { +fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1846,13 +1867,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC object.alive = must_link; try object.parse(self); try self.objects.append(gpa, index); - - ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; - if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; } } -fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { +fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1872,12 +1890,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError const shared_object = self.file(index).?.shared_object; try shared_object.parse(self); - - ctx.detected_cpu_arch = shared_object.header.?.e_machine.toTargetCpuArch().?; - if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; } -fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { +fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1891,11 +1906,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi defer script.deinit(gpa); try script.parse(data, self); - if (script.cpu_arch) |cpu_arch| { - ctx.detected_cpu_arch = cpu_arch; - if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; - } - const lib_dirs = self.base.options.lib_dirs; var arena_allocator = std.heap.ArenaAllocator.init(gpa); @@ -1949,11 +1959,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi } const full_path = test_path.items; - var scr_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; self.parseLibrary(.{ .needed = scr_obj.needed, .path = full_path, - }, false, &scr_ctx) catch |err| try self.handleAndReportParseError(full_path, err, &scr_ctx); + }, false) catch |err| switch (err) { + error.LinkFail, error.InvalidCpuArch => {}, // already reported + else => |e| try self.reportParseError( + full_path, + "unexpected error: parsing library failed with error {s}", + .{@errorName(e)}, + ), + }; } } @@ -3009,6 +3025,8 @@ fn writePhdrTable(self: *Elf) !void { } fn writeElfHeader(self: *Elf) !void { + if (self.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable + var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; var index: usize = 0; @@ -6047,33 +6065,6 @@ fn reportMissingLibraryError( } } -const ParseErrorCtx = struct { - detected_cpu_arch: std.Target.Cpu.Arch, -}; - -fn handleAndReportParseError( - self: *Elf, - path: []const u8, - err: ParseError, - ctx: *const ParseErrorCtx, -) error{OutOfMemory}!void { - const cpu_arch = self.base.options.target.cpu.arch; - switch (err) { - error.LinkFail => {}, // already reported - error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), - error.InvalidCpuArch => try self.reportParseError( - path, - "invalid cpu architecture: expected '{s}', but found '{s}'", - .{ @tagName(cpu_arch), @tagName(ctx.detected_cpu_arch) }, - ), - else => |e| try self.reportParseError( - path, - "unexpected error: parsing object failed with error {s}", - .{@errorName(e)}, - ), - } -} - fn reportParseError( self: *Elf, path: []const u8, diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 4f390f31fa..f6e2a79a76 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -54,6 +54,15 @@ pub fn parse(self: *Object, elf_file: *Elf) !void { self.header = try reader.readStruct(elf.Elf64_Ehdr); + if (elf_file.base.options.target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { + try elf_file.reportParseError2( + self.index, + "invalid cpu architecture: {s}", + .{@tagName(self.header.?.e_machine.toTargetCpuArch().?)}, + ); + return error.InvalidCpuArch; + } + if (self.header.?.e_shnum == 0) return; const gpa = elf_file.base.allocator; |
