| ... | ... | @@ -81,6 +81,10 @@ lazy_bind: LazyBindSection = .{}, |
| 81 | 81 | export_trie: ExportTrieSection = .{}, |
| 82 | 82 | unwind_info: UnwindInfo = .{}, |
| 83 | 83 | |
| 84 | has_tlv: bool = false, |
| 85 | binds_to_weak: bool = false, |
| 86 | weak_defines: bool = false, |
| 87 | |
| 84 | 88 | /// Options |
| 85 | 89 | /// SDK layout |
| 86 | 90 | sdk_layout: ?SdkLayout, |
| ... | ... | @@ -513,6 +517,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 513 | 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 | 528 | state_log.debug("{}", .{self.dumpState()}); |
| 517 | 529 | |
| 518 | 530 | @panic("TODO"); |
| ... | ... | @@ -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 | 1559 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { |
| 1422 | 1560 | _ = self; |
| 1423 | 1561 | _ = atom_index; |
| ... | ... | @@ -1899,33 +2037,10 @@ fn reportDependencyError( |
| 1899 | 2037 | }); |
| 1900 | 2038 | } |
| 1901 | 2039 | |
| 1902 | | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 1903 | | const comp = self.base.comp; |
| 1904 | | const gpa = comp.gpa; |
| 1905 | | const count = self.unresolved.count(); |
| 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 | | } |
| 2040 | fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytype) error{OutOfMemory}!void { |
| 2041 | var err = try self.addErrorWithNotes(1); |
| 2042 | try err.addMsg(self, format, args); |
| 2043 | try err.addNote(self, "please report this as a linker bug on https://github.com/ziglang/zig/issues/new/choose", .{}); |
| 1929 | 2044 | } |
| 1930 | 2045 | |
| 1931 | 2046 | // fn reportSymbolCollision( |