authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-28 07:53:03+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:40:20+02:00
log68dc1a3e3fc8ab739cb34ed536c71a02727b3825
treed2dc4f02055667163af318520600d8da9b9be865
parent0f02a1fcb0ea82c98de509e7ba9b7b8768f0d4ee

macho: report symbol collision as compiler error


2 files changed, 50 insertions(+), 18 deletions(-)

src/link/MachO.zig+46-17
......@@ -428,11 +428,14 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
428428 var actions = std.ArrayList(ResolveAction).init(self.base.allocator);
429429 defer actions.deinit();
430430 try self.resolveSymbols(&actions);
431 try self.reportUndefined();
432431
433432 if (self.getEntryPoint() == null) {
434433 self.error_flags.no_entry_point_found = true;
435434 }
435 if (self.unresolved.count() > 0) {
436 try self.reportUndefined();
437 return error.FlushFailure;
438 }
436439
437440 for (actions.items) |action| switch (action.kind) {
438441 .none => {},
......@@ -1642,13 +1645,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
16421645 // TODO redo this logic with corresponding logic in updateDeclExports to avoid this
16431646 // ugly check.
16441647 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);
16521649 }
16531650 return error.MultipleSymbolDefinitions;
16541651 }
......@@ -1714,7 +1711,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void {
17141711 continue;
17151712 }
17161713
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 };
17181721 }
17191722}
17201723
......@@ -4833,20 +4836,16 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 {
48334836 return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence;
48344837}
48354838
4836pub fn reportUndefined(self: *MachO) !void {
4837 const count = self.unresolved.count();
4838 if (count == 0) return;
4839
4839pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
48404840 const gpa = self.base.allocator;
4841
4841 const count = self.unresolved.count();
48424842 try self.misc_errors.ensureUnusedCapacity(gpa, count);
48434843
48444844 for (self.unresolved.keys()) |global_index| {
48454845 const global = self.globals.items[global_index];
48464846 const sym_name = self.getSymbolName(global);
48474847
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);
48504849 defer notes.deinit();
48514850
48524851 if (global.getFile()) |file| {
......@@ -4863,8 +4862,38 @@ pub fn reportUndefined(self: *MachO) !void {
48634862
48644863 self.misc_errors.appendAssumeCapacity(err_msg);
48654864 }
4865}
4866
4867fn 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();
48664895
4867 return error.FlushFailure;
4896 self.misc_errors.appendAssumeCapacity(err_msg);
48684897}
48694898
48704899/// Binary search
src/link/MachO/zld.zig+4-1
......@@ -388,7 +388,10 @@ pub fn linkWithZld(
388388 var actions = std.ArrayList(MachO.ResolveAction).init(gpa);
389389 defer actions.deinit();
390390 try macho_file.resolveSymbols(&actions);
391 try macho_file.reportUndefined();
391 if (macho_file.unresolved.count() > 0) {
392 try macho_file.reportUndefined();
393 return error.FlushFailure;
394 }
392395
393396 for (macho_file.objects.items, 0..) |*object, object_id| {
394397 try object.splitIntoAtoms(macho_file, @as(u32, @intCast(object_id)));