diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-17 19:35:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-17 19:35:09 +0100 |
| commit | 79e99c401ca32031d29aff77e43758ca0b67d5d9 (patch) | |
| tree | f3edc8133467b6be6d7114a6fb0bec4105505c83 /src/link | |
| parent | dd4d320eb9663c7a0ef8dbe3aca220a64795d683 (diff) | |
| parent | d1429a8fa98f85c9fb8d2bd99b7c31eb9de38b38 (diff) | |
| download | zig-79e99c401ca32031d29aff77e43758ca0b67d5d9.tar.gz zig-79e99c401ca32031d29aff77e43758ca0b67d5d9.zip | |
Merge pull request #18973 from ziglang/elf-riscv
lib/std/elf: refactor relocation types + add RISCV relocs
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Elf.zig | 5 | ||||
| -rw-r--r-- | src/link/Elf/Atom.zig | 199 | ||||
| -rw-r--r-- | src/link/Elf/eh_frame.zig | 11 | ||||
| -rw-r--r-- | src/link/Elf/relocation.zig | 285 |
4 files changed, 187 insertions, 313 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 041db6c0d5..a6625556e6 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -6065,8 +6065,9 @@ const RelaSection = struct { }; const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); -pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; -pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; +// TODO: add comptime check we don't clobber any reloc for any ISA +pub const R_ZIG_GOT32: u32 = 0xff00; +pub const R_ZIG_GOTPCREL: u32 = 0xff01; fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { return switch (cpu_arch) { diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 72e7e6bcc0..3064fd6f74 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -336,7 +336,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El } relocs_log.debug(" {s}: [{x} => {d}({s})] + {x}", .{ - relocation.fmtRelocType(r_type, cpu_arch), + relocation.fmtRelocType(rel.r_type(), cpu_arch), r_offset, r_sym, target.name(elf_file), @@ -384,7 +384,10 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool { const cpu_arch = elf_file.getTarget().cpu.arch; for (self.relocs(elf_file)) |rel| { switch (cpu_arch) { - .x86_64 => if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true, + .x86_64 => { + const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); + if (r_type == .GOTTPOFF) return true; + }, else => {}, } } @@ -836,8 +839,9 @@ const x86_64 = struct { var i: usize = 0; while (i < rels.len) : (i += 1) { const rel = rels[i]; + const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); - if (rel.r_type() == elf.R_X86_64_NONE) continue; + if (r_type == .NONE) continue; const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; @@ -869,41 +873,41 @@ const x86_64 = struct { // While traversing relocations, mark symbols that require special handling such as // pointer indirection via GOT, or a stub trampoline via PLT. - switch (rel.r_type()) { - elf.R_X86_64_64 => { + switch (r_type) { + .@"64" => { try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); }, - elf.R_X86_64_32, - elf.R_X86_64_32S, + .@"32", + .@"32S", => { try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); }, - elf.R_X86_64_GOT32, - elf.R_X86_64_GOTPC32, - elf.R_X86_64_GOTPC64, - elf.R_X86_64_GOTPCREL, - elf.R_X86_64_GOTPCREL64, - elf.R_X86_64_GOTPCRELX, - elf.R_X86_64_REX_GOTPCRELX, + .GOT32, + .GOTPC32, + .GOTPC64, + .GOTPCREL, + .GOTPCREL64, + .GOTPCRELX, + .REX_GOTPCRELX, => { symbol.flags.needs_got = true; }, - elf.R_X86_64_PLT32, - elf.R_X86_64_PLTOFF64, + .PLT32, + .PLTOFF64, => { if (symbol.flags.import) { symbol.flags.needs_plt = true; } }, - elf.R_X86_64_PC32 => { + .PC32 => { try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); }, - elf.R_X86_64_TLSGD => { + .TLSGD => { // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr if (is_static or (!symbol.flags.import and !is_dyn_lib)) { @@ -918,7 +922,7 @@ const x86_64 = struct { } }, - elf.R_X86_64_TLSLD => { + .TLSLD => { // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr if (is_static or !is_dyn_lib) { @@ -930,7 +934,7 @@ const x86_64 = struct { } }, - elf.R_X86_64_GOTTPOFF => { + .GOTTPOFF => { const should_relax = blk: { if (is_dyn_lib or symbol.flags.import) break :blk false; if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false; @@ -941,35 +945,37 @@ const x86_64 = struct { } }, - elf.R_X86_64_GOTPC32_TLSDESC => { + .GOTPC32_TLSDESC => { const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import); if (!should_relax) { symbol.flags.needs_tlsdesc = true; } }, - elf.R_X86_64_TPOFF32, - elf.R_X86_64_TPOFF64, + .TPOFF32, + .TPOFF64, => { if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file); }, - elf.R_X86_64_GOTOFF64, - elf.R_X86_64_DTPOFF32, - elf.R_X86_64_DTPOFF64, - elf.R_X86_64_SIZE32, - elf.R_X86_64_SIZE64, - elf.R_X86_64_TLSDESC_CALL, + .GOTOFF64, + .DTPOFF32, + .DTPOFF64, + .SIZE32, + .SIZE64, + .TLSDESC_CALL, => {}, - // Zig custom relocations - Elf.R_X86_64_ZIG_GOT32, - Elf.R_X86_64_ZIG_GOTPCREL, - => { - assert(symbol.flags.has_zig_got); - }, + else => |x| switch (@intFromEnum(x)) { + // Zig custom relocations + Elf.R_ZIG_GOT32, + Elf.R_ZIG_GOTPCREL, + => { + assert(symbol.flags.has_zig_got); + }, - else => try atom.reportUnhandledRelocError(rel, elf_file), + else => try atom.reportUnhandledRelocError(rel, elf_file), + }, } } } @@ -983,8 +989,8 @@ const x86_64 = struct { var i: usize = 0; while (i < rels.len) : (i += 1) { const rel = rels[i]; - const r_type = rel.r_type(); - if (r_type == elf.R_X86_64_NONE) continue; + const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); + if (r_type == .NONE) continue; const target = switch (file_ptr) { .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())), @@ -1022,7 +1028,7 @@ const x86_64 = struct { const DTP = @as(i64, @intCast(elf_file.dtpAddress())); relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ - relocation.fmtRelocType(r_type, .x86_64), + relocation.fmtRelocType(rel.r_type(), .x86_64), r_offset, P, S + A, @@ -1033,10 +1039,10 @@ const x86_64 = struct { try stream.seekTo(r_offset); - switch (rel.r_type()) { - elf.R_X86_64_NONE => unreachable, + switch (r_type) { + .NONE => unreachable, - elf.R_X86_64_64 => { + .@"64" => { try atom.resolveDynAbsReloc( target, rel, @@ -1046,15 +1052,15 @@ const x86_64 = struct { ); }, - elf.R_X86_64_PLT32, - elf.R_X86_64_PC32, + .PLT32, + .PC32, => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), - elf.R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), - elf.R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), - elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), + .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), + .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), + .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), - elf.R_X86_64_GOTPCRELX => { + .GOTPCRELX => { if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk; try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); @@ -1063,7 +1069,7 @@ const x86_64 = struct { try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); }, - elf.R_X86_64_REX_GOTPCRELX => { + .REX_GOTPCRELX => { if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk; try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); @@ -1072,16 +1078,16 @@ const x86_64 = struct { try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); }, - elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), - elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @truncate(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), - elf.R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), - elf.R_X86_64_TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), + .TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), + .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), - elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), - elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), + .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), + .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), - elf.R_X86_64_TLSGD => { + .TLSGD => { if (target.flags.has_tlsgd) { const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); @@ -1101,7 +1107,7 @@ const x86_64 = struct { } }, - elf.R_X86_64_TLSLD => { + .TLSLD => { if (elf_file.got.tlsld_index) |entry_index| { const tlsld_entry = elf_file.got.entries.items[entry_index]; const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file))); @@ -1118,7 +1124,7 @@ const x86_64 = struct { } }, - elf.R_X86_64_GOTPC32_TLSDESC => { + .GOTPC32_TLSDESC => { if (target.flags.has_tlsdesc) { const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file))); try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); @@ -1128,12 +1134,12 @@ const x86_64 = struct { } }, - elf.R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) { + .TLSDESC_CALL => if (!target.flags.has_tlsdesc) { // call -> nop try cwriter.writeAll(&.{ 0x66, 0x90 }); }, - elf.R_X86_64_GOTTPOFF => { + .GOTTPOFF => { if (target.flags.has_gottp) { const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); @@ -1143,13 +1149,15 @@ const x86_64 = struct { } }, - elf.R_X86_64_GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little), + .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little), - // Zig custom relocations - Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little), - Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little), + else => |x| switch (@intFromEnum(x)) { + // Zig custom relocations + Elf.R_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little), + Elf.R_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little), - else => {}, + else => {}, + }, } } } @@ -1163,8 +1171,8 @@ const x86_64 = struct { var i: usize = 0; while (i < rels.len) : (i += 1) { const rel = rels[i]; - const r_type = rel.r_type(); - if (r_type == elf.R_X86_64_NONE) continue; + const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); + if (r_type == .NONE) continue; const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; @@ -1210,8 +1218,8 @@ const x86_64 = struct { // Address of the dynamic thread pointer. const DTP = @as(i64, @intCast(elf_file.dtpAddress())); - relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{ - relocation.fmtRelocType(r_type, .x86_64), + relocs_log.debug(" {}: {x}: [{x} => {x}] ({s})", .{ + relocation.fmtRelocType(rel.r_type(), .x86_64), rel.r_offset, P, S + A, @@ -1221,21 +1229,21 @@ const x86_64 = struct { try stream.seekTo(r_offset); switch (r_type) { - elf.R_X86_64_NONE => unreachable, - elf.R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), - elf.R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), - elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), - elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), - elf.R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little), - elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), - elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), - elf.R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), - elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), - elf.R_X86_64_SIZE32 => { + .NONE => unreachable, + .@"8" => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), + .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), + .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), + .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), + .@"64" => try cwriter.writeInt(i64, S + A, .little), + .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), + .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), + .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), + .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), + .SIZE32 => { const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little); }, - elf.R_X86_64_SIZE64 => { + .SIZE64 => { const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little); }, @@ -1283,9 +1291,10 @@ const x86_64 = struct { ) !void { assert(rels.len == 2); const writer = stream.writer(); - switch (rels[1].r_type()) { - elf.R_X86_64_PC32, - elf.R_X86_64_PLT32, + const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel) { + .PC32, + .PLT32, => { var insts = [_]u8{ 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax @@ -1320,9 +1329,10 @@ const x86_64 = struct { ) !void { assert(rels.len == 2); const writer = stream.writer(); - switch (rels[1].r_type()) { - elf.R_X86_64_PC32, - elf.R_X86_64_PLT32, + const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel) { + .PC32, + .PLT32, => { var insts = [_]u8{ 0x31, 0xc0, // xor %eax, %eax @@ -1334,8 +1344,8 @@ const x86_64 = struct { try writer.writeAll(&insts); }, - elf.R_X86_64_GOTPCREL, - elf.R_X86_64_GOTPCRELX, + .GOTPCREL, + .GOTPCRELX, => { var insts = [_]u8{ 0x31, 0xc0, // xor %eax, %eax @@ -1419,11 +1429,12 @@ const x86_64 = struct { ) !void { assert(rels.len == 2); const writer = stream.writer(); - switch (rels[1].r_type()) { - elf.R_X86_64_PC32, - elf.R_X86_64_PLT32, - elf.R_X86_64_GOTPCREL, - elf.R_X86_64_GOTPCRELX, + const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel) { + .PC32, + .PLT32, + .GOTPCREL, + .GOTPCRELX, => { var insts = [_]u8{ 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index bc4f07279c..6e8e08fab1 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -541,11 +541,12 @@ const EH_PE = struct { const x86_64 = struct { fn resolveReloc(rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) void { - switch (rel.r_type()) { - elf.R_X86_64_32 => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little), - elf.R_X86_64_64 => std.mem.writeInt(i64, data[0..8], target, .little), - elf.R_X86_64_PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little), - elf.R_X86_64_PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little), + const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); + switch (r_type) { + .@"32" => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little), + .@"64" => std.mem.writeInt(i64, data[0..8], target, .little), + .PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little), + .PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little), else => unreachable, } } diff --git a/src/link/Elf/relocation.zig b/src/link/Elf/relocation.zig index 5441663948..a63187925f 100644 --- a/src/link/Elf/relocation.zig +++ b/src/link/Elf/relocation.zig @@ -11,54 +11,78 @@ pub const Kind = enum { tlsdesc, }; -const x86_64_relocs = [_]struct { Kind, u32 }{ - .{ .abs, elf.R_X86_64_64 }, - .{ .copy, elf.R_X86_64_COPY }, - .{ .rel, elf.R_X86_64_RELATIVE }, - .{ .irel, elf.R_X86_64_IRELATIVE }, - .{ .glob_dat, elf.R_X86_64_GLOB_DAT }, - .{ .jump_slot, elf.R_X86_64_JUMP_SLOT }, - .{ .dtpmod, elf.R_X86_64_DTPMOD64 }, - .{ .dtpoff, elf.R_X86_64_DTPOFF64 }, - .{ .tpoff, elf.R_X86_64_TPOFF64 }, - .{ .tlsdesc, elf.R_X86_64_TLSDESC }, -}; +fn Table(comptime len: comptime_int, comptime RelType: type, comptime mapping: [len]struct { Kind, RelType }) type { + return struct { + fn decode(r_type: u32) ?Kind { + inline for (mapping) |entry| { + if (@intFromEnum(entry[1]) == r_type) return entry[0]; + } + return null; + } -const aarch64_relocs = [_]struct { Kind, u32 }{ - .{ .abs, elf.R_AARCH64_ABS64 }, - .{ .copy, elf.R_AARCH64_COPY }, - .{ .rel, elf.R_AARCH64_RELATIVE }, - .{ .irel, elf.R_AARCH64_IRELATIVE }, - .{ .glob_dat, elf.R_AARCH64_GLOB_DAT }, - .{ .jump_slot, elf.R_AARCH64_JUMP_SLOT }, - .{ .dtpmod, elf.R_AARCH64_TLS_DTPMOD }, - .{ .dtpoff, elf.R_AARCH64_TLS_DTPREL }, - .{ .tpoff, elf.R_AARCH64_TLS_TPREL }, - .{ .tlsdesc, elf.R_AARCH64_TLSDESC }, -}; + fn encode(comptime kind: Kind) u32 { + inline for (mapping) |entry| { + if (entry[0] == kind) return @intFromEnum(entry[1]); + } + unreachable; + } + }; +} + +const x86_64_relocs = Table(10, elf.R_X86_64, .{ + .{ .abs, .@"64" }, + .{ .copy, .COPY }, + .{ .rel, .RELATIVE }, + .{ .irel, .IRELATIVE }, + .{ .glob_dat, .GLOB_DAT }, + .{ .jump_slot, .JUMP_SLOT }, + .{ .dtpmod, .DTPMOD64 }, + .{ .dtpoff, .DTPOFF64 }, + .{ .tpoff, .TPOFF64 }, + .{ .tlsdesc, .TLSDESC }, +}); + +const aarch64_relocs = Table(10, elf.R_AARCH64, .{ + .{ .abs, .ABS64 }, + .{ .copy, .COPY }, + .{ .rel, .RELATIVE }, + .{ .irel, .IRELATIVE }, + .{ .glob_dat, .GLOB_DAT }, + .{ .jump_slot, .JUMP_SLOT }, + .{ .dtpmod, .TLS_DTPMOD }, + .{ .dtpoff, .TLS_DTPREL }, + .{ .tpoff, .TLS_TPREL }, + .{ .tlsdesc, .TLSDESC }, +}); + +const riscv64_relocs = Table(9, elf.R_RISCV, .{ + .{ .abs, .@"64" }, + .{ .copy, .COPY }, + .{ .rel, .RELATIVE }, + .{ .irel, .IRELATIVE }, + .{ .jump_slot, .JUMP_SLOT }, + .{ .dtpmod, .TLS_DTPMOD64 }, + .{ .dtpoff, .TLS_DTPREL64 }, + .{ .tpoff, .TLS_TPREL64 }, + .{ .tlsdesc, .TLSDESC }, +}); pub fn decode(r_type: u32, cpu_arch: std.Target.Cpu.Arch) ?Kind { - const relocs = switch (cpu_arch) { - .x86_64 => &x86_64_relocs, - .aarch64 => &aarch64_relocs, + return switch (cpu_arch) { + .x86_64 => x86_64_relocs.decode(r_type), + .aarch64 => aarch64_relocs.decode(r_type), + .riscv64 => riscv64_relocs.decode(r_type), else => @panic("TODO unhandled cpu arch"), }; - inline for (relocs) |entry| { - if (entry[1] == r_type) return entry[0]; - } - return null; } pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 { - const relocs = switch (cpu_arch) { - .x86_64 => &x86_64_relocs, - .aarch64 => &aarch64_relocs, + return switch (cpu_arch) { + .x86_64 => x86_64_relocs.encode(kind), + .aarch64 => aarch64_relocs.encode(kind), + .riscv64 => riscv64_relocs.encode(kind), else => @panic("TODO unhandled cpu arch"), }; - inline for (relocs) |entry| { - if (entry[0] == kind) return entry[1]; - } - unreachable; } const FormatRelocTypeCtx = struct { @@ -82,183 +106,20 @@ fn formatRelocType( _ = unused_fmt_string; _ = options; const r_type = ctx.r_type; - const str = switch (ctx.cpu_arch) { - .x86_64 => switch (r_type) { - elf.R_X86_64_NONE => "R_X86_64_NONE", - elf.R_X86_64_64 => "R_X86_64_64", - elf.R_X86_64_PC32 => "R_X86_64_PC32", - elf.R_X86_64_GOT32 => "R_X86_64_GOT32", - elf.R_X86_64_PLT32 => "R_X86_64_PLT32", - elf.R_X86_64_COPY => "R_X86_64_COPY", - elf.R_X86_64_GLOB_DAT => "R_X86_64_GLOB_DAT", - elf.R_X86_64_JUMP_SLOT => "R_X86_64_JUMP_SLOT", - elf.R_X86_64_RELATIVE => "R_X86_64_RELATIVE", - elf.R_X86_64_GOTPCREL => "R_X86_64_GOTPCREL", - elf.R_X86_64_32 => "R_X86_64_32", - elf.R_X86_64_32S => "R_X86_64_32S", - elf.R_X86_64_16 => "R_X86_64_16", - elf.R_X86_64_PC16 => "R_X86_64_PC16", - elf.R_X86_64_8 => "R_X86_64_8", - elf.R_X86_64_PC8 => "R_X86_64_PC8", - elf.R_X86_64_DTPMOD64 => "R_X86_64_DTPMOD64", - elf.R_X86_64_DTPOFF64 => "R_X86_64_DTPOFF64", - elf.R_X86_64_TPOFF64 => "R_X86_64_TPOFF64", - elf.R_X86_64_TLSGD => "R_X86_64_TLSGD", - elf.R_X86_64_TLSLD => "R_X86_64_TLSLD", - elf.R_X86_64_DTPOFF32 => "R_X86_64_DTPOFF32", - elf.R_X86_64_GOTTPOFF => "R_X86_64_GOTTPOFF", - elf.R_X86_64_TPOFF32 => "R_X86_64_TPOFF32", - elf.R_X86_64_PC64 => "R_X86_64_PC64", - elf.R_X86_64_GOTOFF64 => "R_X86_64_GOTOFF64", - elf.R_X86_64_GOTPC32 => "R_X86_64_GOTPC32", - elf.R_X86_64_GOT64 => "R_X86_64_GOT64", - elf.R_X86_64_GOTPCREL64 => "R_X86_64_GOTPCREL64", - elf.R_X86_64_GOTPC64 => "R_X86_64_GOTPC64", - elf.R_X86_64_GOTPLT64 => "R_X86_64_GOTPLT64", - elf.R_X86_64_PLTOFF64 => "R_X86_64_PLTOFF64", - elf.R_X86_64_SIZE32 => "R_X86_64_SIZE32", - elf.R_X86_64_SIZE64 => "R_X86_64_SIZE64", - elf.R_X86_64_GOTPC32_TLSDESC => "R_X86_64_GOTPC32_TLSDESC", - elf.R_X86_64_TLSDESC_CALL => "R_X86_64_TLSDESC_CALL", - elf.R_X86_64_TLSDESC => "R_X86_64_TLSDESC", - elf.R_X86_64_IRELATIVE => "R_X86_64_IRELATIVE", - elf.R_X86_64_RELATIVE64 => "R_X86_64_RELATIVE64", - elf.R_X86_64_GOTPCRELX => "R_X86_64_GOTPCRELX", - elf.R_X86_64_REX_GOTPCRELX => "R_X86_64_REX_GOTPCRELX", - elf.R_X86_64_NUM => "R_X86_64_NUM", - else => "R_X86_64_UNKNOWN", - }, - .aarch64 => switch (r_type) { - elf.R_AARCH64_NONE => "R_AARCH64_NONE", - elf.R_AARCH64_ABS64 => "R_AARCH64_ABS64", - elf.R_AARCH64_ABS32 => "R_AARCH64_ABS32", - elf.R_AARCH64_ABS16 => "R_AARCH64_ABS16", - elf.R_AARCH64_PREL64 => "R_AARCH64_PREL64", - elf.R_AARCH64_PREL32 => "R_AARCH64_PREL32", - elf.R_AARCH64_PREL16 => "R_AARCH64_PREL16", - elf.R_AARCH64_MOVW_UABS_G0 => "R_AARCH64_MOVW_UABS_G0", - elf.R_AARCH64_MOVW_UABS_G0_NC => "R_AARCH64_MOVW_UABS_G0_NC", - elf.R_AARCH64_MOVW_UABS_G1 => "R_AARCH64_MOVW_UABS_G1", - elf.R_AARCH64_MOVW_UABS_G1_NC => "R_AARCH64_MOVW_UABS_G1_NC", - elf.R_AARCH64_MOVW_UABS_G2 => "R_AARCH64_MOVW_UABS_G2", - elf.R_AARCH64_MOVW_UABS_G2_NC => "R_AARCH64_MOVW_UABS_G2_NC", - elf.R_AARCH64_MOVW_UABS_G3 => "R_AARCH64_MOVW_UABS_G3", - elf.R_AARCH64_MOVW_SABS_G0 => "R_AARCH64_MOVW_SABS_G0", - elf.R_AARCH64_MOVW_SABS_G1 => "R_AARCH64_MOVW_SABS_G1", - elf.R_AARCH64_MOVW_SABS_G2 => "R_AARCH64_MOVW_SABS_G2", - elf.R_AARCH64_LD_PREL_LO19 => "R_AARCH64_LD_PREL_LO19", - elf.R_AARCH64_ADR_PREL_LO21 => "R_AARCH64_ADR_PREL_LO21", - elf.R_AARCH64_ADR_PREL_PG_HI21 => "R_AARCH64_ADR_PREL_PG_HI21", - elf.R_AARCH64_ADR_PREL_PG_HI21_NC => "R_AARCH64_ADR_PREL_PG_HI21_NC", - elf.R_AARCH64_ADD_ABS_LO12_NC => "R_AARCH64_ADD_ABS_LO12_NC", - elf.R_AARCH64_LDST8_ABS_LO12_NC => "R_AARCH64_LDST8_ABS_LO12_NC", - elf.R_AARCH64_TSTBR14 => "R_AARCH64_TSTBR14", - elf.R_AARCH64_CONDBR19 => "R_AARCH64_CONDBR19", - elf.R_AARCH64_JUMP26 => "R_AARCH64_JUMP26", - elf.R_AARCH64_CALL26 => "R_AARCH64_CALL26", - elf.R_AARCH64_LDST16_ABS_LO12_NC => "R_AARCH64_LDST16_ABS_LO12_NC", - elf.R_AARCH64_LDST32_ABS_LO12_NC => "R_AARCH64_LDST32_ABS_LO12_NC", - elf.R_AARCH64_LDST64_ABS_LO12_NC => "R_AARCH64_LDST64_ABS_LO12_NC", - elf.R_AARCH64_MOVW_PREL_G0 => "R_AARCH64_MOVW_PREL_G0", - elf.R_AARCH64_MOVW_PREL_G0_NC => "R_AARCH64_MOVW_PREL_G0_NC", - elf.R_AARCH64_MOVW_PREL_G1 => "R_AARCH64_MOVW_PREL_G1", - elf.R_AARCH64_MOVW_PREL_G1_NC => "R_AARCH64_MOVW_PREL_G1_NC", - elf.R_AARCH64_MOVW_PREL_G2 => "R_AARCH64_MOVW_PREL_G2", - elf.R_AARCH64_MOVW_PREL_G2_NC => "R_AARCH64_MOVW_PREL_G2_NC", - elf.R_AARCH64_MOVW_PREL_G3 => "R_AARCH64_MOVW_PREL_G3", - elf.R_AARCH64_LDST128_ABS_LO12_NC => "R_AARCH64_LDST128_ABS_LO12_NC", - elf.R_AARCH64_MOVW_GOTOFF_G0 => "R_AARCH64_MOVW_GOTOFF_G0", - elf.R_AARCH64_MOVW_GOTOFF_G0_NC => "R_AARCH64_MOVW_GOTOFF_G0_NC", - elf.R_AARCH64_MOVW_GOTOFF_G1 => "R_AARCH64_MOVW_GOTOFF_G1", - elf.R_AARCH64_MOVW_GOTOFF_G1_NC => "R_AARCH64_MOVW_GOTOFF_G1_NC", - elf.R_AARCH64_MOVW_GOTOFF_G2 => "R_AARCH64_MOVW_GOTOFF_G2", - elf.R_AARCH64_MOVW_GOTOFF_G2_NC => "R_AARCH64_MOVW_GOTOFF_G2_NC", - elf.R_AARCH64_MOVW_GOTOFF_G3 => "R_AARCH64_MOVW_GOTOFF_G3", - elf.R_AARCH64_GOTREL64 => "R_AARCH64_GOTREL64", - elf.R_AARCH64_GOTREL32 => "R_AARCH64_GOTREL32", - elf.R_AARCH64_GOT_LD_PREL19 => "R_AARCH64_GOT_LD_PREL19", - elf.R_AARCH64_LD64_GOTOFF_LO15 => "R_AARCH64_LD64_GOTOFF_LO15", - elf.R_AARCH64_ADR_GOT_PAGE => "R_AARCH64_ADR_GOT_PAGE", - elf.R_AARCH64_LD64_GOT_LO12_NC => "R_AARCH64_LD64_GOT_LO12_NC", - elf.R_AARCH64_LD64_GOTPAGE_LO15 => "R_AARCH64_LD64_GOTPAGE_LO15", - elf.R_AARCH64_TLSGD_ADR_PREL21 => "R_AARCH64_TLSGD_ADR_PREL21", - elf.R_AARCH64_TLSGD_ADR_PAGE21 => "R_AARCH64_TLSGD_ADR_PAGE21", - elf.R_AARCH64_TLSGD_ADD_LO12_NC => "R_AARCH64_TLSGD_ADD_LO12_NC", - elf.R_AARCH64_TLSGD_MOVW_G1 => "R_AARCH64_TLSGD_MOVW_G1", - elf.R_AARCH64_TLSGD_MOVW_G0_NC => "R_AARCH64_TLSGD_MOVW_G0_NC", - elf.R_AARCH64_TLSLD_ADR_PREL21 => "R_AARCH64_TLSLD_ADR_PREL21", - elf.R_AARCH64_TLSLD_ADR_PAGE21 => "R_AARCH64_TLSLD_ADR_PAGE21", - elf.R_AARCH64_TLSLD_ADD_LO12_NC => "R_AARCH64_TLSLD_ADD_LO12_NC", - elf.R_AARCH64_TLSLD_MOVW_G1 => "R_AARCH64_TLSLD_MOVW_G1", - elf.R_AARCH64_TLSLD_MOVW_G0_NC => "R_AARCH64_TLSLD_MOVW_G0_NC", - elf.R_AARCH64_TLSLD_LD_PREL19 => "R_AARCH64_TLSLD_LD_PREL19", - elf.R_AARCH64_TLSLD_MOVW_DTPREL_G2 => "R_AARCH64_TLSLD_MOVW_DTPREL_G2", - elf.R_AARCH64_TLSLD_MOVW_DTPREL_G1 => "R_AARCH64_TLSLD_MOVW_DTPREL_G1", - elf.R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC => "R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC", - elf.R_AARCH64_TLSLD_MOVW_DTPREL_G0 => "R_AARCH64_TLSLD_MOVW_DTPREL_G0", - elf.R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC => "R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC", - elf.R_AARCH64_TLSLD_ADD_DTPREL_HI12 => "R_AARCH64_TLSLD_ADD_DTPREL_HI12", - elf.R_AARCH64_TLSLD_ADD_DTPREL_LO12 => "R_AARCH64_TLSLD_ADD_DTPREL_LO12", - elf.R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC => "R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC", - elf.R_AARCH64_TLSLD_LDST8_DTPREL_LO12 => "R_AARCH64_TLSLD_LDST8_DTPREL_LO12", - elf.R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC => "R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC", - elf.R_AARCH64_TLSLD_LDST16_DTPREL_LO12 => "R_AARCH64_TLSLD_LDST16_DTPREL_LO12", - elf.R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC => "R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC", - elf.R_AARCH64_TLSLD_LDST32_DTPREL_LO12 => "R_AARCH64_TLSLD_LDST32_DTPREL_LO12", - elf.R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC => "R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC", - elf.R_AARCH64_TLSLD_LDST64_DTPREL_LO12 => "R_AARCH64_TLSLD_LDST64_DTPREL_LO12", - elf.R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC => "R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC", - elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 => "R_AARCH64_TLSIE_MOVW_GOTTPREL_G1", - elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC => "R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC", - elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 => "R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21", - elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC => "R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", - elf.R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 => "R_AARCH64_TLSIE_LD_GOTTPREL_PREL19", - elf.R_AARCH64_TLSLE_MOVW_TPREL_G2 => "R_AARCH64_TLSLE_MOVW_TPREL_G2", - elf.R_AARCH64_TLSLE_MOVW_TPREL_G1 => "R_AARCH64_TLSLE_MOVW_TPREL_G1", - elf.R_AARCH64_TLSLE_MOVW_TPREL_G1_NC => "R_AARCH64_TLSLE_MOVW_TPREL_G1_NC", - elf.R_AARCH64_TLSLE_MOVW_TPREL_G0 => "R_AARCH64_TLSLE_MOVW_TPREL_G0", - elf.R_AARCH64_TLSLE_MOVW_TPREL_G0_NC => "R_AARCH64_TLSLE_MOVW_TPREL_G0_NC", - elf.R_AARCH64_TLSLE_ADD_TPREL_HI12 => "R_AARCH64_TLSLE_ADD_TPREL_HI12", - elf.R_AARCH64_TLSLE_ADD_TPREL_LO12 => "R_AARCH64_TLSLE_ADD_TPREL_LO12", - elf.R_AARCH64_TLSLE_ADD_TPREL_LO12_NC => "R_AARCH64_TLSLE_ADD_TPREL_LO12_NC", - elf.R_AARCH64_TLSLE_LDST8_TPREL_LO12 => "R_AARCH64_TLSLE_LDST8_TPREL_LO12", - elf.R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC => "R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC", - elf.R_AARCH64_TLSLE_LDST16_TPREL_LO12 => "R_AARCH64_TLSLE_LDST16_TPREL_LO12", - elf.R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC => "R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC", - elf.R_AARCH64_TLSLE_LDST32_TPREL_LO12 => "R_AARCH64_TLSLE_LDST32_TPREL_LO12", - elf.R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC => "R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC", - elf.R_AARCH64_TLSLE_LDST64_TPREL_LO12 => "R_AARCH64_TLSLE_LDST64_TPREL_LO12", - elf.R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC => "R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC", - elf.R_AARCH64_TLSDESC_LD_PREL19 => "R_AARCH64_TLSDESC_LD_PREL19", - elf.R_AARCH64_TLSDESC_ADR_PREL21 => "R_AARCH64_TLSDESC_ADR_PREL21", - elf.R_AARCH64_TLSDESC_ADR_PAGE21 => "R_AARCH64_TLSDESC_ADR_PAGE21", - elf.R_AARCH64_TLSDESC_LD64_LO12 => "R_AARCH64_TLSDESC_LD64_LO12", - elf.R_AARCH64_TLSDESC_ADD_LO12 => "R_AARCH64_TLSDESC_ADD_LO12", - elf.R_AARCH64_TLSDESC_OFF_G1 => "R_AARCH64_TLSDESC_OFF_G1", - elf.R_AARCH64_TLSDESC_OFF_G0_NC => "R_AARCH64_TLSDESC_OFF_G0_NC", - elf.R_AARCH64_TLSDESC_LDR => "R_AARCH64_TLSDESC_LDR", - elf.R_AARCH64_TLSDESC_ADD => "R_AARCH64_TLSDESC_ADD", - elf.R_AARCH64_TLSDESC_CALL => "R_AARCH64_TLSDESC_CALL", - elf.R_AARCH64_TLSLE_LDST128_TPREL_LO12 => "R_AARCH64_TLSLE_LDST128_TPREL_LO12", - elf.R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC => "R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC", - elf.R_AARCH64_TLSLD_LDST128_DTPREL_LO12 => "R_AARCH64_TLSLD_LDST128_DTPREL_LO12", - elf.R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC => "R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC", - elf.R_AARCH64_COPY => "R_AARCH64_COPY", - elf.R_AARCH64_GLOB_DAT => "R_AARCH64_GLOB_DAT", - elf.R_AARCH64_JUMP_SLOT => "R_AARCH64_JUMP_SLOT", - elf.R_AARCH64_RELATIVE => "R_AARCH64_RELATIVE", - elf.R_AARCH64_TLS_DTPMOD => "R_AARCH64_TLS_DTPMOD", - elf.R_AARCH64_TLS_DTPREL => "R_AARCH64_TLS_DTPREL", - elf.R_AARCH64_TLS_TPREL => "R_AARCH64_TLS_TPREL", - elf.R_AARCH64_TLSDESC => "R_AARCH64_TLSDESC", - elf.R_AARCH64_IRELATIVE => "R_AARCH64_IRELATIVE", - else => "R_AARCH64_UNKNOWN", + switch (r_type) { + Elf.R_ZIG_GOT32 => try writer.writeAll("R_ZIG_GOT32"), + Elf.R_ZIG_GOTPCREL => try writer.writeAll("R_ZIG_GOTPCREL"), + else => switch (ctx.cpu_arch) { + .x86_64 => try writer.print("R_X86_64_{s}", .{@tagName(@as(elf.R_X86_64, @enumFromInt(r_type)))}), + .aarch64 => try writer.print("R_AARCH64_{s}", .{@tagName(@as(elf.R_AARCH64, @enumFromInt(r_type)))}), + .riscv64 => try writer.print("R_RISCV_{s}", .{@tagName(@as(elf.R_RISCV, @enumFromInt(r_type)))}), + else => unreachable, }, - else => unreachable, - }; - try writer.print("{s}", .{str}); + } } const assert = std.debug.assert; const elf = std.elf; const std = @import("std"); + +const Elf = @import("../Elf.zig"); |
