| author | |
| committer | |
| log | 05c9d6c00babc4ccc7949b3eb0224f70719d12a5 |
| tree | 35fc484baeda4c590d7fec3423468d06118e334a |
| parent | 7b282dffe68a7187a4fa4b5c11c82f1f67248a96 |
5 files changed, 85 insertions(+), 19 deletions(-)
src/Compilation.zig+16| ... | ... | @@ -2609,6 +2609,9 @@ pub fn totalErrorCount(self: *Compilation) u32 { |
| 2609 | 2609 | } |
| 2610 | 2610 | total += @intFromBool(self.link_error_flags.missing_libc); |
| 2611 | 2611 | |
| 2612 | // Misc linker errors | |
| 2613 | total += self.bin_file.miscErrors().len; | |
| 2614 | ||
| 2612 | 2615 | // Compile log errors only count if there are no other errors. |
| 2613 | 2616 | if (total == 0) { |
| 2614 | 2617 | if (self.bin_file.options.module) |module| { |
| ... | ... | @@ -2759,6 +2762,19 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle { |
| 2759 | 2762 | })); |
| 2760 | 2763 | } |
| 2761 | 2764 | |
| 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 | 2778 | if (self.bin_file.options.module) |module| { |
| 2763 | 2779 | if (bundle.root_list.items.len == 0 and module.compile_log_decls.count() != 0) { |
| 2764 | 2780 | const keys = module.compile_log_decls.keys(); |
src/link.zig+20| ... | ... | @@ -866,6 +866,13 @@ pub const File = struct { |
| 866 | 866 | } |
| 867 | 867 | } |
| 868 | 868 | |
| 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 | 876 | pub const UpdateDeclExportsError = error{ |
| 870 | 877 | OutOfMemory, |
| 871 | 878 | AnalysisFail, |
| ... | ... | @@ -1129,6 +1136,19 @@ pub const File = struct { |
| 1129 | 1136 | missing_libc: bool = false, |
| 1130 | 1137 | }; |
| 1131 | 1138 | |
| 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 | 1152 | pub const LazySymbol = struct { |
| 1133 | 1153 | pub const Kind = enum { code, const_data }; |
| 1134 | 1154 |
src/link/MachO.zig+46-2| ... | ... | @@ -52,8 +52,8 @@ const Value = @import("../value.zig").Value; |
| 52 | 52 | |
| 53 | 53 | pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); |
| 54 | 54 | |
| 55 | const Bind = @import("MachO/dyld_info/bind.zig").Bind(*const MachO, MachO.SymbolWithLoc); | |
| 56 | const LazyBind = @import("MachO/dyld_info/bind.zig").LazyBind(*const MachO, MachO.SymbolWithLoc); | |
| 55 | const Bind = @import("MachO/dyld_info/bind.zig").Bind(*const MachO, SymbolWithLoc); | |
| 56 | const LazyBind = @import("MachO/dyld_info/bind.zig").LazyBind(*const MachO, SymbolWithLoc); | |
| 57 | 57 | const Rebase = @import("MachO/dyld_info/Rebase.zig"); |
| 58 | 58 | |
| 59 | 59 | pub const base_tag: File.Tag = File.Tag.macho; |
| ... | ... | @@ -154,6 +154,7 @@ got_table: TableSection(SymbolWithLoc) = .{}, |
| 154 | 154 | stub_table: TableSection(SymbolWithLoc) = .{}, |
| 155 | 155 | |
| 156 | 156 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 157 | misc_errors: std.ArrayListUnmanaged(File.ErrorMsg) = .{}, | |
| 157 | 158 | |
| 158 | 159 | segment_table_dirty: bool = false, |
| 159 | 160 | got_table_count_dirty: bool = false, |
| ... | ... | @@ -295,6 +296,12 @@ pub const SymbolWithLoc = extern struct { |
| 295 | 296 | } |
| 296 | 297 | }; |
| 297 | 298 | |
| 299 | pub const SymbolResolver = struct { | |
| 300 | arena: Allocator, | |
| 301 | table: std.StringHashMap(u32), | |
| 302 | unresolved: std.AutoArrayHashMap(u32, void), | |
| 303 | }; | |
| 304 | ||
| 298 | 305 | const HotUpdateState = struct { |
| 299 | 306 | mach_task: ?std.os.darwin.MachTask = null, |
| 300 | 307 | }; |
| ... | ... | @@ -1856,6 +1863,11 @@ pub fn deinit(self: *MachO) void { |
| 1856 | 1863 | bindings.deinit(gpa); |
| 1857 | 1864 | } |
| 1858 | 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 | } |
| 1860 | 1872 | |
| 1861 | 1873 | fn freeAtom(self: *MachO, atom_index: Atom.Index) void { |
| ... | ... | @@ -4021,6 +4033,38 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 { |
| 4021 | 4033 | }; |
| 4022 | 4034 | } |
| 4023 | 4035 | |
| 4036 | pub 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 | 4068 | /// Binary search |
| 4025 | 4069 | pub fn bsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize { |
| 4026 | 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 | 13 | const Atom = @import("ZldAtom.zig"); |
| 14 | 14 | const MachO = @import("../MachO.zig"); |
| 15 | 15 | const SymbolWithLoc = MachO.SymbolWithLoc; |
| 16 | const SymbolResolver = @import("zld.zig").SymbolResolver; | |
| 16 | const SymbolResolver = MachO.SymbolResolver; | |
| 17 | 17 | const UnwindInfo = @import("UnwindInfo.zig"); |
| 18 | 18 | const Zld = @import("zld.zig").Zld; |
| 19 | 19 |
src/link/MachO/zld.zig+2-16| ... | ... | @@ -33,6 +33,7 @@ const LibStub = @import("../tapi.zig").LibStub; |
| 33 | 33 | const Object = @import("Object.zig"); |
| 34 | 34 | const StringTable = @import("../strtab.zig").StringTable; |
| 35 | 35 | const SymbolWithLoc = MachO.SymbolWithLoc; |
| 36 | const SymbolResolver = MachO.SymbolResolver; | |
| 36 | 37 | const Trie = @import("Trie.zig"); |
| 37 | 38 | const UnwindInfo = @import("UnwindInfo.zig"); |
| 38 | 39 | |
| ... | ... | @@ -788,7 +789,6 @@ pub const Zld = struct { |
| 788 | 789 | const global_index = resolver.unresolved.keys()[next_sym]; |
| 789 | 790 | const global = self.globals.items[global_index]; |
| 790 | 791 | const sym = self.getSymbolPtr(global); |
| 791 | const sym_name = self.getSymbolName(global); | |
| 792 | 792 | |
| 793 | 793 | if (sym.discarded()) { |
| 794 | 794 | sym.* = .{ |
| ... | ... | @@ -811,11 +811,6 @@ pub const Zld = struct { |
| 811 | 811 | continue; |
| 812 | 812 | } |
| 813 | 813 | |
| 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 | 814 | next_sym += 1; |
| 820 | 815 | } |
| 821 | 816 | } |
| ... | ... | @@ -3022,12 +3017,6 @@ const IndirectPointer = struct { |
| 3022 | 3017 | } |
| 3023 | 3018 | }; |
| 3024 | 3019 | |
| 3025 | pub const SymbolResolver = struct { | |
| 3026 | arena: Allocator, | |
| 3027 | table: std.StringHashMap(u32), | |
| 3028 | unresolved: std.AutoArrayHashMap(u32, void), | |
| 3029 | }; | |
| 3030 | ||
| 3031 | 3020 | pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 3032 | 3021 | const tracy = trace(@src()); |
| 3033 | 3022 | defer tracy.end(); |
| ... | ... | @@ -3419,10 +3408,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 3419 | 3408 | .unresolved = std.AutoArrayHashMap(u32, void).init(arena), |
| 3420 | 3409 | }; |
| 3421 | 3410 | try zld.resolveSymbols(&resolver); |
| 3422 | ||
| 3423 | if (resolver.unresolved.count() > 0) { | |
| 3424 | return error.UndefinedSymbolReference; | |
| 3425 | } | |
| 3411 | try macho_file.reportUndefined(&zld, &resolver); | |
| 3426 | 3412 | |
| 3427 | 3413 | if (options.output_mode == .Exe) { |
| 3428 | 3414 | const entry_name = options.entry orelse load_commands.default_entry_point; |