| ... | ... | @@ -1041,9 +1041,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1041 | 1041 | } |
| 1042 | 1042 | |
| 1043 | 1043 | 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 | }; |
| 1047 | 1052 | } |
| 1048 | 1053 | |
| 1049 | 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 | 1127 | } |
| 1123 | 1128 | |
| 1124 | 1129 | 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 | }; |
| 1128 | 1138 | } |
| 1129 | 1139 | |
| 1130 | 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 | 1150 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); |
| 1141 | 1151 | |
| 1142 | 1152 | 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 | }; |
| 1146 | 1161 | } |
| 1147 | 1162 | |
| 1148 | 1163 | // Init all objects |
| ... | ... | @@ -1300,9 +1315,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1300 | 1315 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1301 | 1316 | |
| 1302 | 1317 | 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 | }; |
| 1306 | 1326 | } |
| 1307 | 1327 | |
| 1308 | 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 | 1452 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1433 | 1453 | |
| 1434 | 1454 | 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 | }; |
| 1438 | 1463 | } |
| 1439 | 1464 | |
| 1440 | 1465 | // Init all objects |
| ... | ... | @@ -1770,37 +1795,36 @@ const ParseError = error{ |
| 1770 | 1795 | FileSystem, |
| 1771 | 1796 | NotSupported, |
| 1772 | 1797 | InvalidCharacter, |
| 1773 | | MalformedObject, |
| 1774 | 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 | 1801 | const tracy = trace(@src()); |
| 1778 | 1802 | defer tracy.end(); |
| 1779 | 1803 | if (try Object.isObject(path)) { |
| 1780 | | try self.parseObject(path, ctx); |
| 1804 | try self.parseObject(path); |
| 1781 | 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 | 1811 | const tracy = trace(@src()); |
| 1788 | 1812 | defer tracy.end(); |
| 1789 | 1813 | |
| 1790 | 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 | 1816 | } else if (try SharedObject.isSharedObject(lib.path)) { |
| 1793 | | try self.parseSharedObject(lib, ctx); |
| 1817 | try self.parseSharedObject(lib); |
| 1794 | 1818 | } else { |
| 1795 | 1819 | // TODO if the script has a top-level comment identifying it as GNU ld script, |
| 1796 | 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 | 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 | 1828 | const tracy = trace(@src()); |
| 1805 | 1829 | defer tracy.end(); |
| 1806 | 1830 | |
| ... | ... | @@ -1818,12 +1842,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi |
| 1818 | 1842 | |
| 1819 | 1843 | const object = self.file(index).?.object; |
| 1820 | 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 | 1848 | const tracy = trace(@src()); |
| 1828 | 1849 | defer tracy.end(); |
| 1829 | 1850 | |
| ... | ... | @@ -1846,13 +1867,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC |
| 1846 | 1867 | object.alive = must_link; |
| 1847 | 1868 | try object.parse(self); |
| 1848 | 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 | 1874 | const tracy = trace(@src()); |
| 1857 | 1875 | defer tracy.end(); |
| 1858 | 1876 | |
| ... | ... | @@ -1872,12 +1890,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError |
| 1872 | 1890 | |
| 1873 | 1891 | const shared_object = self.file(index).?.shared_object; |
| 1874 | 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 | 1896 | const tracy = trace(@src()); |
| 1882 | 1897 | defer tracy.end(); |
| 1883 | 1898 | |
| ... | ... | @@ -1891,11 +1906,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1891 | 1906 | defer script.deinit(gpa); |
| 1892 | 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 | 1909 | const lib_dirs = self.base.options.lib_dirs; |
| 1900 | 1910 | |
| 1901 | 1911 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -1949,11 +1959,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1949 | 1959 | } |
| 1950 | 1960 | |
| 1951 | 1961 | const full_path = test_path.items; |
| 1952 | | var scr_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| 1953 | 1962 | self.parseLibrary(.{ |
| 1954 | 1963 | .needed = scr_obj.needed, |
| 1955 | 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 | 3025 | } |
| 3010 | 3026 | |
| 3011 | 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 | 3030 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 3013 | 3031 | |
| 3014 | 3032 | var index: usize = 0; |
| ... | ... | @@ -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 | 6068 | fn reportParseError( |
| 6078 | 6069 | self: *Elf, |
| 6079 | 6070 | path: []const u8, |