| ... | ... | @@ -428,11 +428,14 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 428 | 428 | var actions = std.ArrayList(ResolveAction).init(self.base.allocator); |
| 429 | 429 | defer actions.deinit(); |
| 430 | 430 | try self.resolveSymbols(&actions); |
| 431 | | try self.reportUndefined(); |
| 432 | 431 | |
| 433 | 432 | if (self.getEntryPoint() == null) { |
| 434 | 433 | self.error_flags.no_entry_point_found = true; |
| 435 | 434 | } |
| 435 | if (self.unresolved.count() > 0) { |
| 436 | try self.reportUndefined(); |
| 437 | return error.FlushFailure; |
| 438 | } |
| 436 | 439 | |
| 437 | 440 | for (actions.items) |action| switch (action.kind) { |
| 438 | 441 | .none => {}, |
| ... | ... | @@ -1642,13 +1645,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 1642 | 1645 | // TODO redo this logic with corresponding logic in updateDeclExports to avoid this |
| 1643 | 1646 | // ugly check. |
| 1644 | 1647 | if (self.mode == .zld) { |
| 1645 | | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 1646 | | if (global.getFile()) |file| { |
| 1647 | | log.err(" first definition in '{s}'", .{self.objects.items[file].name}); |
| 1648 | | } |
| 1649 | | if (current.getFile()) |file| { |
| 1650 | | log.err(" next definition in '{s}'", .{self.objects.items[file].name}); |
| 1651 | | } |
| 1648 | try self.reportSymbolCollision(global, current); |
| 1652 | 1649 | } |
| 1653 | 1650 | return error.MultipleSymbolDefinitions; |
| 1654 | 1651 | } |
| ... | ... | @@ -1714,7 +1711,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void { |
| 1714 | 1711 | continue; |
| 1715 | 1712 | } |
| 1716 | 1713 | |
| 1717 | | try self.resolveGlobalSymbol(.{ .sym_index = sym_index, .file = object_id + 1 }); |
| 1714 | self.resolveGlobalSymbol(.{ |
| 1715 | .sym_index = sym_index, |
| 1716 | .file = object_id + 1, |
| 1717 | }) catch |err| switch (err) { |
| 1718 | error.MultipleSymbolDefinitions => return error.FlushFailure, |
| 1719 | else => |e| return e, |
| 1720 | }; |
| 1718 | 1721 | } |
| 1719 | 1722 | } |
| 1720 | 1723 | |
| ... | ... | @@ -4833,20 +4836,16 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 { |
| 4833 | 4836 | return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; |
| 4834 | 4837 | } |
| 4835 | 4838 | |
| 4836 | | pub fn reportUndefined(self: *MachO) !void { |
| 4837 | | const count = self.unresolved.count(); |
| 4838 | | if (count == 0) return; |
| 4839 | | |
| 4839 | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 4840 | 4840 | const gpa = self.base.allocator; |
| 4841 | | |
| 4841 | const count = self.unresolved.count(); |
| 4842 | 4842 | try self.misc_errors.ensureUnusedCapacity(gpa, count); |
| 4843 | 4843 | |
| 4844 | 4844 | for (self.unresolved.keys()) |global_index| { |
| 4845 | 4845 | const global = self.globals.items[global_index]; |
| 4846 | 4846 | const sym_name = self.getSymbolName(global); |
| 4847 | 4847 | |
| 4848 | | const nnotes: usize = if (global.getFile() == null) @as(usize, 0) else 1; |
| 4849 | | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, nnotes); |
| 4848 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 1); |
| 4850 | 4849 | defer notes.deinit(); |
| 4851 | 4850 | |
| 4852 | 4851 | if (global.getFile()) |file| { |
| ... | ... | @@ -4863,8 +4862,38 @@ pub fn reportUndefined(self: *MachO) !void { |
| 4863 | 4862 | |
| 4864 | 4863 | self.misc_errors.appendAssumeCapacity(err_msg); |
| 4865 | 4864 | } |
| 4865 | } |
| 4866 | |
| 4867 | fn reportSymbolCollision( |
| 4868 | self: *MachO, |
| 4869 | first: SymbolWithLoc, |
| 4870 | other: SymbolWithLoc, |
| 4871 | ) error{OutOfMemory}!void { |
| 4872 | const gpa = self.base.allocator; |
| 4873 | try self.misc_errors.ensureUnusedCapacity(gpa, 1); |
| 4874 | |
| 4875 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); |
| 4876 | defer notes.deinit(); |
| 4877 | |
| 4878 | if (first.getFile()) |file| { |
| 4879 | const note = try std.fmt.allocPrint(gpa, "first definition in {s}", .{ |
| 4880 | self.objects.items[file].name, |
| 4881 | }); |
| 4882 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 4883 | } |
| 4884 | if (other.getFile()) |file| { |
| 4885 | const note = try std.fmt.allocPrint(gpa, "next definition in {s}", .{ |
| 4886 | self.objects.items[file].name, |
| 4887 | }); |
| 4888 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 4889 | } |
| 4890 | |
| 4891 | var err_msg = File.ErrorMsg{ .msg = try std.fmt.allocPrint(gpa, "symbol {s} defined multiple times", .{ |
| 4892 | self.getSymbolName(first), |
| 4893 | }) }; |
| 4894 | err_msg.notes = try notes.toOwnedSlice(); |
| 4866 | 4895 | |
| 4867 | | return error.FlushFailure; |
| 4896 | self.misc_errors.appendAssumeCapacity(err_msg); |
| 4868 | 4897 | } |
| 4869 | 4898 | |
| 4870 | 4899 | /// Binary search |