authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-03 19:30:13-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
log77accf597d845245847b143e42ec4109c9468480
tree176ace677fe750bde50b689176644829f0a63588
parentda25ed95fce32449f70942ea77aa5e00e75dbbdd

elf linker: conform to explicit error sets


9 files changed, 147 insertions(+), 55 deletions(-)

src/Compilation.zig+4
...@@ -3208,6 +3208,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3208,6 +3208,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3208 if (!zcu.navFileScope(nav).okToReportErrors()) continue;3208 if (!zcu.navFileScope(nav).okToReportErrors()) continue;
3209 try addModuleErrorMsg(zcu, &bundle, error_msg.*);3209 try addModuleErrorMsg(zcu, &bundle, error_msg.*);
3210 }3210 }
3211 for (zcu.failed_types.keys(), zcu.failed_types.values()) |ty_index, error_msg| {
3212 if (!zcu.typeFileScope(ty_index).okToReportErrors()) continue;
3213 try addModuleErrorMsg(zcu, &bundle, error_msg.*);
3214 }
3211 for (zcu.failed_exports.values()) |value| {3215 for (zcu.failed_exports.values()) |value| {
3212 try addModuleErrorMsg(zcu, &bundle, value.*);3216 try addModuleErrorMsg(zcu, &bundle, value.*);
3213 }3217 }
src/Zcu.zig+30-6
...@@ -127,6 +127,7 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp...@@ -127,6 +127,7 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp
127/// This may be a simple "value" `Nav`, or it may be a function.127/// This may be a simple "value" `Nav`, or it may be a function.
128/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.128/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
129failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty,129failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty,
130failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty,
130/// Keep track of one `@compileLog` callsite per `AnalUnit`.131/// Keep track of one `@compileLog` callsite per `AnalUnit`.
131/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.132/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.
132compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {133compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
...@@ -2448,16 +2449,14 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2448,16 +2449,14 @@ pub fn deinit(zcu: *Zcu) void {
2448 zcu.local_zir_cache.handle.close();2449 zcu.local_zir_cache.handle.close();
2449 zcu.global_zir_cache.handle.close();2450 zcu.global_zir_cache.handle.close();
24502451
2451 for (zcu.failed_analysis.values()) |value| {2452 for (zcu.failed_analysis.values()) |value| value.destroy(gpa);
2452 value.destroy(gpa);2453 for (zcu.failed_codegen.values()) |value| value.destroy(gpa);
2453 }2454 for (zcu.failed_types.values()) |value| value.destroy(gpa);
2454 for (zcu.failed_codegen.values()) |value| {
2455 value.destroy(gpa);
2456 }
2457 zcu.analysis_in_progress.deinit(gpa);2455 zcu.analysis_in_progress.deinit(gpa);
2458 zcu.failed_analysis.deinit(gpa);2456 zcu.failed_analysis.deinit(gpa);
2459 zcu.transitive_failed_analysis.deinit(gpa);2457 zcu.transitive_failed_analysis.deinit(gpa);
2460 zcu.failed_codegen.deinit(gpa);2458 zcu.failed_codegen.deinit(gpa);
2459 zcu.failed_types.deinit(gpa);
24612460
2462 for (zcu.failed_files.values()) |value| {2461 for (zcu.failed_files.values()) |value| {
2463 if (value) |msg| msg.destroy(gpa);2462 if (value) |msg| msg.destroy(gpa);
...@@ -3800,6 +3799,18 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {...@@ -3800,6 +3799,18 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {
3800 };3799 };
3801}3800}
38023801
3802pub fn typeSrcLoc(zcu: *const Zcu, ty_index: InternPool.Index) LazySrcLoc {
3803 _ = zcu;
3804 _ = ty_index;
3805 @panic("TODO");
3806}
3807
3808pub fn typeFileScope(zcu: *Zcu, ty_index: InternPool.Index) *File {
3809 _ = zcu;
3810 _ = ty_index;
3811 @panic("TODO");
3812}
3813
3803pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {3814pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
3804 const ip = &zcu.intern_pool;3815 const ip = &zcu.intern_pool;
3805 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;3816 const inst_info = ip.getNav(nav_index).srcInst(ip).resolveFull(ip).?;
...@@ -4060,3 +4071,16 @@ pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool {...@@ -4060,3 +4071,16 @@ pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool {
4060 else => true,4071 else => true,
4061 };4072 };
4062}4073}
4074
4075pub fn codegenFail(
4076 zcu: *Zcu,
4077 nav_index: InternPool.Nav.Index,
4078 comptime format: []const u8,
4079 args: anytype,
4080) error{ CodegenFail, OutOfMemory } {
4081 const gpa = zcu.gpa;
4082 try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
4083 const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
4084 zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, msg);
4085 return error.CodegenFail;
4086}
src/Zcu/PerThread.zig+15-8
...@@ -3130,24 +3130,31 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error...@@ -3130,24 +3130,31 @@ pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error
3130 }3130 }
3131}3131}
31323132
3133pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) !void {3133pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) error{OutOfMemory}!void {
3134 const zcu = pt.zcu;3134 const zcu = pt.zcu;
3135 const gpa = zcu.gpa;
3135 const comp = zcu.comp;3136 const comp = zcu.comp;
3136 const ip = &zcu.intern_pool;3137 const ip = &zcu.intern_pool;
31373138
3138 const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0);3139 const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0);
3139 defer codegen_prog_node.end();3140 defer codegen_prog_node.end();
31403141
3142 if (zcu.failed_types.fetchSwapRemove(ty)) |entry| entry.deinit();
3143
3141 if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) {3144 if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) {
3142 // This type failed to resolve. This is a transitive failure.3145 // This type failed to resolve. This is a transitive failure.
3143 // TODO: do we need to mark this failure anywhere? I don't think so, since compilation3146 return;
3144 // will fail due to the type error anyway.
3145 } else if (comp.bin_file) |lf| {
3146 lf.updateContainerType(pt, ty) catch |err| switch (err) {
3147 error.OutOfMemory => return error.OutOfMemory,
3148 else => |e| log.err("codegen type failed: {s}", .{@errorName(e)}),
3149 };
3150 }3147 }
3148
3149 if (comp.bin_file) |lf| lf.updateContainerType(pt, ty) catch |err| switch (err) {
3150 error.OutOfMemory => return error.OutOfMemory,
3151 else => |e| try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create(
3152 gpa,
3153 zcu.typeSrcLoc(ty),
3154 "failed to update container type: {s}",
3155 .{@errorName(e)},
3156 )),
3157 };
3151}3158}
31523159
3153pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {3160pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {
src/link.zig+1-5
...@@ -1290,11 +1290,7 @@ pub const File = struct {...@@ -1290,11 +1290,7 @@ pub const File = struct {
1290 args: anytype,1290 args: anytype,
1291 ) error{ CodegenFail, OutOfMemory } {1291 ) error{ CodegenFail, OutOfMemory } {
1292 @branchHint(.cold);1292 @branchHint(.cold);
1293 const zcu = base.comp.zcu.?;1293 return base.comp.zcu.?.codegenFail(nav_index, format, args);
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 }1294 }
12991295
1300 pub const C = @import("link/C.zig");1296 pub const C = @import("link/C.zig");
src/link/Dwarf.zig+62-12
...@@ -21,12 +21,24 @@ debug_rnglists: DebugRngLists,...@@ -21,12 +21,24 @@ debug_rnglists: DebugRngLists,
21debug_str: StringSection,21debug_str: StringSection,
2222
23pub const UpdateError = error{23pub const UpdateError = error{
24 /// Indicates the error is already reported on `failed_codegen` in the Zcu.
25 CodegenFail,24 CodegenFail,
25 ReinterpretDeclRef,
26 Unimplemented,
26 OutOfMemory,27 OutOfMemory,
27};28 EndOfStream,
29 Overflow,
30 Underflow,
31 UnexpectedEndOfFile,
32} ||
33 std.fs.File.OpenError ||
34 std.fs.File.SetEndPosError ||
35 std.fs.File.CopyRangeError ||
36 std.fs.File.PReadError ||
37 std.fs.File.PWriteError;
2838
29pub const FlushError = UpdateError || std.process.GetCwdError;39pub const FlushError =
40 UpdateError ||
41 std.process.GetCwdError;
3042
31pub const RelocError =43pub const RelocError =
32 std.fs.File.PWriteError;44 std.fs.File.PWriteError;
...@@ -587,14 +599,13 @@ const Unit = struct {...@@ -587,14 +599,13 @@ const Unit = struct {
587599
588 fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {600 fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void {
589 if (unit.off == new_off) return;601 if (unit.off == new_off) return;
590 const diags = &dwarf.bin_file.base.comp.link_diags;602 const n = try dwarf.getFile().?.copyRangeAll(
591 const n = dwarf.getFile().?.copyRangeAll(
592 sec.off(dwarf) + unit.off,603 sec.off(dwarf) + unit.off,
593 dwarf.getFile().?,604 dwarf.getFile().?,
594 sec.off(dwarf) + new_off,605 sec.off(dwarf) + new_off,
595 unit.len,606 unit.len,
596 ) catch |err| return diags.fail("failed to copy file range: {s}", .{@errorName(err)});607 );
597 if (n != unit.len) return diags.fail("unexpected short write from copy file range", .{});608 if (n != unit.len) return error.InputOutput;
598 unit.off = new_off;609 unit.off = new_off;
599 }610 }
600611
...@@ -2267,7 +2278,7 @@ pub fn deinit(dwarf: *Dwarf) void {...@@ -2267,7 +2278,7 @@ pub fn deinit(dwarf: *Dwarf) void {
2267 dwarf.* = undefined;2278 dwarf.* = undefined;
2268}2279}
22692280
2270fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index {2281fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {
2271 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);2282 const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);
2272 const unit: Unit.Index = @enumFromInt(mod_gop.index);2283 const unit: Unit.Index = @enumFromInt(mod_gop.index);
2273 if (!mod_gop.found_existing) {2284 if (!mod_gop.found_existing) {
...@@ -2327,7 +2338,25 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo {...@@ -2327,7 +2338,25 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo {
2327 return &dwarf.mods.values()[@intFromEnum(unit)];2338 return &dwarf.mods.values()[@intFromEnum(unit)];
2328}2339}
23292340
2330pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, sym_index: u32) UpdateError!?WipNav {2341pub fn initWipNav(
2342 dwarf: *Dwarf,
2343 pt: Zcu.PerThread,
2344 nav_index: InternPool.Nav.Index,
2345 sym_index: u32,
2346) error{ OutOfMemory, CodegenFail }!?WipNav {
2347 return initWipNavInner(dwarf, pt, nav_index, sym_index) catch |err| switch (err) {
2348 error.OutOfMemory => return error.OutOfMemory,
2349 error.CodegenFail => return error.CodegenFail,
2350 else => |e| return pt.zcu.codegenFail(nav_index, "failed to init dwarf: {s}", .{@errorName(e)}),
2351 };
2352}
2353
2354fn initWipNavInner(
2355 dwarf: *Dwarf,
2356 pt: Zcu.PerThread,
2357 nav_index: InternPool.Nav.Index,
2358 sym_index: u32,
2359) !?WipNav {
2331 const zcu = pt.zcu;2360 const zcu = pt.zcu;
2332 const ip = &zcu.intern_pool;2361 const ip = &zcu.intern_pool;
23332362
...@@ -2637,7 +2666,20 @@ pub fn finishWipNav(...@@ -2637,7 +2666,20 @@ pub fn finishWipNav(
2637 pt: Zcu.PerThread,2666 pt: Zcu.PerThread,
2638 nav_index: InternPool.Nav.Index,2667 nav_index: InternPool.Nav.Index,
2639 wip_nav: *WipNav,2668 wip_nav: *WipNav,
2640) UpdateError!void {2669) error{ OutOfMemory, CodegenFail }!void {
2670 return finishWipNavInner(dwarf, pt, nav_index, wip_nav) catch |err| switch (err) {
2671 error.OutOfMemory => return error.OutOfMemory,
2672 error.CodegenFail => return error.CodegenFail,
2673 else => |e| return pt.zcu.codegenFail(nav_index, "failed to finish dwarf: {s}", .{@errorName(e)}),
2674 };
2675}
2676
2677fn finishWipNavInner(
2678 dwarf: *Dwarf,
2679 pt: Zcu.PerThread,
2680 nav_index: InternPool.Nav.Index,
2681 wip_nav: *WipNav,
2682) !void {
2641 const zcu = pt.zcu;2683 const zcu = pt.zcu;
2642 const ip = &zcu.intern_pool;2684 const ip = &zcu.intern_pool;
2643 const nav = ip.getNav(nav_index);2685 const nav = ip.getNav(nav_index);
...@@ -2656,7 +2698,15 @@ pub fn finishWipNav(...@@ -2656,7 +2698,15 @@ pub fn finishWipNav(
2656 try wip_nav.updateLazy(zcu.navSrcLoc(nav_index));2698 try wip_nav.updateLazy(zcu.navSrcLoc(nav_index));
2657}2699}
26582700
2659pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateError!void {2701pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void {
2702 return updateComptimeNavInner(dwarf, pt, nav_index) catch |err| switch (err) {
2703 error.OutOfMemory => return error.OutOfMemory,
2704 error.CodegenFail => return error.CodegenFail,
2705 else => |e| return pt.zcu.codegenFail(nav_index, "failed to update dwarf: {s}", .{@errorName(e)}),
2706 };
2707}
2708
2709fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
2660 const zcu = pt.zcu;2710 const zcu = pt.zcu;
2661 const ip = &zcu.intern_pool;2711 const ip = &zcu.intern_pool;
2662 const nav_src_loc = zcu.navSrcLoc(nav_index);2712 const nav_src_loc = zcu.navSrcLoc(nav_index);
...@@ -4310,7 +4360,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A...@@ -4310,7 +4360,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
4310 return @intFromEnum(abbrev_code);4360 return @intFromEnum(abbrev_code);
4311}4361}
43124362
4313pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) !void {4363pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4314 const zcu = pt.zcu;4364 const zcu = pt.zcu;
4315 const ip = &zcu.intern_pool;4365 const ip = &zcu.intern_pool;
43164366
src/link/Elf.zig+2-2
...@@ -575,7 +575,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {...@@ -575,7 +575,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 {
575 }575 }
576 }576 }
577577
578 if (at_end) try self.setEndPos(end);578 if (at_end) try self.base.file.?.setEndPos(end);
579 return null;579 return null;
580}580}
581581
...@@ -638,7 +638,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment:...@@ -638,7 +638,7 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment:
638638
639 shdr.sh_offset = new_offset;639 shdr.sh_offset = new_offset;
640 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {640 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
641 try self.setEndPos(shdr.sh_offset + needed_size);641 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
642 }642 }
643 }643 }
644644
src/link/Elf/ZigObject.zig+16-8
...@@ -1300,7 +1300,9 @@ fn updateNavCode(...@@ -1300,7 +1300,9 @@ fn updateNavCode(
1300 const capacity = atom_ptr.capacity(elf_file);1300 const capacity = atom_ptr.capacity(elf_file);
1301 const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));1301 const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));
1302 if (need_realloc) {1302 if (need_realloc) {
1303 try self.allocateAtom(atom_ptr, true, elf_file);1303 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1304 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
1305
1304 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });1306 log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
1305 if (old_vaddr != atom_ptr.value) {1307 if (old_vaddr != atom_ptr.value) {
1306 sym.value = 0;1308 sym.value = 0;
...@@ -1310,7 +1312,9 @@ fn updateNavCode(...@@ -1310,7 +1312,9 @@ fn updateNavCode(
1310 // TODO shrink section size1312 // TODO shrink section size
1311 }1313 }
1312 } else {1314 } else {
1313 try self.allocateAtom(atom_ptr, true, elf_file);1315 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1316 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
1317
1314 errdefer self.freeNavMetadata(elf_file, sym_index);1318 errdefer self.freeNavMetadata(elf_file, sym_index);
1315 sym.value = 0;1319 sym.value = 0;
1316 esym.st_value = 0;1320 esym.st_value = 0;
...@@ -1342,7 +1346,8 @@ fn updateNavCode(...@@ -1342,7 +1346,8 @@ fn updateNavCode(
1342 const shdr = elf_file.sections.items(.shdr)[shdr_index];1346 const shdr = elf_file.sections.items(.shdr)[shdr_index];
1343 if (shdr.sh_type != elf.SHT_NOBITS) {1347 if (shdr.sh_type != elf.SHT_NOBITS) {
1344 const file_offset = atom_ptr.offset(elf_file);1348 const file_offset = atom_ptr.offset(elf_file);
1345 try elf_file.pwriteAll(code, file_offset);1349 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|
1350 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});
1346 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });1351 log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
1347 }1352 }
1348}1353}
...@@ -1385,7 +1390,8 @@ fn updateTlv(...@@ -1385,7 +1390,8 @@ fn updateTlv(
1385 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);1390 const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
1386 assert(!gop.found_existing); // TODO incremental updates1391 assert(!gop.found_existing); // TODO incremental updates
13871392
1388 try self.allocateAtom(atom_ptr, true, elf_file);1393 self.allocateAtom(atom_ptr, true, elf_file) catch |err|
1394 return elf_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
1389 sym.value = 0;1395 sym.value = 0;
1390 esym.st_value = 0;1396 esym.st_value = 0;
13911397
...@@ -1394,7 +1400,8 @@ fn updateTlv(...@@ -1394,7 +1400,8 @@ fn updateTlv(
1394 const shdr = elf_file.sections.items(.shdr)[shndx];1400 const shdr = elf_file.sections.items(.shdr)[shndx];
1395 if (shdr.sh_type != elf.SHT_NOBITS) {1401 if (shdr.sh_type != elf.SHT_NOBITS) {
1396 const file_offset = atom_ptr.offset(elf_file);1402 const file_offset = atom_ptr.offset(elf_file);
1397 try elf_file.pwriteAll(code, file_offset);1403 elf_file.base.file.?.pwriteAll(code, file_offset) catch |err|
1404 return elf_file.base.cgFail(nav_index, "failed to write to output file: {s}", .{@errorName(err)});
1398 log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{1405 log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{
1399 atom_ptr.name(elf_file),1406 atom_ptr.name(elf_file),
1400 file_offset,1407 file_offset,
...@@ -1513,7 +1520,8 @@ pub fn updateFunc(...@@ -1513,7 +1520,8 @@ pub fn updateFunc(
1513 target_sym.flags.has_trampoline = true;1520 target_sym.flags.has_trampoline = true;
1514 }1521 }
1515 const target_sym = self.symbol(sym_index);1522 const target_sym = self.symbol(sym_index);
1516 try writeTrampoline(self.symbol(target_sym.extra(elf_file).trampoline).*, target_sym.*, elf_file);1523 writeTrampoline(self.symbol(target_sym.extra(elf_file).trampoline).*, target_sym.*, elf_file) catch |err|
1524 return elf_file.base.cgFail(func.owner_nav, "failed to write trampoline: {s}", .{@errorName(err)});
1517 }1525 }
1518}1526}
15191527
...@@ -1898,7 +1906,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {...@@ -1898,7 +1906,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
1898 return len;1906 return len;
1899}1907}
19001908
1901fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.UpdateNavError!void {1909fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
1902 const atom_ptr = tr_sym.atom(elf_file).?;1910 const atom_ptr = tr_sym.atom(elf_file).?;
1903 const fileoff = atom_ptr.offset(elf_file);1911 const fileoff = atom_ptr.offset(elf_file);
1904 const source_addr = tr_sym.address(.{}, elf_file);1912 const source_addr = tr_sym.address(.{}, elf_file);
...@@ -1908,7 +1916,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.Upd...@@ -1908,7 +1916,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.Upd
1908 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),1916 .x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
1909 else => @panic("TODO implement write trampoline for this CPU arch"),1917 else => @panic("TODO implement write trampoline for this CPU arch"),
1910 };1918 };
1911 try elf_file.pwriteAll(out, fileoff);1919 try elf_file.base.file.?.pwriteAll(out, fileoff);
19121920
1913 if (elf_file.base.child_pid) |pid| {1921 if (elf_file.base.child_pid) |pid| {
1914 switch (builtin.os.tag) {1922 switch (builtin.os.tag) {
src/link/MachO.zig+13-13
...@@ -532,7 +532,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -532,7 +532,10 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
532 try self.generateUnwindInfo();532 try self.generateUnwindInfo();
533533
534 try self.initSegments();534 try self.initSegments();
535 try self.allocateSections();535 self.allocateSections() catch |err| switch (err) {
536 error.LinkFailure => return error.LinkFailure,
537 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
538 };
536 self.allocateSegments();539 self.allocateSegments();
537 self.allocateSyntheticSymbols();540 self.allocateSyntheticSymbols();
538541
...@@ -3133,7 +3136,7 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) !?u64 {...@@ -3133,7 +3136,7 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) !?u64 {
3133 }3136 }
3134 }3137 }
31353138
3136 if (at_end) try self.setEndPos(end);3139 if (at_end) try self.base.file.?.setEndPos(end);
3137 return null;3140 return null;
3138}3141}
31393142
...@@ -3217,25 +3220,22 @@ pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32)...@@ -3217,25 +3220,22 @@ pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32)
3217 return start;3220 return start;
3218}3221}
32193222
3220pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) error{LinkFailure}!void {3223pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void {
3221 const diags = &self.base.comp.link_diags;
3222 const file = self.base.file.?;3224 const file = self.base.file.?;
3223 const amt = file.copyRangeAll(old_offset, file, new_offset, size) catch |err|3225 const amt = try file.copyRangeAll(old_offset, file, new_offset, size);
3224 return diags.fail("failed to copy file range: {s}", .{@errorName(err)});3226 if (amt != size) return error.InputOutput;
3225 if (amt != size)
3226 return diags.fail("unexpected short write in copy file range", .{});
3227}3227}
32283228
3229/// Like File.copyRangeAll but also ensures the source region is zeroed out after copy.3229/// Like File.copyRangeAll but also ensures the source region is zeroed out after copy.
3230/// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader.3230/// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader.
3231fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) error{ LinkFailure, OutOfMemory }!void {3231fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void {
3232 const gpa = self.base.comp.gpa;3232 const gpa = self.base.comp.gpa;
3233 try self.copyRangeAll(old_offset, new_offset, size);3233 try self.copyRangeAll(old_offset, new_offset, size);
3234 const size_u = try self.cast(usize, size);3234 const size_u = math.cast(usize, size) orelse return error.Overflow;
3235 const zeroes = try gpa.alloc(u8, size_u); // TODO no need to allocate here.3235 const zeroes = try gpa.alloc(u8, size_u); // TODO no need to allocate here.
3236 defer gpa.free(zeroes);3236 defer gpa.free(zeroes);
3237 @memset(zeroes, 0);3237 @memset(zeroes, 0);
3238 try self.pwriteAll(zeroes, old_offset);3238 try self.base.file.?.pwriteAll(zeroes, old_offset);
3239}3239}
32403240
3241const InitMetadataOptions = struct {3241const InitMetadataOptions = struct {
...@@ -3459,7 +3459,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo...@@ -3459,7 +3459,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo
34593459
3460 sect.offset = @intCast(new_offset);3460 sect.offset = @intCast(new_offset);
3461 } else if (sect.offset + allocated_size == std.math.maxInt(u64)) {3461 } else if (sect.offset + allocated_size == std.math.maxInt(u64)) {
3462 try self.setEndPos(sect.offset + needed_size);3462 try self.base.file.?.setEndPos(sect.offset + needed_size);
3463 }3463 }
3464 seg.filesize = needed_size;3464 seg.filesize = needed_size;
3465 }3465 }
...@@ -3508,7 +3508,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void...@@ -3508,7 +3508,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void
3508 sect.offset = @intCast(new_offset);3508 sect.offset = @intCast(new_offset);
3509 sect.addr = new_addr;3509 sect.addr = new_addr;
3510 } else if (sect.offset + allocated_size == std.math.maxInt(u64)) {3510 } else if (sect.offset + allocated_size == std.math.maxInt(u64)) {
3511 try self.setEndPos(sect.offset + needed_size);3511 try self.base.file.?.setEndPos(sect.offset + needed_size);
3512 }3512 }
3513 }3513 }
3514 sect.size = needed_size;3514 sect.size = needed_size;
src/link/MachO/relocatable.zig+4-1
...@@ -55,7 +55,10 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat...@@ -55,7 +55,10 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
55 try calcSectionSizes(macho_file);55 try calcSectionSizes(macho_file);
5656
57 try createSegment(macho_file);57 try createSegment(macho_file);
58 try allocateSections(macho_file);58 allocateSections(macho_file) catch |err| switch (err) {
59 error.LinkFailure => return error.LinkFailure,
60 else => |e| return diags.fail("failed to allocate sections: {s}", .{@errorName(e)}),
61 };
59 allocateSegment(macho_file);62 allocateSegment(macho_file);
6063
61 if (build_options.enable_logging) {64 if (build_options.enable_logging) {