elf: make zig jump table indirection implicit via Symbol.address
This commit is contained in:
@@ -750,8 +750,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
|
||||
const S = target.address(.{}, elf_file);
|
||||
// Address of the global offset table.
|
||||
const GOT = elf_file.gotAddress();
|
||||
// Address of the zig jump table entry if any.
|
||||
const ZJT = target.zigJumpTableAddress(elf_file);
|
||||
// Relative offset to the start of the global offset table.
|
||||
const G = target.gotAddress(elf_file) - GOT;
|
||||
// // Address of the thread pointer.
|
||||
@@ -759,19 +757,18 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
|
||||
// Address of the dynamic thread pointer.
|
||||
const DTP = elf_file.dtpAddress();
|
||||
|
||||
relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ZJT({x}) ({s})", .{
|
||||
relocs_log.debug(" {s}: {x}: [{x} => {x}] GOT({x}) ({s})", .{
|
||||
relocation.fmtRelocType(rel.r_type(), cpu_arch),
|
||||
r_offset,
|
||||
P,
|
||||
S + A,
|
||||
G + GOT + A,
|
||||
ZJT + A,
|
||||
target.name(elf_file),
|
||||
});
|
||||
|
||||
try stream.seekTo(r_offset);
|
||||
|
||||
const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP, ZJT };
|
||||
const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };
|
||||
|
||||
switch (cpu_arch) {
|
||||
.x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {
|
||||
@@ -956,7 +953,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
|
||||
// Address of the dynamic thread pointer.
|
||||
const DTP = elf_file.dtpAddress();
|
||||
|
||||
const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP, 0 };
|
||||
const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP };
|
||||
|
||||
relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{
|
||||
relocation.fmtRelocType(rel.r_type(), cpu_arch),
|
||||
@@ -1200,7 +1197,7 @@ const x86_64 = struct {
|
||||
|
||||
const cwriter = stream.writer();
|
||||
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZJT = args;
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP = args;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@@ -1215,10 +1212,7 @@ const x86_64 = struct {
|
||||
);
|
||||
},
|
||||
|
||||
.PLT32 => {
|
||||
const S_ = if (target.flags.zig_jump_table) ZJT else S;
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
|
||||
},
|
||||
.PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
|
||||
.PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
|
||||
|
||||
.GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
|
||||
@@ -1243,10 +1237,7 @@ const x86_64 = struct {
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
|
||||
},
|
||||
|
||||
.@"32" => {
|
||||
const S_ = if (target.flags.zig_jump_table) ZJT else S;
|
||||
try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S_ + A)))), .little);
|
||||
},
|
||||
.@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
|
||||
.@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),
|
||||
|
||||
.TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),
|
||||
@@ -1345,7 +1336,7 @@ const x86_64 = struct {
|
||||
const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
|
||||
const cwriter = stream.writer();
|
||||
|
||||
_, const A, const S, const GOT, _, _, const DTP, _ = args;
|
||||
_, const A, const S, const GOT, _, _, const DTP = args;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@@ -1728,9 +1719,8 @@ const aarch64 = struct {
|
||||
const code = code_buffer[r_offset..][0..4];
|
||||
const file_ptr = atom.file(elf_file).?;
|
||||
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZJT = args;
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP = args;
|
||||
_ = DTP;
|
||||
_ = ZJT;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@@ -1932,7 +1922,7 @@ const aarch64 = struct {
|
||||
const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
|
||||
const cwriter = stream.writer();
|
||||
|
||||
_, const A, const S, _, _, _, _, _ = args;
|
||||
_, const A, const S, _, _, _, _ = args;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@@ -2012,10 +2002,9 @@ const riscv = struct {
|
||||
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
|
||||
const cwriter = stream.writer();
|
||||
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP, const ZJT = args;
|
||||
const P, const A, const S, const GOT, const G, const TP, const DTP = args;
|
||||
_ = TP;
|
||||
_ = DTP;
|
||||
_ = ZJT;
|
||||
|
||||
switch (r_type) {
|
||||
.NONE => unreachable,
|
||||
@@ -2167,7 +2156,7 @@ const riscv = struct {
|
||||
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
|
||||
const cwriter = stream.writer();
|
||||
|
||||
_, const A, const S, const GOT, _, _, const DTP, _ = args;
|
||||
_, const A, const S, const GOT, _, _, const DTP = args;
|
||||
_ = GOT;
|
||||
_ = DTP;
|
||||
|
||||
@@ -2203,7 +2192,7 @@ const riscv = struct {
|
||||
const riscv_util = @import("../riscv.zig");
|
||||
};
|
||||
|
||||
const ResolveArgs = struct { i64, i64, i64, i64, i64, i64, i64, i64 };
|
||||
const ResolveArgs = struct { i64, i64, i64, i64, i64, i64, i64 };
|
||||
|
||||
const RelocError = error{
|
||||
Overflow,
|
||||
|
||||
@@ -101,7 +101,7 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
|
||||
return file_ptr.symbolRank(sym, in_archive);
|
||||
}
|
||||
|
||||
pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf) i64 {
|
||||
pub fn address(symbol: Symbol, opts: struct { plt: bool = true, zjt: bool = true }, elf_file: *Elf) i64 {
|
||||
if (symbol.mergeSubsection(elf_file)) |msub| {
|
||||
if (!msub.alive) return 0;
|
||||
return msub.address(elf_file) + symbol.value;
|
||||
@@ -109,6 +109,9 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
|
||||
if (symbol.flags.has_copy_rel) {
|
||||
return symbol.copyRelAddress(elf_file);
|
||||
}
|
||||
if (symbol.flags.has_zjt and opts.zjt) {
|
||||
return symbol.zjtAddress(elf_file);
|
||||
}
|
||||
if (symbol.flags.has_plt and opts.plt) {
|
||||
if (!symbol.flags.is_canonical and symbol.flags.has_got) {
|
||||
// We have a non-lazy bound function pointer, use that!
|
||||
@@ -217,12 +220,12 @@ pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 {
|
||||
return entry.address(elf_file);
|
||||
}
|
||||
|
||||
pub fn zigJumpTableAddress(symbol: Symbol, elf_file: *Elf) i64 {
|
||||
if (!symbol.flags.zig_jump_table) return 0;
|
||||
pub fn zjtAddress(symbol: Symbol, elf_file: *Elf) i64 {
|
||||
if (!symbol.flags.has_zjt) return 0;
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const jump_table = zo.jumpTablePtr().?;
|
||||
const jt_index = symbol.extra(elf_file).zig_jump_table;
|
||||
return jump_table.entryAddress(jt_index, zo, elf_file);
|
||||
const index = symbol.extra(elf_file).zjt;
|
||||
return jump_table.entryAddress(index, zo, elf_file);
|
||||
}
|
||||
|
||||
pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
|
||||
@@ -248,7 +251,7 @@ const AddExtraOpts = struct {
|
||||
tlsgd: ?u32 = null,
|
||||
gottp: ?u32 = null,
|
||||
tlsdesc: ?u32 = null,
|
||||
zig_jump_table: ?u32 = null,
|
||||
zjt: ?u32 = null,
|
||||
};
|
||||
|
||||
pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
|
||||
@@ -377,7 +380,7 @@ fn format2(
|
||||
try writer.print("%{d} : {s} : @{x}", .{
|
||||
symbol.esym_index,
|
||||
symbol.fmtName(elf_file),
|
||||
symbol.address(.{}, elf_file),
|
||||
symbol.address(.{ .plt = false, .zjt = false }, elf_file),
|
||||
});
|
||||
if (symbol.file(elf_file)) |file_ptr| {
|
||||
if (symbol.isAbs(elf_file)) {
|
||||
@@ -454,7 +457,7 @@ pub const Flags = packed struct {
|
||||
merge_subsection: bool = false,
|
||||
|
||||
/// Whether the symbol has __zig_jump_table indirection.
|
||||
zig_jump_table: bool = false,
|
||||
has_zjt: bool = false,
|
||||
};
|
||||
|
||||
pub const Extra = struct {
|
||||
@@ -468,7 +471,7 @@ pub const Extra = struct {
|
||||
gottp: u32 = 0,
|
||||
tlsdesc: u32 = 0,
|
||||
merge_section: u32 = 0,
|
||||
zig_jump_table: u32 = 0,
|
||||
zjt: u32 = 0,
|
||||
};
|
||||
|
||||
pub const Index = u32;
|
||||
|
||||
@@ -918,7 +918,7 @@ fn updateNavCode(
|
||||
if (stt_bits == elf.STT_FUNC) {
|
||||
const extra = sym.extra(elf_file);
|
||||
const jump_table = self.jumpTablePtr().?;
|
||||
jump_table.entries.items(.dirty)[extra.zig_jump_table] = true;
|
||||
jump_table.entries.items(.dirty)[extra.zjt] = true;
|
||||
}
|
||||
}
|
||||
} else if (code.len < old_size) {
|
||||
@@ -1045,10 +1045,10 @@ pub fn updateFunc(
|
||||
|
||||
{
|
||||
const sym = self.symbol(sym_index);
|
||||
if (!sym.flags.zig_jump_table) {
|
||||
if (!sym.flags.has_zjt) {
|
||||
const index = try jump_table.addSymbol(gpa, sym_index);
|
||||
sym.flags.zig_jump_table = true;
|
||||
sym.addExtra(.{ .zig_jump_table = index }, elf_file);
|
||||
sym.flags.has_zjt = true;
|
||||
sym.addExtra(.{ .zjt = index }, elf_file);
|
||||
try jump_table.updateSize(self, elf_file);
|
||||
const old_vaddr = jump_table.address(self, elf_file);
|
||||
try self.symbol(jump_table.sym_index).atom(elf_file).?.allocate(elf_file);
|
||||
@@ -1108,7 +1108,7 @@ pub fn updateFunc(
|
||||
}
|
||||
} else {
|
||||
const sym = self.symbol(sym_index);
|
||||
const jt_index = sym.extra(elf_file).zig_jump_table;
|
||||
const jt_index = sym.extra(elf_file).zjt;
|
||||
var jt_entry = jump_table.entries.get(jt_index);
|
||||
if (jt_entry.dirty) {
|
||||
try jump_table.writeEntry(jt_index, self, elf_file);
|
||||
@@ -1896,7 +1896,12 @@ pub const JumpTable = struct {
|
||||
try writer.print(" @{x} : size({x})\n", .{ jt.address(zo, ef), jt.size(zo, ef) });
|
||||
for (jt.entries.items(.sym_index), jt.entries.items(.dirty)) |sym_index, dirty| {
|
||||
const sym = zo.symbol(sym_index);
|
||||
try writer.print(" %{d} : {s} : @{x}", .{ sym_index, sym.name(ef), sym.address(.{}, ef) });
|
||||
try writer.print(" {x} => {x} : %{d} : {s}", .{
|
||||
sym.address(.{}, ef),
|
||||
sym.address(.{ .zjt = false }, ef),
|
||||
sym_index,
|
||||
sym.name(ef),
|
||||
});
|
||||
if (dirty) try writer.writeAll(" : [!]");
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user