elf: fix compile errors
This commit is contained in:
@@ -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 });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, .{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).?;
|
||||
|
||||
131
src/link/Elf.zig
131
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 {
|
||||
|
||||
@@ -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_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),
|
||||
sym_name,
|
||||
});
|
||||
continue;
|
||||
};
|
||||
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) {
|
||||
// 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),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
@@ -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)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -286,8 +286,8 @@ pub fn markImportExports(self: *SharedObject, elf_file: *Elf) void {
|
||||
for (0..self.symbols.items.len) |i| {
|
||||
const ref = self.resolveSymbol(@intCast(i), elf_file);
|
||||
const ref_sym = elf_file.symbol(ref) orelse continue;
|
||||
const ref_file = ref_sym.file(self).?;
|
||||
const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(self).st_other));
|
||||
const ref_file = ref_sym.file(elf_file).?;
|
||||
const vis = @as(elf.STV, @enumFromInt(ref_sym.elfSym(elf_file).st_other));
|
||||
if (ref_file != .shared_object and vis != .HIDDEN) ref_sym.flags.@"export" = true;
|
||||
}
|
||||
}
|
||||
@@ -349,9 +349,12 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
|
||||
assert(self.aliases == null);
|
||||
|
||||
const SortAlias = struct {
|
||||
pub fn lessThan(ctx: *Elf, lhs: Symbol.Index, rhs: Symbol.Index) bool {
|
||||
const lhs_sym = ctx.symbol(lhs).elfSym(ctx);
|
||||
const rhs_sym = ctx.symbol(rhs).elfSym(ctx);
|
||||
so: *SharedObject,
|
||||
ef: *Elf,
|
||||
|
||||
pub fn lessThan(ctx: @This(), lhs: Symbol.Index, rhs: Symbol.Index) bool {
|
||||
const lhs_sym = ctx.so.symbols.items[lhs].elfSym(ctx.ef);
|
||||
const rhs_sym = ctx.so.symbols.items[rhs].elfSym(ctx.ef);
|
||||
return lhs_sym.st_value < rhs_sym.st_value;
|
||||
}
|
||||
};
|
||||
@@ -362,14 +365,14 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
|
||||
defer aliases.deinit();
|
||||
try aliases.ensureTotalCapacityPrecise(self.symbols.items.len);
|
||||
|
||||
for (self.symbols_resolvers.items, 0..) |resolv, index| {
|
||||
for (self.symbols_resolver.items, 0..) |resolv, index| {
|
||||
const ref = elf_file.resolver.get(resolv).?;
|
||||
const ref_sym = elf_file.symbol(ref) orelse continue;
|
||||
if (ref_sym.file(elf_file).?.index() != self.index) continue;
|
||||
aliases.appendAssumeCapacity(index);
|
||||
aliases.appendAssumeCapacity(@intCast(index));
|
||||
}
|
||||
|
||||
std.mem.sort(u32, aliases.items, elf_file, SortAlias.lessThan);
|
||||
std.mem.sort(u32, aliases.items, SortAlias{ .so = self, .ef = elf_file }, SortAlias.lessThan);
|
||||
|
||||
self.aliases = aliases.moveToUnmanaged();
|
||||
}
|
||||
@@ -377,16 +380,16 @@ pub fn initSymbolAliases(self: *SharedObject, elf_file: *Elf) !void {
|
||||
pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u32 {
|
||||
assert(self.aliases != null);
|
||||
|
||||
const symbol = self.symbol(index).elfSym(elf_file);
|
||||
const symbol = self.symbols.items[index].elfSym(elf_file);
|
||||
const aliases = self.aliases.?;
|
||||
|
||||
const start = for (aliases.items, 0..) |alias, i| {
|
||||
const alias_sym = self.symbol(alias).elfSym(elf_file);
|
||||
const alias_sym = self.symbols.items[alias].elfSym(elf_file);
|
||||
if (symbol.st_value == alias_sym.st_value) break i;
|
||||
} else aliases.items.len;
|
||||
|
||||
const end = for (aliases.items[start..], 0..) |alias, i| {
|
||||
const alias_sym = self.symbol(alias).elfSym(elf_file);
|
||||
const alias_sym = self.symbols.items[alias].elfSym(elf_file);
|
||||
if (symbol.st_value < alias_sym.st_value) break i + start;
|
||||
} else aliases.items.len;
|
||||
|
||||
@@ -403,8 +406,12 @@ pub fn resolveSymbol(self: SharedObject, index: Symbol.Index, elf_file: *Elf) El
|
||||
return elf_file.resolver.get(resolv).?;
|
||||
}
|
||||
|
||||
pub fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index {
|
||||
fn addSymbol(self: *SharedObject, allocator: Allocator) !Symbol.Index {
|
||||
try self.symbols.ensureUnusedCapacity(allocator, 1);
|
||||
return self.addSymbolAssumeCapacity();
|
||||
}
|
||||
|
||||
fn addSymbolAssumeCapacity(self: *SharedObject) Symbol.Index {
|
||||
const index: Symbol.Index = @intCast(self.symbols.items.len);
|
||||
self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
|
||||
return index;
|
||||
@@ -486,10 +493,10 @@ fn formatSymtab(
|
||||
_ = unused_fmt_string;
|
||||
_ = options;
|
||||
const shared = ctx.shared;
|
||||
const elf_file = ctx.elf_file;
|
||||
try writer.writeAll(" globals\n");
|
||||
for (shared.symbols.items) |index| {
|
||||
const global = ctx.elf_file.symbol(index);
|
||||
try writer.print(" {}\n", .{global.fmt(ctx.elf_file)});
|
||||
for (shared.symbols.items) |sym| {
|
||||
try writer.print(" {}\n", .{sym.fmt(elf_file)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,72 +1,85 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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()));
|
||||
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 (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), elf_file: *Elf) !void {
|
||||
@@ -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");
|
||||
|
||||
@@ -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).?);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user