| ... | @@ -1041,9 +1041,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1041,9 +1041,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1041 | } | 1041 | } |
| 1042 | | 1042 | |
| 1043 | for (positionals.items) |obj| { | 1043 | for (positionals.items) |obj| { |
| 1044 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1044 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1045 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1045 | error.LinkFail, error.InvalidCpuArch => {}, // already reported |
| 1046 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1046 | else => |e| try self.reportParseError( |
| | 1047 | obj.path, |
| | 1048 | "unexpected error: parsing input file failed with error {s}", |
| | 1049 | .{@errorName(e)}, |
| | 1050 | ), |
| | 1051 | }; |
| 1047 | } | 1052 | } |
| 1048 | | 1053 | |
| 1049 | var system_libs = std.ArrayList(SystemLib).init(arena); | 1054 | var system_libs = std.ArrayList(SystemLib).init(arena); |
| ... | @@ -1122,9 +1127,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1122,9 +1127,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1122 | } | 1127 | } |
| 1123 | | 1128 | |
| 1124 | for (system_libs.items) |lib| { | 1129 | for (system_libs.items) |lib| { |
| 1125 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1130 | self.parseLibrary(lib, false) catch |err| switch (err) { |
| 1126 | self.parseLibrary(lib, false, &parse_ctx) catch |err| | 1131 | error.LinkFail, error.InvalidCpuArch => {}, // already reported |
| 1127 | try self.handleAndReportParseError(lib.path, err, &parse_ctx); | 1132 | else => |e| try self.reportParseError( |
| | 1133 | lib.path, |
| | 1134 | "unexpected error: parsing library failed with error {s}", |
| | 1135 | .{@errorName(e)}, |
| | 1136 | ), |
| | 1137 | }; |
| 1128 | } | 1138 | } |
| 1129 | | 1139 | |
| 1130 | // Finally, as the last input objects we add compiler_rt and CSU postlude (if any). | 1140 | // 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 | ... | @@ -1140,9 +1150,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1140 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); | 1150 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); |
| 1141 | | 1151 | |
| 1142 | for (positionals.items) |obj| { | 1152 | for (positionals.items) |obj| { |
| 1143 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1153 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1144 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1154 | error.LinkFail, error.InvalidCpuArch => {}, // already reported |
| 1145 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1155 | else => |e| try self.reportParseError( |
| | 1156 | obj.path, |
| | 1157 | "unexpected error: parsing input file failed with error {s}", |
| | 1158 | .{@errorName(e)}, |
| | 1159 | ), |
| | 1160 | }; |
| 1146 | } | 1161 | } |
| 1147 | | 1162 | |
| 1148 | // Init all objects | 1163 | // Init all objects |
| ... | @@ -1300,9 +1315,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1300,9 +1315,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1300 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 1315 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1301 | | 1316 | |
| 1302 | for (positionals.items) |obj| { | 1317 | for (positionals.items) |obj| { |
| 1303 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1318 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1304 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1319 | error.LinkFail, error.InvalidCpuArch => {}, // already reported |
| 1305 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1320 | else => |e| try self.reportParseError( |
| | 1321 | obj.path, |
| | 1322 | "unexpected error: parsing input file failed with error {s}", |
| | 1323 | .{@errorName(e)}, |
| | 1324 | ), |
| | 1325 | }; |
| 1306 | } | 1326 | } |
| 1307 | | 1327 | |
| 1308 | // First, we flush relocatable object file generated with our backends. | 1328 | // 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) | ... | @@ -1432,9 +1452,14 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) |
| 1432 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 1452 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1433 | | 1453 | |
| 1434 | for (positionals.items) |obj| { | 1454 | for (positionals.items) |obj| { |
| 1435 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1455 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1436 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1456 | error.LinkFail, error.InvalidCpuArch => {}, // already reported |
| 1437 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1457 | else => |e| try self.reportParseError( |
| | 1458 | obj.path, |
| | 1459 | "unexpected error: parsing input file failed with error {s}", |
| | 1460 | .{@errorName(e)}, |
| | 1461 | ), |
| | 1462 | }; |
| 1438 | } | 1463 | } |
| 1439 | | 1464 | |
| 1440 | // Init all objects | 1465 | // Init all objects |
| ... | @@ -1770,37 +1795,36 @@ const ParseError = error{ | ... | @@ -1770,37 +1795,36 @@ const ParseError = error{ |
| 1770 | FileSystem, | 1795 | FileSystem, |
| 1771 | NotSupported, | 1796 | NotSupported, |
| 1772 | InvalidCharacter, | 1797 | InvalidCharacter, |
| 1773 | MalformedObject, | | |
| 1774 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; | 1798 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; |
| 1775 | | 1799 | |
| 1776 | fn parsePositional(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1800 | fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1777 | const tracy = trace(@src()); | 1801 | const tracy = trace(@src()); |
| 1778 | defer tracy.end(); | 1802 | defer tracy.end(); |
| 1779 | if (try Object.isObject(path)) { | 1803 | if (try Object.isObject(path)) { |
| 1780 | try self.parseObject(path, ctx); | 1804 | try self.parseObject(path); |
| 1781 | } else { | 1805 | } else { |
| 1782 | try self.parseLibrary(.{ .path = path }, must_link, ctx); | 1806 | try self.parseLibrary(.{ .path = path }, must_link); |
| 1783 | } | 1807 | } |
| 1784 | } | 1808 | } |
| 1785 | | 1809 | |
| 1786 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1810 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { |
| 1787 | const tracy = trace(@src()); | 1811 | const tracy = trace(@src()); |
| 1788 | defer tracy.end(); | 1812 | defer tracy.end(); |
| 1789 | | 1813 | |
| 1790 | if (try Archive.isArchive(lib.path)) { | 1814 | if (try Archive.isArchive(lib.path)) { |
| 1791 | try self.parseArchive(lib.path, must_link, ctx); | 1815 | try self.parseArchive(lib.path, must_link); |
| 1792 | } else if (try SharedObject.isSharedObject(lib.path)) { | 1816 | } else if (try SharedObject.isSharedObject(lib.path)) { |
| 1793 | try self.parseSharedObject(lib, ctx); | 1817 | try self.parseSharedObject(lib); |
| 1794 | } else { | 1818 | } else { |
| 1795 | // TODO if the script has a top-level comment identifying it as GNU ld script, | 1819 | // TODO if the script has a top-level comment identifying it as GNU ld script, |
| 1796 | // then report parse errors. Otherwise return UnknownFileType. | 1820 | // then report parse errors. Otherwise return UnknownFileType. |
| 1797 | self.parseLdScript(lib, ctx) catch |err| switch (err) { | 1821 | self.parseLdScript(lib) catch |err| switch (err) { |
| 1798 | else => return error.UnknownFileType, | 1822 | else => return error.UnknownFileType, |
| 1799 | }; | 1823 | }; |
| 1800 | } | 1824 | } |
| 1801 | } | 1825 | } |
| 1802 | | 1826 | |
| 1803 | fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!void { | 1827 | fn parseObject(self: *Elf, path: []const u8) ParseError!void { |
| 1804 | const tracy = trace(@src()); | 1828 | const tracy = trace(@src()); |
| 1805 | defer tracy.end(); | 1829 | defer tracy.end(); |
| 1806 | | 1830 | |
| ... | @@ -1818,12 +1842,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1818,12 +1842,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi |
| 1818 | | 1842 | |
| 1819 | const object = self.file(index).?.object; | 1843 | const object = self.file(index).?.object; |
| 1820 | try object.parse(self); | 1844 | 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; | | |
| 1824 | } | 1845 | } |
| 1825 | | 1846 | |
| 1826 | fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1847 | fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1827 | const tracy = trace(@src()); | 1848 | const tracy = trace(@src()); |
| 1828 | defer tracy.end(); | 1849 | defer tracy.end(); |
| 1829 | | 1850 | |
| ... | @@ -1846,13 +1867,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC | ... | @@ -1846,13 +1867,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC |
| 1846 | object.alive = must_link; | 1867 | object.alive = must_link; |
| 1847 | try object.parse(self); | 1868 | try object.parse(self); |
| 1848 | try self.objects.append(gpa, index); | 1869 | 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; | | |
| 1852 | } | 1870 | } |
| 1853 | } | 1871 | } |
| 1854 | | 1872 | |
| 1855 | fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { | 1873 | fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { |
| 1856 | const tracy = trace(@src()); | 1874 | const tracy = trace(@src()); |
| 1857 | defer tracy.end(); | 1875 | defer tracy.end(); |
| 1858 | | 1876 | |
| ... | @@ -1872,12 +1890,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError | ... | @@ -1872,12 +1890,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError |
| 1872 | | 1890 | |
| 1873 | const shared_object = self.file(index).?.shared_object; | 1891 | const shared_object = self.file(index).?.shared_object; |
| 1874 | try shared_object.parse(self); | 1892 | 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; | | |
| 1878 | } | 1893 | } |
| 1879 | | 1894 | |
| 1880 | fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { | 1895 | fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1881 | const tracy = trace(@src()); | 1896 | const tracy = trace(@src()); |
| 1882 | defer tracy.end(); | 1897 | defer tracy.end(); |
| 1883 | | 1898 | |
| ... | @@ -1891,11 +1906,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1891,11 +1906,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1891 | defer script.deinit(gpa); | 1906 | defer script.deinit(gpa); |
| 1892 | try script.parse(data, self); | 1907 | try script.parse(data, self); |
| 1893 | | 1908 | |
| 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 | | | |
| 1899 | const lib_dirs = self.base.options.lib_dirs; | 1909 | const lib_dirs = self.base.options.lib_dirs; |
| 1900 | | 1910 | |
| 1901 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | 1911 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -1949,11 +1959,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1949,11 +1959,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1949 | } | 1959 | } |
| 1950 | | 1960 | |
| 1951 | const full_path = test_path.items; | 1961 | const full_path = test_path.items; |
| 1952 | var scr_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | | |
| 1953 | self.parseLibrary(.{ | 1962 | self.parseLibrary(.{ |
| 1954 | .needed = scr_obj.needed, | 1963 | .needed = scr_obj.needed, |
| 1955 | .path = full_path, | 1964 | .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 | }; |
| 1957 | } | 1973 | } |
| 1958 | } | 1974 | } |
| 1959 | | 1975 | |
| ... | @@ -3009,6 +3025,8 @@ fn writePhdrTable(self: *Elf) !void { | ... | @@ -3009,6 +3025,8 @@ fn writePhdrTable(self: *Elf) !void { |
| 3009 | } | 3025 | } |
| 3010 | | 3026 | |
| 3011 | fn writeElfHeader(self: *Elf) !void { | 3027 | fn 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 | |
| 3012 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | 3030 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 3013 | | 3031 | |
| 3014 | var index: usize = 0; | 3032 | var index: usize = 0; |
| ... | @@ -6047,33 +6065,6 @@ fn reportMissingLibraryError( | ... | @@ -6047,33 +6065,6 @@ fn reportMissingLibraryError( |
| 6047 | } | 6065 | } |
| 6048 | } | 6066 | } |
| 6049 | | 6067 | |
| 6050 | const ParseErrorCtx = struct { | | |
| 6051 | detected_cpu_arch: std.Target.Cpu.Arch, | | |
| 6052 | }; | | |
| 6053 | | | |
| 6054 | fn 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 | | | |
| 6077 | fn reportParseError( | 6068 | fn reportParseError( |
| 6078 | self: *Elf, | 6069 | self: *Elf, |
| 6079 | path: []const u8, | 6070 | path: []const u8, |