diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-13 10:28:01 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-13 13:30:24 +0200 |
| commit | ce8886d57d1593a7eb4909e518fc49e1c95360dd (patch) | |
| tree | f9000ced65ae45021af02da0474dac13a03e77c6 /src/link/Elf | |
| parent | d25c93a868585e4e2f5941fcff15fa49c90510e9 (diff) | |
| download | zig-ce8886d57d1593a7eb4909e518fc49e1c95360dd.tar.gz zig-ce8886d57d1593a7eb4909e518fc49e1c95360dd.zip | |
elf: make zig jump table indirection implicit via Symbol.address
Diffstat (limited to 'src/link/Elf')
| -rw-r--r-- | src/link/Elf/Atom.zig | 35 | ||||
| -rw-r--r-- | src/link/Elf/Symbol.zig | 21 | ||||
| -rw-r--r-- | src/link/Elf/ZigObject.zig | 17 |
3 files changed, 35 insertions, 38 deletions
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 32583b39d7..e067e53c10 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -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, diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 38ef6bb8f7..8b30f0ab03 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -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; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 596ed781ca..9069e180a3 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -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'); } |
