aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2024-01-14 19:20:11 +0100
committerJakub Konka <kubkon@jakubkonka.com>2024-01-14 20:39:00 +0100
commit7a96907b9233cd1385472a03ff75530d3a02556f (patch)
tree6ab7e0ca09fb13cbde775f282a381dbbf03de5ff /src/link/Elf.zig
parent89d4ac628959fe301ee93b88fdc66ab1988d5f33 (diff)
downloadzig-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.zig56
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,