mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 23:23:07 +00:00
macho linker conforms to explicit error sets, again
This commit is contained in:
parent
6235cc3da4
commit
da25ed95fc
19
src/link.zig
19
src/link.zig
@ -632,15 +632,14 @@ pub const File = struct {
|
||||
pub const UpdateDebugInfoError = Dwarf.UpdateError;
|
||||
pub const FlushDebugInfoError = Dwarf.FlushError;
|
||||
|
||||
/// Note that `LinkFailure` is not a member of this error set because the error message
|
||||
/// must be attached to `Zcu.failed_codegen` rather than `Compilation.link_diags`.
|
||||
pub const UpdateNavError = error{
|
||||
Overflow,
|
||||
OutOfMemory,
|
||||
/// Indicates the error is already reported and stored in
|
||||
/// `failed_codegen` on the Zcu.
|
||||
CodegenFail,
|
||||
/// Indicates the error is already reported and stored in `link_diags`
|
||||
/// on the Compilation.
|
||||
LinkFailure,
|
||||
};
|
||||
|
||||
/// Called from within CodeGen to retrieve the symbol index of a global symbol.
|
||||
@ -1284,6 +1283,20 @@ pub const File = struct {
|
||||
}, llvm_object, prog_node);
|
||||
}
|
||||
|
||||
pub fn cgFail(
|
||||
base: *File,
|
||||
nav_index: InternPool.Nav.Index,
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) error{ CodegenFail, OutOfMemory } {
|
||||
@branchHint(.cold);
|
||||
const zcu = base.comp.zcu.?;
|
||||
const gpa = zcu.gpa;
|
||||
try zcu.failed_codegen.ensureUnusedCapacity(gpa, 1);
|
||||
const msg = try Zcu.ErrorMsg.create(gpa, zcu.navSrcLoc(nav_index), format, args);
|
||||
zcu.failed_codegen.putAssumeCapacityNoClobber(gpa, nav_index, msg);
|
||||
}
|
||||
|
||||
pub const C = @import("link/C.zig");
|
||||
pub const Coff = @import("link/Coff.zig");
|
||||
pub const Plan9 = @import("link/Plan9.zig");
|
||||
|
||||
@ -26,9 +26,7 @@ pub const UpdateError = error{
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
pub const FlushError =
|
||||
UpdateError ||
|
||||
std.process.GetCwdError;
|
||||
pub const FlushError = UpdateError || std.process.GetCwdError;
|
||||
|
||||
pub const RelocError =
|
||||
std.fs.File.PWriteError;
|
||||
@ -4312,7 +4310,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
|
||||
return @intFromEnum(abbrev_code);
|
||||
}
|
||||
|
||||
pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
|
||||
pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) !void {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
|
||||
@ -807,7 +807,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
defer tracy.end();
|
||||
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const diags = &comp.link_diags;
|
||||
|
||||
if (self.llvm_object) |llvm_object| {
|
||||
@ -821,6 +820,18 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
const sub_prog_node = prog_node.start("ELF Flush", 0);
|
||||
defer sub_prog_node.end();
|
||||
|
||||
return flushModuleInner(self, arena, tid) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.LinkFailure => return error.LinkFailure,
|
||||
else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
|
||||
fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const diags = &comp.link_diags;
|
||||
|
||||
const module_obj_path: ?Path = if (self.base.zcu_object_sub_path) |path| .{
|
||||
.root_dir = self.base.emit.root_dir,
|
||||
.sub_path = if (fs.path.dirname(self.base.emit.sub_path)) |dirname|
|
||||
@ -2432,7 +2443,7 @@ pub fn addCommentString(self: *Elf) !void {
|
||||
self.comment_merge_section_index = msec_index;
|
||||
}
|
||||
|
||||
pub fn resolveMergeSections(self: *Elf) link.File.FlushError!void {
|
||||
pub fn resolveMergeSections(self: *Elf) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
|
||||
@ -264,7 +264,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.FlushError!void {
|
||||
pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
|
||||
// Handle any lazy symbols that were emitted by incremental compilation.
|
||||
if (self.lazy_syms.getPtr(.anyerror_type)) |metadata| {
|
||||
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.
|
||||
metadata.text_symbol_index,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.LinkFailure,
|
||||
else => |e| e,
|
||||
else => |e| return e,
|
||||
};
|
||||
if (metadata.rodata_state != .unused) self.updateLazySymbol(
|
||||
elf_file,
|
||||
@ -288,7 +288,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) link.File.
|
||||
metadata.rodata_symbol_index,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.LinkFailure,
|
||||
else => |e| e,
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
@ -1263,7 +1263,7 @@ fn updateNavCode(
|
||||
shdr_index: u32,
|
||||
code: []const u8,
|
||||
stt_bits: u8,
|
||||
) !void {
|
||||
) link.File.UpdateNavError!void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
@ -1342,7 +1342,7 @@ fn updateNavCode(
|
||||
const shdr = elf_file.sections.items(.shdr)[shdr_index];
|
||||
if (shdr.sh_type != elf.SHT_NOBITS) {
|
||||
const file_offset = atom_ptr.offset(elf_file);
|
||||
try elf_file.base.file.?.pwriteAll(code, file_offset);
|
||||
try elf_file.pwriteAll(code, file_offset);
|
||||
log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len });
|
||||
}
|
||||
}
|
||||
@ -1355,7 +1355,7 @@ fn updateTlv(
|
||||
sym_index: Symbol.Index,
|
||||
shndx: u32,
|
||||
code: []const u8,
|
||||
) !void {
|
||||
) link.File.UpdateNavError!void {
|
||||
const zcu = pt.zcu;
|
||||
const ip = &zcu.intern_pool;
|
||||
const gpa = zcu.gpa;
|
||||
@ -1394,7 +1394,7 @@ fn updateTlv(
|
||||
const shdr = elf_file.sections.items(.shdr)[shndx];
|
||||
if (shdr.sh_type != elf.SHT_NOBITS) {
|
||||
const file_offset = atom_ptr.offset(elf_file);
|
||||
try elf_file.base.file.?.pwriteAll(code, file_offset);
|
||||
try elf_file.pwriteAll(code, file_offset);
|
||||
log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{
|
||||
atom_ptr.name(elf_file),
|
||||
file_offset,
|
||||
@ -1617,7 +1617,7 @@ fn updateLazySymbol(
|
||||
pt: Zcu.PerThread,
|
||||
sym: link.File.LazySymbol,
|
||||
symbol_index: Symbol.Index,
|
||||
) link.File.FlushError!void {
|
||||
) !void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
|
||||
@ -1698,7 +1698,7 @@ fn updateLazySymbol(
|
||||
local_sym.value = 0;
|
||||
local_esym.st_value = 0;
|
||||
|
||||
try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
|
||||
try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
|
||||
}
|
||||
|
||||
const LowerConstResult = union(enum) {
|
||||
@ -1750,7 +1750,7 @@ fn lowerConst(
|
||||
try self.allocateAtom(atom_ptr, true, elf_file);
|
||||
errdefer self.freeNavMetadata(elf_file, sym_index);
|
||||
|
||||
try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
|
||||
try elf_file.pwriteAll(code, atom_ptr.offset(elf_file));
|
||||
|
||||
return .{ .ok = sym_index };
|
||||
}
|
||||
@ -1898,7 +1898,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 {
|
||||
return len;
|
||||
}
|
||||
|
||||
fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
|
||||
fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) link.File.UpdateNavError!void {
|
||||
const atom_ptr = tr_sym.atom(elf_file).?;
|
||||
const fileoff = atom_ptr.offset(elf_file);
|
||||
const source_addr = tr_sym.address(.{}, elf_file);
|
||||
@ -1908,7 +1908,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
|
||||
.x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
|
||||
else => @panic("TODO implement write trampoline for this CPU arch"),
|
||||
};
|
||||
try elf_file.base.file.?.pwriteAll(out, fileoff);
|
||||
try elf_file.pwriteAll(out, fileoff);
|
||||
|
||||
if (elf_file.base.child_pid) |pid| {
|
||||
switch (builtin.os.tag) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
|
||||
pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
|
||||
const gpa = comp.gpa;
|
||||
const diags = &comp.link_diags;
|
||||
|
||||
@ -130,7 +130,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) link.File.FlushError!v
|
||||
if (diags.hasErrors()) return error.LinkFailure;
|
||||
}
|
||||
|
||||
pub fn flushObject(elf_file: *Elf, comp: *Compilation) link.File.FlushError!void {
|
||||
pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
|
||||
const diags = &comp.link_diags;
|
||||
|
||||
if (diags.hasErrors()) return error.LinkFailure;
|
||||
@ -259,7 +259,7 @@ fn initComdatGroups(elf_file: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn updateSectionSizes(elf_file: *Elf) link.File.FlushError!void {
|
||||
fn updateSectionSizes(elf_file: *Elf) !void {
|
||||
const slice = elf_file.sections.slice();
|
||||
for (slice.items(.atom_list_2)) |*atom_list| {
|
||||
if (atom_list.atoms.keys().len == 0) continue;
|
||||
|
||||
@ -3423,7 +3423,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
|
||||
pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
|
||||
if (self.base.isRelocatable()) {
|
||||
try self.growSectionRelocatable(sect_index, needed_size);
|
||||
} else {
|
||||
@ -3431,7 +3431,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfM
|
||||
}
|
||||
}
|
||||
|
||||
fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
|
||||
fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
|
||||
const diags = &self.base.comp.link_diags;
|
||||
const sect = &self.sections.items(.header)[sect_index];
|
||||
|
||||
@ -3480,7 +3480,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) err
|
||||
seg.vmsize = needed_size;
|
||||
}
|
||||
|
||||
fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{ OutOfMemory, LinkFailure }!void {
|
||||
fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
|
||||
const sect = &self.sections.items(.header)[sect_index];
|
||||
|
||||
if (!sect.isZerofill()) {
|
||||
@ -3490,7 +3490,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) error{
|
||||
sect.size = 0;
|
||||
|
||||
// Must move the entire section.
|
||||
const alignment = try self.alignPow(sect.@"align");
|
||||
const alignment = try math.powi(u32, 2, sect.@"align");
|
||||
const new_offset = try self.findFreeSpace(needed_size, alignment);
|
||||
const new_addr = self.findFreeSpaceVirtual(needed_size, alignment);
|
||||
|
||||
|
||||
@ -559,18 +559,26 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
|
||||
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) try self.updateLazySymbol(
|
||||
if (metadata.text_state != .unused) self.updateLazySymbol(
|
||||
macho_file,
|
||||
pt,
|
||||
.{ .kind = .code, .ty = .anyerror_type },
|
||||
metadata.text_symbol_index,
|
||||
);
|
||||
if (metadata.const_state != .unused) try self.updateLazySymbol(
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.LinkFailure => return error.LinkFailure,
|
||||
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
|
||||
};
|
||||
if (metadata.const_state != .unused) self.updateLazySymbol(
|
||||
macho_file,
|
||||
pt,
|
||||
.{ .kind = .const_data, .ty = .anyerror_type },
|
||||
metadata.const_symbol_index,
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.LinkFailure => return error.LinkFailure,
|
||||
else => |e| return diags.fail("failed to update lazy symbol: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
@ -803,7 +811,7 @@ pub fn updateFunc(
|
||||
.ok => code_buffer.items,
|
||||
.fail => |em| {
|
||||
try zcu.failed_codegen.put(gpa, func.owner_nav, em);
|
||||
return;
|
||||
return error.CodegenFail;
|
||||
},
|
||||
};
|
||||
|
||||
@ -855,7 +863,8 @@ pub fn updateFunc(
|
||||
}
|
||||
const target_sym = self.symbols.items[sym_index];
|
||||
const source_sym = self.symbols.items[target_sym.getExtra(macho_file).trampoline];
|
||||
try writeTrampoline(source_sym, target_sym, macho_file);
|
||||
writeTrampoline(source_sym, target_sym, macho_file) catch |err|
|
||||
return macho_file.base.cgFail(func.owner_nav, "failed to write trampoline: {s}", .{@errorName(err)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -955,7 +964,6 @@ fn updateNavCode(
|
||||
else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
|
||||
};
|
||||
|
||||
const diags = &macho_file.base.comp.link_diags;
|
||||
const sect = &macho_file.sections.items(.header)[sect_index];
|
||||
const sym = &self.symbols.items[sym_index];
|
||||
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
|
||||
@ -984,7 +992,8 @@ fn updateNavCode(
|
||||
const need_realloc = code.len > capacity or !required_alignment.check(atom.value);
|
||||
|
||||
if (need_realloc) {
|
||||
atom.grow(macho_file) catch |err| return diags.fail("failed to grow atom: {s}", .{@errorName(err)});
|
||||
atom.grow(macho_file) catch |err|
|
||||
return macho_file.base.cgFail(nav_index, "failed to grow atom: {s}", .{@errorName(err)});
|
||||
log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom.value });
|
||||
if (old_vaddr != atom.value) {
|
||||
sym.value = 0;
|
||||
@ -997,7 +1006,8 @@ fn updateNavCode(
|
||||
sect.size = needed_size;
|
||||
}
|
||||
} else {
|
||||
try atom.allocate(macho_file);
|
||||
atom.allocate(macho_file) catch |err|
|
||||
return macho_file.base.cgFail(nav_index, "failed to allocate atom: {s}", .{@errorName(err)});
|
||||
errdefer self.freeNavMetadata(macho_file, sym_index);
|
||||
|
||||
sym.value = 0;
|
||||
@ -1006,7 +1016,8 @@ fn updateNavCode(
|
||||
|
||||
if (!sect.isZerofill()) {
|
||||
const file_offset = sect.offset + atom.value;
|
||||
try macho_file.pwriteAll(code, file_offset);
|
||||
macho_file.base.file.?.pwriteAll(code, file_offset) catch |err|
|
||||
return macho_file.base.cgFail(nav_index, "failed to write output file: {s}", .{@errorName(err)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1353,7 +1364,7 @@ fn updateLazySymbol(
|
||||
pt: Zcu.PerThread,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
symbol_index: Symbol.Index,
|
||||
) error{ OutOfMemory, LinkFailure }!void {
|
||||
) !void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
const diags = &macho_file.base.comp.link_diags;
|
||||
@ -1494,7 +1505,7 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, macho_file: *MachO) !void {
|
||||
.x86_64 => try x86_64.writeTrampolineCode(source_addr, target_addr, &buf),
|
||||
else => @panic("TODO implement write trampoline for this CPU arch"),
|
||||
};
|
||||
try macho_file.pwriteAll(out, fileoff);
|
||||
try macho_file.base.file.?.pwriteAll(out, fileoff);
|
||||
}
|
||||
|
||||
pub fn getOrCreateMetadataForNav(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user