Commit 41e9b8b6c8
Changed files (22)
src/arch/aarch64/CodeGen.zig
@@ -4354,8 +4354,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
if (try self.air.value(callee, pt)) |func_value| {
if (func_value.getFunction(mod)) |func| {
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
+ const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file)));
try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr });
src/arch/arm/CodeGen.zig
@@ -4336,8 +4336,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
if (try self.air.value(callee, pt)) |func_value| {
if (func_value.getFunction(mod)) |func| {
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
+ const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file));
try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr });
src/arch/riscv64/CodeGen.zig
@@ -1409,12 +1409,13 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void {
defer func.register_manager.unlockReg(data_lock);
const elf_file = func.bin_file.cast(link.File.Elf).?;
- const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, .{
.kind = .const_data,
.ty = enum_ty,
}) catch |err|
return func.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym = elf_file.symbol(sym_index);
+ const sym = zo.symbol(sym_index);
try func.genSetReg(Type.u64, data_reg, .{ .lea_symbol = .{ .sym = sym.esym_index } });
@@ -4946,8 +4947,9 @@ fn genCall(
}) {
.func => |func_val| {
if (func.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func_val.owner_decl);
+ const sym = zo.symbol(sym_index);
if (func.mod.pic) {
return func.fail("TODO: genCall pic", .{});
@@ -7822,9 +7824,10 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void {
const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(zcu), zcu);
const elf_file = func.bin_file.cast(link.File.Elf).?;
- const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
return func.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym = elf_file.symbol(sym_index);
+ const sym = zo.symbol(sym_index);
if (func.mod.pic) {
return func.fail("TODO: airTagName pic", .{});
@@ -8049,7 +8052,8 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
switch (lf.tag) {
.elf => {
const elf_file = lf.cast(link.File.Elf).?;
- const local = elf_file.symbol(local_sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const local = zo.symbol(local_sym_index);
return MCValue{ .undef = local.esym_index };
},
else => unreachable,
src/arch/riscv64/Emit.zig
@@ -50,16 +50,16 @@ pub fn emitMir(emit: *Emit) Error!void {
};
const elf_file = emit.bin_file.cast(link.File.Elf).?;
+ const zo = elf_file.zigObjectPtr().?;
- const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
- const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index);
- const sym = elf_file.symbol(sym_index);
+ const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
+ const sym = zo.symbol(symbol.sym_index);
var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
- _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
+ _ = try sym.getOrCreateZigGotEntry(symbol.sym_index, elf_file);
hi_r_type = Elf.R_ZIG_GOT_HI20;
lo_r_type = Elf.R_ZIG_GOT_LO12;
@@ -82,8 +82,9 @@ pub fn emitMir(emit: *Emit) Error!void {
},
.load_tlv_reloc => |symbol| {
const elf_file = emit.bin_file.cast(link.File.Elf).?;
+ const zo = elf_file.zigObjectPtr().?;
- const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
+ const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
const R_RISCV = std.elf.R_RISCV;
@@ -107,7 +108,8 @@ pub fn emitMir(emit: *Emit) Error!void {
},
.call_extern_fn_reloc => |symbol| {
const elf_file = emit.bin_file.cast(link.File.Elf).?;
- const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
+ const zo = elf_file.zigObjectPtr().?;
+ const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);
src/arch/sparc64/CodeGen.zig
@@ -1354,8 +1354,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
.func => |func| {
const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
+ const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file)));
} else unreachable;
src/arch/x86_64/CodeGen.zig
@@ -12327,8 +12327,9 @@ fn genCall(self: *Self, info: union(enum) {
}) {
.func => |func| {
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
+ const sym = zo.symbol(sym_index);
if (self.mod.pic) {
const callee_reg: Register = switch (resolved_cc) {
.SysV => callee: {
@@ -15320,9 +15321,10 @@ fn genLazySymbolRef(
) InnerError!void {
const pt = self.pt;
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
+ const zo = elf_file.zigObjectPtr().?;
+ const sym_index = zo.getOrCreateMetadataForLazySymbol(elf_file, pt, lazy_sym) catch |err|
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
- const sym = elf_file.symbol(sym_index);
+ const sym = zo.symbol(sym_index);
if (self.mod.pic) {
switch (tag) {
.lea, .call => try self.genSetReg(reg, Type.usize, .{
src/arch/x86_64/Emit.zig
@@ -42,7 +42,8 @@ pub fn emitMir(emit: *Emit) Error!void {
}),
.linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
// Add relocation to the decl.
- const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
+ const zo = elf_file.zigObjectPtr().?;
+ const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
try atom_ptr.addReloc(elf_file, .{
.r_offset = end_offset - 4,
@@ -88,7 +89,8 @@ pub fn emitMir(emit: *Emit) Error!void {
}),
.linker_tlsld => |data| {
const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
- const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(data.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
@@ -98,7 +100,8 @@ pub fn emitMir(emit: *Emit) Error!void {
},
.linker_dtpoff => |data| {
const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
- const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(data.atom_index).atom(elf_file).?;
const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
try atom.addReloc(elf_file, .{
.r_offset = end_offset - 4,
@@ -112,11 +115,11 @@ pub fn emitMir(emit: *Emit) Error!void {
.Obj => true,
.Lib => emit.lower.link_mode == .static,
};
- const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
- const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
- const sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const atom = zo.symbol(data.atom_index).atom(elf_file).?;
+ const sym = zo.symbol(data.sym_index);
if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
- _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
+ _ = try sym.getOrCreateZigGotEntry(data.sym_index, elf_file);
}
if (emit.lower.pic) {
const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
src/arch/x86_64/Lower.zig
@@ -349,8 +349,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
assert(mem_op.sib.scale_index.scale == 0);
if (lower.bin_file.cast(link.File.Elf)) |elf_file| {
- const sym_index = elf_file.zigObjectPtr().?.symbol(sym.sym_index);
- const elf_sym = elf_file.symbol(sym_index);
+ const zo = elf_file.zigObjectPtr().?;
+ const elf_sym = zo.symbol(sym.sym_index);
if (elf_sym.flags.is_tls) {
// TODO handle extern TLS vars, i.e., emit GD model
src/link/Elf/Atom.zig
@@ -326,12 +326,8 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
const cpu_arch = elf_file.getTarget().cpu.arch;
const file_ptr = self.file(elf_file).?;
for (self.relocs(elf_file)) |rel| {
- const target_index = switch (file_ptr) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
- };
- const target = elf_file.symbol(target_index);
+ const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
+ const target = elf_file.symbol(target_ref).?;
const r_type = rel.r_type();
const r_offset: u64 = @intCast(self.value + @as(i64, @intCast(rel.r_offset)));
var r_addend = rel.r_addend;
@@ -422,12 +418,21 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
const r_kind = relocation.decode(rel.r_type(), cpu_arch);
if (r_kind == .none) continue;
- const symbol_index = switch (file_ptr) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
+ const symbol_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
+ const symbol = elf_file.symbol(symbol_ref) orelse {
+ const sym_name = switch (file_ptr) {
+ .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file),
+ inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file),
+ };
+ // Violation of One Definition Rule for COMDATs.
+ // TODO convert into an error
+ log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{
+ file_ptr.fmtPath(),
+ self.name(elf_file),
+ sym_name,
+ });
+ continue;
};
- const symbol = elf_file.symbol(symbol_index);
const is_synthetic_symbol = switch (file_ptr) {
.zig_object => false, // TODO: implement this once we support merge sections in ZigObject
@@ -435,19 +440,8 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype
else => unreachable,
};
- // Check for violation of One Definition Rule for COMDATs.
- if (symbol.file(elf_file) == null) {
- // TODO convert into an error
- log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{
- file_ptr.fmtPath(),
- self.name(elf_file),
- symbol.name(elf_file),
- });
- continue;
- }
-
// Report an undefined symbol.
- if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, symbol, symbol_index, rel, undefs)))
+ if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, symbol, rel, undefs)))
continue;
if (symbol.isIFunc(elf_file)) {
@@ -694,16 +688,15 @@ fn reportUndefined(
self: Atom,
elf_file: *Elf,
sym: *const Symbol,
- sym_index: Symbol.Index,
rel: elf.Elf64_Rela,
undefs: anytype,
) !bool {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
- const rel_esym = switch (self.file(elf_file).?) {
- .zig_object => |x| x.elfSym(rel.r_sym()).*,
- .object => |x| x.symtab.items[rel.r_sym()],
- else => unreachable,
+ const file_ptr = self.file(elf_file).?;
+ const rel_esym = switch (file_ptr) {
+ .zig_object => |x| x.symbol(rel.r_sym()).elfSym(elf_file),
+ inline else => |x| x.symtab.items[rel.r_sym()],
};
const esym = sym.elfSym(elf_file);
if (rel_esym.st_shndx == elf.SHN_UNDEF and
@@ -712,7 +705,12 @@ fn reportUndefined(
!sym.flags.import and
esym.st_shndx == elf.SHN_UNDEF)
{
- const gop = try undefs.getOrPut(sym_index);
+ const idx = switch (file_ptr) {
+ .zig_object => |x| x.symbols_resolver.items[rel.r_sym() & ZigObject.symbol_mask],
+ .object => |x| x.symbols_resolver.items[rel.r_sym() - x.first_global.?],
+ inline else => |x| x.symbols_resolver.items[rel.r_sym()],
+ };
+ const gop = try undefs.getOrPut(idx);
if (!gop.found_existing) {
gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa);
}
@@ -737,11 +735,8 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
const r_kind = relocation.decode(rel.r_type(), cpu_arch);
if (r_kind == .none) continue;
- const target = switch (file_ptr) {
- .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())),
- .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
- else => unreachable,
- };
+ const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
+ const target = elf_file.symbol(target_ref).?;
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
// We will use equation format to resolve relocations:
@@ -923,31 +918,29 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
- const target_index = switch (file_ptr) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
- };
- const target = elf_file.symbol(target_index);
- const is_synthetic_symbol = switch (file_ptr) {
- .zig_object => false, // TODO: implement this once we support merge sections in ZigObject
- .object => |x| rel.r_sym() >= x.symtab.items.len,
- else => unreachable,
- };
-
- // Check for violation of One Definition Rule for COMDATs.
- if (target.file(elf_file) == null) {
+ const target_ref = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
+ const target = elf_file.symbol(target_ref) orelse {
+ const sym_name = switch (file_ptr) {
+ .zig_object => |x| x.symbol(rel.r_sym()).name(elf_file),
+ inline else => |x| x.symbols.items[rel.r_sym()].name(elf_file),
+ };
+ // Violation of One Definition Rule for COMDATs.
// TODO convert into an error
log.debug("{}: {s}: {s} refers to a discarded COMDAT section", .{
file_ptr.fmtPath(),
self.name(elf_file),
- target.name(elf_file),
+ sym_name,
});
continue;
- }
+ };
+ const is_synthetic_symbol = switch (file_ptr) {
+ .zig_object => false, // TODO: implement this once we support merge sections in ZigObject
+ .object => |x| rel.r_sym() >= x.symtab.items.len,
+ else => unreachable,
+ };
// Report an undefined symbol.
- if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, target, target_index, rel, undefs)))
+ if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, target, rel, undefs)))
continue;
// We will use equation format to resolve relocations:
@@ -1766,11 +1759,7 @@ const aarch64 = struct {
=> {
const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
const th = atom.thunk(elf_file);
- const target_index = switch (file_ptr) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
- };
+ const target_index = file_ptr.resolveSymbol(rel.r_sym(), elf_file);
const S_ = th.targetAddress(target_index, elf_file);
break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
};
@@ -2106,11 +2095,8 @@ const riscv = struct {
return error.RelocFailure;
};
it.pos = pos;
- const target_ = switch (file_ptr) {
- .zig_object => |x| elf_file.symbol(x.symbol(pair.r_sym())),
- .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]),
- else => unreachable,
- };
+ const target_ref_ = file_ptr.resolveSymbol(pair.r_sym(), elf_file);
+ const target_ = elf_file.symbol(target_ref_).?;
const S_ = target_.address(.{}, elf_file);
const A_ = pair.r_addend;
const P_ = atom_addr + @as(i64, @intCast(pair.r_offset));
@@ -2313,4 +2299,5 @@ const File = @import("file.zig").File;
const Object = @import("Object.zig");
const Symbol = @import("Symbol.zig");
const Thunk = @import("thunks.zig").Thunk;
+const ZigObject = @import("ZigObject.zig");
const dev = @import("../../dev.zig");
src/link/Elf/eh_frame.zig
@@ -339,7 +339,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
const contents = cie.data(elf_file);
for (cie.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
+ const ref = object.resolveSymbol(rel.r_sym(), elf_file);
+ const sym = elf_file.symbol(ref).?;
resolveReloc(cie, sym, rel, elf_file, contents) catch |err| switch (err) {
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
@@ -366,7 +367,8 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
);
for (fde.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
+ const ref = object.resolveSymbol(rel.r_sym(), elf_file);
+ const sym = elf_file.symbol(ref).?;
resolveReloc(fde, sym, rel, elf_file, contents) catch |err| switch (err) {
error.RelocFailure => has_reloc_errors = true,
else => |e| return e,
@@ -452,7 +454,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
for (object.cies.items) |cie| {
if (!cie.alive) continue;
for (cie.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
+ const ref = object.resolveSymbol(rel.r_sym(), elf_file);
+ const sym = elf_file.symbol(ref).?;
const out_rel = emitReloc(elf_file, cie, sym, rel);
try writer.writeStruct(out_rel);
}
@@ -461,7 +464,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
for (object.fdes.items) |fde| {
if (!fde.alive) continue;
for (fde.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
+ const ref = object.resolveSymbol(rel.r_sym(), elf_file);
+ const sym = elf_file.symbol(ref).?;
const out_rel = emitReloc(elf_file, fde, sym, rel);
try writer.writeStruct(out_rel);
}
@@ -513,7 +517,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
const relocs = fde.relocs(elf_file);
assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...
const rel = relocs[0];
- const sym = elf_file.symbol(object.symbols.items[rel.r_sym()]);
+ const ref = object.resolveSymbol(rel.r_sym(), elf_file);
+ const sym = elf_file.symbol(ref).?;
const P = @as(i64, @intCast(fde.address(elf_file)));
const S = @as(i64, @intCast(sym.address(.{}, elf_file)));
const A = rel.r_addend;
src/link/Elf/file.zig
@@ -61,10 +61,10 @@ pub const File = union(enum) {
return (@as(u32, base) << 24) + file.index();
}
- pub fn resolveSymbols(file: File, elf_file: *Elf) void {
- switch (file) {
+ pub fn resolveSymbols(file: File, elf_file: *Elf) !void {
+ return switch (file) {
inline else => |x| x.resolveSymbols(elf_file),
- }
+ };
}
pub fn resetGlobals(file: File, elf_file: *Elf) void {
@@ -100,6 +100,13 @@ pub const File = union(enum) {
}
}
+ pub fn createSymbolIndirection(file: File, elf_file: *Elf) !void {
+ return switch (file) {
+ .linker_defined, .shared_object => unreachable,
+ inline else => |x| x.createSymbolIndirection(elf_file),
+ };
+ }
+
pub fn atom(file: File, atom_index: Atom.Index) ?*Atom {
return switch (file) {
.shared_object => unreachable,
@@ -146,10 +153,16 @@ pub const File = union(enum) {
};
}
- pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index {
+ pub fn resolveSymbol(file: File, ind: Symbol.Index, elf_file: *Elf) Elf.Ref {
+ return switch (file) {
+ inline else => |x| x.resolveSymbol(ind, elf_file),
+ };
+ }
+
+ pub fn symbol(file: File, ind: Symbol.Index) *Symbol {
return switch (file) {
.zig_object => |x| x.symbol(ind),
- inline else => |x| x.symbols.items[ind],
+ inline else => |x| &x.symbols.items[ind],
};
}
src/link/Elf/gc.zig
@@ -1,71 +1,84 @@
pub fn gcAtoms(elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
- const num_files = elf_file.objects.items.len + @intFromBool(elf_file.zig_object_index != null);
- var files = try std.ArrayList(File.Index).initCapacity(gpa, num_files);
- defer files.deinit();
- if (elf_file.zig_object_index) |index| files.appendAssumeCapacity(index);
- for (elf_file.objects.items) |index| files.appendAssumeCapacity(index);
-
var roots = std.ArrayList(*Atom).init(gpa);
defer roots.deinit();
- try collectRoots(&roots, files.items, elf_file);
-
+ try collectRoots(&roots, elf_file);
mark(roots, elf_file);
- prune(files.items, elf_file);
+ prune(elf_file);
}
-fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_file: *Elf) !void {
+fn collectRoots(roots: *std.ArrayList(*Atom), elf_file: *Elf) !void {
if (elf_file.linkerDefinedPtr()) |obj| {
- if (obj.entry_index) |index| {
- const global = elf_file.symbol(index);
- try markSymbol(global, roots, elf_file);
+ if (obj.entrySymbol(elf_file)) |sym| {
+ try markSymbol(sym, roots, elf_file);
}
}
- for (files) |index| {
- for (elf_file.file(index).?.globals()) |global_index| {
- const global = elf_file.symbol(global_index);
- if (global.file(elf_file)) |file| {
- if (file.index() == index and global.flags.@"export")
- try markSymbol(global, roots, elf_file);
+ if (elf_file.zigObjectPtr()) |zo| {
+ for (0..zo.global_symbols.items.len) |i| {
+ const ref = zo.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file);
+ const sym = elf_file.symbol(ref) orelse continue;
+ if (sym.file(elf_file).?.index() != zo.index) continue;
+ if (sym.flags.@"export") {
+ try markSymbol(sym, roots, elf_file);
}
}
}
- for (files) |index| {
- const file = elf_file.file(index).?;
-
- for (file.atoms()) |atom_index| {
- const atom = file.atom(atom_index) orelse continue;
- if (!atom.alive) continue;
-
- const shdr = atom.inputShdr(elf_file);
- const name = atom.name(elf_file);
- const is_gc_root = blk: {
- if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true;
- if (shdr.sh_type == elf.SHT_NOTE) break :blk true;
- if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true;
- if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true;
- if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true;
- if (mem.startsWith(u8, name, ".ctors")) break :blk true;
- if (mem.startsWith(u8, name, ".dtors")) break :blk true;
- if (mem.startsWith(u8, name, ".init")) break :blk true;
- if (mem.startsWith(u8, name, ".fini")) break :blk true;
- if (Elf.isCIdentifier(name)) break :blk true;
- break :blk false;
- };
- if (is_gc_root and markAtom(atom)) try roots.append(atom);
- if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true;
+ for (elf_file.objects.items) |index| {
+ const object = elf_file.file(index).?.object;
+ for (0..object.globals().len) |i| {
+ const ref = object.resolveSymbol(@intCast(i), elf_file);
+ const sym = elf_file.symbol(ref) orelse continue;
+ if (sym.file(elf_file).?.index() != object.index) continue;
+ if (sym.flags.@"export") {
+ try markSymbol(sym, roots, elf_file);
+ }
}
+ }
- // Mark every atom referenced by CIE as alive.
- for (file.cies()) |cie| {
- for (cie.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(file.symbol(rel.r_sym()));
- try markSymbol(sym, roots, elf_file);
+ const atomRoots = struct {
+ fn atomRoots(file: File, rs: anytype, ef: *Elf) !void {
+ for (file.atoms()) |atom_index| {
+ const atom = file.atom(atom_index) orelse continue;
+ if (!atom.alive) continue;
+
+ const shdr = atom.inputShdr(ef);
+ const name = atom.name(ef);
+ const is_gc_root = blk: {
+ if (shdr.sh_flags & elf.SHF_GNU_RETAIN != 0) break :blk true;
+ if (shdr.sh_type == elf.SHT_NOTE) break :blk true;
+ if (shdr.sh_type == elf.SHT_PREINIT_ARRAY) break :blk true;
+ if (shdr.sh_type == elf.SHT_INIT_ARRAY) break :blk true;
+ if (shdr.sh_type == elf.SHT_FINI_ARRAY) break :blk true;
+ if (mem.startsWith(u8, name, ".ctors")) break :blk true;
+ if (mem.startsWith(u8, name, ".dtors")) break :blk true;
+ if (mem.startsWith(u8, name, ".init")) break :blk true;
+ if (mem.startsWith(u8, name, ".fini")) break :blk true;
+ if (Elf.isCIdentifier(name)) break :blk true;
+ break :blk false;
+ };
+ if (is_gc_root and markAtom(atom)) try rs.append(atom);
+ if (shdr.sh_flags & elf.SHF_ALLOC == 0) atom.visited = true;
+ }
+
+ // Mark every atom referenced by CIE as alive.
+ for (file.cies()) |cie| {
+ for (cie.relocs(ef)) |rel| {
+ const ref = file.resolveSymbol(rel.r_sym(), ef);
+ const sym = ef.symbol(ref) orelse continue;
+ try markSymbol(sym, rs, ef);
+ }
}
}
+ }.atomRoots;
+
+ if (elf_file.zigObjectPtr()) |zo| {
+ try atomRoots(zo.asFile(), roots, elf_file);
+ }
+ for (elf_file.objects.items) |index| {
+ try atomRoots(elf_file.file(index).?, roots, elf_file);
}
}
@@ -92,7 +105,8 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
for (atom.fdes(elf_file)) |fde| {
for (fde.relocs(elf_file)[1..]) |rel| {
- const target_sym = elf_file.symbol(file.symbol(rel.r_sym()));
+ const ref = file.resolveSymbol(rel.r_sym(), elf_file);
+ const target_sym = elf_file.symbol(ref) orelse continue;
const target_atom = target_sym.atom(elf_file) orelse continue;
target_atom.alive = true;
gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index });
@@ -101,7 +115,8 @@ fn markLive(atom: *Atom, elf_file: *Elf) void {
}
for (atom.relocs(elf_file)) |rel| {
- const target_sym = elf_file.symbol(file.symbol(rel.r_sym()));
+ const ref = file.resolveSymbol(rel.r_sym(), elf_file);
+ const target_sym = elf_file.symbol(ref) orelse continue;
if (target_sym.mergeSubsection(elf_file)) |msub| {
msub.alive = true;
continue;
@@ -120,16 +135,23 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {
}
}
-fn prune(files: []const File.Index, elf_file: *Elf) void {
- for (files) |index| {
- const file = elf_file.file(index).?;
- for (file.atoms()) |atom_index| {
- const atom = file.atom(atom_index) orelse continue;
- if (atom.alive and !atom.visited) {
- atom.alive = false;
- atom.markFdesDead(elf_file);
+fn prune(elf_file: *Elf) void {
+ const pruneInFile = struct {
+ fn pruneInFile(file: File, ef: *Elf) void {
+ for (file.atoms()) |atom_index| {
+ const atom = file.atom(atom_index) orelse continue;
+ if (atom.alive and !atom.visited) {
+ atom.alive = false;
+ atom.markFdesDead(ef);
+ }
}
}
+ }.pruneInFile;
+ if (elf_file.zigObjectPtr()) |zo| {
+ pruneInFile(zo.asFile(), elf_file);
+ }
+ for (elf_file.objects.items) |index| {
+ pruneInFile(elf_file.file(index).?, elf_file);
}
}
@@ -181,3 +203,4 @@ const Atom = @import("Atom.zig");
const Elf = @import("../Elf.zig");
const File = @import("file.zig").File;
const Symbol = @import("Symbol.zig");
+const ZigObject = @import("ZigObject.zig");
src/link/Elf/LinkerDefined.zig
@@ -44,7 +44,7 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
const newSymbolAssumeCapacity = struct {
- fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32) Symbol.Index {
+ fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32, ef: *Elf) Symbol.Index {
const esym_index: u32 = @intCast(ld.symtab.items.len);
const esym = ld.symtab.addOneAssumeCapacity();
esym.* = .{
@@ -61,7 +61,8 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{});
symbol.ref = .{ .index = 0, .file = 0 };
symbol.esym_index = esym_index;
- symbol.version_index = elf_file.default_sym_version;
+ symbol.version_index = ef.default_sym_version;
+ return index;
}
}.newSymbolAssumeCapacity;
@@ -111,31 +112,31 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
@memset(self.symbols_resolver.items, 0);
if (elf_file.entry_name) |name| {
- self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name));
+ self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name), elf_file);
}
- self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"));
- self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"));
- self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"));
- self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"));
- self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"));
- self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"));
- self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"));
- self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"));
- self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"));
- self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"));
- self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"));
+ self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"), elf_file);
+ self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"), elf_file);
+ self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"), elf_file);
+ self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"), elf_file);
+ self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"), elf_file);
+ self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"), elf_file);
+ self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"), elf_file);
+ self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"), elf_file);
+ self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
+ self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
+ self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"), elf_file);
if (elf_file.base.comp.link_eh_frame_hdr) {
- self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"));
+ self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file);
}
- self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"));
- self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"));
- self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"));
+ self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"), elf_file);
+ self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"), elf_file);
+ self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"), elf_file);
if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
- self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"));
+ self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"), elf_file);
}
for (elf_file.objects.items) |index| {
@@ -145,8 +146,8 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
defer gpa.free(start_name);
const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
defer gpa.free(stop_name);
- const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name));
- const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name));
+ const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name), elf_file);
+ const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name), elf_file);
self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop });
}
}
@@ -268,7 +269,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
for (elf_file.shdrs.items, 0..) |shdr, shndx| {
if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
value = shdr.sh_addr + shdr.sh_size;
- osec = shndx;
+ osec = @intCast(shndx);
}
}
allocSymbol(self, self.end_index.?, value, osec, elf_file);
@@ -287,10 +288,10 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
{
var index: usize = 0;
while (index < self.start_stop_indexes.items.len) : (index += 2) {
- const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index]);
+ const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index], elf_file);
const start = elf_file.symbol(start_ref).?;
const name = start.name(elf_file);
- const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1]);
+ const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file);
const stop = elf_file.symbol(stop_ref).?;
const shndx = elf_file.sectionByName(name["__start_".len..]).?;
const shdr = &elf_file.shdrs.items[shndx];
@@ -334,6 +335,18 @@ pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void {
}
}
+pub fn dynamicSymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol {
+ const index = self.dynamic_index orelse return null;
+ const resolv = self.resolveSymbol(index, elf_file);
+ return elf_file.symbol(resolv);
+}
+
+pub fn entrySymbol(self: LinkerDefined, elf_file: *Elf) ?*Symbol {
+ const index = self.entry_index orelse return null;
+ const resolv = self.resolveSymbol(index, elf_file);
+ return elf_file.symbol(resolv);
+}
+
pub fn asFile(self: *LinkerDefined) File {
return .{ .linker_defined = self };
}
@@ -356,8 +369,12 @@ pub fn resolveSymbol(self: LinkerDefined, index: Symbol.Index, elf_file: *Elf) E
return elf_file.resolver.get(resolv).?;
}
-pub fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index {
+fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index {
try self.symbols.ensureUnusedCapacity(allocator, 1);
+ return self.addSymbolAssumeCapacity();
+}
+
+fn addSymbolAssumeCapacity(self: *LinkerDefined) Symbol.Index {
const index: Symbol.Index = @intCast(self.symbols.items.len);
self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
return index;
@@ -425,10 +442,11 @@ fn formatSymtab(
) !void {
_ = unused_fmt_string;
_ = options;
+ const self = ctx.self;
+ const elf_file = ctx.elf_file;
try writer.writeAll(" globals\n");
- for (ctx.self.globals()) |index| {
- const global = ctx.elf_file.symbol(index);
- try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
+ for (self.symbols.items) |sym| {
+ try writer.print(" {}\n", .{sym.fmt(elf_file)});
}
}
src/link/Elf/Object.zig
@@ -394,10 +394,9 @@ fn initSymbols(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
sym_ptr.value = @intCast(sym.st_value);
sym_ptr.name_offset = sym.st_name;
sym_ptr.esym_index = @intCast(i);
- sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{
- .weak = sym.st_bind() == elf.STB_WEAK,
- });
+ sym_ptr.extra_index = self.addSymbolExtraAssumeCapacity(.{});
sym_ptr.version_index = if (i >= first_global) elf_file.default_sym_version else elf.VER_NDX_LOCAL;
+ sym_ptr.flags.weak = sym.st_bind() == elf.STB_WEAK;
if (sym.st_shndx != elf.SHN_ABS and sym.st_shndx != elf.SHN_COMMON) {
sym_ptr.ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
}
@@ -548,7 +547,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
for (self.cies.items) |cie| {
for (cie.relocs(elf_file)) |rel| {
- const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym()));
+ const sym = elf_file.symbol(self.resolveSymbol(rel.r_sym(), elf_file)).?;
if (sym.flags.import) {
if (sym.type(elf_file) != elf.STT_FUNC)
// TODO convert into an error
@@ -562,6 +561,51 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
}
}
+pub fn createSymbolIndirection(self: *Object, elf_file: *Elf) !void {
+ for (self.symbols.items, 0..) |*sym, i| {
+ const ref = self.resolveSymbol(@intCast(i), elf_file);
+ const ref_sym = elf_file.symbol(ref) orelse continue;
+ if (ref_sym.file(elf_file).?.index() != self.index) continue;
+ if (!sym.isLocal(elf_file) and !sym.flags.has_dynamic) {
+ log.debug("'{s}' is non-local", .{sym.name(elf_file)});
+ try elf_file.dynsym.addSymbol(ref, elf_file);
+ }
+ if (sym.flags.needs_got) {
+ log.debug("'{s}' needs GOT", .{sym.name(elf_file)});
+ _ = try elf_file.got.addGotSymbol(ref, elf_file);
+ }
+ if (sym.flags.needs_plt) {
+ if (sym.flags.is_canonical) {
+ log.debug("'{s}' needs CPLT", .{sym.name(elf_file)});
+ sym.flags.@"export" = true;
+ try elf_file.plt.addSymbol(ref, elf_file);
+ } else if (sym.flags.needs_got) {
+ log.debug("'{s}' needs PLTGOT", .{sym.name(elf_file)});
+ try elf_file.plt_got.addSymbol(ref, elf_file);
+ } else {
+ log.debug("'{s}' needs PLT", .{sym.name(elf_file)});
+ try elf_file.plt.addSymbol(ref, elf_file);
+ }
+ }
+ if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) {
+ log.debug("'{s}' needs COPYREL", .{sym.name(elf_file)});
+ try elf_file.copy_rel.addSymbol(ref, elf_file);
+ }
+ if (sym.flags.needs_tlsgd) {
+ log.debug("'{s}' needs TLSGD", .{sym.name(elf_file)});
+ try elf_file.got.addTlsGdSymbol(ref, elf_file);
+ }
+ if (sym.flags.needs_gottp) {
+ log.debug("'{s}' needs GOTTP", .{sym.name(elf_file)});
+ try elf_file.got.addGotTpSymbol(ref, elf_file);
+ }
+ if (sym.flags.needs_tlsdesc) {
+ log.debug("'{s}' needs TLSDESC", .{sym.name(elf_file)});
+ try elf_file.got.addTlsDescSymbol(ref, elf_file);
+ }
+ }
+}
+
pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void {
const gpa = elf_file.base.comp.gpa;
@@ -643,7 +687,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
sym.file_index = self.index;
const idx = self.symbols_resolver.items[i];
- elf_file.resolver.items[idx - 1] = .{ .index = esym_index, .file = self.index };
+ elf_file.resolver.values.items[idx - 1] = .{ .index = esym_index, .file = self.index };
}
}
@@ -1120,7 +1164,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
}
for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
- const ref = elf_file.resolver.items[resolv];
+ const ref = elf_file.resolver.values.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
if (!isAlive(global, elf_file)) continue;
@@ -1136,7 +1180,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
}
}
-pub fn writeSymtab(self: Object, elf_file: *Elf) void {
+pub fn writeSymtab(self: *Object, elf_file: *Elf) void {
for (self.locals()) |local| {
const idx = local.outputSymtabIndex(elf_file) orelse continue;
const out_sym = &elf_file.symtab.items[idx];
@@ -1147,7 +1191,7 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void {
}
for (self.globals(), self.symbols_resolver.items) |global, resolv| {
- const ref = elf_file.resolver.items[resolv];
+ const ref = elf_file.resolver.values.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
const idx = global.outputSymtabIndex(elf_file) orelse continue;
@@ -1199,7 +1243,7 @@ fn locals(self: *Object) []Symbol {
return self.symbols.items[0..end];
}
-fn globals(self: *Object) []Symbol {
+pub fn globals(self: *Object) []Symbol {
if (self.symbols.items.len == 0) return &[0]Symbol{};
assert(self.symbols.items.len >= self.symtab.items.len);
const start = self.first_global orelse self.symtab.items.len;
@@ -1214,8 +1258,12 @@ pub fn resolveSymbol(self: Object, index: Symbol.Index, elf_file: *Elf) Elf.Ref
return elf_file.resolver.get(resolv).?;
}
-pub fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index {
+fn addSymbol(self: *Object, allocator: Allocator) !Symbol.Index {
try self.symbols.ensureUnusedCapacity(allocator, 1);
+ return self.addSymbolAssumeCapacity();
+}
+
+fn addSymbolAssumeCapacity(self: *Object) Symbol.Index {
const index: Symbol.Index = @intCast(self.symbols.items.len);
self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
return index;
@@ -1430,15 +1478,14 @@ fn formatSymtab(
_ = unused_fmt_string;
_ = options;
const object = ctx.object;
+ const elf_file = ctx.elf_file;
try writer.writeAll(" locals\n");
- for (object.locals()) |index| {
- const local = ctx.elf_file.symbol(index);
- try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
+ for (object.locals()) |sym| {
+ try writer.print(" {}\n", .{sym.fmt(elf_file)});
}
try writer.writeAll(" globals\n");
- for (object.globals()) |index| {
- const global = ctx.elf_file.symbol(index);
- try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
+ for (object.globals()) |sym| {
+ try writer.print(" {}\n", .{sym.fmt(elf_file)});
}
}
src/link/Elf/relocatable.zig
@@ -37,7 +37,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
// First, we flush relocatable object file generated with our backends.
if (elf_file.zigObjectPtr()) |zig_object| {
- zig_object.resolveSymbols(elf_file);
+ try zig_object.resolveSymbols(elf_file);
try elf_file.addCommentString();
try elf_file.finalizeMergeSections();
zig_object.claimUnresolvedObject(elf_file);
@@ -383,7 +383,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {
shdr.sh_size = cg.size(elf_file);
shdr.sh_link = elf_file.symtab_section_index.?;
- const sym = elf_file.symbol(cg.symbol(elf_file));
+ const sym = cg.symbol(elf_file);
shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse
elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
}
src/link/Elf/Symbol.zig
@@ -86,6 +86,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
return switch (symbol.file(elf_file).?) {
+ .zig_object => |x| x.symtab.items(.elf_sym)[symbol.esym_index],
inline else => |x| x.symtab.items[symbol.esym_index],
};
}
@@ -261,7 +262,7 @@ const AddExtraOpts = struct {
zig_got: ?u32 = null,
};
-pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
+pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
var extras = symbol.extra(elf_file);
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
if (@field(opts, field.name)) |x| {
@@ -272,11 +273,15 @@ pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void {
}
pub fn extra(symbol: Symbol, elf_file: *Elf) Extra {
- return elf_file.symbolExtra(symbol.extra_index);
+ return switch (symbol.file(elf_file).?) {
+ inline else => |x| x.symbolExtra(symbol.extra_index),
+ };
}
pub fn setExtra(symbol: Symbol, extras: Extra, elf_file: *Elf) void {
- elf_file.setSymbolExtra(symbol.extra_index, extras);
+ return switch (symbol.file(elf_file).?) {
+ inline else => |x| x.setSymbolExtra(symbol.extra_index, extras),
+ };
}
pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
src/link/Elf/synthetic_sections.zig
@@ -251,15 +251,16 @@ pub const ZigGotSection = struct {
pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
+ const zo = elf_file.zigObjectPtr().?;
const index = try zig_got.allocateEntry(gpa);
const entry = &zig_got.entries.items[index];
entry.* = sym_index;
- const symbol = elf_file.symbol(sym_index);
+ const symbol = zo.symbol(sym_index);
symbol.flags.has_zig_got = true;
if (elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) {
zig_got.flags.needs_rela = true;
}
- try symbol.addExtra(.{ .zig_got = index }, elf_file);
+ symbol.addExtra(.{ .zig_got = index }, elf_file);
return index;
}
@@ -282,6 +283,7 @@ pub const ZigGotSection = struct {
}
pub fn writeOne(zig_got: *ZigGotSection, elf_file: *Elf, index: Index) !void {
+ const zo = elf_file.zigObjectPtr().?;
if (zig_got.flags.dirty) {
const needed_size = zig_got.size(elf_file);
try elf_file.growAllocSection(elf_file.zig_got_section_index.?, needed_size);
@@ -293,7 +295,7 @@ pub const ZigGotSection = struct {
const off = zig_got.entryOffset(index, elf_file);
const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file));
const entry = zig_got.entries.items[index];
- const value = elf_file.symbol(entry).address(.{}, elf_file);
+ const value = zo.symbol(entry).address(.{}, elf_file);
switch (entry_size) {
2 => {
var buf: [2]u8 = undefined;
@@ -336,8 +338,9 @@ pub const ZigGotSection = struct {
}
pub fn writeAll(zig_got: ZigGotSection, elf_file: *Elf, writer: anytype) !void {
+ const zo = elf_file.zigObjectPtr().?;
for (zig_got.entries.items) |entry| {
- const symbol = elf_file.symbol(entry);
+ const symbol = zo.symbol(entry);
const value = symbol.address(.{ .plt = false }, elf_file);
try writeInt(value, elf_file, writer);
}
@@ -351,9 +354,10 @@ pub const ZigGotSection = struct {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
+ const zo = elf_file.zigObjectPtr().?;
try elf_file.rela_dyn.ensureUnusedCapacity(gpa, zig_got.numRela());
for (zig_got.entries.items) |entry| {
- const symbol = elf_file.symbol(entry);
+ const symbol = zo.symbol(entry);
const offset = symbol.zigGotAddress(elf_file);
elf_file.addRelaDynAssumeCapacity(.{
.offset = @intCast(offset),
@@ -364,16 +368,18 @@ pub const ZigGotSection = struct {
}
pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void {
+ const zo = elf_file.zigObjectPtr().?;
zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len));
for (zig_got.entries.items) |entry| {
- const name = elf_file.symbol(entry).name(elf_file);
+ const name = zo.symbol(entry).name(elf_file);
zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1;
}
}
pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void {
+ const zo = elf_file.zigObjectPtr().?;
for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| {
- const symbol = elf_file.symbol(entry);
+ const symbol = zo.symbol(entry);
const symbol_name = symbol.name(elf_file);
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(symbol_name);
@@ -409,15 +415,18 @@ pub const ZigGotSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
+ const zig_got = ctx.zig_got;
+ const elf_file = ctx.elf_file;
+ const zo = elf_file.zigObjectPtr().?;
try writer.writeAll(".zig.got\n");
- for (ctx.zig_got.entries.items, 0..) |entry, index| {
- const symbol = ctx.elf_file.symbol(entry);
+ for (zig_got.entries.items, 0..) |entry, index| {
+ const symbol = zo.symbol(entry);
try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
index,
- ctx.zig_got.entryAddress(@intCast(index), ctx.elf_file),
+ zig_got.entryAddress(@intCast(index), elf_file),
entry,
- symbol.address(.{}, ctx.elf_file),
- symbol.name(ctx.elf_file),
+ symbol.address(.{}, elf_file),
+ symbol.name(elf_file),
});
}
}
@@ -446,7 +455,7 @@ pub const GotSection = struct {
const Entry = struct {
tag: Tag,
- symbol_index: Symbol.Index,
+ ref: Elf.Ref,
cell_index: Index,
/// Returns how many indexes in the GOT this entry uses.
@@ -477,25 +486,25 @@ pub const GotSection = struct {
const last = got.entries.items[index - 1];
break :blk last.cell_index + @as(Index, @intCast(last.len()));
} else 0;
- entry.* = .{ .tag = undefined, .symbol_index = undefined, .cell_index = cell_index };
+ entry.* = .{ .tag = undefined, .ref = undefined, .cell_index = cell_index };
return index;
}
- pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
+ pub fn addGotSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !Index {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = try got.allocateEntry(gpa);
const entry = &got.entries.items[index];
entry.tag = .got;
- entry.symbol_index = sym_index;
- const symbol = elf_file.symbol(sym_index);
+ entry.ref = ref;
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_got = true;
if (symbol.flags.import or symbol.isIFunc(elf_file) or
((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
{
got.flags.needs_rela = true;
}
- try symbol.addExtra(.{ .got = index }, elf_file);
+ symbol.addExtra(.{ .got = index }, elf_file);
return index;
}
@@ -506,48 +515,48 @@ pub const GotSection = struct {
const index = try got.allocateEntry(gpa);
const entry = &got.entries.items[index];
entry.tag = .tlsld;
- entry.symbol_index = undefined; // unused
+ entry.ref = .{ .index = 0, .file = 0 }; // unused
got.flags.needs_rela = true;
got.tlsld_index = index;
}
- pub fn addTlsGdSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addTlsGdSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = try got.allocateEntry(gpa);
const entry = &got.entries.items[index];
entry.tag = .tlsgd;
- entry.symbol_index = sym_index;
- const symbol = elf_file.symbol(sym_index);
+ entry.ref = ref;
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_tlsgd = true;
if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true;
- try symbol.addExtra(.{ .tlsgd = index }, elf_file);
+ symbol.addExtra(.{ .tlsgd = index }, elf_file);
}
- pub fn addGotTpSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addGotTpSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = try got.allocateEntry(gpa);
const entry = &got.entries.items[index];
entry.tag = .gottp;
- entry.symbol_index = sym_index;
- const symbol = elf_file.symbol(sym_index);
+ entry.ref = ref;
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_gottp = true;
if (symbol.flags.import or elf_file.isEffectivelyDynLib()) got.flags.needs_rela = true;
- try symbol.addExtra(.{ .gottp = index }, elf_file);
+ symbol.addExtra(.{ .gottp = index }, elf_file);
}
- pub fn addTlsDescSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addTlsDescSymbol(got: *GotSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = try got.allocateEntry(gpa);
const entry = &got.entries.items[index];
entry.tag = .tlsdesc;
- entry.symbol_index = sym_index;
- const symbol = elf_file.symbol(sym_index);
+ entry.ref = ref;
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_tlsdesc = true;
got.flags.needs_rela = true;
- try symbol.addExtra(.{ .tlsdesc = index }, elf_file);
+ symbol.addExtra(.{ .tlsdesc = index }, elf_file);
}
pub fn size(got: GotSection, elf_file: *Elf) usize {
@@ -564,10 +573,7 @@ pub const GotSection = struct {
const apply_relocs = true; // TODO add user option for this
for (got.entries.items) |entry| {
- const symbol = switch (entry.tag) {
- .tlsld => null,
- inline else => elf_file.symbol(entry.symbol_index),
- };
+ const symbol = elf_file.symbol(entry.ref);
switch (entry.tag) {
.got => {
const value = blk: {
@@ -637,10 +643,7 @@ pub const GotSection = struct {
try elf_file.rela_dyn.ensureUnusedCapacity(gpa, got.numRela(elf_file));
for (got.entries.items) |entry| {
- const symbol = switch (entry.tag) {
- .tlsld => null,
- inline else => elf_file.symbol(entry.symbol_index),
- };
+ const symbol = elf_file.symbol(entry.ref);
const extra = if (symbol) |s| s.extra(elf_file) else null;
switch (entry.tag) {
@@ -740,10 +743,7 @@ pub const GotSection = struct {
const is_dyn_lib = elf_file.isEffectivelyDynLib();
var num: usize = 0;
for (got.entries.items) |entry| {
- const symbol = switch (entry.tag) {
- .tlsld => null,
- inline else => elf_file.symbol(entry.symbol_index),
- };
+ const symbol = elf_file.symbol(entry.ref);
switch (entry.tag) {
.got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
((elf_file.isEffectivelyDynLib() or (elf_file.base.isExe() and comp.config.pie)) and
@@ -775,24 +775,15 @@ pub const GotSection = struct {
pub fn updateSymtabSize(got: *GotSection, elf_file: *Elf) void {
got.output_symtab_ctx.nlocals = @as(u32, @intCast(got.entries.items.len));
for (got.entries.items) |entry| {
- const symbol_name = switch (entry.tag) {
- .tlsld => "",
- inline else => elf_file.symbol(entry.symbol_index).name(elf_file),
- };
+ const symbol_name = if (elf_file.symbol(entry.ref)) |sym| sym.name(elf_file) else "";
got.output_symtab_ctx.strsize += @as(u32, @intCast(symbol_name.len + @tagName(entry.tag).len)) + 1 + 1;
}
}
pub fn writeSymtab(got: GotSection, elf_file: *Elf) void {
for (got.entries.items, got.output_symtab_ctx.ilocal..) |entry, ilocal| {
- const symbol = switch (entry.tag) {
- .tlsld => null,
- inline else => elf_file.symbol(entry.symbol_index),
- };
- const symbol_name = switch (entry.tag) {
- .tlsld => "",
- inline else => symbol.?.name(elf_file),
- };
+ const symbol = elf_file.symbol(entry.ref);
+ const symbol_name = if (symbol) |s| s.name(elf_file) else "";
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(symbol_name);
elf_file.strtab.appendAssumeCapacity('$');
@@ -828,36 +819,38 @@ pub const GotSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
+ const got = ctx.got;
+ const elf_file = ctx.elf_file;
try writer.writeAll("GOT\n");
- for (ctx.got.entries.items) |entry| {
- const symbol = ctx.elf_file.symbol(entry.symbol_index);
- try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
+ for (got.entries.items) |entry| {
+ const symbol = elf_file.symbol(entry.ref).?;
+ try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
entry.cell_index,
- entry.address(ctx.elf_file),
- entry.symbol_index,
- symbol.address(.{}, ctx.elf_file),
- symbol.name(ctx.elf_file),
+ entry.address(elf_file),
+ entry.ref,
+ symbol.address(.{}, elf_file),
+ symbol.name(elf_file),
});
}
}
};
pub const PltSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
output_symtab_ctx: Elf.SymtabCtx = .{},
pub fn deinit(plt: *PltSection, allocator: Allocator) void {
plt.symbols.deinit(allocator);
}
- pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addSymbol(plt: *PltSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = @as(u32, @intCast(plt.symbols.items.len));
- const symbol = elf_file.symbol(sym_index);
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_plt = true;
- try symbol.addExtra(.{ .plt = index }, elf_file);
- try plt.symbols.append(gpa, sym_index);
+ symbol.addExtra(.{ .plt = index }, elf_file);
+ try plt.symbols.append(gpa, ref);
}
pub fn size(plt: PltSection, elf_file: *Elf) usize {
@@ -895,8 +888,8 @@ pub const PltSection = struct {
const gpa = comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
try elf_file.rela_plt.ensureUnusedCapacity(gpa, plt.numRela());
- for (plt.symbols.items) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (plt.symbols.items) |ref| {
+ const sym = elf_file.symbol(ref).?;
assert(sym.flags.import);
const extra = sym.extra(elf_file);
const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file));
@@ -916,16 +909,16 @@ pub const PltSection = struct {
pub fn updateSymtabSize(plt: *PltSection, elf_file: *Elf) void {
plt.output_symtab_ctx.nlocals = @as(u32, @intCast(plt.symbols.items.len));
- for (plt.symbols.items) |sym_index| {
- const name = elf_file.symbol(sym_index).name(elf_file);
+ for (plt.symbols.items) |ref| {
+ const name = elf_file.symbol(ref).?.name(elf_file);
plt.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$plt".len)) + 1;
}
}
pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
const cpu_arch = elf_file.getTarget().cpu.arch;
- for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
- const sym = elf_file.symbol(sym_index);
+ for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |ref, ilocal| {
+ const sym = elf_file.symbol(ref).?;
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
elf_file.strtab.appendSliceAssumeCapacity("$plt");
@@ -958,15 +951,17 @@ pub const PltSection = struct {
) !void {
_ = options;
_ = unused_fmt_string;
+ const plt = ctx.plt;
+ const elf_file = ctx.elf_file;
try writer.writeAll("PLT\n");
- for (ctx.plt.symbols.items, 0..) |symbol_index, i| {
- const symbol = ctx.elf_file.symbol(symbol_index);
- try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
+ for (plt.symbols.items, 0..) |ref, i| {
+ const symbol = elf_file.symbol(ref).?;
+ try writer.print(" {d}@0x{x} => {}@0x{x} ({s})\n", .{
i,
- symbol.pltAddress(ctx.elf_file),
- symbol_index,
- symbol.address(.{}, ctx.elf_file),
- symbol.name(ctx.elf_file),
+ symbol.pltAddress(elf_file),
+ ref,
+ symbol.address(.{}, elf_file),
+ symbol.name(elf_file),
});
}
}
@@ -988,8 +983,8 @@ pub const PltSection = struct {
try writer.writeAll(&preamble);
try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len);
- for (plt.symbols.items, 0..) |sym_index, i| {
- const sym = elf_file.symbol(sym_index);
+ for (plt.symbols.items, 0..) |ref, i| {
+ const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotPltAddress(elf_file);
const source_addr = sym.pltAddress(elf_file);
disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4;
@@ -1037,8 +1032,8 @@ pub const PltSection = struct {
}
}
- for (plt.symbols.items) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (plt.symbols.items) |ref| {
+ const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotPltAddress(elf_file);
const source_addr = sym.pltAddress(elf_file);
const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
@@ -1075,7 +1070,7 @@ pub const GotPltSection = struct {
_ = got_plt;
{
// [0]: _DYNAMIC
- const symbol = elf_file.symbol(elf_file.linkerDefinedPtr().?.dynamic_index.?);
+ const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;
try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);
}
// [1]: 0x0
@@ -1093,22 +1088,22 @@ pub const GotPltSection = struct {
};
pub const PltGotSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
output_symtab_ctx: Elf.SymtabCtx = .{},
pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void {
plt_got.symbols.deinit(allocator);
}
- pub fn addSymbol(plt_got: *PltGotSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addSymbol(plt_got: *PltGotSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = @as(u32, @intCast(plt_got.symbols.items.len));
- const symbol = elf_file.symbol(sym_index);
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.has_plt = true;
symbol.flags.has_got = true;
- try symbol.addExtra(.{ .plt_got = index }, elf_file);
- try plt_got.symbols.append(gpa, sym_index);
+ symbol.addExtra(.{ .plt_got = index }, elf_file);
+ try plt_got.symbols.append(gpa, ref);
}
pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
@@ -1134,15 +1129,15 @@ pub const PltGotSection = struct {
pub fn updateSymtabSize(plt_got: *PltGotSection, elf_file: *Elf) void {
plt_got.output_symtab_ctx.nlocals = @as(u32, @intCast(plt_got.symbols.items.len));
- for (plt_got.symbols.items) |sym_index| {
- const name = elf_file.symbol(sym_index).name(elf_file);
+ for (plt_got.symbols.items) |ref| {
+ const name = elf_file.symbol(ref).?.name(elf_file);
plt_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$pltgot".len)) + 1;
}
}
pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void {
- for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
- const sym = elf_file.symbol(sym_index);
+ for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |ref, ilocal| {
+ const sym = elf_file.symbol(ref).?;
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
elf_file.strtab.appendSliceAssumeCapacity("$pltgot");
@@ -1160,8 +1155,8 @@ pub const PltGotSection = struct {
const x86_64 = struct {
pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
- for (plt_got.symbols.items) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (plt_got.symbols.items) |ref| {
+ const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotAddress(elf_file);
const source_addr = sym.pltGotAddress(elf_file);
const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
@@ -1178,8 +1173,8 @@ pub const PltGotSection = struct {
const aarch64 = struct {
fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
- for (plt_got.symbols.items) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (plt_got.symbols.items) |ref| {
+ const sym = elf_file.symbol(ref).?;
const target_addr = sym.gotAddress(elf_file);
const source_addr = sym.pltGotAddress(elf_file);
const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
@@ -1204,56 +1199,56 @@ pub const PltGotSection = struct {
};
pub const CopyRelSection = struct {
- symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ symbols: std.ArrayListUnmanaged(Elf.Ref) = .{},
pub fn deinit(copy_rel: *CopyRelSection, allocator: Allocator) void {
copy_rel.symbols.deinit(allocator);
}
- pub fn addSymbol(copy_rel: *CopyRelSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addSymbol(copy_rel: *CopyRelSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = @as(u32, @intCast(copy_rel.symbols.items.len));
- const symbol = elf_file.symbol(sym_index);
+ const symbol = elf_file.symbol(ref).?;
symbol.flags.import = true;
symbol.flags.@"export" = true;
symbol.flags.has_copy_rel = true;
symbol.flags.weak = false;
- try symbol.addExtra(.{ .copy_rel = index }, elf_file);
- try copy_rel.symbols.append(gpa, sym_index);
+ symbol.addExtra(.{ .copy_rel = index }, elf_file);
+ try copy_rel.symbols.append(gpa, ref);
const shared_object = symbol.file(elf_file).?.shared_object;
if (shared_object.aliases == null) {
try shared_object.initSymbolAliases(elf_file);
}
- const aliases = shared_object.symbolAliases(sym_index, elf_file);
+ const aliases = shared_object.symbolAliases(ref.index, elf_file);
for (aliases) |alias| {
- if (alias == sym_index) continue;
- const alias_sym = elf_file.symbol(alias);
+ if (alias == ref.index) continue;
+ const alias_sym = &shared_object.symbols.items[alias];
alias_sym.flags.import = true;
alias_sym.flags.@"export" = true;
alias_sym.flags.has_copy_rel = true;
alias_sym.flags.needs_copy_rel = true;
alias_sym.flags.weak = false;
- try elf_file.dynsym.addSymbol(alias, elf_file);
+ try elf_file.dynsym.addSymbol(.{ .index = alias, .file = shared_object.index }, elf_file);
}
}
pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void {
const shdr = &elf_file.shdrs.items[shndx];
- for (copy_rel.symbols.items) |sym_index| {
- const symbol = elf_file.symbol(sym_index);
+ for (copy_rel.symbols.items) |ref| {
+ const symbol = elf_file.symbol(ref).?;
const shared_object = symbol.file(elf_file).?.shared_object;
const alignment = try symbol.dsoAlignment(elf_file);
symbol.value = @intCast(mem.alignForward(u64, shdr.sh_size, alignment));
shdr.sh_addralign = @max(shdr.sh_addralign, alignment);
shdr.sh_size = @as(u64, @intCast(symbol.value)) + symbol.elfSym(elf_file).st_size;
- const aliases = shared_object.symbolAliases(sym_index, elf_file);
+ const aliases = shared_object.symbolAliases(ref.index, elf_file);
for (aliases) |alias| {
- if (alias == sym_index) continue;
- const alias_sym = elf_file.symbol(alias);
+ if (alias == ref.index) continue;
+ const alias_sym = &shared_object.symbols.items[alias];
alias_sym.value = symbol.value;
}
}
@@ -1264,8 +1259,8 @@ pub const CopyRelSection = struct {
const gpa = comp.gpa;
const cpu_arch = elf_file.getTarget().cpu.arch;
try elf_file.rela_dyn.ensureUnusedCapacity(gpa, copy_rel.numRela());
- for (copy_rel.symbols.items) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (copy_rel.symbols.items) |ref| {
+ const sym = elf_file.symbol(ref).?;
assert(sym.flags.import and sym.flags.has_copy_rel);
const extra = sym.extra(elf_file);
elf_file.addRelaDynAssumeCapacity(.{
@@ -1285,8 +1280,8 @@ pub const DynsymSection = struct {
entries: std.ArrayListUnmanaged(Entry) = .{},
pub const Entry = struct {
- /// Index of the symbol which gets privilege of getting a dynamic treatment
- symbol_index: Symbol.Index,
+ /// Ref of the symbol which gets privilege of getting a dynamic treatment
+ ref: Elf.Ref,
/// Offset into .dynstrtab
off: u32,
};
@@ -1295,22 +1290,22 @@ pub const DynsymSection = struct {
dynsym.entries.deinit(allocator);
}
- pub fn addSymbol(dynsym: *DynsymSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
+ pub fn addSymbol(dynsym: *DynsymSection, ref: Elf.Ref, elf_file: *Elf) !void {
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const index = @as(u32, @intCast(dynsym.entries.items.len + 1));
- const sym = elf_file.symbol(sym_index);
+ const sym = elf_file.symbol(ref).?;
sym.flags.has_dynamic = true;
- try sym.addExtra(.{ .dynamic = index }, elf_file);
+ sym.addExtra(.{ .dynamic = index }, elf_file);
const off = try elf_file.insertDynString(sym.name(elf_file));
- try dynsym.entries.append(gpa, .{ .symbol_index = sym_index, .off = off });
+ try dynsym.entries.append(gpa, .{ .ref = ref, .off = off });
}
pub fn sort(dynsym: *DynsymSection, elf_file: *Elf) void {
const Sort = struct {
pub fn lessThan(ctx: *Elf, lhs: Entry, rhs: Entry) bool {
- const lhs_sym = ctx.symbol(lhs.symbol_index);
- const rhs_sym = ctx.symbol(rhs.symbol_index);
+ const lhs_sym = ctx.symbol(lhs.ref).?;
+ const rhs_sym = ctx.symbol(rhs.ref).?;
if (lhs_sym.flags.@"export" != rhs_sym.flags.@"export") {
return rhs_sym.flags.@"export";
@@ -1329,7 +1324,7 @@ pub const DynsymSection = struct {
var num_exports: u32 = 0;
for (dynsym.entries.items) |entry| {
- const sym = elf_file.symbol(entry.symbol_index);
+ const sym = elf_file.symbol(entry.ref).?;
if (sym.flags.@"export") num_exports += 1;
}
@@ -1338,7 +1333,7 @@ pub const DynsymSection = struct {
std.mem.sort(Entry, dynsym.entries.items, elf_file, Sort.lessThan);
for (dynsym.entries.items, 1..) |entry, index| {
- const sym = elf_file.symbol(entry.symbol_index);
+ const sym = elf_file.symbol(entry.ref).?;
var extra = sym.extra(elf_file);
extra.dynamic = @as(u32, @intCast(index));
sym.setExtra(extra, elf_file);
@@ -1356,7 +1351,7 @@ pub const DynsymSection = struct {
pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void {
try writer.writeStruct(Elf.null_sym);
for (dynsym.entries.items) |entry| {
- const sym = elf_file.symbol(entry.symbol_index);
+ const sym = elf_file.symbol(entry.ref).?;
var out_sym: elf.Elf64_Sym = Elf.null_sym;
sym.setOutputSym(elf_file, &out_sym);
out_sym.st_name = entry.off;
@@ -1429,7 +1424,7 @@ pub const GnuHashSection = struct {
fn getExports(elf_file: *Elf) []const DynsymSection.Entry {
const start = for (elf_file.dynsym.entries.items, 0..) |entry, i| {
- const sym = elf_file.symbol(entry.symbol_index);
+ const sym = elf_file.symbol(entry.ref).?;
if (sym.flags.@"export") break i;
} else elf_file.dynsym.entries.items.len;
return elf_file.dynsym.entries.items[start..];
@@ -1477,7 +1472,7 @@ pub const GnuHashSection = struct {
@memset(bloom, 0);
for (exports, 0..) |entry, i| {
- const sym = elf_file.symbol(entry.symbol_index);
+ const sym = elf_file.symbol(entry.ref).?;
const h = hasher(sym.name(elf_file));
hashes[i] = h;
indices[i] = h % hash.num_buckets;
@@ -1574,7 +1569,7 @@ pub const VerneedSection = struct {
try verneed.ensureTotalCapacity(dynsyms.len);
for (dynsyms, 1..) |entry, i| {
- const symbol = elf_file.symbol(entry.symbol_index);
+ const symbol = elf_file.symbol(entry.ref).?;
if (symbol.flags.import and symbol.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) {
const shared_object = symbol.file(elf_file).?.shared_object;
verneed.appendAssumeCapacity(.{
@@ -1677,11 +1672,11 @@ pub const ComdatGroupSection = struct {
return cg_file.object.comdatGroup(cgs.cg_ref.index);
}
- pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index {
+ pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) *Symbol {
const cg = cgs.comdatGroup(elf_file);
const object = cg.file(elf_file).object;
const shdr = object.shdrs.items[cg.shndx];
- return object.symbols.items[shdr.sh_info];
+ return &object.symbols.items[shdr.sh_info];
}
pub fn size(cgs: ComdatGroupSection, elf_file: *Elf) usize {
src/link/Elf/thunks.zig
@@ -43,11 +43,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
else => @panic("unsupported arch"),
};
if (is_reachable) continue;
- const target = switch (file) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
- };
+ const target = file.resolveSymbol(rel.r_sym(), elf_file);
try thunk.symbols.put(gpa, target, {});
}
atom.addExtra(.{ .thunk = thunk_index }, elf_file);
@@ -80,7 +76,7 @@ fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 {
pub const Thunk = struct {
value: i64 = 0,
output_section_index: u32 = 0,
- symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
+ symbols: std.AutoArrayHashMapUnmanaged(Elf.Ref, void) = .{},
output_symtab_ctx: Elf.SymtabCtx = .{},
pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
@@ -97,9 +93,9 @@ pub const Thunk = struct {
return @as(i64, @intCast(shdr.sh_addr)) + thunk.value;
}
- pub fn targetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) i64 {
+ pub fn targetAddress(thunk: Thunk, ref: Elf.Ref, elf_file: *Elf) i64 {
const cpu_arch = elf_file.getTarget().cpu.arch;
- return thunk.address(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch)));
+ return thunk.address(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(ref).? * trampolineSize(cpu_arch)));
}
pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
@@ -112,16 +108,16 @@ pub const Thunk = struct {
pub fn calcSymtabSize(thunk: *Thunk, elf_file: *Elf) void {
thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len));
- for (thunk.symbols.keys()) |sym_index| {
- const sym = elf_file.symbol(sym_index);
+ for (thunk.symbols.keys()) |ref| {
+ const sym = elf_file.symbol(ref).?;
thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.name(elf_file).len + "$thunk".len + 1));
}
}
pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void {
const cpu_arch = elf_file.getTarget().cpu.arch;
- for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
- const sym = elf_file.symbol(sym_index);
+ for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |ref, ilocal| {
+ const sym = elf_file.symbol(ref).?;
const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
elf_file.strtab.appendSliceAssumeCapacity("$thunk");
@@ -131,7 +127,7 @@ pub const Thunk = struct {
.st_info = elf.STT_FUNC,
.st_other = 0,
.st_shndx = @intCast(thunk.output_section_index),
- .st_value = @intCast(thunk.targetAddress(sym_index, elf_file)),
+ .st_value = @intCast(thunk.targetAddress(ref, elf_file)),
.st_size = trampolineSize(cpu_arch),
};
}
@@ -181,9 +177,9 @@ pub const Thunk = struct {
const thunk = ctx.thunk;
const elf_file = ctx.elf_file;
try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
- for (thunk.symbols.keys()) |index| {
- const sym = elf_file.symbol(index);
- try writer.print(" %{d} : {s} : @{x}\n", .{ index, sym.name(elf_file), sym.value });
+ for (thunk.symbols.keys()) |ref| {
+ const sym = elf_file.symbol(ref).?;
+ try writer.print(" {} : {s} : @{x}\n", .{ ref, sym.name(elf_file), sym.value });
}
}
@@ -195,12 +191,8 @@ const aarch64 = struct {
const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
if (r_type != .CALL26 and r_type != .JUMP26) return true;
const file = atom.file(elf_file).?;
- const target_index = switch (file) {
- .zig_object => |x| x.symbol(rel.r_sym()),
- .object => |x| x.symbols.items[rel.r_sym()],
- else => unreachable,
- };
- const target = elf_file.symbol(target_index);
+ const target_ref = file.resolveSymbol(rel.r_sym(), elf_file);
+ const target = elf_file.symbol(target_ref).?;
if (target.flags.has_plt) return false;
if (atom.output_section_index != target.output_section_index) return false;
const target_atom = target.atom(elf_file).?;
@@ -212,8 +204,8 @@ const aarch64 = struct {
}
fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
- for (thunk.symbols.keys(), 0..) |sym_index, i| {
- const sym = elf_file.symbol(sym_index);
+ for (thunk.symbols.keys(), 0..) |ref, i| {
+ const sym = elf_file.symbol(ref).?;
const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size));
const taddr = sym.address(.{}, elf_file);
const pages = try util.calcNumberOfPages(saddr, taddr);
src/link/Elf/ZigObject.zig
@@ -89,19 +89,11 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
try self.strtab.buffer.append(gpa, 0);
const name_off = try self.strtab.insert(gpa, self.path);
- const symbol_index = try elf_file.addSymbol();
- try self.local_symbols.append(gpa, symbol_index);
- const symbol_ptr = elf_file.symbol(symbol_index);
- symbol_ptr.file_index = self.index;
- symbol_ptr.name_offset = name_off;
- symbol_ptr.extra_index = try elf_file.addSymbolExtra(.{});
-
- const esym_index = try self.addLocalEsym(gpa);
- const esym = &self.local_esyms.items(.elf_sym)[esym_index];
- esym.st_name = name_off;
+ const symbol_index = try self.newLocalSymbol(gpa, name_off);
+ const sym = self.symbol(symbol_index);
+ const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
esym.st_info = elf.STT_FILE;
esym.st_shndx = elf.SHN_ABS;
- symbol_ptr.esym_index = esym_index;
switch (comp.config.debug_format) {
.strip => {},
@@ -275,7 +267,7 @@ fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4)
const index = self.addSymbolAssumeCapacity();
const sym = &self.symbols.items[index];
sym.name_offset = name_off;
- sym.extra = self.addSymbolExtraAssumeCapacity(.{});
+ sym.extra_index = self.addSymbolExtraAssumeCapacity(.{});
const esym_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
const esym = ElfSym{ .elf_sym = .{
@@ -377,7 +369,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void {
continue;
}
- if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
+ if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
}
}
@@ -428,7 +420,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
global.file_index = self.index;
const idx = self.symbols_resolver.items[i];
- elf_file.resolver.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
+ elf_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i | global_symbol_bit), .file = self.index };
}
}
@@ -450,6 +442,64 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
}
}
+pub fn createSymbolIndirection(self: *ZigObject, elf_file: *Elf) !void {
+ const impl = struct {
+ fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void {
+ if (!sym.isLocal(ef) and !sym.flags.has_dynamic) {
+ log.debug("'{s}' is non-local", .{sym.name(ef)});
+ try ef.dynsym.addSymbol(ref, ef);
+ }
+ if (sym.flags.needs_got) {
+ log.debug("'{s}' needs GOT", .{sym.name(ef)});
+ _ = try ef.got.addGotSymbol(ref, ef);
+ }
+ if (sym.flags.needs_plt) {
+ if (sym.flags.is_canonical) {
+ log.debug("'{s}' needs CPLT", .{sym.name(ef)});
+ sym.flags.@"export" = true;
+ try ef.plt.addSymbol(ref, ef);
+ } else if (sym.flags.needs_got) {
+ log.debug("'{s}' needs PLTGOT", .{sym.name(ef)});
+ try ef.plt_got.addSymbol(ref, ef);
+ } else {
+ log.debug("'{s}' needs PLT", .{sym.name(ef)});
+ try ef.plt.addSymbol(ref, ef);
+ }
+ }
+ if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) {
+ log.debug("'{s}' needs COPYREL", .{sym.name(ef)});
+ try ef.copy_rel.addSymbol(ref, ef);
+ }
+ if (sym.flags.needs_tlsgd) {
+ log.debug("'{s}' needs TLSGD", .{sym.name(ef)});
+ try ef.got.addTlsGdSymbol(ref, ef);
+ }
+ if (sym.flags.needs_gottp) {
+ log.debug("'{s}' needs GOTTP", .{sym.name(ef)});
+ try ef.got.addGotTpSymbol(ref, ef);
+ }
+ if (sym.flags.needs_tlsdesc) {
+ log.debug("'{s}' needs TLSDESC", .{sym.name(ef)});
+ try ef.got.addTlsDescSymbol(ref, ef);
+ }
+ }
+ }.impl;
+ for (self.local_symbols.items, 0..) |index, i| {
+ const sym = &self.symbols.items[index];
+ const ref = self.resolveSymbol(@intCast(i), elf_file);
+ const ref_sym = elf_file.symbol(ref) orelse continue;
+ if (ref_sym.file(elf_file).?.index() != self.index) continue;
+ try impl(sym, ref, elf_file);
+ }
+ for (self.global_symbols.items, 0..) |index, i| {
+ const sym = &self.symbols.items[index];
+ const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
+ const ref_sym = elf_file.symbol(ref) orelse continue;
+ if (ref_sym.file(elf_file).?.index() != self.index) continue;
+ try impl(sym, ref, elf_file);
+ }
+}
+
pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
for (self.global_symbols.items, 0..) |index, i| {
const global = self.symbols.items[index];
@@ -468,7 +518,7 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
}
}
-pub fn markImportsExports(self: *Object, elf_file: *Elf) void {
+pub fn markImportsExports(self: *ZigObject, elf_file: *Elf) void {
for (0..self.global_symbols.items.len) |i| {
const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file);
const sym = elf_file.symbol(ref) orelse continue;
@@ -604,7 +654,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
const global = &self.symbols.items[index];
- const ref = elf_file.resolver.items[resolv];
+ const ref = elf_file.resolver.values.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.alive) continue;
@@ -633,7 +683,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
for (self.global_symbols.items, self.symbols_resolver.items) |index, resolv| {
const global = self.symbols.items[index];
- const ref = elf_file.resolver.items[resolv];
+ const ref = elf_file.resolver.values.items[resolv];
const ref_sym = elf_file.symbol(ref) orelse continue;
if (ref_sym.file(elf_file).?.index() != self.index) continue;
const idx = global.outputSymtabIndex(elf_file) orelse continue;
@@ -678,13 +728,13 @@ pub fn getDeclVAddr(
reloc_info: link.File.RelocInfo,
) !u64 {
const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index);
- const this_sym = elf_file.symbol(this_sym_index);
+ const this_sym = self.symbol(this_sym_index);
const vaddr = this_sym.address(.{}, elf_file);
- const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
+ const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
try parent_atom.addReloc(elf_file, .{
.r_offset = reloc_info.offset,
- .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type,
+ .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
.r_addend = reloc_info.addend,
});
return @intCast(vaddr);
@@ -697,13 +747,13 @@ pub fn getAnonDeclVAddr(
reloc_info: link.File.RelocInfo,
) !u64 {
const sym_index = self.anon_decls.get(decl_val).?.symbol_index;
- const sym = elf_file.symbol(sym_index);
+ const sym = self.symbol(sym_index);
const vaddr = sym.address(.{}, elf_file);
- const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
+ const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
try parent_atom.addReloc(elf_file, .{
.r_offset = reloc_info.offset,
- .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type,
+ .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
.r_addend = reloc_info.addend,
});
return @intCast(vaddr);
@@ -725,7 +775,7 @@ pub fn lowerAnonDecl(
else => explicit_alignment,
};
if (self.anon_decls.get(decl_val)) |metadata| {
- const existing_alignment = elf_file.symbol(metadata.symbol_index).atom(elf_file).?.alignment;
+ const existing_alignment = self.symbol(metadata.symbol_index).atom(elf_file).?.alignment;
if (decl_alignment.order(existing_alignment).compare(.lte))
return .ok;
}
@@ -811,11 +861,10 @@ fn freeUnnamedConsts(self: *ZigObject, elf_file: *Elf, decl_index: InternPool.De
}
fn freeDeclMetadata(self: *ZigObject, elf_file: *Elf, sym_index: Symbol.Index) void {
- _ = self;
- const sym = elf_file.symbol(sym_index);
+ const sym = self.symbol(sym_index);
sym.atom(elf_file).?.free(elf_file);
log.debug("adding %{d} to local symbols free list", .{sym_index});
- elf_file.symbols.items[sym_index] = .{};
+ self.symbols.items[sym_index] = .{};
// TODO free GOT entry here
}
@@ -940,8 +989,8 @@ fn updateDeclCode(
target_util.minFunctionAlignment(mod.getTarget()),
);
- const sym = elf_file.symbol(sym_index);
- const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
+ const sym = self.symbol(sym_index);
+ const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
const atom_ptr = sym.atom(elf_file).?;
const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
@@ -1038,8 +1087,8 @@ fn updateTlv(
const required_alignment = decl.getAlignment(pt);
- const sym = elf_file.symbol(sym_index);
- const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
+ const sym = self.symbol(sym_index);
+ const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
const atom_ptr = sym.atom(elf_file).?;
const name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
@@ -1264,9 +1313,9 @@ fn updateLazySymbol(
.code => elf_file.zig_text_section_index.?,
.const_data => elf_file.zig_data_rel_ro_section_index.?,
};
- const local_sym = elf_file.symbol(symbol_index);
+ const local_sym = self.symbol(symbol_index);
local_sym.name_offset = name_str_index;
- const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
+ const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index];
local_esym.st_name = name_str_index;
local_esym.st_info |= elf.STT_OBJECT;
local_esym.st_size = code.len;
@@ -1372,7 +1421,7 @@ fn lowerConst(
};
const local_sym = self.symbol(sym_index);
- const local_esym = local_sym.elfSym(elf_file);
+ const local_esym = &self.symtab.items(.elf_sym)[local_sym.esym_index];
local_esym.st_info |= elf.STT_OBJECT;
local_esym.st_size = code.len;
const atom_ptr = local_sym.atom(elf_file).?;
@@ -1473,9 +1522,9 @@ pub fn updateExports(
const global_sym = self.symbol(global_sym_index);
global_sym.value = value;
global_sym.flags.weak = exp.opts.linkage == .weak;
- global_sym.version_index = elf_file.default_version_index;
+ global_sym.version_index = elf_file.default_sym_version;
global_sym.ref = .{ .index = esym_shndx, .file = self.index };
- const global_esym = global_sym.elfSym(elf_file);
+ const global_esym = &self.symtab.items(.elf_sym)[global_sym.esym_index];
global_esym.st_value = @intCast(value);
global_esym.st_shndx = esym.st_shndx;
global_esym.st_info = (stb_bits << 4) | stt_bits;
@@ -1517,16 +1566,16 @@ pub fn deleteExport(
const exp_name = name.toSlice(&mod.intern_pool);
const esym_index = metadata.@"export"(self, exp_name) orelse return;
log.debug("deleting export '{s}'", .{exp_name});
- const esym = &self.global_esyms.items(.elf_sym)[esym_index.*];
+ const esym = &self.symtab.items(.elf_sym)[esym_index.*];
_ = self.globals_lookup.remove(esym.st_name);
- const sym_index = elf_file.resolver.get(esym.st_name).?;
- const sym = elf_file.symbol(sym_index);
- if (sym.file_index == self.index) {
- _ = elf_file.resolver.swapRemove(esym.st_name);
- sym.* = .{};
- }
+ // const sym_index = elf_file.resolver.get(esym.st_name).?;
+ // const sym = elf_file.symbol(sym_index);
+ // if (sym.file_index == self.index) {
+ // _ = elf_file.resolver.swapRemove(esym.st_name);
+ // sym.* = .{};
+ // }
esym.* = Elf.null_sym;
- self.global_esyms.items(.shndx)[esym_index.*] = elf.SHN_UNDEF;
+ self.symtab.items(.shndx)[esym_index.*] = elf.SHN_UNDEF;
}
pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 {
@@ -1535,7 +1584,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
const off = try self.strtab.insert(gpa, name);
const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
if (!lookup_gop.found_existing) {
- lookup_gop.value_ptr.* = try self.newSymbol(gpa, off);
+ lookup_gop.value_ptr.* = try self.newGlobalSymbol(gpa, off);
}
return lookup_gop.value_ptr.*;
}
@@ -1636,8 +1685,12 @@ pub fn resolveSymbol(self: ZigObject, index: Symbol.Index, elf_file: *Elf) Elf.R
return .{ .index = index, .file = self.index };
}
-pub fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
+fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
try self.symbols.ensureUnusedCapacity(allocator, 1);
+ return self.addSymbolAssumeCapacity();
+}
+
+fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index {
const index: Symbol.Index = @intCast(self.symbols.items.len);
self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
return index;
@@ -1705,15 +1758,17 @@ fn formatSymtab(
) !void {
_ = unused_fmt_string;
_ = options;
+ const self = ctx.self;
+ const elf_file = ctx.elf_file;
try writer.writeAll(" locals\n");
- for (ctx.self.locals()) |index| {
- const local = ctx.elf_file.symbol(index);
- try writer.print(" {}\n", .{local.fmt(ctx.elf_file)});
+ for (self.local_symbols.items) |index| {
+ const local = self.symbols.items[index];
+ try writer.print(" {}\n", .{local.fmt(elf_file)});
}
try writer.writeAll(" globals\n");
- for (ctx.self.globals()) |index| {
- const global = ctx.elf_file.symbol(index);
- try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
+ for (ctx.self.global_symbols.items) |index| {
+ const global = self.symbols.items[index];
+ try writer.print(" {}\n", .{global.fmt(elf_file)});
}
}
@@ -1759,7 +1814,7 @@ const DeclMetadata = struct {
fn @"export"(m: DeclMetadata, zo: *ZigObject, name: []const u8) ?*u32 {
for (m.exports.items) |*exp| {
- const exp_name = zo.getString(zo.symbol(exp.*).name_off);
+ const exp_name = zo.getString(zo.symbol(exp.*).name_offset);
if (mem.eql(u8, name, exp_name)) return exp;
}
return null;
src/link/Elf.zig
@@ -2013,11 +2013,10 @@ fn claimUnresolved(self: *Elf) void {
fn scanRelocs(self: *Elf) !void {
const gpa = self.base.comp.gpa;
- var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
+ var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
defer {
- var it = undefs.iterator();
- while (it.next()) |entry| {
- entry.value_ptr.deinit();
+ for (undefs.values()) |*refs| {
+ refs.deinit();
}
undefs.deinit();
}
@@ -2028,7 +2027,18 @@ fn scanRelocs(self: *Elf) !void {
objects.appendSliceAssumeCapacity(self.objects.items);
var has_reloc_errors = false;
- for (objects.items) |index| {
+ if (self.zigObjectPtr()) |zo| {
+ zo.asFile().scanRelocs(self, &undefs) catch |err| switch (err) {
+ error.RelaxFailure => unreachable,
+ error.UnsupportedCpuArch => {
+ try self.reportUnsupportedCpuArch();
+ return error.FlushFailure;
+ },
+ error.RelocFailure => has_reloc_errors = true,
+ else => |e| return e,
+ };
+ }
+ for (self.objects.items) |index| {
self.file(index).?.scanRelocs(self, &undefs) catch |err| switch (err) {
error.RelaxFailure => unreachable,
error.UnsupportedCpuArch => {
@@ -2044,47 +2054,12 @@ fn scanRelocs(self: *Elf) !void {
if (has_reloc_errors) return error.FlushFailure;
- for (self.symbols.items, 0..) |*sym, i| {
- const index = @as(u32, @intCast(i));
- if (!sym.isLocal(self) and !sym.flags.has_dynamic) {
- log.debug("'{s}' is non-local", .{sym.name(self)});
- try self.dynsym.addSymbol(index, self);
- }
- if (sym.flags.needs_got) {
- log.debug("'{s}' needs GOT", .{sym.name(self)});
- _ = try self.got.addGotSymbol(index, self);
- }
- if (sym.flags.needs_plt) {
- if (sym.flags.is_canonical) {
- log.debug("'{s}' needs CPLT", .{sym.name(self)});
- sym.flags.@"export" = true;
- try self.plt.addSymbol(index, self);
- } else if (sym.flags.needs_got) {
- log.debug("'{s}' needs PLTGOT", .{sym.name(self)});
- try self.plt_got.addSymbol(index, self);
- } else {
- log.debug("'{s}' needs PLT", .{sym.name(self)});
- try self.plt.addSymbol(index, self);
- }
- }
- if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) {
- log.debug("'{s}' needs COPYREL", .{sym.name(self)});
- try self.copy_rel.addSymbol(index, self);
- }
- if (sym.flags.needs_tlsgd) {
- log.debug("'{s}' needs TLSGD", .{sym.name(self)});
- try self.got.addTlsGdSymbol(index, self);
- }
- if (sym.flags.needs_gottp) {
- log.debug("'{s}' needs GOTTP", .{sym.name(self)});
- try self.got.addGotTpSymbol(index, self);
- }
- if (sym.flags.needs_tlsdesc) {
- log.debug("'{s}' needs TLSDESC", .{sym.name(self)});
- try self.got.addTlsDescSymbol(index, self);
- }
+ if (self.zigObjectPtr()) |zo| {
+ try zo.asFile().createSymbolIndirection(self);
+ }
+ for (self.objects.items) |index| {
+ try self.file(index).?.createSymbolIndirection(self);
}
-
if (self.got.flags.needs_tlsld) {
log.debug("program needs TLSLD", .{});
try self.got.addTlsLdSymbol(self);
@@ -2861,8 +2836,8 @@ pub fn writeElfHeader(self: *Elf) !void {
index += 4;
const e_entry: u64 = if (self.linkerDefinedPtr()) |obj| blk: {
- const entry_index = obj.entry_index orelse break :blk 0;
- break :blk @intCast(self.symbol(entry_index).address(.{}, self));
+ const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
+ break :blk @intCast(entry_sym.address(.{}, self));
} else 0;
const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;
switch (self.ptr_width) {
@@ -2993,7 +2968,7 @@ pub fn deleteExport(
fn checkDuplicates(self: *Elf) !void {
const gpa = self.base.comp.gpa;
- var dupes = std.AutoArrayHashMap(Symbol.Index, std.ArrayListUnmanaged(File.Index)).init(gpa);
+ var dupes = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)).init(gpa);
defer {
for (dupes.values()) |*list| {
list.deinit(gpa);
@@ -3301,7 +3276,7 @@ fn initSyntheticSections(self: *Elf) !void {
});
const needs_versions = for (self.dynsym.entries.items) |entry| {
- const sym = self.symbol(entry.symbol_index);
+ const sym = self.symbol(entry.ref).?;
if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
} else false;
if (needs_versions) {
@@ -3515,7 +3490,7 @@ fn setVersionSymtab(self: *Elf) !void {
try self.versym.resize(gpa, self.dynsym.count());
self.versym.items[0] = elf.VER_NDX_LOCAL;
for (self.dynsym.entries.items, 1..) |entry, i| {
- const sym = self.symbol(entry.symbol_index);
+ const sym = self.symbol(entry.ref).?;
self.versym.items[i] = sym.version_index;
}
@@ -4307,11 +4282,10 @@ fn allocateSpecialPhdrs(self: *Elf) void {
fn writeAtoms(self: *Elf) !void {
const gpa = self.base.comp.gpa;
- var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
+ var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa);
defer {
- var it = undefs.iterator();
- while (it.next()) |entry| {
- entry.value_ptr.deinit();
+ for (undefs.values()) |*refs| {
+ refs.deinit();
}
undefs.deinit();
}
@@ -5261,7 +5235,7 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize {
for (self.got.entries.items) |entry| {
if (entry.tag != .got) continue;
- const sym = self.symbol(entry.symbol_index);
+ const sym = self.symbol(entry.ref).?;
if (sym.isIFunc(self)) count += 1;
}
@@ -5443,36 +5417,34 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
try self.base.comp.link_errors.ensureUnusedCapacity(gpa, undefs.count());
- var it = undefs.iterator();
- while (it.next()) |entry| {
- const undef_index = entry.key_ptr.*;
- const atoms = entry.value_ptr.*.items;
- const natoms = @min(atoms.len, max_notes);
- const nnotes = natoms + @intFromBool(atoms.len > max_notes);
+ for (undefs.keys(), undefs.values()) |key, refs| {
+ const undef_sym = self.resolver.keys.items[key - 1];
+ const nrefs = @min(refs.items.len, max_notes);
+ const nnotes = nrefs + @intFromBool(refs.items.len > max_notes);
var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes);
- try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)});
+ try err.addMsg("undefined symbol: {s}", .{undef_sym.name(self)});
- for (atoms[0..natoms]) |ref| {
+ for (refs.items[0..nrefs]) |ref| {
const atom_ptr = self.atom(ref).?;
- const file_ptr = self.file(ref.file).?;
+ const file_ptr = atom_ptr.file(self).?;
try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
}
- if (atoms.len > max_notes) {
- const remaining = atoms.len - max_notes;
+ if (refs.items.len > max_notes) {
+ const remaining = refs.items.len - max_notes;
try err.addNote("referenced {d} more times", .{remaining});
}
}
}
fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemory }!void {
+ if (dupes.keys().len == 0) return; // Nothing to do
+
const max_notes = 3;
- var has_dupes = false;
- var it = dupes.iterator();
- while (it.next()) |entry| {
- const sym = self.symbol(entry.key_ptr.*);
- const notes = entry.value_ptr.*;
+
+ for (dupes.keys(), dupes.values()) |key, notes| {
+ const sym = self.resolver.keys.items[key - 1];
const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
var err = try self.base.addErrorWithNotes(nnotes + 1);
@@ -5489,11 +5461,9 @@ fn reportDuplicates(self: *Elf, dupes: anytype) error{ HasDuplicates, OutOfMemor
const remaining = notes.items.len - max_notes;
try err.addNote("defined {d} more times", .{remaining});
}
-
- has_dupes = true;
}
- if (has_dupes) return error.HasDuplicates;
+ return error.HasDuplicates;
}
fn reportMissingLibraryError(
@@ -5918,7 +5888,7 @@ pub const SymbolResolver = struct {
elf_file: *Elf,
) !Result {
const adapter = Adapter{ .keys = resolver.keys.items, .elf_file = elf_file };
- const key = Key{ .index = ref.index, .file = ref.file };
+ const key = Key{ .index = ref.index, .file_index = ref.file };
const gop = try resolver.table.getOrPutAdapted(allocator, key, adapter);
if (!gop.found_existing) {
try resolver.keys.append(allocator, key);
@@ -5944,16 +5914,15 @@ pub const SymbolResolver = struct {
const Key = struct {
index: Symbol.Index,
- file: File.Index,
+ file_index: File.Index,
fn name(key: Key, elf_file: *Elf) [:0]const u8 {
- const ref = Ref{ .index = key.index, .file = key.file };
- return ref.symbol(elf_file).?.name(elf_file);
+ const ref = Ref{ .index = key.index, .file = key.file_index };
+ return elf_file.symbol(ref).?.name(elf_file);
}
- pub fn file(key: Key, elf_file: *Elf) ?File {
- const ref = Ref{ .index = key.index, .file = key.file };
- return ref.file(elf_file);
+ fn file(key: Key, elf_file: *Elf) ?File {
+ return elf_file.file(key.file_index);
}
fn eql(key: Key, other: Key, elf_file: *Elf) bool {
src/codegen.zig
@@ -906,20 +906,20 @@ fn genDeclRef(
const is_extern = decl.isExtern(zcu);
if (lf.cast(link.File.Elf)) |elf_file| {
+ const zo = elf_file.zigObjectPtr().?;
if (is_extern) {
const name = decl.name.toSlice(ip);
// TODO audit this
const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
const sym_index = try elf_file.getGlobalSymbol(name, lib_name);
- elf_file.symbol(elf_file.zigObjectPtr().?.symbol(sym_index)).flags.needs_got = true;
+ zo.symbol(sym_index).flags.needs_got = true;
return GenResult.mcv(.{ .load_symbol = sym_index });
}
- const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
- const sym = elf_file.symbol(sym_index);
+ const sym_index = try zo.getOrCreateMetadataForDecl(elf_file, decl_index);
if (is_threadlocal) {
- return GenResult.mcv(.{ .load_tlv = sym.esym_index });
+ return GenResult.mcv(.{ .load_tlv = sym_index });
}
- return GenResult.mcv(.{ .load_symbol = sym.esym_index });
+ return GenResult.mcv(.{ .load_symbol = sym_index });
} else if (lf.cast(link.File.MachO)) |macho_file| {
const zo = macho_file.getZigObject().?;
if (is_extern) {
@@ -971,9 +971,7 @@ fn genUnnamedConst(
};
switch (lf.tag) {
.elf => {
- const elf_file = lf.cast(link.File.Elf).?;
- const local = elf_file.symbol(local_sym_index);
- return GenResult.mcv(.{ .load_symbol = local.esym_index });
+ return GenResult.mcv(.{ .load_symbol = local_sym_index });
},
.macho => {
const macho_file = lf.cast(link.File.MachO).?;