| ... | @@ -428,11 +428,14 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -428,11 +428,14 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 428 | var actions = std.ArrayList(ResolveAction).init(self.base.allocator); | 428 | var actions = std.ArrayList(ResolveAction).init(self.base.allocator); |
| 429 | defer actions.deinit(); | 429 | defer actions.deinit(); |
| 430 | try self.resolveSymbols(&actions); | 430 | try self.resolveSymbols(&actions); |
| 431 | try self.reportUndefined(); | | |
| 432 | | 431 | |
| 433 | if (self.getEntryPoint() == null) { | 432 | if (self.getEntryPoint() == null) { |
| 434 | self.error_flags.no_entry_point_found = true; | 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 | for (actions.items) |action| switch (action.kind) { | 440 | for (actions.items) |action| switch (action.kind) { |
| 438 | .none => {}, | 441 | .none => {}, |
| ... | @@ -1642,13 +1645,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { | ... | @@ -1642,13 +1645,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 1642 | // TODO redo this logic with corresponding logic in updateDeclExports to avoid this | 1645 | // TODO redo this logic with corresponding logic in updateDeclExports to avoid this |
| 1643 | // ugly check. | 1646 | // ugly check. |
| 1644 | if (self.mode == .zld) { | 1647 | if (self.mode == .zld) { |
| 1645 | log.err("symbol '{s}' defined multiple times", .{sym_name}); | 1648 | try self.reportSymbolCollision(global, current); |
| 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 | } | | |
| 1652 | } | 1649 | } |
| 1653 | return error.MultipleSymbolDefinitions; | 1650 | return error.MultipleSymbolDefinitions; |
| 1654 | } | 1651 | } |
| ... | @@ -1714,7 +1711,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void { | ... | @@ -1714,7 +1711,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void { |
| 1714 | continue; | 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,20 +4836,16 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 { |
| 4833 | return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; | 4836 | return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence; |
| 4834 | } | 4837 | } |
| 4835 | | 4838 | |
| 4836 | pub fn reportUndefined(self: *MachO) !void { | 4839 | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 4837 | const count = self.unresolved.count(); | | |
| 4838 | if (count == 0) return; | | |
| 4839 | | | |
| 4840 | const gpa = self.base.allocator; | 4840 | const gpa = self.base.allocator; |
| 4841 | | 4841 | const count = self.unresolved.count(); |
| 4842 | try self.misc_errors.ensureUnusedCapacity(gpa, count); | 4842 | try self.misc_errors.ensureUnusedCapacity(gpa, count); |
| 4843 | | 4843 | |
| 4844 | for (self.unresolved.keys()) |global_index| { | 4844 | for (self.unresolved.keys()) |global_index| { |
| 4845 | const global = self.globals.items[global_index]; | 4845 | const global = self.globals.items[global_index]; |
| 4846 | const sym_name = self.getSymbolName(global); | 4846 | const sym_name = self.getSymbolName(global); |
| 4847 | | 4847 | |
| 4848 | const nnotes: usize = if (global.getFile() == null) @as(usize, 0) else 1; | 4848 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 1); |
| 4849 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, nnotes); | | |
| 4850 | defer notes.deinit(); | 4849 | defer notes.deinit(); |
| 4851 | | 4850 | |
| 4852 | if (global.getFile()) |file| { | 4851 | if (global.getFile()) |file| { |
| ... | @@ -4863,8 +4862,38 @@ pub fn reportUndefined(self: *MachO) !void { | ... | @@ -4863,8 +4862,38 @@ pub fn reportUndefined(self: *MachO) !void { |
| 4863 | | 4862 | |
| 4864 | self.misc_errors.appendAssumeCapacity(err_msg); | 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 | /// Binary search | 4899 | /// Binary search |