| ... | @@ -27,7 +27,7 @@ sections: std.MultiArrayList(Section) = .{}, | ... | @@ -27,7 +27,7 @@ sections: std.MultiArrayList(Section) = .{}, |
| 27 | resolver: SymbolResolver = .{}, | 27 | resolver: SymbolResolver = .{}, |
| 28 | /// This table will be populated after `scanRelocs` has run. | 28 | /// This table will be populated after `scanRelocs` has run. |
| 29 | /// Key is symbol index. | 29 | /// Key is symbol index. |
| 30 | undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(Ref)) = .empty, | 30 | undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, UndefRefs) = .empty, |
| 31 | undefs_mutex: std.Thread.Mutex = .{}, | 31 | undefs_mutex: std.Thread.Mutex = .{}, |
| 32 | dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)) = .empty, | 32 | dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)) = .empty, |
| 33 | dupes_mutex: std.Thread.Mutex = .{}, | 33 | dupes_mutex: std.Thread.Mutex = .{}, |
| ... | @@ -1470,6 +1470,9 @@ fn scanRelocs(self: *MachO) !void { | ... | @@ -1470,6 +1470,9 @@ fn scanRelocs(self: *MachO) !void { |
| 1470 | | 1470 | |
| 1471 | if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure; | 1471 | if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure; |
| 1472 | | 1472 | |
| | 1473 | if (self.getInternalObject()) |obj| { |
| | 1474 | try obj.checkUndefs(self); |
| | 1475 | } |
| 1473 | try self.reportUndefs(); | 1476 | try self.reportUndefs(); |
| 1474 | | 1477 | |
| 1475 | if (self.getZigObject()) |zo| { | 1478 | if (self.getZigObject()) |zo| { |
| ... | @@ -1530,29 +1533,43 @@ fn reportUndefs(self: *MachO) !void { | ... | @@ -1530,29 +1533,43 @@ fn reportUndefs(self: *MachO) !void { |
| 1530 | } | 1533 | } |
| 1531 | }.lessThan; | 1534 | }.lessThan; |
| 1532 | | 1535 | |
| 1533 | for (self.undefs.values()) |*refs| { | 1536 | for (self.undefs.values()) |*undefs| switch (undefs.*) { |
| 1534 | mem.sort(Ref, refs.items, {}, refLessThan); | 1537 | .refs => |refs| mem.sort(Ref, refs.items, {}, refLessThan), |
| 1535 | } | 1538 | else => {}, |
| | 1539 | }; |
| 1536 | | 1540 | |
| 1537 | for (keys.items) |key| { | 1541 | for (keys.items) |key| { |
| 1538 | const undef_sym = self.resolver.keys.items[key - 1]; | 1542 | const undef_sym = self.resolver.keys.items[key - 1]; |
| 1539 | const notes = self.undefs.get(key).?; | 1543 | const notes = self.undefs.get(key).?; |
| 1540 | const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); | 1544 | const nnotes = nnotes: { |
| | 1545 | const nnotes = switch (notes) { |
| | 1546 | .refs => |refs| refs.items.len, |
| | 1547 | else => 1, |
| | 1548 | }; |
| | 1549 | break :nnotes @min(nnotes, max_notes) + @intFromBool(nnotes > max_notes); |
| | 1550 | }; |
| 1541 | | 1551 | |
| 1542 | var err = try self.base.addErrorWithNotes(nnotes); | 1552 | var err = try self.base.addErrorWithNotes(nnotes); |
| 1543 | try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)}); | 1553 | try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)}); |
| 1544 | | 1554 | |
| 1545 | var inote: usize = 0; | 1555 | switch (notes) { |
| 1546 | while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { | 1556 | .force_undefined => try err.addNote("referenced with linker flag -u", .{}), |
| 1547 | const note = notes.items[inote]; | 1557 | .entry => try err.addNote("referenced with linker flag -e", .{}), |
| 1548 | const file = self.getFile(note.file).?; | 1558 | .dyld_stub_binder, .objc_msgsend => try err.addNote("referenced implicitly", .{}), |
| 1549 | const atom = note.getAtom(self).?; | 1559 | .refs => |refs| { |
| 1550 | try err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) }); | 1560 | var inote: usize = 0; |
| 1551 | } | 1561 | while (inote < @min(refs.items.len, max_notes)) : (inote += 1) { |
| | 1562 | const ref = refs.items[inote]; |
| | 1563 | const file = self.getFile(ref.file).?; |
| | 1564 | const atom = ref.getAtom(self).?; |
| | 1565 | try err.addNote("referenced by {}:{s}", .{ file.fmtPath(), atom.getName(self) }); |
| | 1566 | } |
| 1552 | | 1567 | |
| 1553 | if (notes.items.len > max_notes) { | 1568 | if (refs.items.len > max_notes) { |
| 1554 | const remaining = notes.items.len - max_notes; | 1569 | const remaining = refs.items.len - max_notes; |
| 1555 | try err.addNote("referenced {d} more times", .{remaining}); | 1570 | try err.addNote("referenced {d} more times", .{remaining}); |
| | 1571 | } |
| | 1572 | }, |
| 1556 | } | 1573 | } |
| 1557 | } | 1574 | } |
| 1558 | | 1575 | |
| ... | @@ -4584,78 +4601,20 @@ pub const String = struct { | ... | @@ -4584,78 +4601,20 @@ pub const String = struct { |
| 4584 | len: u32 = 0, | 4601 | len: u32 = 0, |
| 4585 | }; | 4602 | }; |
| 4586 | | 4603 | |
| 4587 | const MachO = @This(); | 4604 | pub const UndefRefs = union(enum) { |
| 4588 | | 4605 | force_undefined, |
| 4589 | const std = @import("std"); | 4606 | entry, |
| 4590 | const build_options = @import("build_options"); | 4607 | dyld_stub_binder, |
| 4591 | const builtin = @import("builtin"); | 4608 | objc_msgsend, |
| 4592 | const assert = std.debug.assert; | 4609 | refs: std.ArrayListUnmanaged(Ref), |
| 4593 | const fs = std.fs; | | |
| 4594 | const log = std.log.scoped(.link); | | |
| 4595 | const state_log = std.log.scoped(.link_state); | | |
| 4596 | const macho = std.macho; | | |
| 4597 | const math = std.math; | | |
| 4598 | const mem = std.mem; | | |
| 4599 | const meta = std.meta; | | |
| 4600 | | | |
| 4601 | const aarch64 = @import("../arch/aarch64/bits.zig"); | | |
| 4602 | const bind = @import("MachO/dyld_info/bind.zig"); | | |
| 4603 | const calcUuid = @import("MachO/uuid.zig").calcUuid; | | |
| 4604 | const codegen = @import("../codegen.zig"); | | |
| 4605 | const dead_strip = @import("MachO/dead_strip.zig"); | | |
| 4606 | const eh_frame = @import("MachO/eh_frame.zig"); | | |
| 4607 | const fat = @import("MachO/fat.zig"); | | |
| 4608 | const link = @import("../link.zig"); | | |
| 4609 | const load_commands = @import("MachO/load_commands.zig"); | | |
| 4610 | const relocatable = @import("MachO/relocatable.zig"); | | |
| 4611 | const tapi = @import("tapi.zig"); | | |
| 4612 | const target_util = @import("../target.zig"); | | |
| 4613 | const trace = @import("../tracy.zig").trace; | | |
| 4614 | const synthetic = @import("MachO/synthetic.zig"); | | |
| 4615 | | 4610 | |
| 4616 | const Air = @import("../Air.zig"); | 4611 | pub fn deinit(self: *UndefRefs, allocator: Allocator) void { |
| 4617 | const Alignment = Atom.Alignment; | 4612 | switch (self.*) { |
| 4618 | const Allocator = mem.Allocator; | 4613 | .refs => |*refs| refs.deinit(allocator), |
| 4619 | const Archive = @import("MachO/Archive.zig"); | 4614 | else => {}, |
| 4620 | pub const Atom = @import("MachO/Atom.zig"); | 4615 | } |
| 4621 | const AtomicBool = std.atomic.Value(bool); | 4616 | } |
| 4622 | const Bind = bind.Bind; | 4617 | }; |
| 4623 | const Cache = std.Build.Cache; | | |
| 4624 | const Path = Cache.Path; | | |
| 4625 | const CodeSignature = @import("MachO/CodeSignature.zig"); | | |
| 4626 | const Compilation = @import("../Compilation.zig"); | | |
| 4627 | const DataInCode = synthetic.DataInCode; | | |
| 4628 | pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); | | |
| 4629 | const Dylib = @import("MachO/Dylib.zig"); | | |
| 4630 | const ExportTrie = @import("MachO/dyld_info/Trie.zig"); | | |
| 4631 | const File = @import("MachO/file.zig").File; | | |
| 4632 | const GotSection = synthetic.GotSection; | | |
| 4633 | const Hash = std.hash.Wyhash; | | |
| 4634 | const Indsymtab = synthetic.Indsymtab; | | |
| 4635 | const InternalObject = @import("MachO/InternalObject.zig"); | | |
| 4636 | const ObjcStubsSection = synthetic.ObjcStubsSection; | | |
| 4637 | const Object = @import("MachO/Object.zig"); | | |
| 4638 | const LazyBind = bind.LazyBind; | | |
| 4639 | const LaSymbolPtrSection = synthetic.LaSymbolPtrSection; | | |
| 4640 | const Liveness = @import("../Liveness.zig"); | | |
| 4641 | const LlvmObject = @import("../codegen/llvm.zig").Object; | | |
| 4642 | const Md5 = std.crypto.hash.Md5; | | |
| 4643 | const Zcu = @import("../Zcu.zig"); | | |
| 4644 | const InternPool = @import("../InternPool.zig"); | | |
| 4645 | const Rebase = @import("MachO/dyld_info/Rebase.zig"); | | |
| 4646 | pub const Relocation = @import("MachO/Relocation.zig"); | | |
| 4647 | const StringTable = @import("StringTable.zig"); | | |
| 4648 | const StubsSection = synthetic.StubsSection; | | |
| 4649 | const StubsHelperSection = synthetic.StubsHelperSection; | | |
| 4650 | const Symbol = @import("MachO/Symbol.zig"); | | |
| 4651 | const Thunk = @import("MachO/Thunk.zig"); | | |
| 4652 | const TlvPtrSection = synthetic.TlvPtrSection; | | |
| 4653 | const Value = @import("../Value.zig"); | | |
| 4654 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); | | |
| 4655 | const WaitGroup = std.Thread.WaitGroup; | | |
| 4656 | const WeakBind = bind.WeakBind; | | |
| 4657 | const ZigObject = @import("MachO/ZigObject.zig"); | | |
| 4658 | const dev = @import("../dev.zig"); | | |
| 4659 | | 4618 | |
| 4660 | pub const MachError = error{ | 4619 | pub const MachError = error{ |
| 4661 | /// Not enough permissions held to perform the requested kernel | 4620 | /// Not enough permissions held to perform the requested kernel |
| ... | @@ -5392,3 +5351,76 @@ const max_distance = (1 << (jump_bits - 1)); | ... | @@ -5392,3 +5351,76 @@ const max_distance = (1 << (jump_bits - 1)); |
| 5392 | /// mold uses 5MiB margin, while ld64 uses 4MiB margin. We will follow mold | 5351 | /// mold uses 5MiB margin, while ld64 uses 4MiB margin. We will follow mold |
| 5393 | /// and assume margin to be 5MiB. | 5352 | /// and assume margin to be 5MiB. |
| 5394 | const max_allowed_distance = max_distance - 0x500_000; | 5353 | const max_allowed_distance = max_distance - 0x500_000; |
| | 5354 | |
| | 5355 | const MachO = @This(); |
| | 5356 | |
| | 5357 | const std = @import("std"); |
| | 5358 | const build_options = @import("build_options"); |
| | 5359 | const builtin = @import("builtin"); |
| | 5360 | const assert = std.debug.assert; |
| | 5361 | const fs = std.fs; |
| | 5362 | const log = std.log.scoped(.link); |
| | 5363 | const state_log = std.log.scoped(.link_state); |
| | 5364 | const macho = std.macho; |
| | 5365 | const math = std.math; |
| | 5366 | const mem = std.mem; |
| | 5367 | const meta = std.meta; |
| | 5368 | |
| | 5369 | const aarch64 = @import("../arch/aarch64/bits.zig"); |
| | 5370 | const bind = @import("MachO/dyld_info/bind.zig"); |
| | 5371 | const calcUuid = @import("MachO/uuid.zig").calcUuid; |
| | 5372 | const codegen = @import("../codegen.zig"); |
| | 5373 | const dead_strip = @import("MachO/dead_strip.zig"); |
| | 5374 | const eh_frame = @import("MachO/eh_frame.zig"); |
| | 5375 | const fat = @import("MachO/fat.zig"); |
| | 5376 | const link = @import("../link.zig"); |
| | 5377 | const load_commands = @import("MachO/load_commands.zig"); |
| | 5378 | const relocatable = @import("MachO/relocatable.zig"); |
| | 5379 | const tapi = @import("tapi.zig"); |
| | 5380 | const target_util = @import("../target.zig"); |
| | 5381 | const trace = @import("../tracy.zig").trace; |
| | 5382 | const synthetic = @import("MachO/synthetic.zig"); |
| | 5383 | |
| | 5384 | const Air = @import("../Air.zig"); |
| | 5385 | const Alignment = Atom.Alignment; |
| | 5386 | const Allocator = mem.Allocator; |
| | 5387 | const Archive = @import("MachO/Archive.zig"); |
| | 5388 | pub const Atom = @import("MachO/Atom.zig"); |
| | 5389 | const AtomicBool = std.atomic.Value(bool); |
| | 5390 | const Bind = bind.Bind; |
| | 5391 | const Cache = std.Build.Cache; |
| | 5392 | const Path = Cache.Path; |
| | 5393 | const CodeSignature = @import("MachO/CodeSignature.zig"); |
| | 5394 | const Compilation = @import("../Compilation.zig"); |
| | 5395 | const DataInCode = synthetic.DataInCode; |
| | 5396 | pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); |
| | 5397 | const Dylib = @import("MachO/Dylib.zig"); |
| | 5398 | const ExportTrie = @import("MachO/dyld_info/Trie.zig"); |
| | 5399 | const File = @import("MachO/file.zig").File; |
| | 5400 | const GotSection = synthetic.GotSection; |
| | 5401 | const Hash = std.hash.Wyhash; |
| | 5402 | const Indsymtab = synthetic.Indsymtab; |
| | 5403 | const InternalObject = @import("MachO/InternalObject.zig"); |
| | 5404 | const ObjcStubsSection = synthetic.ObjcStubsSection; |
| | 5405 | const Object = @import("MachO/Object.zig"); |
| | 5406 | const LazyBind = bind.LazyBind; |
| | 5407 | const LaSymbolPtrSection = synthetic.LaSymbolPtrSection; |
| | 5408 | const Liveness = @import("../Liveness.zig"); |
| | 5409 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| | 5410 | const Md5 = std.crypto.hash.Md5; |
| | 5411 | const Zcu = @import("../Zcu.zig"); |
| | 5412 | const InternPool = @import("../InternPool.zig"); |
| | 5413 | const Rebase = @import("MachO/dyld_info/Rebase.zig"); |
| | 5414 | pub const Relocation = @import("MachO/Relocation.zig"); |
| | 5415 | const StringTable = @import("StringTable.zig"); |
| | 5416 | const StubsSection = synthetic.StubsSection; |
| | 5417 | const StubsHelperSection = synthetic.StubsHelperSection; |
| | 5418 | const Symbol = @import("MachO/Symbol.zig"); |
| | 5419 | const Thunk = @import("MachO/Thunk.zig"); |
| | 5420 | const TlvPtrSection = synthetic.TlvPtrSection; |
| | 5421 | const Value = @import("../Value.zig"); |
| | 5422 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| | 5423 | const WaitGroup = std.Thread.WaitGroup; |
| | 5424 | const WeakBind = bind.WeakBind; |
| | 5425 | const ZigObject = @import("MachO/ZigObject.zig"); |
| | 5426 | const dev = @import("../dev.zig"); |