diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-17 11:29:06 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-17 11:29:06 +0100 |
| commit | 975862aca9a68f1d6fa786b6cef19bcc7b1aec2a (patch) | |
| tree | bd0c4783671214faa562fd29956ff00bae8b3e5b /src/link/Elf | |
| parent | 601aa10b82a43a9d566e8de3cb784929185411b4 (diff) | |
| download | zig-975862aca9a68f1d6fa786b6cef19bcc7b1aec2a.tar.gz zig-975862aca9a68f1d6fa786b6cef19bcc7b1aec2a.zip | |
elf: add riscv dynamic relocs
Diffstat (limited to 'src/link/Elf')
| -rw-r--r-- | src/link/Elf/Atom.zig | 221 | ||||
| -rw-r--r-- | src/link/Elf/eh_frame.zig | 11 | ||||
| -rw-r--r-- | src/link/Elf/relocation.zig | 53 |
3 files changed, 154 insertions, 131 deletions
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 72e7e6bcc0..debdb22ad8 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -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 == .R_X86_64_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 == .R_X86_64_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) { + .R_X86_64_64 => { try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); }, - elf.R_X86_64_32, - elf.R_X86_64_32S, + .R_X86_64_32, + .R_X86_64_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, + .R_X86_64_GOT32, + .R_X86_64_GOTPC32, + .R_X86_64_GOTPC64, + .R_X86_64_GOTPCREL, + .R_X86_64_GOTPCREL64, + .R_X86_64_GOTPCRELX, + .R_X86_64_REX_GOTPCRELX, => { symbol.flags.needs_got = true; }, - elf.R_X86_64_PLT32, - elf.R_X86_64_PLTOFF64, + .R_X86_64_PLT32, + .R_X86_64_PLTOFF64, => { if (symbol.flags.import) { symbol.flags.needs_plt = true; } }, - elf.R_X86_64_PC32 => { + .R_X86_64_PC32 => { try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file); }, - elf.R_X86_64_TLSGD => { + .R_X86_64_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 => { + .R_X86_64_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 => { + .R_X86_64_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 => { + .R_X86_64_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, + .R_X86_64_TPOFF32, + .R_X86_64_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, + .R_X86_64_GOTOFF64, + .R_X86_64_DTPOFF32, + .R_X86_64_DTPOFF64, + .R_X86_64_SIZE32, + .R_X86_64_SIZE64, + .R_X86_64_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_X86_64_ZIG_GOT32, + Elf.R_X86_64_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 == .R_X86_64_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), + @tagName(r_type), 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) { + .R_X86_64_NONE => unreachable, - elf.R_X86_64_64 => { + .R_X86_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, + .R_X86_64_PLT32, + .R_X86_64_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), + .R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), + .R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), + .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), - elf.R_X86_64_GOTPCRELX => { + .R_X86_64_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 => { + .R_X86_64_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), + .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), + .R_X86_64_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), + .R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), + .R_X86_64_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), + .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), + .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), - elf.R_X86_64_TLSGD => { + .R_X86_64_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 => { + .R_X86_64_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 => { + .R_X86_64_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) { + .R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) { // call -> nop try cwriter.writeAll(&.{ 0x66, 0x90 }); }, - elf.R_X86_64_GOTTPOFF => { + .R_X86_64_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), + .R_X86_64_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_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 => {}, + 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 == .R_X86_64_NONE) continue; const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; @@ -1211,7 +1219,7 @@ const x86_64 = struct { const DTP = @as(i64, @intCast(elf_file.dtpAddress())); relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{ - relocation.fmtRelocType(r_type, .x86_64), + @tagName(r_type), 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 => { + .R_X86_64_NONE => unreachable, + .R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), + .R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), + .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), + .R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), + .R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little), + .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), + .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), + .R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), + .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), + .R_X86_64_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 => { + .R_X86_64_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,11 @@ 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_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); + const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel_1) { + .R_X86_64_PC32, + .R_X86_64_PLT32, => { var insts = [_]u8{ 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax @@ -1298,9 +1308,9 @@ const x86_64 = struct { else => { var err = try elf_file.addErrorWithNotes(1); - try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ - relocation.fmtRelocType(rels[0].r_type(), .x86_64), - relocation.fmtRelocType(rels[1].r_type(), .x86_64), + try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ + @tagName(rel_0), + @tagName(rel_1), }); try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ self.file(elf_file).?.fmtPath(), @@ -1320,9 +1330,11 @@ 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_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); + const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel_1) { + .R_X86_64_PC32, + .R_X86_64_PLT32, => { var insts = [_]u8{ 0x31, 0xc0, // xor %eax, %eax @@ -1334,8 +1346,8 @@ const x86_64 = struct { try writer.writeAll(&insts); }, - elf.R_X86_64_GOTPCREL, - elf.R_X86_64_GOTPCRELX, + .R_X86_64_GOTPCREL, + .R_X86_64_GOTPCRELX, => { var insts = [_]u8{ 0x31, 0xc0, // xor %eax, %eax @@ -1350,9 +1362,9 @@ const x86_64 = struct { else => { var err = try elf_file.addErrorWithNotes(1); - try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ - relocation.fmtRelocType(rels[0].r_type(), .x86_64), - relocation.fmtRelocType(rels[1].r_type(), .x86_64), + try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ + @tagName(rel_0), + @tagName(rel_1), }); try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ self.file(elf_file).?.fmtPath(), @@ -1419,11 +1431,13 @@ 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_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type()); + const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); + switch (rel_1) { + .R_X86_64_PC32, + .R_X86_64_PLT32, + .R_X86_64_GOTPCREL, + .R_X86_64_GOTPCRELX, => { var insts = [_]u8{ 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax @@ -1432,17 +1446,14 @@ const x86_64 = struct { std.mem.writeInt(i32, insts[12..][0..4], value, .little); try stream.seekBy(-4); try writer.writeAll(&insts); - relocs_log.debug(" relaxing {} and {}", .{ - relocation.fmtRelocType(rels[0].r_type(), .x86_64), - relocation.fmtRelocType(rels[1].r_type(), .x86_64), - }); + relocs_log.debug(" relaxing {s} and {s}", .{ @tagName(rel_0), @tagName(rel_1) }); }, else => { var err = try elf_file.addErrorWithNotes(1); - try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{ - relocation.fmtRelocType(rels[0].r_type(), .x86_64), - relocation.fmtRelocType(rels[1].r_type(), .x86_64), + try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{ + @tagName(rel_0), + @tagName(rel_1), }); try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ self.file(elf_file).?.fmtPath(), diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index bc4f07279c..3aa1da94ca 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) { + .R_X86_64_32 => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little), + .R_X86_64_64 => std.mem.writeInt(i64, data[0..8], target, .little), + .R_X86_64_PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little), + .R_X86_64_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 4cfdd031e1..10a7d25871 100644 --- a/src/link/Elf/relocation.zig +++ b/src/link/Elf/relocation.zig @@ -11,7 +11,25 @@ pub const Kind = enum { tlsdesc, }; -const x86_64_relocs = [_]struct { Kind, elf.R_X86_64 }{ +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; + } + + 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, .R_X86_64_64 }, .{ .copy, .R_X86_64_COPY }, .{ .rel, .R_X86_64_RELATIVE }, @@ -22,9 +40,9 @@ const x86_64_relocs = [_]struct { Kind, elf.R_X86_64 }{ .{ .dtpoff, .R_X86_64_DTPOFF64 }, .{ .tpoff, .R_X86_64_TPOFF64 }, .{ .tlsdesc, .R_X86_64_TLSDESC }, -}; +}); -const aarch64_relocs = [_]struct { Kind, elf.R_AARCH64 }{ +const aarch64_relocs = Table(10, elf.R_AARCH64, .{ .{ .abs, .R_AARCH64_ABS64 }, .{ .copy, .R_AARCH64_COPY }, .{ .rel, .R_AARCH64_RELATIVE }, @@ -35,9 +53,9 @@ const aarch64_relocs = [_]struct { Kind, elf.R_AARCH64 }{ .{ .dtpoff, .R_AARCH64_TLS_DTPREL }, .{ .tpoff, .R_AARCH64_TLS_TPREL }, .{ .tlsdesc, .R_AARCH64_TLSDESC }, -}; +}); -const riscv64_relocs = [_]struct { Kind, elf.R_RISCV }{ +const riscv64_relocs = Table(8, elf.R_RISCV, .{ .{ .abs, .R_RISCV_64 }, .{ .copy, .R_RISCV_COPY }, .{ .rel, .R_RISCV_RELATIVE }, @@ -46,31 +64,24 @@ const riscv64_relocs = [_]struct { Kind, elf.R_RISCV }{ .{ .dtpmod, .R_RISCV_TLS_DTPMOD64 }, .{ .dtpoff, .R_RISCV_TLS_DTPREL64 }, .{ .tpoff, .R_RISCV_TLS_TPREL64 }, - .{ .tpoff, .R_RISCV_TLS_TPREL64 }, -}; +}); 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 { |
