authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-15 08:43:19+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log91de8dc8abd9db03ba4ac4c4a5fcbe86e8bc7ee4
tree912e5f4fd4c3483e6e8dc2721ed85d5968b9e621
parent521933e1c05977105ee4eee70096a13064068f8b

macho: fix unresolved symbols error reporting


3 files changed, 32 insertions(+), 3 deletions(-)

src/link/MachO.zig+2-2
...@@ -25,7 +25,7 @@ sections: std.MultiArrayList(Section) = .{},...@@ -25,7 +25,7 @@ sections: std.MultiArrayList(Section) = .{},
25resolver: SymbolResolver = .{},25resolver: SymbolResolver = .{},
26/// This table will be populated after `scanRelocs` has run.26/// This table will be populated after `scanRelocs` has run.
27/// Key is symbol index.27/// Key is symbol index.
28undefs: std.AutoHashMapUnmanaged(Ref, std.ArrayListUnmanaged(Ref)) = .{},28undefs: std.AutoHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(Ref)) = .{},
2929
30dyld_info_cmd: macho.dyld_info_command = .{},30dyld_info_cmd: macho.dyld_info_command = .{},
31symtab_cmd: macho.symtab_command = .{},31symtab_cmd: macho.symtab_command = .{},
...@@ -1531,7 +1531,7 @@ fn reportUndefs(self: *MachO) !void {...@@ -1531,7 +1531,7 @@ fn reportUndefs(self: *MachO) !void {
1531 var has_undefs = false;1531 var has_undefs = false;
1532 var it = self.undefs.iterator();1532 var it = self.undefs.iterator();
1533 while (it.next()) |entry| {1533 while (it.next()) |entry| {
1534 const undef_sym = entry.key_ptr.getSymbol(self).?;1534 const undef_sym = self.resolver.keys.items[entry.key_ptr.* - 1];
1535 const notes = entry.value_ptr.*;1535 const notes = entry.value_ptr.*;
1536 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);1536 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
15371537
src/link/MachO/Atom.zig+1-1
...@@ -549,7 +549,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {...@@ -549,7 +549,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {
549 const ref = file.getSymbolRef(rel.target, macho_file);549 const ref = file.getSymbolRef(rel.target, macho_file);
550 if (ref.getFile(macho_file) == null) {550 if (ref.getFile(macho_file) == null) {
551 const gpa = macho_file.base.comp.gpa;551 const gpa = macho_file.base.comp.gpa;
552 const gop = try macho_file.undefs.getOrPut(gpa, .{ .index = rel.target, .file = self.file });552 const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]);
553 if (!gop.found_existing) {553 if (!gop.found_existing) {
554 gop.value_ptr.* = .{};554 gop.value_ptr.* = .{};
555 }555 }
test/link/macho.zig+29
...@@ -26,6 +26,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -26,6 +26,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
26 macho_step.dependOn(testReexportsZig(b, .{ .use_llvm = false, .target = x86_64_target }));26 macho_step.dependOn(testReexportsZig(b, .{ .use_llvm = false, .target = x86_64_target }));
27 macho_step.dependOn(testRelocatableZig(b, .{ .use_llvm = false, .target = x86_64_target }));27 macho_step.dependOn(testRelocatableZig(b, .{ .use_llvm = false, .target = x86_64_target }));
28 macho_step.dependOn(testTlsZig(b, .{ .use_llvm = false, .target = x86_64_target }));28 macho_step.dependOn(testTlsZig(b, .{ .use_llvm = false, .target = x86_64_target }));
29 macho_step.dependOn(testUnresolvedError(b, .{ .use_llvm = false, .target = x86_64_target }));
2930
30 // Exercise linker with LLVM backend31 // Exercise linker with LLVM backend
31 macho_step.dependOn(testDeadStrip(b, .{ .target = default_target }));32 macho_step.dependOn(testDeadStrip(b, .{ .target = default_target }));
...@@ -59,6 +60,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -59,6 +60,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
59 macho_step.dependOn(testTlsLargeTbss(b, .{ .target = default_target }));60 macho_step.dependOn(testTlsLargeTbss(b, .{ .target = default_target }));
60 macho_step.dependOn(testTlsZig(b, .{ .target = default_target }));61 macho_step.dependOn(testTlsZig(b, .{ .target = default_target }));
61 macho_step.dependOn(testUndefinedFlag(b, .{ .target = default_target }));62 macho_step.dependOn(testUndefinedFlag(b, .{ .target = default_target }));
63 macho_step.dependOn(testUnresolvedError(b, .{ .target = default_target }));
62 macho_step.dependOn(testUnwindInfo(b, .{ .target = default_target }));64 macho_step.dependOn(testUnwindInfo(b, .{ .target = default_target }));
63 macho_step.dependOn(testUnwindInfoNoSubsectionsX64(b, .{ .target = x86_64_target }));65 macho_step.dependOn(testUnwindInfoNoSubsectionsX64(b, .{ .target = x86_64_target }));
64 macho_step.dependOn(testUnwindInfoNoSubsectionsArm64(b, .{ .target = aarch64_target }));66 macho_step.dependOn(testUnwindInfoNoSubsectionsArm64(b, .{ .target = aarch64_target }));
...@@ -2499,6 +2501,33 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step {...@@ -2499,6 +2501,33 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step {
2499 return test_step;2501 return test_step;
2500}2502}
25012503
2504fn testUnresolvedError(b: *Build, opts: Options) *Step {
2505 const test_step = addTestStep(b, "unresolved-error", opts);
2506
2507 const obj = addObject(b, opts, .{ .name = "a", .zig_source_bytes =
2508 \\extern fn foo() i32;
2509 \\export fn bar() i32 { return foo() + 1; }
2510 });
2511
2512 const exe = addExecutable(b, opts, .{ .name = "main", .zig_source_bytes =
2513 \\const std = @import("std");
2514 \\extern fn foo() i32;
2515 \\extern fn bar() i32;
2516 \\pub fn main() void {
2517 \\ std.debug.print("foo() + bar() = {d}", .{foo() + bar()});
2518 \\}
2519 });
2520 exe.addObject(obj);
2521
2522 expectLinkErrors(exe, test_step, .{ .exact = &.{
2523 "error: undefined symbol: _foo",
2524 "note: referenced by /?/a.o:_bar",
2525 "note: referenced by /?/main.o:_a.main",
2526 } });
2527
2528 return test_step;
2529}
2530
2502fn testUnwindInfo(b: *Build, opts: Options) *Step {2531fn testUnwindInfo(b: *Build, opts: Options) *Step {
2503 const test_step = addTestStep(b, "unwind-info", opts);2532 const test_step = addTestStep(b, "unwind-info", opts);
25042533