| ... | ... | @@ -87,7 +87,7 @@ start_stop_indexes: std.ArrayListUnmanaged(u32) = .{}, |
| 87 | 87 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 88 | 88 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 89 | 89 | resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{}, |
| 90 | | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 90 | unresolved: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, |
| 91 | 91 | symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 92 | 92 | |
| 93 | 93 | phdr_table_dirty: bool = false, |
| ... | ... | @@ -102,6 +102,7 @@ debug_info_header_dirty: bool = false, |
| 102 | 102 | debug_line_header_dirty: bool = false, |
| 103 | 103 | |
| 104 | 104 | error_flags: link.File.ErrorFlags = link.File.ErrorFlags{}, |
| 105 | misc_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, |
| 105 | 106 | |
| 106 | 107 | /// Table of tracked LazySymbols. |
| 107 | 108 | lazy_syms: LazySymbolTable = .{}, |
| ... | ... | @@ -292,6 +293,8 @@ pub fn deinit(self: *Elf) void { |
| 292 | 293 | if (self.dwarf) |*dw| { |
| 293 | 294 | dw.deinit(); |
| 294 | 295 | } |
| 296 | |
| 297 | self.misc_errors.deinit(gpa); |
| 295 | 298 | } |
| 296 | 299 | |
| 297 | 300 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { |
| ... | ... | @@ -1015,6 +1018,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1015 | 1018 | |
| 1016 | 1019 | try self.addLinkerDefinedSymbols(); |
| 1017 | 1020 | |
| 1021 | if (self.unresolved.keys().len > 0) try self.reportUndefined(); |
| 1022 | |
| 1018 | 1023 | self.allocateLinkerDefinedSymbols(); |
| 1019 | 1024 | |
| 1020 | 1025 | // Beyond this point, everything has been allocated a virtual address and we can resolve |
| ... | ... | @@ -3392,11 +3397,60 @@ pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 |
| 3392 | 3397 | const name_off = try self.strtab.insert(gpa, name); |
| 3393 | 3398 | const gop = try self.getOrPutGlobal(name_off); |
| 3394 | 3399 | if (!gop.found_existing) { |
| 3395 | | try self.unresolved.putNoClobber(gpa, name_off, {}); |
| 3400 | try self.unresolved.putNoClobber(gpa, gop.index, {}); |
| 3396 | 3401 | } |
| 3397 | 3402 | return gop.index; |
| 3398 | 3403 | } |
| 3399 | 3404 | |
| 3405 | fn reportUndefined(self: *Elf) !void { |
| 3406 | const gpa = self.base.allocator; |
| 3407 | const max_notes = 4; |
| 3408 | |
| 3409 | try self.misc_errors.ensureUnusedCapacity(gpa, self.unresolved.keys().len); |
| 3410 | |
| 3411 | for (self.unresolved.keys()) |sym_index| { |
| 3412 | const undef_sym = self.symbol(sym_index); |
| 3413 | |
| 3414 | var all_notes: usize = 0; |
| 3415 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, max_notes + 1); |
| 3416 | defer notes.deinit(); |
| 3417 | |
| 3418 | // Collect all references across all input files |
| 3419 | if (self.zig_module_index) |index| { |
| 3420 | const zig_module = self.file(index).?.zig_module; |
| 3421 | for (zig_module.atoms.keys()) |atom_index| { |
| 3422 | const atom_ptr = self.atom(atom_index).?; |
| 3423 | if (!atom_ptr.alive) continue; |
| 3424 | |
| 3425 | for (atom_ptr.relocs(self)) |rel| { |
| 3426 | if (sym_index == rel.r_sym()) { |
| 3427 | const note = try std.fmt.allocPrint(gpa, "referenced by {s}:{s}", .{ |
| 3428 | zig_module.path, |
| 3429 | atom_ptr.name(self), |
| 3430 | }); |
| 3431 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 3432 | all_notes += 1; |
| 3433 | break; |
| 3434 | } |
| 3435 | } |
| 3436 | } |
| 3437 | } |
| 3438 | |
| 3439 | if (all_notes > max_notes) { |
| 3440 | const remaining = all_notes - max_notes; |
| 3441 | const note = try std.fmt.allocPrint(gpa, "referenced {d} more times", .{remaining}); |
| 3442 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 3443 | } |
| 3444 | |
| 3445 | var err_msg = link.File.ErrorMsg{ |
| 3446 | .msg = try std.fmt.allocPrint(gpa, "undefined symbol: {s}", .{undef_sym.name(self)}), |
| 3447 | }; |
| 3448 | err_msg.notes = try notes.toOwnedSlice(); |
| 3449 | |
| 3450 | self.misc_errors.appendAssumeCapacity(err_msg); |
| 3451 | } |
| 3452 | } |
| 3453 | |
| 3400 | 3454 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 3401 | 3455 | return .{ .data = self }; |
| 3402 | 3456 | } |