| ... | @@ -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.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // 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.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // 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,11 +1150,18 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1140,11 +1150,18 @@ 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.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // 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 | |
| | 1163 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| | 1164 | |
| 1148 | // Init all objects | 1165 | // Init all objects |
| 1149 | for (self.objects.items) |index| { | 1166 | for (self.objects.items) |index| { |
| 1150 | try self.file(index).?.object.init(self); | 1167 | try self.file(index).?.object.init(self); |
| ... | @@ -1153,6 +1170,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1153,6 +1170,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1153 | try self.file(index).?.shared_object.init(self); | 1170 | try self.file(index).?.shared_object.init(self); |
| 1154 | } | 1171 | } |
| 1155 | | 1172 | |
| | 1173 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| | 1174 | |
| 1156 | // Dedup shared objects | 1175 | // Dedup shared objects |
| 1157 | { | 1176 | { |
| 1158 | var seen_dsos = std.StringHashMap(void).init(gpa); | 1177 | var seen_dsos = std.StringHashMap(void).init(gpa); |
| ... | @@ -1279,6 +1298,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1279,6 +1298,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1279 | self.error_flags.no_entry_point_found = false; | 1298 | self.error_flags.no_entry_point_found = false; |
| 1280 | try self.writeElfHeader(); | 1299 | try self.writeElfHeader(); |
| 1281 | } | 1300 | } |
| | 1301 | |
| | 1302 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| 1282 | } | 1303 | } |
| 1283 | | 1304 | |
| 1284 | pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 1305 | pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| ... | @@ -1300,11 +1321,18 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1300,11 +1321,18 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1300 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 1321 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1301 | | 1322 | |
| 1302 | for (positionals.items) |obj| { | 1323 | for (positionals.items) |obj| { |
| 1303 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1324 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1304 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1325 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported |
| 1305 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1326 | else => |e| try self.reportParseError( |
| | 1327 | obj.path, |
| | 1328 | "unexpected error: parsing input file failed with error {s}", |
| | 1329 | .{@errorName(e)}, |
| | 1330 | ), |
| | 1331 | }; |
| 1306 | } | 1332 | } |
| 1307 | | 1333 | |
| | 1334 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| | 1335 | |
| 1308 | // First, we flush relocatable object file generated with our backends. | 1336 | // First, we flush relocatable object file generated with our backends. |
| 1309 | if (self.zigObjectPtr()) |zig_object| { | 1337 | if (self.zigObjectPtr()) |zig_object| { |
| 1310 | zig_object.resolveSymbols(self); | 1338 | zig_object.resolveSymbols(self); |
| ... | @@ -1316,6 +1344,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1316,6 +1344,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1316 | try zig_object.addAtomsToRelaSections(self); | 1344 | try zig_object.addAtomsToRelaSections(self); |
| 1317 | try self.updateSectionSizesObject(); | 1345 | try self.updateSectionSizesObject(); |
| 1318 | | 1346 | |
| | 1347 | try self.allocateAllocSectionsObject(); |
| 1319 | try self.allocateNonAllocSections(); | 1348 | try self.allocateNonAllocSections(); |
| 1320 | | 1349 | |
| 1321 | if (build_options.enable_logging) { | 1350 | if (build_options.enable_logging) { |
| ... | @@ -1325,14 +1354,15 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1325,14 +1354,15 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1325 | try self.writeSyntheticSectionsObject(); | 1354 | try self.writeSyntheticSectionsObject(); |
| 1326 | try self.writeShdrTable(); | 1355 | try self.writeShdrTable(); |
| 1327 | try self.writeElfHeader(); | 1356 | try self.writeElfHeader(); |
| | 1357 | |
| | 1358 | // TODO we can avoid reading in the file contents we just wrote if we give the linker |
| | 1359 | // ability to write directly to a buffer. |
| | 1360 | try zig_object.readFileContents(self); |
| 1328 | } | 1361 | } |
| 1329 | | 1362 | |
| 1330 | var files = std.ArrayList(File.Index).init(gpa); | 1363 | var files = std.ArrayList(File.Index).init(gpa); |
| 1331 | defer files.deinit(); | 1364 | defer files.deinit(); |
| 1332 | try files.ensureTotalCapacityPrecise(self.objects.items.len + 1); | 1365 | try files.ensureTotalCapacityPrecise(self.objects.items.len + 1); |
| 1333 | // Note to self: we currently must have ZigObject written out first as we write the object | | |
| 1334 | // file into the same file descriptor and then re-read its contents. | | |
| 1335 | // TODO implement writing ZigObject to a buffer instead of file. | | |
| 1336 | if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index); | 1366 | if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index); |
| 1337 | for (self.objects.items) |index| files.appendAssumeCapacity(index); | 1367 | for (self.objects.items) |index| files.appendAssumeCapacity(index); |
| 1338 | | 1368 | |
| ... | @@ -1353,7 +1383,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1353,7 +1383,7 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1353 | for (files.items) |index| { | 1383 | for (files.items) |index| { |
| 1354 | const file_ptr = self.file(index).?; | 1384 | const file_ptr = self.file(index).?; |
| 1355 | try file_ptr.updateArStrtab(gpa, &ar_strtab); | 1385 | try file_ptr.updateArStrtab(gpa, &ar_strtab); |
| 1356 | file_ptr.updateArSize(self); | 1386 | file_ptr.updateArSize(); |
| 1357 | } | 1387 | } |
| 1358 | | 1388 | |
| 1359 | // Update file offsets of contributing objects. | 1389 | // Update file offsets of contributing objects. |
| ... | @@ -1405,13 +1435,15 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -1405,13 +1435,15 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 1405 | // Write object files | 1435 | // Write object files |
| 1406 | for (files.items) |index| { | 1436 | for (files.items) |index| { |
| 1407 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | 1437 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); |
| 1408 | try self.file(index).?.writeAr(self, buffer.writer()); | 1438 | try self.file(index).?.writeAr(buffer.writer()); |
| 1409 | } | 1439 | } |
| 1410 | | 1440 | |
| 1411 | assert(buffer.items.len == total_size); | 1441 | assert(buffer.items.len == total_size); |
| 1412 | | 1442 | |
| 1413 | try self.base.file.?.setEndPos(total_size); | 1443 | try self.base.file.?.setEndPos(total_size); |
| 1414 | try self.base.file.?.pwriteAll(buffer.items, 0); | 1444 | try self.base.file.?.pwriteAll(buffer.items, 0); |
| | 1445 | |
| | 1446 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| 1415 | } | 1447 | } |
| 1416 | | 1448 | |
| 1417 | pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 1449 | pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| ... | @@ -1432,16 +1464,25 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) | ... | @@ -1432,16 +1464,25 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) |
| 1432 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | 1464 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| 1433 | | 1465 | |
| 1434 | for (positionals.items) |obj| { | 1466 | for (positionals.items) |obj| { |
| 1435 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1467 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { |
| 1436 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1468 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported |
| 1437 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1469 | else => |e| try self.reportParseError( |
| | 1470 | obj.path, |
| | 1471 | "unexpected error: parsing input file failed with error {s}", |
| | 1472 | .{@errorName(e)}, |
| | 1473 | ), |
| | 1474 | }; |
| 1438 | } | 1475 | } |
| 1439 | | 1476 | |
| | 1477 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| | 1478 | |
| 1440 | // Init all objects | 1479 | // Init all objects |
| 1441 | for (self.objects.items) |index| { | 1480 | for (self.objects.items) |index| { |
| 1442 | try self.file(index).?.object.init(self); | 1481 | try self.file(index).?.object.init(self); |
| 1443 | } | 1482 | } |
| 1444 | | 1483 | |
| | 1484 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| | 1485 | |
| 1445 | // Now, we are ready to resolve the symbols across all input files. | 1486 | // Now, we are ready to resolve the symbols across all input files. |
| 1446 | // We will first resolve the files in the ZigObject, next in the parsed | 1487 | // We will first resolve the files in the ZigObject, next in the parsed |
| 1447 | // input Object files. | 1488 | // input Object files. |
| ... | @@ -1473,6 +1514,8 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) | ... | @@ -1473,6 +1514,8 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) |
| 1473 | try self.writeSyntheticSectionsObject(); | 1514 | try self.writeSyntheticSectionsObject(); |
| 1474 | try self.writeShdrTable(); | 1515 | try self.writeShdrTable(); |
| 1475 | try self.writeElfHeader(); | 1516 | try self.writeElfHeader(); |
| | 1517 | |
| | 1518 | if (self.misc_errors.items.len > 0) return error.FlushFailure; |
| 1476 | } | 1519 | } |
| 1477 | | 1520 | |
| 1478 | /// --verbose-link output | 1521 | /// --verbose-link output |
| ... | @@ -1760,7 +1803,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1760,7 +1803,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1760 | } | 1803 | } |
| 1761 | | 1804 | |
| 1762 | const ParseError = error{ | 1805 | const ParseError = error{ |
| 1763 | UnknownFileType, | 1806 | MalformedObject, |
| | 1807 | MalformedArchive, |
| 1764 | InvalidCpuArch, | 1808 | InvalidCpuArch, |
| 1765 | OutOfMemory, | 1809 | OutOfMemory, |
| 1766 | Overflow, | 1810 | Overflow, |
| ... | @@ -1771,34 +1815,30 @@ const ParseError = error{ | ... | @@ -1771,34 +1815,30 @@ const ParseError = error{ |
| 1771 | InvalidCharacter, | 1815 | InvalidCharacter, |
| 1772 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; | 1816 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; |
| 1773 | | 1817 | |
| 1774 | fn parsePositional(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1818 | fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1775 | const tracy = trace(@src()); | 1819 | const tracy = trace(@src()); |
| 1776 | defer tracy.end(); | 1820 | defer tracy.end(); |
| 1777 | if (try Object.isObject(path)) { | 1821 | if (try Object.isObject(path)) { |
| 1778 | try self.parseObject(path, ctx); | 1822 | try self.parseObject(path); |
| 1779 | } else { | 1823 | } else { |
| 1780 | try self.parseLibrary(.{ .path = path }, must_link, ctx); | 1824 | try self.parseLibrary(.{ .path = path }, must_link); |
| 1781 | } | 1825 | } |
| 1782 | } | 1826 | } |
| 1783 | | 1827 | |
| 1784 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1828 | fn parseLibrary(self: *Elf, lib: SystemLib, must_link: bool) ParseError!void { |
| 1785 | const tracy = trace(@src()); | 1829 | const tracy = trace(@src()); |
| 1786 | defer tracy.end(); | 1830 | defer tracy.end(); |
| 1787 | | 1831 | |
| 1788 | if (try Archive.isArchive(lib.path)) { | 1832 | if (try Archive.isArchive(lib.path)) { |
| 1789 | try self.parseArchive(lib.path, must_link, ctx); | 1833 | try self.parseArchive(lib.path, must_link); |
| 1790 | } else if (try SharedObject.isSharedObject(lib.path)) { | 1834 | } else if (try SharedObject.isSharedObject(lib.path)) { |
| 1791 | try self.parseSharedObject(lib, ctx); | 1835 | try self.parseSharedObject(lib); |
| 1792 | } else { | 1836 | } else { |
| 1793 | // TODO if the script has a top-level comment identifying it as GNU ld script, | 1837 | try self.parseLdScript(lib); |
| 1794 | // then report parse errors. Otherwise return UnknownFileType. | | |
| 1795 | self.parseLdScript(lib, ctx) catch |err| switch (err) { | | |
| 1796 | else => return error.UnknownFileType, | | |
| 1797 | }; | | |
| 1798 | } | 1838 | } |
| 1799 | } | 1839 | } |
| 1800 | | 1840 | |
| 1801 | fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!void { | 1841 | fn parseObject(self: *Elf, path: []const u8) ParseError!void { |
| 1802 | const tracy = trace(@src()); | 1842 | const tracy = trace(@src()); |
| 1803 | defer tracy.end(); | 1843 | defer tracy.end(); |
| 1804 | | 1844 | |
| ... | @@ -1816,12 +1856,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1816,12 +1856,9 @@ fn parseObject(self: *Elf, path: []const u8, ctx: *ParseErrorCtx) ParseError!voi |
| 1816 | | 1856 | |
| 1817 | const object = self.file(index).?.object; | 1857 | const object = self.file(index).?.object; |
| 1818 | try object.parse(self); | 1858 | try object.parse(self); |
| 1819 | | | |
| 1820 | ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; | | |
| 1821 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; | | |
| 1822 | } | 1859 | } |
| 1823 | | 1860 | |
| 1824 | fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorCtx) ParseError!void { | 1861 | fn parseArchive(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1825 | const tracy = trace(@src()); | 1862 | const tracy = trace(@src()); |
| 1826 | defer tracy.end(); | 1863 | defer tracy.end(); |
| 1827 | | 1864 | |
| ... | @@ -1844,13 +1881,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC | ... | @@ -1844,13 +1881,10 @@ fn parseArchive(self: *Elf, path: []const u8, must_link: bool, ctx: *ParseErrorC |
| 1844 | object.alive = must_link; | 1881 | object.alive = must_link; |
| 1845 | try object.parse(self); | 1882 | try object.parse(self); |
| 1846 | try self.objects.append(gpa, index); | 1883 | try self.objects.append(gpa, index); |
| 1847 | | | |
| 1848 | ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; | | |
| 1849 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; | | |
| 1850 | } | 1884 | } |
| 1851 | } | 1885 | } |
| 1852 | | 1886 | |
| 1853 | fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { | 1887 | fn parseSharedObject(self: *Elf, lib: SystemLib) ParseError!void { |
| 1854 | const tracy = trace(@src()); | 1888 | const tracy = trace(@src()); |
| 1855 | defer tracy.end(); | 1889 | defer tracy.end(); |
| 1856 | | 1890 | |
| ... | @@ -1870,12 +1904,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError | ... | @@ -1870,12 +1904,9 @@ fn parseSharedObject(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError |
| 1870 | | 1904 | |
| 1871 | const shared_object = self.file(index).?.shared_object; | 1905 | const shared_object = self.file(index).?.shared_object; |
| 1872 | try shared_object.parse(self); | 1906 | try shared_object.parse(self); |
| 1873 | | | |
| 1874 | ctx.detected_cpu_arch = shared_object.header.?.e_machine.toTargetCpuArch().?; | | |
| 1875 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; | | |
| 1876 | } | 1907 | } |
| 1877 | | 1908 | |
| 1878 | fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!void { | 1909 | fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1879 | const tracy = trace(@src()); | 1910 | const tracy = trace(@src()); |
| 1880 | defer tracy.end(); | 1911 | defer tracy.end(); |
| 1881 | | 1912 | |
| ... | @@ -1885,15 +1916,10 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1885,15 +1916,10 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1885 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); | 1916 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); |
| 1886 | defer gpa.free(data); | 1917 | defer gpa.free(data); |
| 1887 | | 1918 | |
| 1888 | var script = LdScript{}; | 1919 | var script = LdScript{ .path = lib.path }; |
| 1889 | defer script.deinit(gpa); | 1920 | defer script.deinit(gpa); |
| 1890 | try script.parse(data, self); | 1921 | try script.parse(data, self); |
| 1891 | | 1922 | |
| 1892 | if (script.cpu_arch) |cpu_arch| { | | |
| 1893 | ctx.detected_cpu_arch = cpu_arch; | | |
| 1894 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; | | |
| 1895 | } | | |
| 1896 | | | |
| 1897 | const lib_dirs = self.base.options.lib_dirs; | 1923 | const lib_dirs = self.base.options.lib_dirs; |
| 1898 | | 1924 | |
| 1899 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | 1925 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -1947,11 +1973,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi | ... | @@ -1947,11 +1973,17 @@ fn parseLdScript(self: *Elf, lib: SystemLib, ctx: *ParseErrorCtx) ParseError!voi |
| 1947 | } | 1973 | } |
| 1948 | | 1974 | |
| 1949 | const full_path = test_path.items; | 1975 | const full_path = test_path.items; |
| 1950 | var scr_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | | |
| 1951 | self.parseLibrary(.{ | 1976 | self.parseLibrary(.{ |
| 1952 | .needed = scr_obj.needed, | 1977 | .needed = scr_obj.needed, |
| 1953 | .path = full_path, | 1978 | .path = full_path, |
| 1954 | }, false, &scr_ctx) catch |err| try self.handleAndReportParseError(full_path, err, &scr_ctx); | 1979 | }, false) catch |err| switch (err) { |
| | 1980 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported |
| | 1981 | else => |e| try self.reportParseError( |
| | 1982 | full_path, |
| | 1983 | "unexpected error: parsing library failed with error {s}", |
| | 1984 | .{@errorName(e)}, |
| | 1985 | ), |
| | 1986 | }; |
| 1955 | } | 1987 | } |
| 1956 | } | 1988 | } |
| 1957 | | 1989 | |
| ... | @@ -2177,7 +2209,7 @@ fn scanRelocs(self: *Elf) !void { | ... | @@ -2177,7 +2209,7 @@ fn scanRelocs(self: *Elf) !void { |
| 2177 | try object.scanRelocs(self, &undefs); | 2209 | try object.scanRelocs(self, &undefs); |
| 2178 | } | 2210 | } |
| 2179 | | 2211 | |
| 2180 | try self.reportUndefined(&undefs); | 2212 | try self.reportUndefinedSymbols(&undefs); |
| 2181 | | 2213 | |
| 2182 | for (self.symbols.items, 0..) |*sym, i| { | 2214 | for (self.symbols.items, 0..) |*sym, i| { |
| 2183 | const index = @as(u32, @intCast(i)); | 2215 | const index = @as(u32, @intCast(i)); |
| ... | @@ -2789,7 +2821,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v | ... | @@ -2789,7 +2821,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 2789 | })); | 2821 | })); |
| 2790 | } else { | 2822 | } else { |
| 2791 | self.error_flags.missing_libc = true; | 2823 | self.error_flags.missing_libc = true; |
| 2792 | return error.FlushFailure; | | |
| 2793 | } | 2824 | } |
| 2794 | } | 2825 | } |
| 2795 | } | 2826 | } |
| ... | @@ -2945,6 +2976,7 @@ fn writeShdrTable(self: *Elf) !void { | ... | @@ -2945,6 +2976,7 @@ fn writeShdrTable(self: *Elf) !void { |
| 2945 | defer gpa.free(buf); | 2976 | defer gpa.free(buf); |
| 2946 | | 2977 | |
| 2947 | for (buf, 0..) |*shdr, i| { | 2978 | for (buf, 0..) |*shdr, i| { |
| | 2979 | assert(self.shdrs.items[i].sh_offset != math.maxInt(u64)); |
| 2948 | shdr.* = shdrTo32(self.shdrs.items[i]); | 2980 | shdr.* = shdrTo32(self.shdrs.items[i]); |
| 2949 | if (foreign_endian) { | 2981 | if (foreign_endian) { |
| 2950 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); | 2982 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); |
| ... | @@ -2957,6 +2989,7 @@ fn writeShdrTable(self: *Elf) !void { | ... | @@ -2957,6 +2989,7 @@ fn writeShdrTable(self: *Elf) !void { |
| 2957 | defer gpa.free(buf); | 2989 | defer gpa.free(buf); |
| 2958 | | 2990 | |
| 2959 | for (buf, 0..) |*shdr, i| { | 2991 | for (buf, 0..) |*shdr, i| { |
| | 2992 | assert(self.shdrs.items[i].sh_offset != math.maxInt(u64)); |
| 2960 | shdr.* = self.shdrs.items[i]; | 2993 | shdr.* = self.shdrs.items[i]; |
| 2961 | if (foreign_endian) { | 2994 | if (foreign_endian) { |
| 2962 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); | 2995 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); |
| ... | @@ -3007,6 +3040,8 @@ fn writePhdrTable(self: *Elf) !void { | ... | @@ -3007,6 +3040,8 @@ fn writePhdrTable(self: *Elf) !void { |
| 3007 | } | 3040 | } |
| 3008 | | 3041 | |
| 3009 | fn writeElfHeader(self: *Elf) !void { | 3042 | fn writeElfHeader(self: *Elf) !void { |
| | 3043 | if (self.misc_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable |
| | 3044 | |
| 3010 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | 3045 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 3011 | | 3046 | |
| 3012 | var index: usize = 0; | 3047 | var index: usize = 0; |
| ... | @@ -4740,7 +4775,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4740,7 +4775,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4740 | try self.base.file.?.pwriteAll(buffer, sh_offset); | 4775 | try self.base.file.?.pwriteAll(buffer, sh_offset); |
| 4741 | } | 4776 | } |
| 4742 | | 4777 | |
| 4743 | try self.reportUndefined(&undefs); | 4778 | try self.reportUndefinedSymbols(&undefs); |
| 4744 | } | 4779 | } |
| 4745 | | 4780 | |
| 4746 | fn writeAtomsObject(self: *Elf) !void { | 4781 | fn writeAtomsObject(self: *Elf) !void { |
| ... | @@ -6003,7 +6038,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { | ... | @@ -6003,7 +6038,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { |
| 6003 | return off; | 6038 | return off; |
| 6004 | } | 6039 | } |
| 6005 | | 6040 | |
| 6006 | fn reportUndefined(self: *Elf, undefs: anytype) !void { | 6041 | fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { |
| 6007 | const gpa = self.base.allocator; | 6042 | const gpa = self.base.allocator; |
| 6008 | const max_notes = 4; | 6043 | const max_notes = 4; |
| 6009 | | 6044 | |
| ... | @@ -6045,41 +6080,26 @@ fn reportMissingLibraryError( | ... | @@ -6045,41 +6080,26 @@ fn reportMissingLibraryError( |
| 6045 | } | 6080 | } |
| 6046 | } | 6081 | } |
| 6047 | | 6082 | |
| 6048 | const ParseErrorCtx = struct { | 6083 | pub fn reportParseError( |
| 6049 | detected_cpu_arch: std.Target.Cpu.Arch, | | |
| 6050 | }; | | |
| 6051 | | | |
| 6052 | fn handleAndReportParseError( | | |
| 6053 | self: *Elf, | 6084 | self: *Elf, |
| 6054 | path: []const u8, | 6085 | path: []const u8, |
| 6055 | err: ParseError, | 6086 | comptime format: []const u8, |
| 6056 | ctx: *const ParseErrorCtx, | 6087 | args: anytype, |
| 6057 | ) error{OutOfMemory}!void { | 6088 | ) error{OutOfMemory}!void { |
| 6058 | const cpu_arch = self.base.options.target.cpu.arch; | 6089 | var err = try self.addErrorWithNotes(1); |
| 6059 | switch (err) { | 6090 | try err.addMsg(self, format, args); |
| 6060 | error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), | 6091 | try err.addNote(self, "while parsing {s}", .{path}); |
| 6061 | error.InvalidCpuArch => try self.reportParseError( | 6092 | } |
| 6062 | path, | 6093 | |
| 6063 | "invalid cpu architecture: expected '{s}', but found '{s}'", | 6094 | pub fn reportParseError2( |
| 6064 | .{ @tagName(cpu_arch), @tagName(ctx.detected_cpu_arch) }, | | |
| 6065 | ), | | |
| 6066 | else => |e| try self.reportParseError( | | |
| 6067 | path, | | |
| 6068 | "unexpected error: parsing object failed with error {s}", | | |
| 6069 | .{@errorName(e)}, | | |
| 6070 | ), | | |
| 6071 | } | | |
| 6072 | } | | |
| 6073 | | | |
| 6074 | fn reportParseError( | | |
| 6075 | self: *Elf, | 6095 | self: *Elf, |
| 6076 | path: []const u8, | 6096 | file_index: File.Index, |
| 6077 | comptime format: []const u8, | 6097 | comptime format: []const u8, |
| 6078 | args: anytype, | 6098 | args: anytype, |
| 6079 | ) error{OutOfMemory}!void { | 6099 | ) error{OutOfMemory}!void { |
| 6080 | var err = try self.addErrorWithNotes(1); | 6100 | var err = try self.addErrorWithNotes(1); |
| 6081 | try err.addMsg(self, format, args); | 6101 | try err.addMsg(self, format, args); |
| 6082 | try err.addNote(self, "while parsing {s}", .{path}); | 6102 | try err.addNote(self, "while parsing {}", .{self.file(file_index).?.fmtPath()}); |
| 6083 | } | 6103 | } |
| 6084 | | 6104 | |
| 6085 | const FormatShdrCtx = struct { | 6105 | const FormatShdrCtx = struct { |