| ... | @@ -81,6 +81,10 @@ lazy_bind: LazyBindSection = .{}, | ... | @@ -81,6 +81,10 @@ lazy_bind: LazyBindSection = .{}, |
| 81 | export_trie: ExportTrieSection = .{}, | 81 | export_trie: ExportTrieSection = .{}, |
| 82 | unwind_info: UnwindInfo = .{}, | 82 | unwind_info: UnwindInfo = .{}, |
| 83 | | 83 | |
| | 84 | has_tlv: bool = false, |
| | 85 | binds_to_weak: bool = false, |
| | 86 | weak_defines: bool = false, |
| | 87 | |
| 84 | /// Options | 88 | /// Options |
| 85 | /// SDK layout | 89 | /// SDK layout |
| 86 | sdk_layout: ?SdkLayout, | 90 | sdk_layout: ?SdkLayout, |
| ... | @@ -513,6 +517,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -513,6 +517,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 513 | dylib.ordinal = @intCast(ord); | 517 | dylib.ordinal = @intCast(ord); |
| 514 | } | 518 | } |
| 515 | | 519 | |
| | 520 | self.scanRelocs() catch |err| switch (err) { |
| | 521 | error.HasUndefinedSymbols => return error.FlushFailure, |
| | 522 | else => |e| { |
| | 523 | try self.reportUnexpectedError("unexpected error while scanning relocations", .{}); |
| | 524 | return e; |
| | 525 | }, |
| | 526 | }; |
| | 527 | |
| 516 | state_log.debug("{}", .{self.dumpState()}); | 528 | state_log.debug("{}", .{self.dumpState()}); |
| 517 | | 529 | |
| 518 | @panic("TODO"); | 530 | @panic("TODO"); |
| ... | @@ -1418,6 +1430,132 @@ fn deadStripDylibs(self: *MachO) void { | ... | @@ -1418,6 +1430,132 @@ fn deadStripDylibs(self: *MachO) void { |
| 1418 | } | 1430 | } |
| 1419 | } | 1431 | } |
| 1420 | | 1432 | |
| | 1433 | fn scanRelocs(self: *MachO) !void { |
| | 1434 | const tracy = trace(@src()); |
| | 1435 | defer tracy.end(); |
| | 1436 | |
| | 1437 | for (self.objects.items) |index| { |
| | 1438 | try self.getFile(index).?.object.scanRelocs(self); |
| | 1439 | } |
| | 1440 | |
| | 1441 | try self.reportUndefs(); |
| | 1442 | |
| | 1443 | if (self.entry_index) |index| { |
| | 1444 | const sym = self.getSymbol(index); |
| | 1445 | if (sym.getFile(self) != null) { |
| | 1446 | if (sym.flags.import) sym.flags.stubs = true; |
| | 1447 | } |
| | 1448 | } |
| | 1449 | |
| | 1450 | if (self.dyld_stub_binder_index) |index| { |
| | 1451 | const sym = self.getSymbol(index); |
| | 1452 | if (sym.getFile(self) != null) sym.flags.got = true; |
| | 1453 | } |
| | 1454 | |
| | 1455 | if (self.objc_msg_send_index) |index| { |
| | 1456 | const sym = self.getSymbol(index); |
| | 1457 | if (sym.getFile(self) != null) |
| | 1458 | sym.flags.got = true; // TODO is it always needed, or only if we are synthesising fast stubs? |
| | 1459 | } |
| | 1460 | |
| | 1461 | for (self.symbols.items, 0..) |*symbol, i| { |
| | 1462 | const index = @as(Symbol.Index, @intCast(i)); |
| | 1463 | if (symbol.flags.got) { |
| | 1464 | log.debug("'{s}' needs GOT", .{symbol.getName(self)}); |
| | 1465 | try self.got.addSymbol(index, self); |
| | 1466 | } |
| | 1467 | if (symbol.flags.stubs) { |
| | 1468 | log.debug("'{s}' needs STUBS", .{symbol.getName(self)}); |
| | 1469 | try self.stubs.addSymbol(index, self); |
| | 1470 | } |
| | 1471 | if (symbol.flags.tlv_ptr) { |
| | 1472 | log.debug("'{s}' needs TLV pointer", .{symbol.getName(self)}); |
| | 1473 | try self.tlv_ptr.addSymbol(index, self); |
| | 1474 | } |
| | 1475 | if (symbol.flags.objc_stubs) { |
| | 1476 | log.debug("'{s}' needs OBJC STUBS", .{symbol.getName(self)}); |
| | 1477 | try self.objc_stubs.addSymbol(index, self); |
| | 1478 | } |
| | 1479 | } |
| | 1480 | } |
| | 1481 | |
| | 1482 | fn reportUndefs(self: *MachO) !void { |
| | 1483 | const tracy = trace(@src()); |
| | 1484 | defer tracy.end(); |
| | 1485 | |
| | 1486 | switch (self.undefined_treatment) { |
| | 1487 | .dynamic_lookup, .suppress => return, |
| | 1488 | .@"error", .warn => {}, |
| | 1489 | } |
| | 1490 | |
| | 1491 | const max_notes = 4; |
| | 1492 | |
| | 1493 | var has_undefs = false; |
| | 1494 | var it = self.undefs.iterator(); |
| | 1495 | while (it.next()) |entry| { |
| | 1496 | const undef_sym = self.getSymbol(entry.key_ptr.*); |
| | 1497 | const notes = entry.value_ptr.*; |
| | 1498 | const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); |
| | 1499 | |
| | 1500 | var err = try self.addErrorWithNotes(nnotes); |
| | 1501 | try err.addMsg(self, "undefined symbol: {s}", .{undef_sym.getName(self)}); |
| | 1502 | has_undefs = true; |
| | 1503 | |
| | 1504 | var inote: usize = 0; |
| | 1505 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { |
| | 1506 | const atom = self.getAtom(notes.items[inote]).?; |
| | 1507 | const file = atom.getFile(self); |
| | 1508 | try err.addNote(self, "referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) }); |
| | 1509 | } |
| | 1510 | |
| | 1511 | if (notes.items.len > max_notes) { |
| | 1512 | const remaining = notes.items.len - max_notes; |
| | 1513 | try err.addNote(self, "referenced {d} more times", .{remaining}); |
| | 1514 | } |
| | 1515 | } |
| | 1516 | |
| | 1517 | for (self.undefined_symbols.items) |index| { |
| | 1518 | const sym = self.getSymbol(index); |
| | 1519 | if (sym.getFile(self) != null) continue; // If undefined in an object file, will be reported above |
| | 1520 | has_undefs = true; |
| | 1521 | var err = try self.addErrorWithNotes(1); |
| | 1522 | try err.addMsg(self, "undefined symbol: {s}", .{sym.getName(self)}); |
| | 1523 | try err.addNote(self, "-u command line option", .{}); |
| | 1524 | } |
| | 1525 | |
| | 1526 | if (self.entry_index) |index| { |
| | 1527 | const sym = self.getSymbol(index); |
| | 1528 | if (sym.getFile(self) == null) { |
| | 1529 | has_undefs = true; |
| | 1530 | var err = try self.addErrorWithNotes(1); |
| | 1531 | try err.addMsg(self, "undefined symbol: {s}", .{sym.getName(self)}); |
| | 1532 | try err.addNote(self, "implicit entry/start for main executable", .{}); |
| | 1533 | } |
| | 1534 | } |
| | 1535 | |
| | 1536 | if (self.dyld_stub_binder_index) |index| { |
| | 1537 | const sym = self.getSymbol(index); |
| | 1538 | if (sym.getFile(self) == null and self.stubs_sect_index != null) { |
| | 1539 | has_undefs = true; |
| | 1540 | var err = try self.addErrorWithNotes(1); |
| | 1541 | try err.addMsg(self, "undefined symbol: {s}", .{sym.getName(self)}); |
| | 1542 | try err.addNote(self, "implicit -u command line option", .{}); |
| | 1543 | } |
| | 1544 | } |
| | 1545 | |
| | 1546 | if (self.objc_msg_send_index) |index| { |
| | 1547 | const sym = self.getSymbol(index); |
| | 1548 | if (sym.getFile(self) == null and self.objc_stubs_sect_index != null) { |
| | 1549 | has_undefs = true; |
| | 1550 | var err = try self.addErrorWithNotes(1); |
| | 1551 | try err.addMsg(self, "undefined symbol: {s}", .{sym.getName(self)}); |
| | 1552 | try err.addNote(self, "implicit -u command line option", .{}); |
| | 1553 | } |
| | 1554 | } |
| | 1555 | |
| | 1556 | if (has_undefs) return error.HasUndefinedSymbols; |
| | 1557 | } |
| | 1558 | |
| 1421 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { | 1559 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { |
| 1422 | _ = self; | 1560 | _ = self; |
| 1423 | _ = atom_index; | 1561 | _ = atom_index; |
| ... | @@ -1899,33 +2037,10 @@ fn reportDependencyError( | ... | @@ -1899,33 +2037,10 @@ fn reportDependencyError( |
| 1899 | }); | 2037 | }); |
| 1900 | } | 2038 | } |
| 1901 | | 2039 | |
| 1902 | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { | 2040 | fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytype) error{OutOfMemory}!void { |
| 1903 | const comp = self.base.comp; | 2041 | var err = try self.addErrorWithNotes(1); |
| 1904 | const gpa = comp.gpa; | 2042 | try err.addMsg(self, format, args); |
| 1905 | const count = self.unresolved.count(); | 2043 | try err.addNote(self, "please report this as a linker bug on https://github.com/ziglang/zig/issues/new/choose", .{}); |
| 1906 | try comp.link_errors.ensureUnusedCapacity(gpa, count); | | |
| 1907 | | | |
| 1908 | for (self.unresolved.keys()) |global_index| { | | |
| 1909 | const global = self.globals.items[global_index]; | | |
| 1910 | const sym_name = self.getSymbolName(global); | | |
| 1911 | | | |
| 1912 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, 1); | | |
| 1913 | defer notes.deinit(); | | |
| 1914 | | | |
| 1915 | if (global.getFile()) |file| { | | |
| 1916 | const note = try std.fmt.allocPrint(gpa, "referenced in {s}", .{ | | |
| 1917 | self.objects.items[file].name, | | |
| 1918 | }); | | |
| 1919 | notes.appendAssumeCapacity(.{ .msg = note }); | | |
| 1920 | } | | |
| 1921 | | | |
| 1922 | var err_msg = link.File.ErrorMsg{ | | |
| 1923 | .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}), | | |
| 1924 | }; | | |
| 1925 | err_msg.notes = try notes.toOwnedSlice(); | | |
| 1926 | | | |
| 1927 | comp.link_errors.appendAssumeCapacity(err_msg); | | |
| 1928 | } | | |
| 1929 | } | 2044 | } |
| 1930 | | 2045 | |
| 1931 | // fn reportSymbolCollision( | 2046 | // fn reportSymbolCollision( |