authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-19 16:59:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log05c9d6c00babc4ccc7949b3eb0224f70719d12a5
tree35fc484baeda4c590d7fec3423468d06118e334a
parent7b282dffe68a7187a4fa4b5c11c82f1f67248a96

macho: add simple error reporting for misc errors


5 files changed, 85 insertions(+), 19 deletions(-)

src/Compilation.zig+16
...@@ -2609,6 +2609,9 @@ pub fn totalErrorCount(self: *Compilation) u32 {...@@ -2609,6 +2609,9 @@ pub fn totalErrorCount(self: *Compilation) u32 {
2609 }2609 }
2610 total += @intFromBool(self.link_error_flags.missing_libc);2610 total += @intFromBool(self.link_error_flags.missing_libc);
26112611
2612 // Misc linker errors
2613 total += self.bin_file.miscErrors().len;
2614
2612 // Compile log errors only count if there are no other errors.2615 // Compile log errors only count if there are no other errors.
2613 if (total == 0) {2616 if (total == 0) {
2614 if (self.bin_file.options.module) |module| {2617 if (self.bin_file.options.module) |module| {
...@@ -2759,6 +2762,19 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {...@@ -2759,6 +2762,19 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
2759 }));2762 }));
2760 }2763 }
27612764
2765 for (self.bin_file.miscErrors()) |link_err| {
2766 try bundle.addRootErrorMessage(.{
2767 .msg = try bundle.addString(link_err.msg),
2768 .notes_len = @intCast(link_err.notes.len),
2769 });
2770 const notes_start = try bundle.reserveNotes(@intCast(link_err.notes.len));
2771 for (link_err.notes, 0..) |note, i| {
2772 bundle.extra.items[notes_start + i] = @intFromEnum(try bundle.addErrorMessage(.{
2773 .msg = try bundle.addString(note.msg),
2774 }));
2775 }
2776 }
2777
2762 if (self.bin_file.options.module) |module| {2778 if (self.bin_file.options.module) |module| {
2763 if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) {2779 if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) {
2764 const keys = module.compile_log_decls.keys();2780 const keys = module.compile_log_decls.keys();
src/link.zig+20
...@@ -866,6 +866,13 @@ pub const File = struct {...@@ -866,6 +866,13 @@ pub const File = struct {
866 }866 }
867 }867 }
868868
869 pub fn miscErrors(base: *File) []const ErrorMsg {
870 switch (base.tag) {
871 .macho => return @fieldParentPtr(MachO, "base", base).misc_errors.items,
872 else => return &.{},
873 }
874 }
875
869 pub const UpdateDeclExportsError = error{876 pub const UpdateDeclExportsError = error{
870 OutOfMemory,877 OutOfMemory,
871 AnalysisFail,878 AnalysisFail,
...@@ -1129,6 +1136,19 @@ pub const File = struct {...@@ -1129,6 +1136,19 @@ pub const File = struct {
1129 missing_libc: bool = false,1136 missing_libc: bool = false,
1130 };1137 };
11311138
1139 pub const ErrorMsg = struct {
1140 msg: []const u8,
1141 notes: []ErrorMsg = &.{},
1142
1143 pub fn deinit(self: *ErrorMsg, gpa: Allocator) void {
1144 for (self.notes) |*note| {
1145 note.deinit(gpa);
1146 }
1147 gpa.free(self.notes);
1148 gpa.free(self.msg);
1149 }
1150 };
1151
1132 pub const LazySymbol = struct {1152 pub const LazySymbol = struct {
1133 pub const Kind = enum { code, const_data };1153 pub const Kind = enum { code, const_data };
11341154
src/link/MachO.zig+46-2
...@@ -52,8 +52,8 @@ const Value = @import("../value.zig").Value;...@@ -52,8 +52,8 @@ const Value = @import("../value.zig").Value;
5252
53pub const DebugSymbols = @import("MachO/DebugSymbols.zig");53pub const DebugSymbols = @import("MachO/DebugSymbols.zig");
5454
55const Bind = @import("MachO/dyld_info/bind.zig").Bind(*const MachO, MachO.SymbolWithLoc);55const Bind = @import("MachO/dyld_info/bind.zig").Bind(*const MachO, SymbolWithLoc);
56const LazyBind = @import("MachO/dyld_info/bind.zig").LazyBind(*const MachO, MachO.SymbolWithLoc);56const LazyBind = @import("MachO/dyld_info/bind.zig").LazyBind(*const MachO, SymbolWithLoc);
57const Rebase = @import("MachO/dyld_info/Rebase.zig");57const Rebase = @import("MachO/dyld_info/Rebase.zig");
5858
59pub const base_tag: File.Tag = File.Tag.macho;59pub const base_tag: File.Tag = File.Tag.macho;
...@@ -154,6 +154,7 @@ got_table: TableSection(SymbolWithLoc) = .{},...@@ -154,6 +154,7 @@ got_table: TableSection(SymbolWithLoc) = .{},
154stub_table: TableSection(SymbolWithLoc) = .{},154stub_table: TableSection(SymbolWithLoc) = .{},
155155
156error_flags: File.ErrorFlags = File.ErrorFlags{},156error_flags: File.ErrorFlags = File.ErrorFlags{},
157misc_errors: std.ArrayListUnmanaged(File.ErrorMsg) = .{},
157158
158segment_table_dirty: bool = false,159segment_table_dirty: bool = false,
159got_table_count_dirty: bool = false,160got_table_count_dirty: bool = false,
...@@ -295,6 +296,12 @@ pub const SymbolWithLoc = extern struct {...@@ -295,6 +296,12 @@ pub const SymbolWithLoc = extern struct {
295 }296 }
296};297};
297298
299pub const SymbolResolver = struct {
300 arena: Allocator,
301 table: std.StringHashMap(u32),
302 unresolved: std.AutoArrayHashMap(u32, void),
303};
304
298const HotUpdateState = struct {305const HotUpdateState = struct {
299 mach_task: ?std.os.darwin.MachTask = null,306 mach_task: ?std.os.darwin.MachTask = null,
300};307};
...@@ -1856,6 +1863,11 @@ pub fn deinit(self: *MachO) void {...@@ -1856,6 +1863,11 @@ pub fn deinit(self: *MachO) void {
1856 bindings.deinit(gpa);1863 bindings.deinit(gpa);
1857 }1864 }
1858 self.bindings.deinit(gpa);1865 self.bindings.deinit(gpa);
1866
1867 for (self.misc_errors.items) |*err| {
1868 err.deinit(gpa);
1869 }
1870 self.misc_errors.deinit(gpa);
1859}1871}
18601872
1861fn freeAtom(self: *MachO, atom_index: Atom.Index) void {1873fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
...@@ -4021,6 +4033,38 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {...@@ -4021,6 +4033,38 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {
4021 };4033 };
4022}4034}
40234035
4036pub fn reportUndefined(self: *MachO, ctx: anytype, resolver: *const SymbolResolver) !void {
4037 const count = resolver.unresolved.count();
4038 if (count == 0) return;
4039
4040 const gpa = self.base.allocator;
4041
4042 try self.misc_errors.ensureUnusedCapacity(gpa, count);
4043
4044 for (resolver.unresolved.keys()) |global_index| {
4045 const global = ctx.globals.items[global_index];
4046 const sym_name = ctx.getSymbolName(global);
4047
4048 const nnotes: usize = if (global.getFile() == null) @as(usize, 0) else 1;
4049 var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, nnotes);
4050 defer notes.deinit();
4051
4052 if (global.getFile()) |file| {
4053 const note = try std.fmt.allocPrint(gpa, "referenced in {s}", .{ctx.objects.items[file].name});
4054 notes.appendAssumeCapacity(.{ .msg = note });
4055 }
4056
4057 var err_msg = File.ErrorMsg{
4058 .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}),
4059 };
4060 err_msg.notes = try notes.toOwnedSlice();
4061
4062 self.misc_errors.appendAssumeCapacity(err_msg);
4063 }
4064
4065 return error.FlushFailure;
4066}
4067
4024/// Binary search4068/// Binary search
4025pub fn bsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {4069pub fn bsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {
4026 if (!@hasDecl(@TypeOf(predicate), "predicate"))4070 if (!@hasDecl(@TypeOf(predicate), "predicate"))
src/link/MachO/dead_strip.zig+1-1
...@@ -13,7 +13,7 @@ const AtomIndex = @import("zld.zig").AtomIndex;...@@ -13,7 +13,7 @@ const AtomIndex = @import("zld.zig").AtomIndex;
13const Atom = @import("ZldAtom.zig");13const Atom = @import("ZldAtom.zig");
14const MachO = @import("../MachO.zig");14const MachO = @import("../MachO.zig");
15const SymbolWithLoc = MachO.SymbolWithLoc;15const SymbolWithLoc = MachO.SymbolWithLoc;
16const SymbolResolver = @import("zld.zig").SymbolResolver;16const SymbolResolver = MachO.SymbolResolver;
17const UnwindInfo = @import("UnwindInfo.zig");17const UnwindInfo = @import("UnwindInfo.zig");
18const Zld = @import("zld.zig").Zld;18const Zld = @import("zld.zig").Zld;
1919
src/link/MachO/zld.zig+2-16
...@@ -33,6 +33,7 @@ const LibStub = @import("../tapi.zig").LibStub;...@@ -33,6 +33,7 @@ const LibStub = @import("../tapi.zig").LibStub;
33const Object = @import("Object.zig");33const Object = @import("Object.zig");
34const StringTable = @import("../strtab.zig").StringTable;34const StringTable = @import("../strtab.zig").StringTable;
35const SymbolWithLoc = MachO.SymbolWithLoc;35const SymbolWithLoc = MachO.SymbolWithLoc;
36const SymbolResolver = MachO.SymbolResolver;
36const Trie = @import("Trie.zig");37const Trie = @import("Trie.zig");
37const UnwindInfo = @import("UnwindInfo.zig");38const UnwindInfo = @import("UnwindInfo.zig");
3839
...@@ -788,7 +789,6 @@ pub const Zld = struct {...@@ -788,7 +789,6 @@ pub const Zld = struct {
788 const global_index = resolver.unresolved.keys()[next_sym];789 const global_index = resolver.unresolved.keys()[next_sym];
789 const global = self.globals.items[global_index];790 const global = self.globals.items[global_index];
790 const sym = self.getSymbolPtr(global);791 const sym = self.getSymbolPtr(global);
791 const sym_name = self.getSymbolName(global);
792792
793 if (sym.discarded()) {793 if (sym.discarded()) {
794 sym.* = .{794 sym.* = .{
...@@ -811,11 +811,6 @@ pub const Zld = struct {...@@ -811,11 +811,6 @@ pub const Zld = struct {
811 continue;811 continue;
812 }812 }
813813
814 log.err("undefined reference to symbol '{s}'", .{sym_name});
815 if (global.getFile()) |file| {
816 log.err(" first referenced in '{s}'", .{self.objects.items[file].name});
817 }
818
819 next_sym += 1;814 next_sym += 1;
820 }815 }
821 }816 }
...@@ -3022,12 +3017,6 @@ const IndirectPointer = struct {...@@ -3022,12 +3017,6 @@ const IndirectPointer = struct {
3022 }3017 }
3023};3018};
30243019
3025pub const SymbolResolver = struct {
3026 arena: Allocator,
3027 table: std.StringHashMap(u32),
3028 unresolved: std.AutoArrayHashMap(u32, void),
3029};
3030
3031pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {3020pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
3032 const tracy = trace(@src());3021 const tracy = trace(@src());
3033 defer tracy.end();3022 defer tracy.end();
...@@ -3419,10 +3408,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -3419,10 +3408,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
3419 .unresolved = std.AutoArrayHashMap(u32, void).init(arena),3408 .unresolved = std.AutoArrayHashMap(u32, void).init(arena),
3420 };3409 };
3421 try zld.resolveSymbols(&resolver);3410 try zld.resolveSymbols(&resolver);
34223411 try macho_file.reportUndefined(&zld, &resolver);
3423 if (resolver.unresolved.count() > 0) {
3424 return error.UndefinedSymbolReference;
3425 }
34263412
3427 if (options.output_mode == .Exe) {3413 if (options.output_mode == .Exe) {
3428 const entry_name = options.entry orelse load_commands.default_entry_point;3414 const entry_name = options.entry orelse load_commands.default_entry_point;