Commit 68dc1a3e3f
src/link/MachO/zld.zig
@@ -388,7 +388,10 @@ pub fn linkWithZld(
var actions = std.ArrayList(MachO.ResolveAction).init(gpa);
defer actions.deinit();
try macho_file.resolveSymbols(&actions);
- try macho_file.reportUndefined();
+ if (macho_file.unresolved.count() > 0) {
+ try macho_file.reportUndefined();
+ return error.FlushFailure;
+ }
for (macho_file.objects.items, 0..) |*object, object_id| {
try object.splitIntoAtoms(macho_file, @as(u32, @intCast(object_id)));
src/link/MachO.zig
@@ -428,11 +428,14 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
var actions = std.ArrayList(ResolveAction).init(self.base.allocator);
defer actions.deinit();
try self.resolveSymbols(&actions);
- try self.reportUndefined();
if (self.getEntryPoint() == null) {
self.error_flags.no_entry_point_found = true;
}
+ if (self.unresolved.count() > 0) {
+ try self.reportUndefined();
+ return error.FlushFailure;
+ }
for (actions.items) |action| switch (action.kind) {
.none => {},
@@ -1642,13 +1645,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void {
// TODO redo this logic with corresponding logic in updateDeclExports to avoid this
// ugly check.
if (self.mode == .zld) {
- log.err("symbol '{s}' defined multiple times", .{sym_name});
- if (global.getFile()) |file| {
- log.err(" first definition in '{s}'", .{self.objects.items[file].name});
- }
- if (current.getFile()) |file| {
- log.err(" next definition in '{s}'", .{self.objects.items[file].name});
- }
+ try self.reportSymbolCollision(global, current);
}
return error.MultipleSymbolDefinitions;
}
@@ -1714,7 +1711,13 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u32) !void {
continue;
}
- try self.resolveGlobalSymbol(.{ .sym_index = sym_index, .file = object_id + 1 });
+ self.resolveGlobalSymbol(.{
+ .sym_index = sym_index,
+ .file = object_id + 1,
+ }) catch |err| switch (err) {
+ error.MultipleSymbolDefinitions => return error.FlushFailure,
+ else => |e| return e,
+ };
}
}
@@ -4833,20 +4836,16 @@ pub fn getSectionPrecedence(header: macho.section_64) u8 {
return (@as(u8, @intCast(segment_precedence)) << 4) + section_precedence;
}
-pub fn reportUndefined(self: *MachO) !void {
- const count = self.unresolved.count();
- if (count == 0) return;
-
+pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void {
const gpa = self.base.allocator;
-
+ const count = self.unresolved.count();
try self.misc_errors.ensureUnusedCapacity(gpa, count);
for (self.unresolved.keys()) |global_index| {
const global = self.globals.items[global_index];
const sym_name = self.getSymbolName(global);
- const nnotes: usize = if (global.getFile() == null) @as(usize, 0) else 1;
- var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, nnotes);
+ var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 1);
defer notes.deinit();
if (global.getFile()) |file| {
@@ -4863,8 +4862,38 @@ pub fn reportUndefined(self: *MachO) !void {
self.misc_errors.appendAssumeCapacity(err_msg);
}
+}
+
+fn reportSymbolCollision(
+ self: *MachO,
+ first: SymbolWithLoc,
+ other: SymbolWithLoc,
+) error{OutOfMemory}!void {
+ const gpa = self.base.allocator;
+ try self.misc_errors.ensureUnusedCapacity(gpa, 1);
+
+ var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2);
+ defer notes.deinit();
+
+ if (first.getFile()) |file| {
+ const note = try std.fmt.allocPrint(gpa, "first definition in {s}", .{
+ self.objects.items[file].name,
+ });
+ notes.appendAssumeCapacity(.{ .msg = note });
+ }
+ if (other.getFile()) |file| {
+ const note = try std.fmt.allocPrint(gpa, "next definition in {s}", .{
+ self.objects.items[file].name,
+ });
+ notes.appendAssumeCapacity(.{ .msg = note });
+ }
+
+ var err_msg = File.ErrorMsg{ .msg = try std.fmt.allocPrint(gpa, "symbol {s} defined multiple times", .{
+ self.getSymbolName(first),
+ }) };
+ err_msg.notes = try notes.toOwnedSlice();
- return error.FlushFailure;
+ self.misc_errors.appendAssumeCapacity(err_msg);
}
/// Binary search