authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-12 10:24:02+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:39+01:00
logc2a0a882842d8cc9d0ad29781fe1e13c1a5880cd
tree68e529c54403f9cf1f6fd4bad11a34264dbd52b1
parent3968aea8ec98277bcc5b3c26beb5592f26b1a9fd

macho: report duplicate symbols


2 files changed, 71 insertions(+), 57 deletions(-)

src/link/MachO.zig+53-57
......@@ -509,6 +509,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
509509 try dead_strip.gcAtoms(self);
510510 }
511511
512 self.checkDuplicates() catch |err| switch (err) {
513 error.HasDuplicates => return error.FlushFailure,
514 else => |e| {
515 try self.reportUnexpectedError("unexpected error while checking for duplicate symbol definitions", .{});
516 return e;
517 },
518 };
519
512520 self.markImportsAndExports();
513521 self.deadStripDylibs();
514522
......@@ -1414,6 +1422,24 @@ fn claimUnresolved(self: *MachO) error{OutOfMemory}!void {
14141422 }
14151423}
14161424
1425fn checkDuplicates(self: *MachO) !void {
1426 const gpa = self.base.comp.gpa;
1427
1428 var dupes = std.AutoArrayHashMap(Symbol.Index, std.ArrayListUnmanaged(File.Index)).init(gpa);
1429 defer {
1430 for (dupes.values()) |*list| {
1431 list.deinit(gpa);
1432 }
1433 dupes.deinit();
1434 }
1435
1436 for (self.objects.items) |index| {
1437 try self.getFile(index).?.object.checkDuplicates(&dupes, self);
1438 }
1439
1440 try self.reportDuplicates(dupes);
1441}
1442
14171443fn markImportsAndExports(self: *MachO) void {
14181444 for (self.objects.items) |index| {
14191445 for (self.getFile(index).?.getSymbols()) |sym_index| {
......@@ -3468,68 +3494,38 @@ fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytyp
34683494 try err.addNote(self, "please report this as a linker bug on https://github.com/ziglang/zig/issues/new/choose", .{});
34693495}
34703496
3471// fn reportSymbolCollision(
3472// self: *MachO,
3473// first: SymbolWithLoc,
3474// other: SymbolWithLoc,
3475// ) error{OutOfMemory}!void {
3476// const comp = self.base.comp;
3477// const gpa = comp.gpa;
3478// try comp.link_errors.ensureUnusedCapacity(gpa, 1);
3497fn reportDuplicates(self: *MachO, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void {
3498 const tracy = trace(@src());
3499 defer tracy.end();
3500
3501 const max_notes = 4;
34793502
3480// var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);
3481// defer notes.deinit();
3503 var has_dupes = false;
3504 var it = dupes.iterator();
3505 while (it.next()) |entry| {
3506 const sym = self.getSymbol(entry.key_ptr.*);
3507 const notes = entry.value_ptr.*;
3508 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
34823509
3483// if (first.getFile()) |file| {
3484// const note = try std.fmt.allocPrint(gpa, "first definition in {s}", .{
3485// self.objects.items[file].name,
3486// });
3487// notes.appendAssumeCapacity(.{ .msg = note });
3488// }
3489// if (other.getFile()) |file| {
3490// const note = try std.fmt.allocPrint(gpa, "next definition in {s}", .{
3491// self.objects.items[file].name,
3492// });
3493// notes.appendAssumeCapacity(.{ .msg = note });
3494// }
3510 var err = try self.addErrorWithNotes(nnotes);
3511 try err.addMsg(self, "duplicate symbol definition: {s}", .{sym.getName(self)});
3512
3513 var inote: usize = 0;
3514 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
3515 const file = self.getFile(notes.items[inote]).?;
3516 try err.addNote(self, "defined by {}", .{file.fmtPath()});
3517 }
34953518
3496// var err_msg = File.ErrorMsg{ .msg = try std.fmt.allocPrint(gpa, "symbol {s} defined multiple times", .{
3497// self.getSymbolName(first),
3498// }) };
3499// err_msg.notes = try notes.toOwnedSlice();
3519 if (notes.items.len > max_notes) {
3520 const remaining = notes.items.len - max_notes;
3521 try err.addNote(self, "defined {d} more times", .{remaining});
3522 }
35003523
3501// comp.link_errors.appendAssumeCapacity(err_msg);
3502// }
3524 has_dupes = true;
3525 }
35033526
3504// fn reportUnhandledSymbolType(self: *MachO, sym_with_loc: SymbolWithLoc) error{OutOfMemory}!void {
3505// const comp = self.base.comp;
3506// const gpa = comp.gpa;
3507// try comp.link_errors.ensureUnusedCapacity(gpa, 1);
3508
3509// const notes = try gpa.alloc(File.ErrorMsg, 1);
3510// errdefer gpa.free(notes);
3511
3512// const file = sym_with_loc.getFile().?;
3513// notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "defined in {s}", .{self.objects.items[file].name}) };
3514
3515// const sym = self.getSymbol(sym_with_loc);
3516// const sym_type = if (sym.stab())
3517// "stab"
3518// else if (sym.indr())
3519// "indirect"
3520// else if (sym.abs())
3521// "absolute"
3522// else
3523// unreachable;
3524
3525// comp.link_errors.appendAssumeCapacity(.{
3526// .msg = try std.fmt.allocPrint(gpa, "unhandled symbol type: '{s}' has type {s}", .{
3527// self.getSymbolName(sym_with_loc),
3528// sym_type,
3529// }),
3530// .notes = notes,
3531// });
3532// }
3527 if (has_dupes) return error.HasDuplicates;
3528}
35333529
35343530pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols {
35353531 if (self.d_sym) |*ds| {
src/link/MachO/Object.zig+18
......@@ -1070,6 +1070,24 @@ pub fn markLive(self: *Object, macho_file: *MachO) void {
10701070 }
10711071}
10721072
1073pub fn checkDuplicates(self: *Object, dupes: anytype, macho_file: *MachO) error{OutOfMemory}!void {
1074 for (self.symbols.items, 0..) |index, nlist_idx| {
1075 const sym = macho_file.getSymbol(index);
1076 if (sym.visibility != .global) continue;
1077 const file = sym.getFile(macho_file) orelse continue;
1078 if (file.getIndex() == self.index) continue;
1079
1080 const nlist = self.symtab.items(.nlist)[nlist_idx];
1081 if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
1082 const gop = try dupes.getOrPut(index);
1083 if (!gop.found_existing) {
1084 gop.value_ptr.* = .{};
1085 }
1086 try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
1087 }
1088 }
1089}
1090
10731091pub fn scanRelocs(self: Object, macho_file: *MachO) !void {
10741092 const tracy = trace(@src());
10751093 defer tracy.end();