authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-17 11:29:06+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-17 11:29:06+01:00
log975862aca9a68f1d6fa786b6cef19bcc7b1aec2a
treebd0c4783671214faa562fd29956ff00bae8b3e5b
parent601aa10b82a43a9d566e8de3cb784929185411b4

elf: add riscv dynamic relocs


6 files changed, 172 insertions(+), 142 deletions(-)

lib/std/elf.zig+3
...@@ -1891,6 +1891,7 @@ pub const R_X86_64 = enum(u32) {...@@ -1891,6 +1891,7 @@ pub const R_X86_64 = enum(u32) {
1891 R_X86_64_GOTPCRELX = 41,1891 R_X86_64_GOTPCRELX = 41,
1892 /// Load from 32 bit signed PC relative offset to GOT entry with REX prefix, relaxable1892 /// Load from 32 bit signed PC relative offset to GOT entry with REX prefix, relaxable
1893 R_X86_64_REX_GOTPCRELX = 42,1893 R_X86_64_REX_GOTPCRELX = 42,
1894 _,
1894};1895};
18951896
1896/// AArch64 relocs.1897/// AArch64 relocs.
...@@ -2163,6 +2164,7 @@ pub const R_AARCH64 = enum(u32) {...@@ -2163,6 +2164,7 @@ pub const R_AARCH64 = enum(u32) {
2163 R_AARCH64_TLSDESC = 1031,2164 R_AARCH64_TLSDESC = 1031,
2164 /// STT_GNU_IFUNC relocation.2165 /// STT_GNU_IFUNC relocation.
2165 R_AARCH64_IRELATIVE = 1032,2166 R_AARCH64_IRELATIVE = 1032,
2167 _,
2166};2168};
21672169
2168/// RISC-V relocations.2170/// RISC-V relocations.
...@@ -2225,6 +2227,7 @@ pub const R_RISCV = enum(u32) {...@@ -2225,6 +2227,7 @@ pub const R_RISCV = enum(u32) {
2225 R_RISCV_PLT32 = 59,2227 R_RISCV_PLT32 = 59,
2226 R_RISCV_SET_ULEB128 = 60,2228 R_RISCV_SET_ULEB128 = 60,
2227 R_RISCV_SUB_ULEB128 = 61,2229 R_RISCV_SUB_ULEB128 = 61,
2230 _,
2228};2231};
22292232
2230pub const STV = enum(u2) {2233pub const STV = enum(u2) {
src/arch/x86_64/Emit.zig+13-9
...@@ -43,9 +43,10 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -43,9 +43,10 @@ pub fn emitMir(emit: *Emit) Error!void {
43 .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {43 .linker_extern_fn => |symbol| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
44 // Add relocation to the decl.44 // Add relocation to the decl.
45 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;45 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
46 const r_type = @intFromEnum(std.elf.R_X86_64.R_X86_64_PLT32);
46 try atom_ptr.addReloc(elf_file, .{47 try atom_ptr.addReloc(elf_file, .{
47 .r_offset = end_offset - 4,48 .r_offset = end_offset - 4,
48 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | std.elf.R_X86_64_PLT32,49 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
49 .r_addend = -4,50 .r_addend = -4,
50 });51 });
51 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {52 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
...@@ -88,18 +89,20 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -88,18 +89,20 @@ pub fn emitMir(emit: *Emit) Error!void {
88 .linker_tlsld => |data| {89 .linker_tlsld => |data| {
89 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;90 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
90 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;91 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
92 const r_type = @intFromEnum(std.elf.R_X86_64.R_X86_64_TLSLD);
91 try atom.addReloc(elf_file, .{93 try atom.addReloc(elf_file, .{
92 .r_offset = end_offset - 4,94 .r_offset = end_offset - 4,
93 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_TLSLD,95 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
94 .r_addend = -4,96 .r_addend = -4,
95 });97 });
96 },98 },
97 .linker_dtpoff => |data| {99 .linker_dtpoff => |data| {
98 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;100 const elf_file = emit.lower.bin_file.cast(link.File.Elf).?;
99 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;101 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
102 const r_type = @intFromEnum(std.elf.R_X86_64.R_X86_64_DTPOFF32);
100 try atom.addReloc(elf_file, .{103 try atom.addReloc(elf_file, .{
101 .r_offset = end_offset - 4,104 .r_offset = end_offset - 4,
102 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_DTPOFF32,105 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
103 .r_addend = 0,106 .r_addend = 0,
104 });107 });
105 },108 },
...@@ -119,9 +122,9 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -119,9 +122,9 @@ pub fn emitMir(emit: *Emit) Error!void {
119 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)122 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
120 link.File.Elf.R_X86_64_ZIG_GOTPCREL123 link.File.Elf.R_X86_64_ZIG_GOTPCREL
121 else if (sym.flags.needs_got)124 else if (sym.flags.needs_got)
122 std.elf.R_X86_64_GOTPCREL125 @intFromEnum(std.elf.R_X86_64.R_X86_64_GOTPCREL)
123 else126 else
124 std.elf.R_X86_64_PC32;127 @intFromEnum(std.elf.R_X86_64.R_X86_64_PC32);
125 try atom.addReloc(elf_file, .{128 try atom.addReloc(elf_file, .{
126 .r_offset = end_offset - 4,129 .r_offset = end_offset - 4,
127 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,130 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
...@@ -129,20 +132,21 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -129,20 +132,21 @@ pub fn emitMir(emit: *Emit) Error!void {
129 });132 });
130 } else {133 } else {
131 if (lowered_inst.encoding.mnemonic == .call and sym.flags.needs_zig_got and is_obj_or_static_lib) {134 if (lowered_inst.encoding.mnemonic == .call and sym.flags.needs_zig_got and is_obj_or_static_lib) {
135 const r_type = @intFromEnum(std.elf.R_X86_64.R_X86_64_PC32);
132 try atom.addReloc(elf_file, .{136 try atom.addReloc(elf_file, .{
133 .r_offset = end_offset - 4,137 .r_offset = end_offset - 4,
134 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | std.elf.R_X86_64_PC32,138 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
135 .r_addend = -4,139 .r_addend = -4,
136 });140 });
137 } else {141 } else {
138 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)142 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
139 link.File.Elf.R_X86_64_ZIG_GOT32143 link.File.Elf.R_X86_64_ZIG_GOT32
140 else if (sym.flags.needs_got)144 else if (sym.flags.needs_got)
141 std.elf.R_X86_64_GOT32145 @intFromEnum(std.elf.R_X86_64.R_X86_64_GOT32)
142 else if (sym.flags.is_tls)146 else if (sym.flags.is_tls)
143 std.elf.R_X86_64_TPOFF32147 @intFromEnum(std.elf.R_X86_64.R_X86_64_TPOFF32)
144 else148 else
145 std.elf.R_X86_64_32;149 @intFromEnum(std.elf.R_X86_64.R_X86_64_32);
146 try atom.addReloc(elf_file, .{150 try atom.addReloc(elf_file, .{
147 .r_offset = end_offset - 4,151 .r_offset = end_offset - 4,
148 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,152 .r_info = (@as(u64, @intCast(data.sym_index)) << 32) | r_type,
src/link/Elf.zig+2-2
...@@ -6065,8 +6065,8 @@ const RelaSection = struct {...@@ -6065,8 +6065,8 @@ const RelaSection = struct {
6065};6065};
6066const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);6066const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
60676067
6068pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1;6068pub const R_X86_64_ZIG_GOT32: u32 = 0xff00;
6069pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2;6069pub const R_X86_64_ZIG_GOTPCREL: u32 = 0xff01;
60706070
6071fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {6071fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 {
6072 return switch (cpu_arch) {6072 return switch (cpu_arch) {
src/link/Elf/Atom.zig+116-105
...@@ -384,7 +384,10 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {...@@ -384,7 +384,10 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {
384 const cpu_arch = elf_file.getTarget().cpu.arch;384 const cpu_arch = elf_file.getTarget().cpu.arch;
385 for (self.relocs(elf_file)) |rel| {385 for (self.relocs(elf_file)) |rel| {
386 switch (cpu_arch) {386 switch (cpu_arch) {
387 .x86_64 => if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true,387 .x86_64 => {
388 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
389 if (r_type == .R_X86_64_GOTTPOFF) return true;
390 },
388 else => {},391 else => {},
389 }392 }
390 }393 }
...@@ -836,8 +839,9 @@ const x86_64 = struct {...@@ -836,8 +839,9 @@ const x86_64 = struct {
836 var i: usize = 0;839 var i: usize = 0;
837 while (i < rels.len) : (i += 1) {840 while (i < rels.len) : (i += 1) {
838 const rel = rels[i];841 const rel = rels[i];
842 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
839843
840 if (rel.r_type() == elf.R_X86_64_NONE) continue;844 if (r_type == .R_X86_64_NONE) continue;
841845
842 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;846 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
843847
...@@ -869,41 +873,41 @@ const x86_64 = struct {...@@ -869,41 +873,41 @@ const x86_64 = struct {
869873
870 // While traversing relocations, mark symbols that require special handling such as874 // While traversing relocations, mark symbols that require special handling such as
871 // pointer indirection via GOT, or a stub trampoline via PLT.875 // pointer indirection via GOT, or a stub trampoline via PLT.
872 switch (rel.r_type()) {876 switch (r_type) {
873 elf.R_X86_64_64 => {877 .R_X86_64_64 => {
874 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);878 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
875 },879 },
876880
877 elf.R_X86_64_32,881 .R_X86_64_32,
878 elf.R_X86_64_32S,882 .R_X86_64_32S,
879 => {883 => {
880 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);884 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
881 },885 },
882886
883 elf.R_X86_64_GOT32,887 .R_X86_64_GOT32,
884 elf.R_X86_64_GOTPC32,888 .R_X86_64_GOTPC32,
885 elf.R_X86_64_GOTPC64,889 .R_X86_64_GOTPC64,
886 elf.R_X86_64_GOTPCREL,890 .R_X86_64_GOTPCREL,
887 elf.R_X86_64_GOTPCREL64,891 .R_X86_64_GOTPCREL64,
888 elf.R_X86_64_GOTPCRELX,892 .R_X86_64_GOTPCRELX,
889 elf.R_X86_64_REX_GOTPCRELX,893 .R_X86_64_REX_GOTPCRELX,
890 => {894 => {
891 symbol.flags.needs_got = true;895 symbol.flags.needs_got = true;
892 },896 },
893897
894 elf.R_X86_64_PLT32,898 .R_X86_64_PLT32,
895 elf.R_X86_64_PLTOFF64,899 .R_X86_64_PLTOFF64,
896 => {900 => {
897 if (symbol.flags.import) {901 if (symbol.flags.import) {
898 symbol.flags.needs_plt = true;902 symbol.flags.needs_plt = true;
899 }903 }
900 },904 },
901905
902 elf.R_X86_64_PC32 => {906 .R_X86_64_PC32 => {
903 try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file);907 try atom.scanReloc(symbol, rel, pcRelocAction(symbol, elf_file), elf_file);
904 },908 },
905909
906 elf.R_X86_64_TLSGD => {910 .R_X86_64_TLSGD => {
907 // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr911 // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr
908912
909 if (is_static or (!symbol.flags.import and !is_dyn_lib)) {913 if (is_static or (!symbol.flags.import and !is_dyn_lib)) {
...@@ -918,7 +922,7 @@ const x86_64 = struct {...@@ -918,7 +922,7 @@ const x86_64 = struct {
918 }922 }
919 },923 },
920924
921 elf.R_X86_64_TLSLD => {925 .R_X86_64_TLSLD => {
922 // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr926 // TODO verify followed by appropriate relocation such as PLT32 __tls_get_addr
923927
924 if (is_static or !is_dyn_lib) {928 if (is_static or !is_dyn_lib) {
...@@ -930,7 +934,7 @@ const x86_64 = struct {...@@ -930,7 +934,7 @@ const x86_64 = struct {
930 }934 }
931 },935 },
932936
933 elf.R_X86_64_GOTTPOFF => {937 .R_X86_64_GOTTPOFF => {
934 const should_relax = blk: {938 const should_relax = blk: {
935 if (is_dyn_lib or symbol.flags.import) break :blk false;939 if (is_dyn_lib or symbol.flags.import) break :blk false;
936 if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false;940 if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false;
...@@ -941,35 +945,37 @@ const x86_64 = struct {...@@ -941,35 +945,37 @@ const x86_64 = struct {
941 }945 }
942 },946 },
943947
944 elf.R_X86_64_GOTPC32_TLSDESC => {948 .R_X86_64_GOTPC32_TLSDESC => {
945 const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import);949 const should_relax = is_static or (!is_dyn_lib and !symbol.flags.import);
946 if (!should_relax) {950 if (!should_relax) {
947 symbol.flags.needs_tlsdesc = true;951 symbol.flags.needs_tlsdesc = true;
948 }952 }
949 },953 },
950954
951 elf.R_X86_64_TPOFF32,955 .R_X86_64_TPOFF32,
952 elf.R_X86_64_TPOFF64,956 .R_X86_64_TPOFF64,
953 => {957 => {
954 if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file);958 if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file);
955 },959 },
956960
957 elf.R_X86_64_GOTOFF64,961 .R_X86_64_GOTOFF64,
958 elf.R_X86_64_DTPOFF32,962 .R_X86_64_DTPOFF32,
959 elf.R_X86_64_DTPOFF64,963 .R_X86_64_DTPOFF64,
960 elf.R_X86_64_SIZE32,964 .R_X86_64_SIZE32,
961 elf.R_X86_64_SIZE64,965 .R_X86_64_SIZE64,
962 elf.R_X86_64_TLSDESC_CALL,966 .R_X86_64_TLSDESC_CALL,
963 => {},967 => {},
964968
965 // Zig custom relocations969 else => |x| switch (@intFromEnum(x)) {
966 Elf.R_X86_64_ZIG_GOT32,970 // Zig custom relocations
967 Elf.R_X86_64_ZIG_GOTPCREL,971 Elf.R_X86_64_ZIG_GOT32,
968 => {972 Elf.R_X86_64_ZIG_GOTPCREL,
969 assert(symbol.flags.has_zig_got);973 => {
970 },974 assert(symbol.flags.has_zig_got);
975 },
971976
972 else => try atom.reportUnhandledRelocError(rel, elf_file),977 else => try atom.reportUnhandledRelocError(rel, elf_file),
978 },
973 }979 }
974 }980 }
975 }981 }
...@@ -983,8 +989,8 @@ const x86_64 = struct {...@@ -983,8 +989,8 @@ const x86_64 = struct {
983 var i: usize = 0;989 var i: usize = 0;
984 while (i < rels.len) : (i += 1) {990 while (i < rels.len) : (i += 1) {
985 const rel = rels[i];991 const rel = rels[i];
986 const r_type = rel.r_type();992 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
987 if (r_type == elf.R_X86_64_NONE) continue;993 if (r_type == .R_X86_64_NONE) continue;
988994
989 const target = switch (file_ptr) {995 const target = switch (file_ptr) {
990 .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())),996 .zig_object => |x| elf_file.symbol(x.symbol(rel.r_sym())),
...@@ -1022,7 +1028,7 @@ const x86_64 = struct {...@@ -1022,7 +1028,7 @@ const x86_64 = struct {
1022 const DTP = @as(i64, @intCast(elf_file.dtpAddress()));1028 const DTP = @as(i64, @intCast(elf_file.dtpAddress()));
10231029
1024 relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{1030 relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{
1025 relocation.fmtRelocType(r_type, .x86_64),1031 @tagName(r_type),
1026 r_offset,1032 r_offset,
1027 P,1033 P,
1028 S + A,1034 S + A,
...@@ -1033,10 +1039,10 @@ const x86_64 = struct {...@@ -1033,10 +1039,10 @@ const x86_64 = struct {
10331039
1034 try stream.seekTo(r_offset);1040 try stream.seekTo(r_offset);
10351041
1036 switch (rel.r_type()) {1042 switch (r_type) {
1037 elf.R_X86_64_NONE => unreachable,1043 .R_X86_64_NONE => unreachable,
10381044
1039 elf.R_X86_64_64 => {1045 .R_X86_64_64 => {
1040 try atom.resolveDynAbsReloc(1046 try atom.resolveDynAbsReloc(
1041 target,1047 target,
1042 rel,1048 rel,
...@@ -1046,15 +1052,15 @@ const x86_64 = struct {...@@ -1046,15 +1052,15 @@ const x86_64 = struct {
1046 );1052 );
1047 },1053 },
10481054
1049 elf.R_X86_64_PLT32,1055 .R_X86_64_PLT32,
1050 elf.R_X86_64_PC32,1056 .R_X86_64_PC32,
1051 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),1057 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
10521058
1053 elf.R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),1059 .R_X86_64_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
1054 elf.R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),1060 .R_X86_64_GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
1055 elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little),1061 .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little),
10561062
1057 elf.R_X86_64_GOTPCRELX => {1063 .R_X86_64_GOTPCRELX => {
1058 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1064 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1059 x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk;1065 x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk;
1060 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1066 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
...@@ -1063,7 +1069,7 @@ const x86_64 = struct {...@@ -1063,7 +1069,7 @@ const x86_64 = struct {
1063 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);1069 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1064 },1070 },
10651071
1066 elf.R_X86_64_REX_GOTPCRELX => {1072 .R_X86_64_REX_GOTPCRELX => {
1067 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1073 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1068 x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk;1074 x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk;
1069 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1075 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
...@@ -1072,16 +1078,16 @@ const x86_64 = struct {...@@ -1072,16 +1078,16 @@ const x86_64 = struct {
1072 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);1078 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);
1073 },1079 },
10741080
1075 elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),1081 .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
1076 elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),1082 .R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),
10771083
1078 elf.R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),1084 .R_X86_64_TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),
1079 elf.R_X86_64_TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little),1085 .R_X86_64_TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little),
10801086
1081 elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little),1087 .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little),
1082 elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),1088 .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),
10831089
1084 elf.R_X86_64_TLSGD => {1090 .R_X86_64_TLSGD => {
1085 if (target.flags.has_tlsgd) {1091 if (target.flags.has_tlsgd) {
1086 const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file)));1092 const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file)));
1087 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1093 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
...@@ -1101,7 +1107,7 @@ const x86_64 = struct {...@@ -1101,7 +1107,7 @@ const x86_64 = struct {
1101 }1107 }
1102 },1108 },
11031109
1104 elf.R_X86_64_TLSLD => {1110 .R_X86_64_TLSLD => {
1105 if (elf_file.got.tlsld_index) |entry_index| {1111 if (elf_file.got.tlsld_index) |entry_index| {
1106 const tlsld_entry = elf_file.got.entries.items[entry_index];1112 const tlsld_entry = elf_file.got.entries.items[entry_index];
1107 const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file)));1113 const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file)));
...@@ -1118,7 +1124,7 @@ const x86_64 = struct {...@@ -1118,7 +1124,7 @@ const x86_64 = struct {
1118 }1124 }
1119 },1125 },
11201126
1121 elf.R_X86_64_GOTPC32_TLSDESC => {1127 .R_X86_64_GOTPC32_TLSDESC => {
1122 if (target.flags.has_tlsdesc) {1128 if (target.flags.has_tlsdesc) {
1123 const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file)));1129 const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file)));
1124 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1130 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
...@@ -1128,12 +1134,12 @@ const x86_64 = struct {...@@ -1128,12 +1134,12 @@ const x86_64 = struct {
1128 }1134 }
1129 },1135 },
11301136
1131 elf.R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) {1137 .R_X86_64_TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1132 // call -> nop1138 // call -> nop
1133 try cwriter.writeAll(&.{ 0x66, 0x90 });1139 try cwriter.writeAll(&.{ 0x66, 0x90 });
1134 },1140 },
11351141
1136 elf.R_X86_64_GOTTPOFF => {1142 .R_X86_64_GOTTPOFF => {
1137 if (target.flags.has_gottp) {1143 if (target.flags.has_gottp) {
1138 const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file)));1144 const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file)));
1139 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1145 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
...@@ -1143,13 +1149,15 @@ const x86_64 = struct {...@@ -1143,13 +1149,15 @@ const x86_64 = struct {
1143 }1149 }
1144 },1150 },
11451151
1146 elf.R_X86_64_GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little),1152 .R_X86_64_GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A)), .little),
11471153
1148 // Zig custom relocations1154 else => |x| switch (@intFromEnum(x)) {
1149 Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little),1155 // Zig custom relocations
1150 Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little),1156 Elf.R_X86_64_ZIG_GOT32 => try cwriter.writeInt(u32, @as(u32, @intCast(ZIG_GOT + A)), .little),
1157 Elf.R_X86_64_ZIG_GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(ZIG_GOT + A - P)), .little),
11511158
1152 else => {},1159 else => {},
1160 },
1153 }1161 }
1154 }1162 }
1155 }1163 }
...@@ -1163,8 +1171,8 @@ const x86_64 = struct {...@@ -1163,8 +1171,8 @@ const x86_64 = struct {
1163 var i: usize = 0;1171 var i: usize = 0;
1164 while (i < rels.len) : (i += 1) {1172 while (i < rels.len) : (i += 1) {
1165 const rel = rels[i];1173 const rel = rels[i];
1166 const r_type = rel.r_type();1174 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1167 if (r_type == elf.R_X86_64_NONE) continue;1175 if (r_type == .R_X86_64_NONE) continue;
11681176
1169 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1177 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
11701178
...@@ -1211,7 +1219,7 @@ const x86_64 = struct {...@@ -1211,7 +1219,7 @@ const x86_64 = struct {
1211 const DTP = @as(i64, @intCast(elf_file.dtpAddress()));1219 const DTP = @as(i64, @intCast(elf_file.dtpAddress()));
12121220
1213 relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{1221 relocs_log.debug(" {s}: {x}: [{x} => {x}] ({s})", .{
1214 relocation.fmtRelocType(r_type, .x86_64),1222 @tagName(r_type),
1215 rel.r_offset,1223 rel.r_offset,
1216 P,1224 P,
1217 S + A,1225 S + A,
...@@ -1221,21 +1229,21 @@ const x86_64 = struct {...@@ -1221,21 +1229,21 @@ const x86_64 = struct {
1221 try stream.seekTo(r_offset);1229 try stream.seekTo(r_offset);
12221230
1223 switch (r_type) {1231 switch (r_type) {
1224 elf.R_X86_64_NONE => unreachable,1232 .R_X86_64_NONE => unreachable,
1225 elf.R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),1233 .R_X86_64_8 => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),
1226 elf.R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),1234 .R_X86_64_16 => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),
1227 elf.R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),1235 .R_X86_64_32 => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),
1228 elf.R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1236 .R_X86_64_32S => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1229 elf.R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little),1237 .R_X86_64_64 => try cwriter.writeInt(i64, S + A, .little),
1230 elf.R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),1238 .R_X86_64_DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),
1231 elf.R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),1239 .R_X86_64_DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),
1232 elf.R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little),1240 .R_X86_64_GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little),
1233 elf.R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),1241 .R_X86_64_GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),
1234 elf.R_X86_64_SIZE32 => {1242 .R_X86_64_SIZE32 => {
1235 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1243 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1236 try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little);1244 try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(size + A)))), .little);
1237 },1245 },
1238 elf.R_X86_64_SIZE64 => {1246 .R_X86_64_SIZE64 => {
1239 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1247 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1240 try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little);1248 try cwriter.writeInt(i64, @as(i64, @intCast(size + A)), .little);
1241 },1249 },
...@@ -1283,9 +1291,11 @@ const x86_64 = struct {...@@ -1283,9 +1291,11 @@ const x86_64 = struct {
1283 ) !void {1291 ) !void {
1284 assert(rels.len == 2);1292 assert(rels.len == 2);
1285 const writer = stream.writer();1293 const writer = stream.writer();
1286 switch (rels[1].r_type()) {1294 const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type());
1287 elf.R_X86_64_PC32,1295 const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1288 elf.R_X86_64_PLT32,1296 switch (rel_1) {
1297 .R_X86_64_PC32,
1298 .R_X86_64_PLT32,
1289 => {1299 => {
1290 var insts = [_]u8{1300 var insts = [_]u8{
1291 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax1301 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax
...@@ -1298,9 +1308,9 @@ const x86_64 = struct {...@@ -1298,9 +1308,9 @@ const x86_64 = struct {
12981308
1299 else => {1309 else => {
1300 var err = try elf_file.addErrorWithNotes(1);1310 var err = try elf_file.addErrorWithNotes(1);
1301 try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{1311 try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{
1302 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1312 @tagName(rel_0),
1303 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1313 @tagName(rel_1),
1304 });1314 });
1305 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{1315 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{
1306 self.file(elf_file).?.fmtPath(),1316 self.file(elf_file).?.fmtPath(),
...@@ -1320,9 +1330,11 @@ const x86_64 = struct {...@@ -1320,9 +1330,11 @@ const x86_64 = struct {
1320 ) !void {1330 ) !void {
1321 assert(rels.len == 2);1331 assert(rels.len == 2);
1322 const writer = stream.writer();1332 const writer = stream.writer();
1323 switch (rels[1].r_type()) {1333 const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type());
1324 elf.R_X86_64_PC32,1334 const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1325 elf.R_X86_64_PLT32,1335 switch (rel_1) {
1336 .R_X86_64_PC32,
1337 .R_X86_64_PLT32,
1326 => {1338 => {
1327 var insts = [_]u8{1339 var insts = [_]u8{
1328 0x31, 0xc0, // xor %eax, %eax1340 0x31, 0xc0, // xor %eax, %eax
...@@ -1334,8 +1346,8 @@ const x86_64 = struct {...@@ -1334,8 +1346,8 @@ const x86_64 = struct {
1334 try writer.writeAll(&insts);1346 try writer.writeAll(&insts);
1335 },1347 },
13361348
1337 elf.R_X86_64_GOTPCREL,1349 .R_X86_64_GOTPCREL,
1338 elf.R_X86_64_GOTPCRELX,1350 .R_X86_64_GOTPCRELX,
1339 => {1351 => {
1340 var insts = [_]u8{1352 var insts = [_]u8{
1341 0x31, 0xc0, // xor %eax, %eax1353 0x31, 0xc0, // xor %eax, %eax
...@@ -1350,9 +1362,9 @@ const x86_64 = struct {...@@ -1350,9 +1362,9 @@ const x86_64 = struct {
13501362
1351 else => {1363 else => {
1352 var err = try elf_file.addErrorWithNotes(1);1364 var err = try elf_file.addErrorWithNotes(1);
1353 try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{1365 try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{
1354 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1366 @tagName(rel_0),
1355 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1367 @tagName(rel_1),
1356 });1368 });
1357 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{1369 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{
1358 self.file(elf_file).?.fmtPath(),1370 self.file(elf_file).?.fmtPath(),
...@@ -1419,11 +1431,13 @@ const x86_64 = struct {...@@ -1419,11 +1431,13 @@ const x86_64 = struct {
1419 ) !void {1431 ) !void {
1420 assert(rels.len == 2);1432 assert(rels.len == 2);
1421 const writer = stream.writer();1433 const writer = stream.writer();
1422 switch (rels[1].r_type()) {1434 const rel_0: elf.R_X86_64 = @enumFromInt(rels[0].r_type());
1423 elf.R_X86_64_PC32,1435 const rel_1: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1424 elf.R_X86_64_PLT32,1436 switch (rel_1) {
1425 elf.R_X86_64_GOTPCREL,1437 .R_X86_64_PC32,
1426 elf.R_X86_64_GOTPCRELX,1438 .R_X86_64_PLT32,
1439 .R_X86_64_GOTPCREL,
1440 .R_X86_64_GOTPCRELX,
1427 => {1441 => {
1428 var insts = [_]u8{1442 var insts = [_]u8{
1429 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax1443 0x64, 0x48, 0x8b, 0x04, 0x25, 0, 0, 0, 0, // movq %fs:0,%rax
...@@ -1432,17 +1446,14 @@ const x86_64 = struct {...@@ -1432,17 +1446,14 @@ const x86_64 = struct {
1432 std.mem.writeInt(i32, insts[12..][0..4], value, .little);1446 std.mem.writeInt(i32, insts[12..][0..4], value, .little);
1433 try stream.seekBy(-4);1447 try stream.seekBy(-4);
1434 try writer.writeAll(&insts);1448 try writer.writeAll(&insts);
1435 relocs_log.debug(" relaxing {} and {}", .{1449 relocs_log.debug(" relaxing {s} and {s}", .{ @tagName(rel_0), @tagName(rel_1) });
1436 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1437 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
1438 });
1439 },1450 },
14401451
1441 else => {1452 else => {
1442 var err = try elf_file.addErrorWithNotes(1);1453 var err = try elf_file.addErrorWithNotes(1);
1443 try err.addMsg(elf_file, "fatal linker error: rewrite {} when followed by {}", .{1454 try err.addMsg(elf_file, "fatal linker error: rewrite {s} when followed by {s}", .{
1444 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1455 @tagName(rel_0),
1445 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1456 @tagName(rel_1),
1446 });1457 });
1447 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{1458 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{
1448 self.file(elf_file).?.fmtPath(),1459 self.file(elf_file).?.fmtPath(),
src/link/Elf/eh_frame.zig+6-5
...@@ -541,11 +541,12 @@ const EH_PE = struct {...@@ -541,11 +541,12 @@ const EH_PE = struct {
541541
542const x86_64 = struct {542const x86_64 = struct {
543 fn resolveReloc(rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) void {543 fn resolveReloc(rel: elf.Elf64_Rela, source: i64, target: i64, data: []u8) void {
544 switch (rel.r_type()) {544 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
545 elf.R_X86_64_32 => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little),545 switch (r_type) {
546 elf.R_X86_64_64 => std.mem.writeInt(i64, data[0..8], target, .little),546 .R_X86_64_32 => std.mem.writeInt(i32, data[0..4], @as(i32, @truncate(target)), .little),
547 elf.R_X86_64_PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little),547 .R_X86_64_64 => std.mem.writeInt(i64, data[0..8], target, .little),
548 elf.R_X86_64_PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little),548 .R_X86_64_PC32 => std.mem.writeInt(i32, data[0..4], @as(i32, @intCast(target - source)), .little),
549 .R_X86_64_PC64 => std.mem.writeInt(i64, data[0..8], target - source, .little),
549 else => unreachable,550 else => unreachable,
550 }551 }
551 }552 }
src/link/Elf/relocation.zig+32-21
...@@ -11,7 +11,25 @@ pub const Kind = enum {...@@ -11,7 +11,25 @@ pub const Kind = enum {
11 tlsdesc,11 tlsdesc,
12};12};
1313
14const x86_64_relocs = [_]struct { Kind, elf.R_X86_64 }{14fn Table(comptime len: comptime_int, comptime RelType: type, comptime mapping: [len]struct { Kind, RelType }) type {
15 return struct {
16 fn decode(r_type: u32) ?Kind {
17 inline for (mapping) |entry| {
18 if (@intFromEnum(entry[1]) == r_type) return entry[0];
19 }
20 return null;
21 }
22
23 fn encode(comptime kind: Kind) u32 {
24 inline for (mapping) |entry| {
25 if (entry[0] == kind) return @intFromEnum(entry[1]);
26 }
27 unreachable;
28 }
29 };
30}
31
32const x86_64_relocs = Table(10, elf.R_X86_64, .{
15 .{ .abs, .R_X86_64_64 },33 .{ .abs, .R_X86_64_64 },
16 .{ .copy, .R_X86_64_COPY },34 .{ .copy, .R_X86_64_COPY },
17 .{ .rel, .R_X86_64_RELATIVE },35 .{ .rel, .R_X86_64_RELATIVE },
...@@ -22,9 +40,9 @@ const x86_64_relocs = [_]struct { Kind, elf.R_X86_64 }{...@@ -22,9 +40,9 @@ const x86_64_relocs = [_]struct { Kind, elf.R_X86_64 }{
22 .{ .dtpoff, .R_X86_64_DTPOFF64 },40 .{ .dtpoff, .R_X86_64_DTPOFF64 },
23 .{ .tpoff, .R_X86_64_TPOFF64 },41 .{ .tpoff, .R_X86_64_TPOFF64 },
24 .{ .tlsdesc, .R_X86_64_TLSDESC },42 .{ .tlsdesc, .R_X86_64_TLSDESC },
25};43});
2644
27const aarch64_relocs = [_]struct { Kind, elf.R_AARCH64 }{45const aarch64_relocs = Table(10, elf.R_AARCH64, .{
28 .{ .abs, .R_AARCH64_ABS64 },46 .{ .abs, .R_AARCH64_ABS64 },
29 .{ .copy, .R_AARCH64_COPY },47 .{ .copy, .R_AARCH64_COPY },
30 .{ .rel, .R_AARCH64_RELATIVE },48 .{ .rel, .R_AARCH64_RELATIVE },
...@@ -35,9 +53,9 @@ const aarch64_relocs = [_]struct { Kind, elf.R_AARCH64 }{...@@ -35,9 +53,9 @@ const aarch64_relocs = [_]struct { Kind, elf.R_AARCH64 }{
35 .{ .dtpoff, .R_AARCH64_TLS_DTPREL },53 .{ .dtpoff, .R_AARCH64_TLS_DTPREL },
36 .{ .tpoff, .R_AARCH64_TLS_TPREL },54 .{ .tpoff, .R_AARCH64_TLS_TPREL },
37 .{ .tlsdesc, .R_AARCH64_TLSDESC },55 .{ .tlsdesc, .R_AARCH64_TLSDESC },
38};56});
3957
40const riscv64_relocs = [_]struct { Kind, elf.R_RISCV }{58const riscv64_relocs = Table(8, elf.R_RISCV, .{
41 .{ .abs, .R_RISCV_64 },59 .{ .abs, .R_RISCV_64 },
42 .{ .copy, .R_RISCV_COPY },60 .{ .copy, .R_RISCV_COPY },
43 .{ .rel, .R_RISCV_RELATIVE },61 .{ .rel, .R_RISCV_RELATIVE },
...@@ -46,31 +64,24 @@ const riscv64_relocs = [_]struct { Kind, elf.R_RISCV }{...@@ -46,31 +64,24 @@ const riscv64_relocs = [_]struct { Kind, elf.R_RISCV }{
46 .{ .dtpmod, .R_RISCV_TLS_DTPMOD64 },64 .{ .dtpmod, .R_RISCV_TLS_DTPMOD64 },
47 .{ .dtpoff, .R_RISCV_TLS_DTPREL64 },65 .{ .dtpoff, .R_RISCV_TLS_DTPREL64 },
48 .{ .tpoff, .R_RISCV_TLS_TPREL64 },66 .{ .tpoff, .R_RISCV_TLS_TPREL64 },
49 .{ .tpoff, .R_RISCV_TLS_TPREL64 },67});
50};
5168
52pub fn decode(r_type: u32, cpu_arch: std.Target.Cpu.Arch) ?Kind {69pub fn decode(r_type: u32, cpu_arch: std.Target.Cpu.Arch) ?Kind {
53 const relocs = switch (cpu_arch) {70 return switch (cpu_arch) {
54 .x86_64 => &x86_64_relocs,71 .x86_64 => x86_64_relocs.decode(r_type),
55 .aarch64 => &aarch64_relocs,72 .aarch64 => aarch64_relocs.decode(r_type),
73 .riscv64 => riscv64_relocs.decode(r_type),
56 else => @panic("TODO unhandled cpu arch"),74 else => @panic("TODO unhandled cpu arch"),
57 };75 };
58 inline for (relocs) |entry| {
59 if (entry[1] == r_type) return entry[0];
60 }
61 return null;
62}76}
6377
64pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {78pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {
65 const relocs = switch (cpu_arch) {79 return switch (cpu_arch) {
66 .x86_64 => &x86_64_relocs,80 .x86_64 => x86_64_relocs.encode(kind),
67 .aarch64 => &aarch64_relocs,81 .aarch64 => aarch64_relocs.encode(kind),
82 .riscv64 => riscv64_relocs.encode(kind),
68 else => @panic("TODO unhandled cpu arch"),83 else => @panic("TODO unhandled cpu arch"),
69 };84 };
70 inline for (relocs) |entry| {
71 if (entry[0] == kind) return entry[1];
72 }
73 unreachable;
74}85}
7586
76const FormatRelocTypeCtx = struct {87const FormatRelocTypeCtx = struct {