diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-14 19:20:11 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-14 20:39:00 +0100 |
| commit | 7a96907b9233cd1385472a03ff75530d3a02556f (patch) | |
| tree | 6ab7e0ca09fb13cbde775f282a381dbbf03de5ff /src/link/Elf.zig | |
| parent | 89d4ac628959fe301ee93b88fdc66ab1988d5f33 (diff) | |
| download | zig-7a96907b9233cd1385472a03ff75530d3a02556f.tar.gz zig-7a96907b9233cd1385472a03ff75530d3a02556f.zip | |
elf: check for and report duplicate symbol definitions
Diffstat (limited to 'src/link/Elf.zig')
| -rw-r--r-- | src/link/Elf.zig | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ef06c8e1dd..6ecafae009 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1323,6 +1323,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) } } + self.checkDuplicates() catch |err| switch (err) { + error.HasDuplicates => return error.FlushFailure, + else => |e| return e, + }; + try self.initOutputSections(); try self.addLinkerDefinedSymbols(); self.claimUnresolved(); @@ -3491,6 +3496,27 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { } } +fn checkDuplicates(self: *Elf) !void { + const gpa = self.base.comp.gpa; + + var dupes = std.AutoArrayHashMap(Symbol.Index, std.ArrayListUnmanaged(File.Index)).init(gpa); + defer { + for (dupes.values()) |*list| { + list.deinit(gpa); + } + dupes.deinit(); + } + + if (self.zigObjectPtr()) |zig_object| { + try zig_object.checkDuplicates(&dupes, self); + } + for (self.objects.items) |index| { + try self.file(index).?.object.checkDuplicates(&dupes, self); + } + + try self.reportDuplicates(dupes); +} + fn initOutputSections(self: *Elf) !void { for (self.objects.items) |index| { try self.file(index).?.object.initOutputSections(self); @@ -6164,6 +6190,36 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void { } } +fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void { + const max_notes = 3; + var has_dupes = false; + var it = dupes.iterator(); + while (it.next()) |entry| { + const sym = self.symbol(entry.key_ptr.*); + const notes = entry.value_ptr.*; + const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes); + + var err = try self.addErrorWithNotes(nnotes + 1); + try err.addMsg(self, "duplicate symbol definition: {s}", .{sym.name(self)}); + try err.addNote(self, "defined by {}", .{sym.file(self).?.fmtPath()}); + + var inote: usize = 0; + while (inote < @min(notes.items.len, max_notes)) : (inote += 1) { + const file_ptr = self.file(notes.items[inote]).?; + try err.addNote(self, "defined by {}", .{file_ptr.fmtPath()}); + } + + if (notes.items.len > max_notes) { + const remaining = notes.items.len - max_notes; + try err.addNote(self, "defined {d} more times", .{remaining}); + } + + has_dupes = true; + } + + if (has_dupes) return error.HasDuplicates; +} + fn reportMissingLibraryError( self: *Elf, checked_paths: []const []const u8, |
