| ... | ... | @@ -509,6 +509,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 509 | 509 | try dead_strip.gcAtoms(self); |
| 510 | 510 | } |
| 511 | 511 | |
| 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 | |
| 512 | 520 | self.markImportsAndExports(); |
| 513 | 521 | self.deadStripDylibs(); |
| 514 | 522 | |
| ... | ... | @@ -1414,6 +1422,24 @@ fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { |
| 1414 | 1422 | } |
| 1415 | 1423 | } |
| 1416 | 1424 | |
| 1425 | fn 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 | |
| 1417 | 1443 | fn markImportsAndExports(self: *MachO) void { |
| 1418 | 1444 | for (self.objects.items) |index| { |
| 1419 | 1445 | for (self.getFile(index).?.getSymbols()) |sym_index| { |
| ... | ... | @@ -3468,68 +3494,38 @@ fn reportUnexpectedError(self: *MachO, comptime format: []const u8, args: anytyp |
| 3468 | 3494 | try err.addNote(self, "please report this as a linker bug on https://github.com/ziglang/zig/issues/new/choose", .{}); |
| 3469 | 3495 | } |
| 3470 | 3496 | |
| 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); |
| 3497 | fn reportDuplicates(self: *MachO, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void { |
| 3498 | const tracy = trace(@src()); |
| 3499 | defer tracy.end(); |
| 3500 | |
| 3501 | const max_notes = 4; |
| 3479 | 3502 | |
| 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); |
| 3482 | 3509 | |
| 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 | } |
| 3495 | 3518 | |
| 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 | } |
| 3500 | 3523 | |
| 3501 | | // comp.link_errors.appendAssumeCapacity(err_msg); |
| 3502 | | // } |
| 3524 | has_dupes = true; |
| 3525 | } |
| 3503 | 3526 | |
| 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 | } |
| 3533 | 3529 | |
| 3534 | 3530 | pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols { |
| 3535 | 3531 | if (self.d_sym) |*ds| { |