authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-03 17:35:47-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
logda25ed95fce32449f70942ea77aa5e00e75dbbdd
tree6e9e979184325aa9f4d73e0c29de5e1f55f5e4f5
parent6235cc3da4d2c6ebf7fd31242e8d82d39f5c81cf

macho linker conforms to explicit error sets, again


7 files changed, 73 insertions(+), 40 deletions(-)

src/link.zig+16-3
......@@ -632,15 +632,14 @@ pub const File = struct {
632632 pub const UpdateDebugInfoError = Dwarf.UpdateError;
633633 pub const FlushDebugInfoError = Dwarf.FlushError;
634634
635 /// Note that `LinkFailure` is not a member of this error set because the error message
636 /// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
635637 pub const UpdateNavError = error{
636638 Overflow,
637639 OutOfMemory,
638640 /// Indicates the error is already reported and stored in
639641 /// `failed_codegen` on the Zcu.
640642 CodegenFail,
641 /// Indicates the error is already reported and stored in `link_diags`
642 /// on the Compilation.
643 LinkFailure,
644643 };
645644
646645 /// Called from within CodeGen to retrieve the symbol index of a global symbol.
......@@ -1284,6 +1283,20 @@ pub const File = struct {
12841283 }, llvm_object, prog_node);
12851284 }
12861285
1286 pub fn cgFail(
1287 base: *File,
1288 nav_index: InternPool.Nav.Index,
1289 comptime format: []const u8,
1290 args: anytype,
1291 ) error{ CodegenFail, OutOfMemory } {
1292 @branchHint(.cold);
1293 const zcu = base.comp.zcu.?;
1294 const gpa = zcu.gpa;
1295 try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
1296 const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
1297 zcu.failed_codegen.putAssumeCapacityNoClobber(gpa, nav_index, msg);
1298 }
1299
12871300 pub const C = @import("link/C.zig");
12881301 pub const Coff = @import("link/Coff.zig");
12891302 pub const Plan9 = @import("link/Plan9.zig");
src/link/Dwarf.zig+2-4
......@@ -26,9 +26,7 @@ pub const UpdateError = error{
2626 OutOfMemory,
2727};
2828
29pub const FlushError =
30 UpdateError ||
31 std.process.GetCwdError;
29pub const FlushError = UpdateError || std.process.GetCwdError;
3230
3331pub const RelocError =
3432 std.fs.File.PWriteError;
......@@ -4312,7 +4310,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
43124310 return @intFromEnum(abbrev_code);
43134311}
43144312
4315pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4313pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) !void {
43164314 const zcu = pt.zcu;
43174315 const ip = &zcu.intern_pool;
43184316
src/link/Elf.zig+13-2
......@@ -807,7 +807,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
807807 defer tracy.end();
808808
809809 const comp = self.base.comp;
810 const gpa = comp.gpa;
811810 const diags = &comp.link_diags;
812811
813812 if (self.llvm_object) |llvm_object| {
......@@ -821,6 +820,18 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
821820 const sub_prog_node = prog_node.start("ELF Flush", 0);
822821 defer sub_prog_node.end();
823822
823 return flushModuleInner(self, arena, tid) catch |err| switch (err) {
824 error.OutOfMemory => return error.OutOfMemory,
825 error.LinkFailure => return error.LinkFailure,
826 else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
827 };
828}
829
830fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
831 const comp = self.base.comp;
832 const gpa = comp.gpa;
833 const diags = &comp.link_diags;
834
824835 const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
825836 .root_dir = self.base.emit.root_dir,
826837 .sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
......@@ -2432,7 +2443,7 @@ pub fn addCommentString(self: *Elf) !void {
24322443 self.comment_merge_section_index = msec_index;
24332444}
24342445
2435pub fn resolveMergeSections(self: *Elf) link.File.FlushError!void {
2446pub fn resolveMergeSections(self: *Elf) !void {
24362447 const tracy = trace(@src());
24372448 defer tracy.end();
24382449
src/link/Elf/ZigObject.zig+12-12
......@@ -264,7 +264,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
264264 }
265265}
266266
267pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.FlushError!void {
267pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
268268 // Handle any lazy symbols that were emitted by incremental compilation.
269269 if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
270270 const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
......@@ -279,7 +279,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.
279279 metadata.text_symbol_index,
280280 ) catch |err| return switch (err) {
281281 error.CodegenFail => error.LinkFailure,
282 else => |e| e,
282 else => |e| return e,
283283 };
284284 if (metadata.rodata_state != .unused) self.updateLazySymbol(
285285 elf_file,
......@@ -288,7 +288,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.
288288 metadata.rodata_symbol_index,
289289 ) catch |err| return switch (err) {
290290 error.CodegenFail => error.LinkFailure,
291 else => |e| e,
291 else => |e| return e,
292292 };
293293 }
294294 for (self.lazy_syms.values()) |*metadata| {
......@@ -1263,7 +1263,7 @@ fn updateNavCode(
12631263 shdr_index: u32,
12641264 code: []const u8,
12651265 stt_bits: u8,
1266) !void {
1266) link.File.UpdateNavError!void {
12671267 const zcu = pt.zcu;
12681268 const gpa = zcu.gpa;
12691269 const ip = &zcu.intern_pool;
......@@ -1342,7 +1342,7 @@ fn updateNavCode(
13421342 const shdr = elf_file.sections.items(.shdr)[shdr_index];
13431343 if (shdr.sh_type != elf.SHT_NOBITS) {
13441344 const file_offset = atom_ptr.offset(elf_file);
1345 try elf_file.base.file.?.pwriteAll(code, file_offset);
1345 try elf_file.pwriteAll(code, file_offset);
13461346 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
13471347 }
13481348}
......@@ -1355,7 +1355,7 @@ fn updateTlv(
13551355 sym_index: Symbol.Index,
13561356 shndx: u32,
13571357 code: []const u8,
1358) !void {
1358) link.File.UpdateNavError!void {
13591359 const zcu = pt.zcu;
13601360 const ip = &zcu.intern_pool;
13611361 const gpa = zcu.gpa;
......@@ -1394,7 +1394,7 @@ fn updateTlv(
13941394 const shdr = elf_file.sections.items(.shdr)[shndx];
13951395 if (shdr.sh_type != elf.SHT_NOBITS) {
13961396 const file_offset = atom_ptr.offset(elf_file);
1397 try elf_file.base.file.?.pwriteAll(code, file_offset);
1397 try elf_file.pwriteAll(code, file_offset);
13981398 log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{
13991399 atom_ptr.name(elf_file),
14001400 file_offset,
......@@ -1617,7 +1617,7 @@ fn updateLazySymbol(
16171617 pt: Zcu.PerThread,
16181618 sym: link.File.LazySymbol,
16191619 symbol_index: Symbol.Index,
1620) link.File.FlushError!void {
1620) !void {
16211621 const zcu = pt.zcu;
16221622 const gpa = zcu.gpa;
16231623
......@@ -1698,7 +1698,7 @@ fn updateLazySymbol(
16981698 local_sym.value = 0;
16991699 local_esym.st_value = 0;
17001700
1701 try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
1701 try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
17021702}
17031703
17041704const LowerConstResult = union(enum) {
......@@ -1750,7 +1750,7 @@ fn lowerConst(
17501750 try self.allocateAtom(atom_ptr, true, elf_file);
17511751 errdefer self.freeNavMetadata(elf_file, sym_index);
17521752
1753 try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
1753 try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
17541754
17551755 return .{ .ok = sym_index };
17561756}
......@@ -1898,7 +1898,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
18981898 return len;
18991899}
19001900
1901fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
1901fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.UpdateNavError!void {
19021902 const atom_ptr = tr_sym.atom(elf_file).?;
19031903 const fileoff = atom_ptr.offset(elf_file);
19041904 const source_addr = tr_sym.address(.{}, elf_file);
......@@ -1908,7 +1908,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
19081908 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
19091909 else => @panic("TODO implement write trampoline for this CPU arch"),
19101910 };
1911 try elf_file.base.file.?.pwriteAll(out, fileoff);
1911 try elf_file.pwriteAll(out, fileoff);
19121912
19131913 if (elf_file.base.child_pid) |pid| {
19141914 switch (builtin.os.tag) {
src/link/Elf/relocatable.zig+3-3
......@@ -1,4 +1,4 @@
1pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
1pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
22 const gpa = comp.gpa;
33 const diags = &comp.link_diags;
44
......@@ -130,7 +130,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!v
130130 if (diags.hasErrors()) return error.LinkFailure;
131131}
132132
133pub fn flushObject(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
133pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
134134 const diags = &comp.link_diags;
135135
136136 if (diags.hasErrors()) return error.LinkFailure;
......@@ -259,7 +259,7 @@ fn initComdatGroups(elf_file: *Elf) !void {
259259 }
260260}
261261
262fn updateSectionSizes(elf_file: *Elf) link.File.FlushError!void {
262fn updateSectionSizes(elf_file: *Elf) !void {
263263 const slice = elf_file.sections.slice();
264264 for (slice.items(.atom_list_2)) |*atom_list| {
265265 if (atom_list.atoms.keys().len == 0) continue;
src/link/MachO.zig+4-4
......@@ -3423,7 +3423,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34233423 };
34243424}
34253425
3426pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
3426pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
34273427 if (self.base.isRelocatable()) {
34283428 try self.growSectionRelocatable(sect_index, needed_size);
34293429 } else {
......@@ -3431,7 +3431,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfM
34313431 }
34323432}
34333433
3434fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
3434fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
34353435 const diags = &self.base.comp.link_diags;
34363436 const sect = &self.sections.items(.header)[sect_index];
34373437
......@@ -3480,7 +3480,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) err
34803480 seg.vmsize = needed_size;
34813481}
34823482
3483fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
3483fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
34843484 const sect = &self.sections.items(.header)[sect_index];
34853485
34863486 if (!sect.isZerofill()) {
......@@ -3490,7 +3490,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{
34903490 sect.size = 0;
34913491
34923492 // Must move the entire section.
3493 const alignment = try self.alignPow(sect.@"align");
3493 const alignment = try math.powi(u32, 2, sect.@"align");
34943494 const new_offset = try self.findFreeSpace(needed_size, alignment);
34953495 const new_addr = self.findFreeSpaceVirtual(needed_size, alignment);
34963496
src/link/MachO/ZigObject.zig+23-12
......@@ -559,18 +559,26 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
559559
560560 // Most lazy symbols can be updated on first use, but
561561 // anyerror needs to wait for everything to be flushed.
562 if (metadata.text_state != .unused) try self.updateLazySymbol(
562 if (metadata.text_state != .unused) self.updateLazySymbol(
563563 macho_file,
564564 pt,
565565 .{ .kind = .code, .ty = .anyerror_type },
566566 metadata.text_symbol_index,
567 );
568 if (metadata.const_state != .unused) try self.updateLazySymbol(
567 ) catch |err| switch (err) {
568 error.OutOfMemory => return error.OutOfMemory,
569 error.LinkFailure => return error.LinkFailure,
570 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
571 };
572 if (metadata.const_state != .unused) self.updateLazySymbol(
569573 macho_file,
570574 pt,
571575 .{ .kind = .const_data, .ty = .anyerror_type },
572576 metadata.const_symbol_index,
573 );
577 ) catch |err| switch (err) {
578 error.OutOfMemory => return error.OutOfMemory,
579 error.LinkFailure => return error.LinkFailure,
580 else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
581 };
574582 }
575583 for (self.lazy_syms.values()) |*metadata| {
576584 if (metadata.text_state != .unused) metadata.text_state = .flushed;
......@@ -803,7 +811,7 @@ pub fn updateFunc(
803811 .ok => code_buffer.items,
804812 .fail => |em| {
805813 try zcu.failed_codegen.put(gpa, func.owner_nav, em);
806 return;
814 return error.CodegenFail;
807815 },
808816 };
809817
......@@ -855,7 +863,8 @@ pub fn updateFunc(
855863 }
856864 const target_sym = self.symbols.items[sym_index];
857865 const source_sym = self.symbols.items[target_sym.getExtra(macho_file).trampoline];
858 try writeTrampoline(source_sym, target_sym, macho_file);
866 writeTrampoline(source_sym, target_sym, macho_file) catch |err|
867 return macho_file.base.cgFail(func.owner_nav, "failed to write trampoline: {s}", .{@errorName(err)});
859868 }
860869}
861870
......@@ -955,7 +964,6 @@ fn updateNavCode(
955964 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
956965 };
957966
958 const diags = &macho_file.base.comp.link_diags;
959967 const sect = &macho_file.sections.items(.header)[sect_index];
960968 const sym = &self.symbols.items[sym_index];
961969 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
......@@ -984,7 +992,8 @@ fn updateNavCode(
984992 const need_realloc = code.len > capacity or !required_alignment.check(atom.value);
985993
986994 if (need_realloc) {
987 atom.grow(macho_file) catch |err| return diags.fail("failed to grow atom: {s}", .{@errorName(err)});
995 atom.grow(macho_file) catch |err|
996 return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});
988997 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });
989998 if (old_vaddr != atom.value) {
990999 sym.value = 0;
......@@ -997,7 +1006,8 @@ fn updateNavCode(
9971006 sect.size = needed_size;
9981007 }
9991008 } else {
1000 try atom.allocate(macho_file);
1009 atom.allocate(macho_file) catch |err|
1010 return macho_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
10011011 errdefer self.freeNavMetadata(macho_file, sym_index);
10021012
10031013 sym.value = 0;
......@@ -1006,7 +1016,8 @@ fn updateNavCode(
10061016
10071017 if (!sect.isZerofill()) {
10081018 const file_offset = sect.offset + atom.value;
1009 try macho_file.pwriteAll(code, file_offset);
1019 macho_file.base.file.?.pwriteAll(code, file_offset) catch |err|
1020 return macho_file.base.cgFail(nav_index, "failed to write output file: {s}", .{@errorName(err)});
10101021 }
10111022}
10121023
......@@ -1353,7 +1364,7 @@ fn updateLazySymbol(
13531364 pt: Zcu.PerThread,
13541365 lazy_sym: link.File.LazySymbol,
13551366 symbol_index: Symbol.Index,
1356) error{ OutOfMemory, LinkFailure }!void {
1367) !void {
13571368 const zcu = pt.zcu;
13581369 const gpa = zcu.gpa;
13591370 const diags = &macho_file.base.comp.link_diags;
......@@ -1494,7 +1505,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void {
14941505 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
14951506 else => @panic("TODO implement write trampoline for this CPU arch"),
14961507 };
1497 try macho_file.pwriteAll(out, fileoff);
1508 try macho_file.base.file.?.pwriteAll(out, fileoff);
14981509}
14991510
15001511pub fn getOrCreateMetadataForNav(