diff options
| -rw-r--r-- | src/link/MachO.zig | 4 | ||||
| -rw-r--r-- | src/link/MachO/Atom.zig | 2 | ||||
| -rw-r--r-- | test/link/macho.zig | 29 |
3 files changed, 32 insertions, 3 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index bb1a9a064e..7b695304bb 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -25,7 +25,7 @@ sections: std.MultiArrayList(Section) = .{}, resolver: SymbolResolver = .{}, /// This table will be populated after `scanRelocs` has run. /// Key is symbol index. -undefs: std.AutoHashMapUnmanaged(Ref, std.ArrayListUnmanaged(Ref)) = .{}, +undefs: std.AutoHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(Ref)) = .{}, dyld_info_cmd: macho.dyld_info_command = .{}, symtab_cmd: macho.symtab_command = .{}, @@ -1531,7 +1531,7 @@ fn reportUndefs(self: *MachO) !void { var has_undefs = false; var it = self.undefs.iterator(); while (it.next()) |entry| { - const undef_sym = entry.key_ptr.getSymbol(self).?; + const undef_sym = self.resolver.keys.items[entry.key_ptr.* - 1]; const notes = entry.value_ptr.*; const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index e858b65a40..0a2ebb931c 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -549,7 +549,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { const ref = file.getSymbolRef(rel.target, macho_file); if (ref.getFile(macho_file) == null) { const gpa = macho_file.base.comp.gpa; - const gop = try macho_file.undefs.getOrPut(gpa, .{ .index = rel.target, .file = self.file }); + const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); if (!gop.found_existing) { gop.value_ptr.* = .{}; } diff --git a/test/link/macho.zig b/test/link/macho.zig index 3bc6b0a289..7dd27c0467 100644 --- a/test/link/macho.zig +++ b/test/link/macho.zig @@ -26,6 +26,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { macho_step.dependOn(testReexportsZig(b, .{ .use_llvm = false, .target = x86_64_target })); macho_step.dependOn(testRelocatableZig(b, .{ .use_llvm = false, .target = x86_64_target })); macho_step.dependOn(testTlsZig(b, .{ .use_llvm = false, .target = x86_64_target })); + macho_step.dependOn(testUnresolvedError(b, .{ .use_llvm = false, .target = x86_64_target })); // Exercise linker with LLVM backend macho_step.dependOn(testDeadStrip(b, .{ .target = default_target })); @@ -59,6 +60,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { macho_step.dependOn(testTlsLargeTbss(b, .{ .target = default_target })); macho_step.dependOn(testTlsZig(b, .{ .target = default_target })); macho_step.dependOn(testUndefinedFlag(b, .{ .target = default_target })); + macho_step.dependOn(testUnresolvedError(b, .{ .target = default_target })); macho_step.dependOn(testUnwindInfo(b, .{ .target = default_target })); macho_step.dependOn(testUnwindInfoNoSubsectionsX64(b, .{ .target = x86_64_target })); macho_step.dependOn(testUnwindInfoNoSubsectionsArm64(b, .{ .target = aarch64_target })); @@ -2499,6 +2501,33 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step { return test_step; } +fn testUnresolvedError(b: *Build, opts: Options) *Step { + const test_step = addTestStep(b, "unresolved-error", opts); + + const obj = addObject(b, opts, .{ .name = "a", .zig_source_bytes = + \\extern fn foo() i32; + \\export fn bar() i32 { return foo() + 1; } + }); + + const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes = + \\const std = @import("std"); + \\extern fn foo() i32; + \\extern fn bar() i32; + \\pub fn main() void { + \\ std.debug.print("foo() + bar() = {d}", .{foo() + bar()}); + \\} + }); + exe.addObject(obj); + + expectLinkErrors(exe, test_step, .{ .exact = &.{ + "error: undefined symbol: _foo", + "note: referenced by /?/a.o:_bar", + "note: referenced by /?/main.o:_a.main", + } }); + + return test_step; +} + fn testUnwindInfo(b: *Build, opts: Options) *Step { const test_step = addTestStep(b, "unwind-info", opts); |
