| ... | ... | @@ -28,8 +28,10 @@ shdrs: std.ArrayList(Section), |
| 28 | 28 | phdrs: std.ArrayList(MappedFile.Node.Index), |
| 29 | 29 | shndx: struct { |
| 30 | 30 | got: Section.Index, |
| 31 | /// Always `.UNDEF` on some targets (e.g. SPARC). |
| 31 | 32 | got_plt: Section.Index, |
| 32 | 33 | plt: Section.Index, |
| 34 | /// Only created for x86 targets; `.UNDEF` everywhere else. |
| 33 | 35 | plt_sec: Section.Index, |
| 34 | 36 | dynsym: Section.Index, |
| 35 | 37 | dynstr: Section.Index, |
| ... | ... | @@ -777,18 +779,26 @@ const GotReloc = struct { |
| 777 | 779 | }; |
| 778 | 780 | |
| 779 | 781 | const Type = enum(u8) { |
| 780 | | offset64, |
| 781 | 782 | offset32, |
| 782 | | rel64, |
| 783 | offset64, |
| 783 | 784 | rel32, |
| 785 | rel64, |
| 784 | 786 | |
| 785 | | rel32_hi20, |
| 786 | | rel64_lo20, |
| 787 | | rel64_hi12, |
| 788 | | abs32_lo12, |
| 789 | | abs32_hi20, |
| 790 | | abs64_lo20, |
| 791 | | abs64_hi12, |
| 787 | larch_rel32_hi20, |
| 788 | larch_rel64_lo20, |
| 789 | larch_rel64_hi12, |
| 790 | larch_abs32_lo12, |
| 791 | larch_abs32_hi20, |
| 792 | larch_abs64_lo20, |
| 793 | larch_abs64_hi12, |
| 794 | |
| 795 | sparc_10, |
| 796 | sparc_13, |
| 797 | sparc_22, |
| 798 | sparc_ldm_hi22, |
| 799 | sparc_ldm_lo10, |
| 800 | sparc_op_hix22, |
| 801 | sparc_op_lox10, |
| 792 | 802 | }; |
| 793 | 803 | |
| 794 | 804 | const Index = enum(u32) { |
| ... | ... | @@ -857,51 +867,96 @@ const GotReloc = struct { |
| 857 | 867 | @intCast(@as(i64, @bitCast(got_vaddr +% got_offset +% addend -% dest_vaddr))), |
| 858 | 868 | target_endian, |
| 859 | 869 | ), |
| 860 | | .rel32_hi20 => { |
| 870 | |
| 871 | .larch_rel32_hi20 => { |
| 861 | 872 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 862 | 873 | const target_value = got_vaddr +% got_offset +% addend; |
| 863 | 874 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); |
| 864 | 875 | }, |
| 865 | | .rel64_lo20 => { |
| 876 | .larch_rel64_lo20 => { |
| 866 | 877 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 867 | 878 | const target_value = got_vaddr +% got_offset +% addend; |
| 868 | 879 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); |
| 869 | 880 | }, |
| 870 | | .rel64_hi12 => { |
| 881 | .larch_rel64_hi12 => { |
| 871 | 882 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 872 | 883 | const target_value = got_vaddr +% got_offset +% addend; |
| 873 | 884 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); |
| 874 | 885 | }, |
| 875 | | .abs32_lo12 => { |
| 886 | .larch_abs32_lo12 => { |
| 876 | 887 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 877 | 888 | const target_value = got_vaddr +% got_offset +% addend; |
| 878 | 889 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 879 | 890 | }, |
| 880 | | .abs32_hi20 => { |
| 891 | .larch_abs32_hi20 => { |
| 881 | 892 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 882 | 893 | const target_value = got_vaddr +% got_offset +% addend; |
| 883 | 894 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); |
| 884 | 895 | }, |
| 885 | | .abs64_lo20 => { |
| 896 | .larch_abs64_lo20 => { |
| 886 | 897 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 887 | 898 | const target_value = got_vaddr +% got_offset +% addend; |
| 888 | 899 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); |
| 889 | 900 | }, |
| 890 | | .abs64_hi12 => { |
| 901 | .larch_abs64_hi12 => { |
| 891 | 902 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 892 | 903 | const target_value = got_vaddr +% got_offset +% addend; |
| 893 | 904 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); |
| 894 | 905 | }, |
| 906 | |
| 907 | .sparc_10 => { |
| 908 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 909 | var result = elf.targetLoad(dest_ptr); |
| 910 | result.simm13 = @as(u10, @truncate(got_offset)); |
| 911 | elf.targetStore(dest_ptr, result); |
| 912 | }, |
| 913 | .sparc_13 => { |
| 914 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 915 | var result = elf.targetLoad(dest_ptr); |
| 916 | result.simm13 = @truncate(got_offset); |
| 917 | elf.targetStore(dest_ptr, result); |
| 918 | }, |
| 919 | .sparc_22 => { |
| 920 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| 921 | var result = elf.targetLoad(dest_ptr); |
| 922 | result.simm22 = @truncate(got_offset >> 10); |
| 923 | elf.targetStore(dest_ptr, result); |
| 924 | }, |
| 925 | .sparc_ldm_hi22 => { |
| 926 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| 927 | var result = elf.targetLoad(dest_ptr); |
| 928 | result.simm22 = @truncate((got_offset +% addend) >> 10); |
| 929 | elf.targetStore(dest_ptr, result); |
| 930 | }, |
| 931 | .sparc_ldm_lo10 => { |
| 932 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 933 | var result = elf.targetLoad(dest_ptr); |
| 934 | result.simm13 = @as(u10, @truncate(got_offset +% addend)); |
| 935 | elf.targetStore(dest_ptr, result); |
| 936 | }, |
| 937 | .sparc_op_hix22 => { |
| 938 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| 939 | var result = elf.targetLoad(dest_ptr); |
| 940 | result.imm22 = @truncate(got_offset >> 10); |
| 941 | elf.targetStore(dest_ptr, result); |
| 942 | }, |
| 943 | .sparc_op_lox10 => { |
| 944 | const dest_ptr: *link.sparc.reloc.Imm13 = @ptrCast(@alignCast(dest_slice)); |
| 945 | var result = elf.targetLoad(dest_ptr); |
| 946 | result.imm13 = @as(u10, @truncate(got_offset)); |
| 947 | elf.targetStore(dest_ptr, result); |
| 948 | }, |
| 895 | 949 | } |
| 896 | 950 | } |
| 897 | 951 | }; |
| 898 | 952 | |
| 899 | 953 | pub const MachineRelocType = union { |
| 900 | | X86_64: std.elf.R_X86_64, |
| 901 | 954 | AARCH64: std.elf.R_AARCH64, |
| 902 | 955 | LOONGARCH: std.elf.R_LARCH, |
| 903 | | RISCV: std.elf.R_RISCV, |
| 904 | 956 | PPC64: std.elf.R_PPC64, |
| 957 | RISCV: std.elf.R_RISCV, |
| 958 | SPARC: std.elf.R_SPARC, |
| 959 | X86_64: std.elf.R_X86_64, |
| 905 | 960 | |
| 906 | 961 | pub fn none(elf: *Elf) MachineRelocType { |
| 907 | 962 | return switch (elf.ehdrField(.machine)) { |
| ... | ... | @@ -910,6 +965,7 @@ pub const MachineRelocType = union { |
| 910 | 965 | .LOONGARCH => .{ .LOONGARCH = .NONE }, |
| 911 | 966 | .PPC64 => .{ .PPC64 = .NONE }, |
| 912 | 967 | .RISCV => .{ .RISCV = .NONE }, |
| 968 | .SPARCV9 => .{ .SPARC = .NONE }, |
| 913 | 969 | .X86_64 => .{ .X86_64 = .NONE }, |
| 914 | 970 | }; |
| 915 | 971 | } |
| ... | ... | @@ -920,6 +976,7 @@ pub const MachineRelocType = union { |
| 920 | 976 | .LOONGARCH => .{ .LOONGARCH = .COPY }, |
| 921 | 977 | .PPC64 => .{ .PPC64 = .COPY }, |
| 922 | 978 | .RISCV => .{ .RISCV = .COPY }, |
| 979 | .SPARCV9 => .{ .SPARC = .COPY }, |
| 923 | 980 | .X86_64 => .{ .X86_64 = .COPY }, |
| 924 | 981 | }; |
| 925 | 982 | } |
| ... | ... | @@ -930,43 +987,57 @@ pub const MachineRelocType = union { |
| 930 | 987 | .LOONGARCH => .{ .LOONGARCH = .RELATIVE }, |
| 931 | 988 | .PPC64 => .{ .PPC64 = .RELATIVE }, |
| 932 | 989 | .RISCV => .{ .RISCV = .RELATIVE }, |
| 990 | .SPARCV9 => .{ .SPARC = .RELATIVE }, |
| 933 | 991 | .X86_64 => .{ .X86_64 = .RELATIVE }, |
| 934 | 992 | }; |
| 935 | 993 | } |
| 936 | 994 | pub fn jumpSlot(elf: *Elf) MachineRelocType { |
| 937 | 995 | return switch (elf.ehdrField(.machine)) { |
| 938 | 996 | else => unreachable, |
| 939 | | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, |
| 997 | .AARCH64 => .{ .AARCH64 = .JUMP_SLOT }, |
| 940 | 998 | .LOONGARCH => .{ .LOONGARCH = .JUMP_SLOT }, |
| 999 | .PPC64 => .{ .PPC64 = .JMP_SLOT }, |
| 1000 | .RISCV => .{ .RISCV = .JUMP_SLOT }, |
| 1001 | .SPARCV9 => .{ .SPARC = .JMP_SLOT }, |
| 1002 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, |
| 941 | 1003 | }; |
| 942 | 1004 | } |
| 943 | 1005 | pub fn globDat(elf: *Elf) MachineRelocType { |
| 944 | 1006 | return switch (elf.ehdrField(.machine)) { |
| 945 | 1007 | else => unreachable, |
| 946 | | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 1008 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, |
| 947 | 1009 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 1010 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, |
| 1011 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 1012 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, |
| 1013 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 948 | 1014 | }; |
| 949 | 1015 | } |
| 950 | 1016 | pub fn dtpOffAddr(elf: *Elf) MachineRelocType { |
| 951 | 1017 | return switch (elf.ehdrField(.machine)) { |
| 952 | 1018 | else => unreachable, |
| 953 | | .X86_64 => .{ .X86_64 = .DTPOFF64 }, |
| 954 | 1019 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| 1020 | .PPC64 => .{ .PPC64 = .DTPREL64 }, |
| 1021 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| 1022 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPOFF64 else .TLS_DTPOFF32 }, |
| 1023 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .DTPOFF64 else .DTPOFF32 }, |
| 955 | 1024 | }; |
| 956 | 1025 | } |
| 957 | 1026 | pub fn absAddr(elf: *Elf) MachineRelocType { |
| 958 | 1027 | return switch (elf.ehdrField(.machine)) { |
| 959 | 1028 | else => unreachable, |
| 960 | | .AARCH64 => .{ .AARCH64 = .ABS64 }, |
| 1029 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .ABS64 else .P32_ABS32 }, |
| 961 | 1030 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 962 | 1031 | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 963 | | .RISCV => .{ .RISCV = .@"64" }, |
| 964 | | .X86_64 => .{ .X86_64 = .@"64" }, |
| 1032 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 1033 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 1034 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 965 | 1035 | }; |
| 966 | 1036 | } |
| 967 | 1037 | pub fn sizeAddr(elf: *Elf) MachineRelocType { |
| 968 | 1038 | return switch (elf.ehdrField(.machine)) { |
| 969 | 1039 | else => unreachable, |
| 1040 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .SIZE64 else .SIZE32 }, |
| 970 | 1041 | .X86_64 => .{ .X86_64 = .SIZE64 }, |
| 971 | 1042 | }; |
| 972 | 1043 | } |
| ... | ... | @@ -974,6 +1045,7 @@ pub const MachineRelocType = union { |
| 974 | 1045 | pub fn wrap(int: u32, elf: *Elf) MachineRelocType { |
| 975 | 1046 | return switch (elf.ehdrField(.machine)) { |
| 976 | 1047 | else => unreachable, |
| 1048 | .SPARCV9 => .{ .SPARC = @enumFromInt(int) }, |
| 977 | 1049 | inline .AARCH64, |
| 978 | 1050 | .LOONGARCH, |
| 979 | 1051 | .PPC64, |
| ... | ... | @@ -985,6 +1057,7 @@ pub const MachineRelocType = union { |
| 985 | 1057 | pub fn unwrap(rt: MachineRelocType, elf: *Elf) u32 { |
| 986 | 1058 | return switch (elf.ehdrField(.machine)) { |
| 987 | 1059 | else => unreachable, |
| 1060 | .SPARCV9 => @intFromEnum(rt.SPARC), |
| 988 | 1061 | inline .AARCH64, |
| 989 | 1062 | .LOONGARCH, |
| 990 | 1063 | .PPC64, |
| ... | ... | @@ -1073,37 +1146,67 @@ const SymbolReloc = struct { |
| 1073 | 1146 | /// This is only used targeting local symbols so can always be statically resolved. |
| 1074 | 1147 | dsorel32, |
| 1075 | 1148 | |
| 1076 | | abs64, |
| 1149 | abs8, |
| 1150 | abs16, |
| 1077 | 1151 | abs32, |
| 1078 | 1152 | abs32s, |
| 1079 | | rel64, |
| 1153 | abs64, |
| 1154 | rel8, |
| 1155 | rel16, |
| 1080 | 1156 | rel32, |
| 1081 | | pltrel64, |
| 1157 | rel64, |
| 1158 | pltabs32, |
| 1159 | pltabs64, |
| 1082 | 1160 | pltrel32, |
| 1083 | | dtpoff64, |
| 1161 | pltrel64, |
| 1084 | 1162 | dtpoff32, |
| 1085 | | tpoff64, |
| 1163 | dtpoff64, |
| 1086 | 1164 | tpoff32, |
| 1087 | | size64, |
| 1165 | tpoff64, |
| 1088 | 1166 | size32, |
| 1167 | size64, |
| 1089 | 1168 | |
| 1090 | | abs32_lo12, |
| 1091 | | rel32_hi20, |
| 1092 | | rel64_lo20, |
| 1093 | | rel64_hi12, |
| 1094 | | branch_rel18, |
| 1095 | | branch_rel23, |
| 1096 | | branch_rel28, |
| 1097 | | call_rel38, |
| 1098 | | tpoff32_lo12, |
| 1099 | | tpoff32_hi20, |
| 1100 | | tpoff64_lo20, |
| 1101 | | tpoff64_hi12, |
| 1169 | larch_abs32_lo12, |
| 1170 | larch_rel32_hi20, |
| 1171 | larch_rel64_lo20, |
| 1172 | larch_rel64_hi12, |
| 1173 | larch_branch_rel18, |
| 1174 | larch_branch_rel23, |
| 1175 | larch_branch_rel28, |
| 1176 | larch_call_rel38, |
| 1177 | larch_tpoff32_lo12, |
| 1178 | larch_tpoff32_hi20, |
| 1179 | larch_tpoff64_lo20, |
| 1180 | larch_tpoff64_hi12, |
| 1181 | |
| 1182 | sparc_wdisp30, |
| 1183 | sparc_pc10, |
| 1184 | sparc_pc22, |
| 1185 | sparc_wplt30, |
| 1186 | sparc_h44, |
| 1187 | sparc_m44, |
| 1188 | sparc_l44, |
| 1189 | sparc_ldo_hix22, |
| 1190 | sparc_ldo_lox10, |
| 1191 | sparc_le_hix22, |
| 1192 | sparc_le_lox10, |
| 1102 | 1193 | |
| 1103 | 1194 | fn dependsOnTlsSize(t: SymbolReloc.Type) bool { |
| 1104 | 1195 | return switch (t) { |
| 1105 | | .tpoff32, .tpoff64 => true, |
| 1106 | | .tpoff32_lo12, .tpoff32_hi20, .tpoff64_lo20, .tpoff64_hi12 => true, |
| 1196 | .tpoff32, |
| 1197 | .tpoff64, |
| 1198 | => true, |
| 1199 | |
| 1200 | .larch_tpoff32_lo12, |
| 1201 | .larch_tpoff32_hi20, |
| 1202 | .larch_tpoff64_lo20, |
| 1203 | .larch_tpoff64_hi12, |
| 1204 | => true, |
| 1205 | |
| 1206 | .sparc_le_hix22, |
| 1207 | .sparc_le_lox10, |
| 1208 | => true, |
| 1209 | |
| 1107 | 1210 | else => false, |
| 1108 | 1211 | }; |
| 1109 | 1212 | } |
| ... | ... | @@ -1111,8 +1214,18 @@ const SymbolReloc = struct { |
| 1111 | 1214 | fn isAbsAddr(t: SymbolReloc.Type, elf: *const Elf) bool { |
| 1112 | 1215 | return switch (elf.identClass()) { |
| 1113 | 1216 | .NONE, _ => unreachable, |
| 1114 | | .@"32" => t == .abs32, |
| 1115 | | .@"64" => t == .abs64, |
| 1217 | .@"32" => switch (t) { |
| 1218 | .abs32, |
| 1219 | .pltabs32, |
| 1220 | => true, |
| 1221 | else => false, |
| 1222 | }, |
| 1223 | .@"64" => switch (t) { |
| 1224 | .abs64, |
| 1225 | .pltabs64, |
| 1226 | => true, |
| 1227 | else => false, |
| 1228 | }, |
| 1116 | 1229 | }; |
| 1117 | 1230 | } |
| 1118 | 1231 | }; |
| ... | ... | @@ -1131,11 +1244,31 @@ const SymbolReloc = struct { |
| 1131 | 1244 | .static => unreachable, |
| 1132 | 1245 | .dynamic => return, // the relocation happens at runtime |
| 1133 | 1246 | .static_relative => { |
| 1134 | | assert(reloc.type.isAbsAddr(elf)); |
| 1135 | 1247 | // We have emitted an R_*_RELATIVE relocation to help lower an abs32/abs64 reloc. |
| 1136 | 1248 | // This is a simplified version of the general relocation handling logic, where we |
| 1137 | 1249 | // know we're using '.abs64' or '.abs32' (matching the ELF ident class). |
| 1138 | | const value = reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend)); |
| 1250 | const value = type: switch (reloc.type) { |
| 1251 | .abs32, |
| 1252 | .abs64, |
| 1253 | => reloc.target.value(elf) +% @as(u64, @bitCast(reloc.addend)), |
| 1254 | .pltabs32, |
| 1255 | .pltabs64, |
| 1256 | => value: { |
| 1257 | const plt_index = switch (reloc.target.unwrap()) { |
| 1258 | .local => continue :type .abs32, |
| 1259 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32, |
| 1260 | }; |
| 1261 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs32; |
| 1262 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1263 | else => |machine| @panic(@tagName(machine)), |
| 1264 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| 1265 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1266 | }; |
| 1267 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1268 | break :value plt_entry +% @as(u64, @bitCast(reloc.addend)); |
| 1269 | }, |
| 1270 | else => unreachable, |
| 1271 | }; |
| 1139 | 1272 | elf.shndx.rela_dyn.relaSetRelativeOffset(elf, rela_index, value); |
| 1140 | 1273 | return; |
| 1141 | 1274 | }, |
| ... | ... | @@ -1182,6 +1315,13 @@ const SymbolReloc = struct { |
| 1182 | 1315 | @intCast(@as(i64, @bitCast(target_value))), |
| 1183 | 1316 | target_endian, |
| 1184 | 1317 | ), |
| 1318 | .abs16 => std.mem.writeInt( |
| 1319 | u16, |
| 1320 | dest_slice[0..2], |
| 1321 | @intCast(target_value), |
| 1322 | target_endian, |
| 1323 | ), |
| 1324 | .abs8 => dest_slice[0] = @intCast(target_value), |
| 1185 | 1325 | .rel64 => std.mem.writeInt( |
| 1186 | 1326 | i64, |
| 1187 | 1327 | dest_slice[0..8], |
| ... | ... | @@ -1194,17 +1334,65 @@ const SymbolReloc = struct { |
| 1194 | 1334 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), |
| 1195 | 1335 | target_endian, |
| 1196 | 1336 | ), |
| 1337 | .rel16 => std.mem.writeInt( |
| 1338 | i16, |
| 1339 | dest_slice[0..2], |
| 1340 | @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))), |
| 1341 | target_endian, |
| 1342 | ), |
| 1343 | .rel8 => dest_slice[0] = @bitCast(@as(i8, @intCast(@as(i64, @bitCast(target_value -% dest_vaddr))))), |
| 1344 | .pltabs64 => { |
| 1345 | const plt_index = switch (reloc.target.unwrap()) { |
| 1346 | .local => continue :type .abs64, |
| 1347 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs64, |
| 1348 | }; |
| 1349 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs64; |
| 1350 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1351 | else => |machine| @panic(@tagName(machine)), |
| 1352 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| 1353 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1354 | }; |
| 1355 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1356 | std.mem.writeInt( |
| 1357 | i64, |
| 1358 | dest_slice[0..8], |
| 1359 | @bitCast(plt_entry +% @as(u64, @bitCast(reloc.addend))), |
| 1360 | target_endian, |
| 1361 | ); |
| 1362 | }, |
| 1363 | .pltabs32 => { |
| 1364 | const plt_index = switch (reloc.target.unwrap()) { |
| 1365 | .local => continue :type .abs32, |
| 1366 | .global => |name| elf.plt.getIndex(name) orelse continue :type .abs32, |
| 1367 | }; |
| 1368 | if (elf.pltEntryIsDead(plt_index)) continue :type .abs32; |
| 1369 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1370 | else => |machine| @panic(@tagName(machine)), |
| 1371 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| 1372 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1373 | }; |
| 1374 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1375 | std.mem.writeInt( |
| 1376 | i32, |
| 1377 | dest_slice[0..4], |
| 1378 | @intCast(@as(i64, @bitCast( |
| 1379 | plt_entry +% @as(u64, @bitCast(reloc.addend)), |
| 1380 | ))), |
| 1381 | target_endian, |
| 1382 | ); |
| 1383 | }, |
| 1197 | 1384 | .pltrel64 => { |
| 1198 | 1385 | const plt_index = switch (reloc.target.unwrap()) { |
| 1199 | 1386 | .local => continue :type .rel64, |
| 1200 | 1387 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel64, |
| 1201 | 1388 | }; |
| 1202 | 1389 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel64; |
| 1203 | | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1390 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1204 | 1391 | else => |machine| @panic(@tagName(machine)), |
| 1205 | | .X86_64 => .{ elf.shndx.plt_sec, 16 }, |
| 1392 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| 1393 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1206 | 1394 | }; |
| 1207 | | const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size; |
| 1395 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1208 | 1396 | std.mem.writeInt( |
| 1209 | 1397 | i64, |
| 1210 | 1398 | dest_slice[0..8], |
| ... | ... | @@ -1218,11 +1406,12 @@ const SymbolReloc = struct { |
| 1218 | 1406 | .global => |name| elf.plt.getIndex(name) orelse continue :type .rel32, |
| 1219 | 1407 | }; |
| 1220 | 1408 | if (elf.pltEntryIsDead(plt_index)) continue :type .rel32; |
| 1221 | | const plt_shndx: Section.Index, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1409 | const plt_shndx: Section.Index, const plt_header_entries: u64, const plt_entry_size: u64 = switch (elf.ehdrField(.machine)) { |
| 1222 | 1410 | else => |machine| @panic(@tagName(machine)), |
| 1223 | | .X86_64 => .{ elf.shndx.plt_sec, 16 }, |
| 1411 | .SPARCV9 => .{ elf.shndx.plt, 4, 32 }, |
| 1412 | .X86_64 => .{ elf.shndx.plt_sec, 0, 16 }, |
| 1224 | 1413 | }; |
| 1225 | | const plt_entry = plt_shndx.vaddr(elf) +% plt_index * plt_entry_size; |
| 1414 | const plt_entry = plt_shndx.vaddr(elf) +% (plt_header_entries + plt_index) * plt_entry_size; |
| 1226 | 1415 | std.mem.writeInt( |
| 1227 | 1416 | i32, |
| 1228 | 1417 | dest_slice[0..4], |
| ... | ... | @@ -1286,42 +1475,43 @@ const SymbolReloc = struct { |
| 1286 | 1475 | target_endian, |
| 1287 | 1476 | ); |
| 1288 | 1477 | }, |
| 1289 | | .abs32_lo12 => { |
| 1478 | |
| 1479 | .larch_abs32_lo12 => { |
| 1290 | 1480 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1291 | 1481 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 1292 | 1482 | }, |
| 1293 | | .rel32_hi20 => { |
| 1483 | .larch_rel32_hi20 => { |
| 1294 | 1484 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1295 | 1485 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcalaHi20(target_value, dest_vaddr)); |
| 1296 | 1486 | }, |
| 1297 | | .rel64_lo20 => { |
| 1487 | .larch_rel64_lo20 => { |
| 1298 | 1488 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1299 | 1489 | link.loongarch.writeJ20(dest_slice[0..4], link.loongarch.toPcala64Lo20(target_value, dest_vaddr)); |
| 1300 | 1490 | }, |
| 1301 | | .rel64_hi12 => { |
| 1491 | .larch_rel64_hi12 => { |
| 1302 | 1492 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1303 | 1493 | link.loongarch.writeK12(dest_slice[0..4], link.loongarch.toPcala64Hi12(target_value, dest_vaddr)); |
| 1304 | 1494 | }, |
| 1305 | 1495 | // TODO: handle bad alignment and overflow gracefully |
| 1306 | | .branch_rel18 => { |
| 1496 | .larch_branch_rel18 => { |
| 1307 | 1497 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1308 | 1498 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1309 | 1499 | const slot_target: i16 = @intCast(@shrExact(target_rel, 2)); |
| 1310 | 1500 | link.loongarch.writeK16(dest_slice[0..4], @bitCast(slot_target)); |
| 1311 | 1501 | }, |
| 1312 | | .branch_rel23 => { |
| 1502 | .larch_branch_rel23 => { |
| 1313 | 1503 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1314 | 1504 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1315 | 1505 | const slot_target: i21 = @intCast(@shrExact(target_rel, 2)); |
| 1316 | 1506 | link.loongarch.writeD5K16(dest_slice[0..4], @bitCast(slot_target)); |
| 1317 | 1507 | }, |
| 1318 | | .branch_rel28 => { |
| 1508 | .larch_branch_rel28 => { |
| 1319 | 1509 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1320 | 1510 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1321 | 1511 | const slot_target: i26 = @intCast(@shrExact(target_rel, 2)); |
| 1322 | 1512 | link.loongarch.writeD10K16(dest_slice[0..4], @bitCast(slot_target)); |
| 1323 | 1513 | }, |
| 1324 | | .call_rel38 => { |
| 1514 | .larch_call_rel38 => { |
| 1325 | 1515 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1326 | 1516 | const target_rel: i64 = @bitCast(target_value -% dest_vaddr); |
| 1327 | 1517 | // We use i64 instead of i36 here because the allowed range is |
| ... | ... | @@ -1331,22 +1521,109 @@ const SymbolReloc = struct { |
| 1331 | 1521 | link.loongarch.writeJ20(dest_slice[0..4], @bitCast(@as(i20, @intCast((slot_target +% 0x8000) >> 16)))); |
| 1332 | 1522 | link.loongarch.writeK16(dest_slice[4..8], @bitCast(@as(i16, @truncate(slot_target)))); |
| 1333 | 1523 | }, |
| 1334 | | .tpoff32_lo12 => { |
| 1524 | .larch_tpoff32_lo12 => { |
| 1335 | 1525 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1336 | 1526 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value)); |
| 1337 | 1527 | }, |
| 1338 | | .tpoff32_hi20 => { |
| 1528 | .larch_tpoff32_hi20 => { |
| 1339 | 1529 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1340 | 1530 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 12)); |
| 1341 | 1531 | }, |
| 1342 | | .tpoff64_lo20 => { |
| 1532 | .larch_tpoff64_lo20 => { |
| 1343 | 1533 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1344 | 1534 | link.loongarch.writeJ20(dest_slice[0..4], @truncate(target_value >> 32)); |
| 1345 | 1535 | }, |
| 1346 | | .tpoff64_hi12 => { |
| 1536 | .larch_tpoff64_hi12 => { |
| 1347 | 1537 | assert(elf.ehdrField(.machine) == .LOONGARCH); |
| 1348 | 1538 | link.loongarch.writeK12(dest_slice[0..4], @truncate(target_value >> 52)); |
| 1349 | 1539 | }, |
| 1540 | |
| 1541 | .sparc_wdisp30 => { |
| 1542 | const dest_ptr: *link.sparc.reloc.Disp30 = @ptrCast(@alignCast(dest_slice)); |
| 1543 | var result = elf.targetLoad(dest_ptr); |
| 1544 | result.disp30 = @truncate((target_value -% dest_vaddr) >> 2); |
| 1545 | elf.targetStore(dest_ptr, result); |
| 1546 | }, |
| 1547 | .sparc_pc10 => { |
| 1548 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 1549 | var result = elf.targetLoad(dest_ptr); |
| 1550 | result.simm13 = @as(u10, @truncate(target_value -% dest_vaddr)); |
| 1551 | elf.targetStore(dest_ptr, result); |
| 1552 | }, |
| 1553 | .sparc_pc22 => { |
| 1554 | const dest_ptr: *link.sparc.reloc.Disp22 = @ptrCast(@alignCast(dest_slice)); |
| 1555 | var result = elf.targetLoad(dest_ptr); |
| 1556 | result.disp22 = @truncate((target_value -% dest_vaddr) >> 10); |
| 1557 | elf.targetStore(dest_ptr, result); |
| 1558 | }, |
| 1559 | .sparc_wplt30 => { |
| 1560 | const plt_index = switch (reloc.target.unwrap()) { |
| 1561 | .local => continue :type .sparc_wdisp30, |
| 1562 | .global => |name| elf.plt.getIndex(name) orelse continue :type .sparc_wdisp30, |
| 1563 | }; |
| 1564 | if (elf.pltEntryIsDead(plt_index)) continue :type .sparc_wdisp30; |
| 1565 | const plt_entry = elf.shndx.plt.vaddr(elf) +% (4 + plt_index) * 32; |
| 1566 | const dest_ptr: *link.sparc.reloc.Disp30 = @ptrCast(@alignCast(dest_slice)); |
| 1567 | var result = elf.targetLoad(dest_ptr); |
| 1568 | result.disp30 = @truncate((plt_entry +% @as(u64, @bitCast(reloc.addend)) -% dest_vaddr) >> 2); |
| 1569 | elf.targetStore(dest_ptr, result); |
| 1570 | }, |
| 1571 | .sparc_h44 => { |
| 1572 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| 1573 | var result = elf.targetLoad(dest_ptr); |
| 1574 | result.imm22 = @truncate(target_value >> 22); |
| 1575 | elf.targetStore(dest_ptr, result); |
| 1576 | }, |
| 1577 | .sparc_m44 => { |
| 1578 | const dest_ptr: *link.sparc.reloc.Imm10 = @ptrCast(@alignCast(dest_slice)); |
| 1579 | var result = elf.targetLoad(dest_ptr); |
| 1580 | result.imm10 = @truncate(target_value >> 12); |
| 1581 | elf.targetStore(dest_ptr, result); |
| 1582 | }, |
| 1583 | .sparc_l44 => { |
| 1584 | const dest_ptr: *link.sparc.reloc.Imm13 = @ptrCast(@alignCast(dest_slice)); |
| 1585 | var result = elf.targetLoad(dest_ptr); |
| 1586 | result.imm13 = @as(u12, @truncate(target_value)); |
| 1587 | elf.targetStore(dest_ptr, result); |
| 1588 | }, |
| 1589 | .sparc_ldo_hix22 => { |
| 1590 | const dest_ptr: *link.sparc.reloc.Simm22 = @ptrCast(@alignCast(dest_slice)); |
| 1591 | var result = elf.targetLoad(dest_ptr); |
| 1592 | result.simm22 = @truncate(target_value >> 10); |
| 1593 | elf.targetStore(dest_ptr, result); |
| 1594 | }, |
| 1595 | .sparc_ldo_lox10 => { |
| 1596 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 1597 | var result = elf.targetLoad(dest_ptr); |
| 1598 | result.simm13 = @as(u10, @truncate(target_value)); |
| 1599 | elf.targetStore(dest_ptr, result); |
| 1600 | }, |
| 1601 | .sparc_le_hix22 => { |
| 1602 | const tls_phndx = elf.getNode(elf.ni.tls).segment; |
| 1603 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| 1604 | inline else => |phdr| tls_size: { |
| 1605 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); |
| 1606 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| 1607 | }, |
| 1608 | }; |
| 1609 | const dest_ptr: *link.sparc.reloc.Imm22 = @ptrCast(@alignCast(dest_slice)); |
| 1610 | var result = elf.targetLoad(dest_ptr); |
| 1611 | result.imm22 = @truncate(~(target_value -% tls_size) >> 10); |
| 1612 | elf.targetStore(dest_ptr, result); |
| 1613 | }, |
| 1614 | .sparc_le_lox10 => { |
| 1615 | const tls_phndx = elf.getNode(elf.ni.tls).segment; |
| 1616 | const tls_size: u64 = switch (elf.phdrSlice()) { |
| 1617 | inline else => |phdr| tls_size: { |
| 1618 | assert(elf.targetLoad(&phdr[tls_phndx].type) == .TLS); |
| 1619 | break :tls_size elf.targetLoad(&phdr[tls_phndx].memsz); |
| 1620 | }, |
| 1621 | }; |
| 1622 | const dest_ptr: *link.sparc.reloc.Simm13 = @ptrCast(@alignCast(dest_slice)); |
| 1623 | var result = elf.targetLoad(dest_ptr); |
| 1624 | result.simm13 = @as(u13, 0b1110000000000) | @as(u10, @truncate(target_value -% tls_size)); |
| 1625 | elf.targetStore(dest_ptr, result); |
| 1626 | }, |
| 1350 | 1627 | } |
| 1351 | 1628 | } |
| 1352 | 1629 | |
| ... | ... | @@ -1448,10 +1725,7 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1448 | 1725 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1449 | 1726 | |
| 1450 | 1727 | // Ensure the `.got.plt` section's node is big enough |
| 1451 | | const got_plt_need_size: usize = switch (elf.identClass()) { |
| 1452 | | .NONE, _ => unreachable, |
| 1453 | | inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity), |
| 1454 | | }; |
| 1728 | const got_plt_need_size: usize = elf.targetPtrSize() * (3 + need_plt_capacity); |
| 1455 | 1729 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1456 | 1730 | |
| 1457 | 1731 | // Ensure the `.plt.sec` section's node is big enough |
| ... | ... | @@ -1460,16 +1734,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1460 | 1734 | }, |
| 1461 | 1735 | .LOONGARCH => { |
| 1462 | 1736 | // Ensure the `.plt` section's node is big enough |
| 1463 | | const plt_need_size: usize = 32 + 16 * need_plt_capacity; |
| 1737 | const plt_need_size: usize = 16 * (2 + need_plt_capacity); |
| 1464 | 1738 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1465 | 1739 | |
| 1466 | 1740 | // Ensure the `.got.plt` section's node is big enough |
| 1467 | | const got_plt_need_size: usize = switch (elf.identClass()) { |
| 1468 | | .NONE, _ => unreachable, |
| 1469 | | inline else => |class| @sizeOf(class.ElfN().Addr) * (2 + need_plt_capacity), |
| 1470 | | }; |
| 1741 | const got_plt_need_size: usize = elf.targetPtrSize() * (2 + need_plt_capacity); |
| 1471 | 1742 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1472 | 1743 | }, |
| 1744 | .SPARCV9 => { |
| 1745 | // Ensure the `.plt` section's node is big enough |
| 1746 | const plt_need_size: usize = 32 * (4 + need_plt_capacity); |
| 1747 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1748 | }, |
| 1473 | 1749 | } |
| 1474 | 1750 | } |
| 1475 | 1751 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at |
| ... | ... | @@ -2090,23 +2366,17 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2090 | 2366 | .addend = 0, |
| 2091 | 2367 | })); |
| 2092 | 2368 | |
| 2093 | | const reserved_got_plt_entries: u32 = switch (elf.ehdrField(.machine)) { |
| 2369 | // Note that some architectures don't have .got.plt (e.g. SPARC), and so |
| 2370 | // these values actually refer to .plt. |
| 2371 | const got_plt_section, const got_plt_offset = switch (elf.ehdrField(.machine)) { |
| 2094 | 2372 | else => |machine| @panic(@tagName(machine)), |
| 2095 | | .X86_64 => 3, |
| 2096 | | .LOONGARCH => 2, |
| 2373 | .LOONGARCH => .{ elf.shndx.got_plt, elf.targetPtrSize() * (2 + plt_index) }, |
| 2374 | .SPARCV9 => .{ elf.shndx.plt, 32 * (4 + plt_index) }, |
| 2375 | .X86_64 => .{ elf.shndx.got_plt, elf.targetPtrSize() * (3 + plt_index) }, |
| 2097 | 2376 | }; |
| 2098 | 2377 | |
| 2099 | 2378 | // Now that we know the index, we can set the relocation's offset. |
| 2100 | | const got_plt_addr = switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2101 | | inline else => |shdr, class| got_plt_addr: { |
| 2102 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2103 | | assert(elf.targetLoad(&shdr.entsize) == ent_size); |
| 2104 | | const offset = ent_size * @as(u64, reserved_got_plt_entries + plt_index); |
| 2105 | | assert(offset <= elf.targetLoad(&shdr.size)); |
| 2106 | | break :got_plt_addr elf.targetLoad(&shdr.addr) + offset; |
| 2107 | | }, |
| 2108 | | }; |
| 2109 | | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_addr); |
| 2379 | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_section.vaddr(elf) + got_plt_offset); |
| 2110 | 2380 | |
| 2111 | 2381 | if (plt_index < elf.plt.count()) { |
| 2112 | 2382 | // We reused a free entry, so we're already done! |
| ... | ... | @@ -2148,13 +2418,11 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2148 | 2418 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2149 | 2419 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2150 | 2420 | inline else => |shdr, class| { |
| 2151 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2152 | | const old_size = ent_size * (3 + plt_index); |
| 2153 | | assert(elf.targetLoad(&shdr.size) == old_size); |
| 2154 | | elf.targetStore(&shdr.size, old_size + ent_size); |
| 2421 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2422 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(class.ElfN().Addr)); |
| 2155 | 2423 | std.mem.writeInt( |
| 2156 | 2424 | class.ElfN().Addr, |
| 2157 | | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], |
| 2425 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(class.ElfN().Addr)], |
| 2158 | 2426 | @intCast(plt_addr), |
| 2159 | 2427 | target_endian, |
| 2160 | 2428 | ); |
| ... | ... | @@ -2176,7 +2444,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2176 | 2444 | i32, |
| 2177 | 2445 | plt_sec_slice[6..][0..4], |
| 2178 | 2446 | @intCast(@as(i64, @bitCast( |
| 2179 | | got_plt_addr -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| 2447 | (got_plt_section.vaddr(elf) + got_plt_offset) -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| 2180 | 2448 | ))), |
| 2181 | 2449 | target_endian, |
| 2182 | 2450 | ); |
| ... | ... | @@ -2212,26 +2480,54 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2212 | 2480 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2213 | 2481 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2214 | 2482 | inline else => |shdr, class| { |
| 2215 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2216 | | const old_size = ent_size * (2 + plt_index); |
| 2217 | | assert(elf.targetLoad(&shdr.size) == old_size); |
| 2218 | | elf.targetStore(&shdr.size, old_size + ent_size); |
| 2483 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2484 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(class.ElfN().Addr)); |
| 2219 | 2485 | std.mem.writeInt( |
| 2220 | 2486 | class.ElfN().Addr, |
| 2221 | | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], |
| 2487 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(class.ElfN().Addr)], |
| 2222 | 2488 | @intCast(plt_addr), |
| 2223 | 2489 | target_endian, |
| 2224 | 2490 | ); |
| 2225 | | assert(got_plt_addr == (elf.targetLoad(&shdr.addr) + old_size)); |
| 2226 | 2491 | }, |
| 2227 | 2492 | } |
| 2228 | 2493 | |
| 2229 | 2494 | // relocate the PLT entry to point to the .GOT.PLT entry |
| 2230 | | const got_plt_abs: u64 = @as(u64, got_plt_addr); |
| 2495 | const got_plt_abs = got_plt_section.vaddr(elf) + got_plt_offset; |
| 2231 | 2496 | // TODO: handle overflow gracefully |
| 2232 | 2497 | link.loongarch.writeJ20(plt_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr)); |
| 2233 | 2498 | link.loongarch.writeK12(plt_slice[4..8], @truncate(got_plt_abs)); |
| 2234 | 2499 | }, |
| 2500 | .SPARCV9 => { |
| 2501 | // add a .PLT entry, writing the template |
| 2502 | const plt_ni = elf.shndx.plt.get(elf).ni; |
| 2503 | switch (elf.shdrPtr(elf.shndx.plt)) { |
| 2504 | inline else => |shdr| { |
| 2505 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2506 | elf.targetStore(&shdr.size, got_plt_offset + 32); |
| 2507 | const plt_slice: []u32 = @ptrCast(@alignCast(plt_ni.slice(&elf.mf)[got_plt_offset..][0..32])); |
| 2508 | // sethi (. - .plt[0]), %g1 |
| 2509 | // ba,a %xcc, .plt[1] |
| 2510 | // nop |
| 2511 | // nop |
| 2512 | // nop |
| 2513 | // nop |
| 2514 | // nop |
| 2515 | // nop |
| 2516 | @memcpy(plt_slice, &([2]u32{ |
| 2517 | // TODO: handle overflow gracefully |
| 2518 | @bitCast(link.sparc.reloc.Imm22{ |
| 2519 | .imm22 = @truncate(got_plt_offset), |
| 2520 | .b22_31 = 0b0000000011, |
| 2521 | }), |
| 2522 | @bitCast(link.sparc.reloc.Disp19{ |
| 2523 | .disp19 = @truncate((got_plt_offset + 4 - 32) >> 2), |
| 2524 | .b19_31 = 0b1100001101000, |
| 2525 | }), |
| 2526 | } ++ @as([6]u32, @splat(0x01000000)))); |
| 2527 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllElements(u32, plt_slice); |
| 2528 | }, |
| 2529 | } |
| 2530 | }, |
| 2235 | 2531 | } |
| 2236 | 2532 | } |
| 2237 | 2533 | |
| ... | ... | @@ -2622,12 +2918,12 @@ pub const ExternSymbolOpts = struct { |
| 2622 | 2918 | }; |
| 2623 | 2919 | pub fn externSymbol(elf: *Elf, opts: ExternSymbolOpts) link.Error!link.File.SymbolId { |
| 2624 | 2920 | const diags = &elf.base.comp.link_diags; |
| 2625 | | return elf.externSymbolInner(opts) catch |err| switch (err) { |
| 2921 | return (elf.externSymbolInner(opts) catch |err| switch (err) { |
| 2626 | 2922 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), |
| 2627 | 2923 | else => |e| return e, |
| 2628 | | }; |
| 2924 | }).toTypeErased(); |
| 2629 | 2925 | } |
| 2630 | | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId { |
| 2926 | fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!Symbol.Id { |
| 2631 | 2927 | try elf.ensureUnusedSymbolCapacity(1, .maybe_global); |
| 2632 | 2928 | const symbol = elf.addGlobalSymbolAssumeCapacity(.{ |
| 2633 | 2929 | .node = .none, |
| ... | ... | @@ -2651,7 +2947,7 @@ fn externSymbolInner(elf: *Elf, opts: ExternSymbolOpts) Error!link.File.SymbolId |
| 2651 | 2947 | }) catch |err| switch (err) { |
| 2652 | 2948 | error.MultipleDefinitions => unreachable, // shndx is undef |
| 2653 | 2949 | }; |
| 2654 | | return symbol.toTypeErased(); |
| 2950 | return symbol; |
| 2655 | 2951 | } |
| 2656 | 2952 | pub fn addReloc( |
| 2657 | 2953 | elf: *Elf, |
| ... | ... | @@ -3084,11 +3380,12 @@ fn initHeaders( |
| 3084 | 3380 | .@"64" => .@"8", |
| 3085 | 3381 | }; |
| 3086 | 3382 | |
| 3087 | | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec = |
| 3383 | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const got_plt, const plt_sec = |
| 3088 | 3384 | switch (machine) { |
| 3089 | 3385 | else => @panic(@tagName(machine)), |
| 3090 | | .X86_64 => .{ 16, .@"16", true }, |
| 3091 | | .LOONGARCH => .{ 32, .@"4", false }, |
| 3386 | .LOONGARCH => .{ 16 * 2, .@"4", true, false }, |
| 3387 | .SPARCV9 => .{ 32 * 4, .fromByteUnits(256), false, false }, |
| 3388 | .X86_64 => .{ 16, .@"16", true, true }, |
| 3092 | 3389 | }; |
| 3093 | 3390 | |
| 3094 | 3391 | const shnum: u32 = shnum: { |
| ... | ... | @@ -3111,7 +3408,7 @@ fn initHeaders( |
| 3111 | 3408 | } |
| 3112 | 3409 | if (@"type" != .REL) { |
| 3113 | 3410 | shnum += 1; // .got |
| 3114 | | shnum += 1; // .got.plt |
| 3411 | shnum += @intFromBool(got_plt); // .got.plt |
| 3115 | 3412 | shnum += 1; // .plt |
| 3116 | 3413 | shnum += @intFromBool(plt_sec); // .plt_sec |
| 3117 | 3414 | } |
| ... | ... | @@ -3212,7 +3509,6 @@ fn initHeaders( |
| 3212 | 3509 | ehdr.phoff = 0; |
| 3213 | 3510 | ehdr.shoff = 0; |
| 3214 | 3511 | ehdr.flags = switch (machine) { |
| 3215 | | .X86_64 => 0, |
| 3216 | 3512 | .LOONGARCH => e_flags: { |
| 3217 | 3513 | const target_cpu = &elf.base.comp.getTarget().cpu; |
| 3218 | 3514 | const e_flags: std.elf.loongarch.EFlags = .{ |
| ... | ... | @@ -3227,6 +3523,20 @@ fn initHeaders( |
| 3227 | 3523 | }; |
| 3228 | 3524 | break :e_flags @bitCast(e_flags); |
| 3229 | 3525 | }, |
| 3526 | .SPARCV9 => e_flags: { |
| 3527 | const e_flags: std.elf.sparc.EFlags = .{ |
| 3528 | .mm = .rmo, |
| 3529 | .ext = .{ |
| 3530 | .@"32plus" = false, |
| 3531 | .sun_us1 = false, |
| 3532 | .hal_r1 = false, |
| 3533 | .sun_us3 = false, |
| 3534 | .le_data = false, |
| 3535 | }, |
| 3536 | }; |
| 3537 | break :e_flags @bitCast(e_flags); |
| 3538 | }, |
| 3539 | .X86_64 => 0, |
| 3230 | 3540 | else => @panic(@tagName(machine)), |
| 3231 | 3541 | }; |
| 3232 | 3542 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); |
| ... | ... | @@ -3247,6 +3557,31 @@ fn initHeaders( |
| 3247 | 3557 | })); |
| 3248 | 3558 | elf.nodes.appendAssumeCapacity(.shdr); |
| 3249 | 3559 | |
| 3560 | const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) { |
| 3561 | .BPF, |
| 3562 | .SPARCV9, |
| 3563 | => 0x100000, |
| 3564 | .AARCH64, |
| 3565 | .AMDGPU, |
| 3566 | .QDSP6, |
| 3567 | .MIPS, |
| 3568 | .PPC, |
| 3569 | .PPC64, |
| 3570 | .SPARC, |
| 3571 | .SPARC32PLUS, |
| 3572 | => 0x10000, |
| 3573 | .LOONGARCH, |
| 3574 | => 0x4000, |
| 3575 | .ARC_COMPACT2, |
| 3576 | .@"68K", |
| 3577 | => 0x2000, |
| 3578 | .MSP430, |
| 3579 | => 0x4, |
| 3580 | .AVR, |
| 3581 | => 0x1, |
| 3582 | else => 0x1000, |
| 3583 | }); |
| 3584 | |
| 3250 | 3585 | var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: { |
| 3251 | 3586 | assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 3252 | 3587 | .alignment = elf.mf.flags.block_size, |
| ... | ... | @@ -3299,8 +3634,8 @@ fn initHeaders( |
| 3299 | 3634 | .@"386" => 0x400000, |
| 3300 | 3635 | .AARCH64, .X86_64 => 0x200000, |
| 3301 | 3636 | .PPC, .PPC64 => 0x10000000, |
| 3302 | | .S390, .S390_OLD => 0x1000000, |
| 3303 | | .OLD_SPARCV9, .SPARCV9 => 0x100000, |
| 3637 | .S390 => 0x1000000, |
| 3638 | .SPARCV9 => 0x100000, |
| 3304 | 3639 | else => 0x10000, |
| 3305 | 3640 | }, |
| 3306 | 3641 | }; |
| ... | ... | @@ -3351,7 +3686,7 @@ fn initHeaders( |
| 3351 | 3686 | .filesz = @intCast(rodata_size), |
| 3352 | 3687 | .memsz = @intCast(rodata_size), |
| 3353 | 3688 | .flags = .{ .R = true }, |
| 3354 | | .@"align" = @intCast(elf.ni.rodata.alignment(&elf.mf).toByteUnits()), |
| 3689 | .@"align" = @intCast(elf.ni.rodata.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3355 | 3690 | }; |
| 3356 | 3691 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); |
| 3357 | 3692 | ph_vaddr += @intCast(rodata_size); |
| ... | ... | @@ -3366,7 +3701,7 @@ fn initHeaders( |
| 3366 | 3701 | .filesz = @intCast(text_size), |
| 3367 | 3702 | .memsz = @intCast(text_size), |
| 3368 | 3703 | .flags = .{ .R = true, .X = true }, |
| 3369 | | .@"align" = @intCast(elf.ni.text.alignment(&elf.mf).toByteUnits()), |
| 3704 | .@"align" = @intCast(elf.ni.text.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3370 | 3705 | }; |
| 3371 | 3706 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); |
| 3372 | 3707 | ph_vaddr += @intCast(text_size); |
| ... | ... | @@ -3381,7 +3716,7 @@ fn initHeaders( |
| 3381 | 3716 | .filesz = @intCast(data_size), |
| 3382 | 3717 | .memsz = @intCast(data_size), |
| 3383 | 3718 | .flags = .{ .R = true, .W = true }, |
| 3384 | | .@"align" = @intCast(elf.ni.data.alignment(&elf.mf).toByteUnits()), |
| 3719 | .@"align" = @intCast(elf.ni.data.alignment(&elf.mf).max(page_align).toByteUnits()), |
| 3385 | 3720 | }; |
| 3386 | 3721 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); |
| 3387 | 3722 | ph_vaddr += @intCast(data_size); |
| ... | ... | @@ -3536,14 +3871,16 @@ fn initHeaders( |
| 3536 | 3871 | // Reserve space for the reserved words, populated later. |
| 3537 | 3872 | .size = switch (machine) { |
| 3538 | 3873 | else => @panic(@tagName(machine)), |
| 3539 | | .X86_64 => 3 * 8, |
| 3540 | | .LOONGARCH => if (elf.identClass() == .@"64") 8 else 4, |
| 3874 | .X86_64 => 3 * elf.targetPtrSize(), |
| 3875 | .LOONGARCH, |
| 3876 | .SPARCV9, |
| 3877 | => elf.targetPtrSize(), |
| 3541 | 3878 | }, |
| 3542 | 3879 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 3543 | 3880 | .addralign = addr_align, |
| 3544 | 3881 | .entsize = @intCast(addr_align.toByteUnits()), |
| 3545 | 3882 | }); |
| 3546 | | elf.shndx.got_plt = try elf.addSection( |
| 3883 | if (got_plt) elf.shndx.got_plt = try elf.addSection( |
| 3547 | 3884 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, |
| 3548 | 3885 | .{ |
| 3549 | 3886 | .name = ".got.plt", |
| ... | ... | @@ -3553,7 +3890,7 @@ fn initHeaders( |
| 3553 | 3890 | else => @panic(@tagName(machine)), |
| 3554 | 3891 | .@"386" => 3 * 4, |
| 3555 | 3892 | .X86_64 => 3 * 8, |
| 3556 | | .LOONGARCH => if (elf.identClass() == .@"64") 2 * 8 else 2 * 4, |
| 3893 | .LOONGARCH => 2 * elf.targetPtrSize(), |
| 3557 | 3894 | }, |
| 3558 | 3895 | .addralign = addr_align, |
| 3559 | 3896 | .entsize = @intCast(addr_align.toByteUnits()), |
| ... | ... | @@ -3562,7 +3899,14 @@ fn initHeaders( |
| 3562 | 3899 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 3563 | 3900 | .name = ".plt", |
| 3564 | 3901 | .type = .PROGBITS, |
| 3565 | | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| 3902 | .flags = .{ |
| 3903 | .ALLOC = true, |
| 3904 | .EXECINSTR = true, |
| 3905 | .WRITE = switch (machine) { |
| 3906 | .SPARCV9 => true, |
| 3907 | else => false, |
| 3908 | }, |
| 3909 | }, |
| 3566 | 3910 | .size = init_plt_size, |
| 3567 | 3911 | .addralign = plt_align, |
| 3568 | 3912 | .node_align = elf.mf.flags.block_size, |
| ... | ... | @@ -3661,7 +4005,7 @@ fn initHeaders( |
| 3661 | 4005 | .type = .RELA, |
| 3662 | 4006 | .flags = .{ .ALLOC = true, .INFO_LINK = true }, |
| 3663 | 4007 | .link = elf.shndx.dynsym.toSection().?, |
| 3664 | | .info = elf.shndx.got_plt.toSection().?, |
| 4008 | .info = (if (got_plt) elf.shndx.got_plt else elf.shndx.plt).toSection().?, |
| 3665 | 4009 | .addralign = addr_align, |
| 3666 | 4010 | .entsize = rela_size, |
| 3667 | 4011 | .node_align = elf.mf.flags.block_size, |
| ... | ... | @@ -3729,10 +4073,11 @@ fn initHeaders( |
| 3729 | 4073 | }); |
| 3730 | 4074 | elf.plt_first_symbol_reloc = @enumFromInt(elf.symbol_relocs.items.len); |
| 3731 | 4075 | try elf.ensureUnusedRelocCapacity(plt_ni, 3); |
| 3732 | | try elf.addSymbolRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .rel32_hi20); |
| 3733 | | try elf.addSymbolRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .abs32_lo12); |
| 3734 | | try elf.addSymbolRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .abs32_lo12); |
| 4076 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 0, got_plt_sym, 0, .larch_rel32_hi20); |
| 4077 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .larch_abs32_lo12); |
| 4078 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .larch_abs32_lo12); |
| 3735 | 4079 | }, |
| 4080 | .SPARCV9 => {}, |
| 3736 | 4081 | } |
| 3737 | 4082 | } |
| 3738 | 4083 | if (comp.config.any_non_single_threaded) { |
| ... | ... | @@ -3757,7 +4102,9 @@ fn initHeaders( |
| 3757 | 4102 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 1 }, .none); |
| 3758 | 4103 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 2 }, .none); |
| 3759 | 4104 | }, |
| 3760 | | .LOONGARCH => { |
| 4105 | .LOONGARCH, |
| 4106 | .SPARCV9, |
| 4107 | => { |
| 3761 | 4108 | try elf.got.ensureUnusedCapacity(gpa, 1); |
| 3762 | 4109 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { |
| 3763 | 4110 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| ... | ... | @@ -4075,35 +4422,38 @@ fn identData(elf: *const Elf) std.elf.DATA { |
| 4075 | 4422 | return @enumFromInt(elf.mf.memory_map.memory[std.elf.EI.DATA]); |
| 4076 | 4423 | } |
| 4077 | 4424 | |
| 4425 | fn targetPtrSize(elf: *const Elf) u32 { |
| 4426 | return elf.identClass().size(); |
| 4427 | } |
| 4078 | 4428 | fn targetEndian(elf: *const Elf) std.lang.Endian { |
| 4079 | | return switch (elf.identData()) { |
| 4080 | | .NONE, _ => unreachable, |
| 4081 | | .@"2LSB" => .little, |
| 4082 | | .@"2MSB" => .big, |
| 4083 | | }; |
| 4429 | return elf.identData().endian(); |
| 4084 | 4430 | } |
| 4085 | 4431 | fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.child { |
| 4086 | | const Child = @typeInfo(@TypeOf(ptr)).pointer.child; |
| 4432 | const pointer_ty = @typeInfo(@TypeOf(ptr)).pointer; |
| 4433 | const Child = pointer_ty.child; |
| 4434 | const alignment = pointer_ty.attrs.@"align" orelse @alignOf(Child); |
| 4087 | 4435 | return switch (@typeInfo(Child)) { |
| 4088 | 4436 | else => @compileError(@typeName(Child)), |
| 4089 | 4437 | .int => std.mem.toNative(Child, ptr.*, elf.targetEndian()), |
| 4090 | | .@"enum" => |@"enum"| @enumFromInt(elf.targetLoad(@as(*@"enum".tag_type, @ptrCast(ptr)))), |
| 4438 | .@"enum" => |@"enum"| @enumFromInt(elf.targetLoad(@as(*align(alignment) @"enum".tag_type, @ptrCast(ptr)))), |
| 4091 | 4439 | .@"struct" => |@"struct"| @bitCast( |
| 4092 | | elf.targetLoad(@as(*@"struct".backing_integer.?, @ptrCast(ptr))), |
| 4440 | elf.targetLoad(@as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr))), |
| 4093 | 4441 | ), |
| 4094 | 4442 | }; |
| 4095 | 4443 | } |
| 4096 | 4444 | fn targetStore(elf: *const Elf, ptr: anytype, val: @typeInfo(@TypeOf(ptr)).pointer.child) void { |
| 4097 | | const Child = @typeInfo(@TypeOf(ptr)).pointer.child; |
| 4445 | const pointer_ty = @typeInfo(@TypeOf(ptr)).pointer; |
| 4446 | const Child = pointer_ty.child; |
| 4447 | const alignment = pointer_ty.attrs.@"align" orelse @alignOf(Child); |
| 4098 | 4448 | return switch (@typeInfo(Child)) { |
| 4099 | 4449 | else => @compileError(@typeName(Child)), |
| 4100 | 4450 | .int => ptr.* = std.mem.nativeTo(Child, val, elf.targetEndian()), |
| 4101 | 4451 | .@"enum" => |@"enum"| elf.targetStore( |
| 4102 | | @as(*@"enum".tag_type, @ptrCast(ptr)), |
| 4452 | @as(*align(alignment) @"enum".tag_type, @ptrCast(ptr)), |
| 4103 | 4453 | @intFromEnum(val), |
| 4104 | 4454 | ), |
| 4105 | 4455 | .@"struct" => |@"struct"| elf.targetStore( |
| 4106 | | @as(*@"struct".backing_integer.?, @ptrCast(ptr)), |
| 4456 | @as(*align(alignment) @"struct".backing_integer.?, @ptrCast(ptr)), |
| 4107 | 4457 | @bitCast(val), |
| 4108 | 4458 | ), |
| 4109 | 4459 | }; |
| ... | ... | @@ -5433,6 +5783,11 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5433 | 5783 | }; |
| 5434 | 5784 | } |
| 5435 | 5785 | |
| 5786 | const got_plt = switch (elf.ehdrField(.machine)) { |
| 5787 | .SPARCV9 => false, |
| 5788 | else => true, |
| 5789 | }; |
| 5790 | |
| 5436 | 5791 | if (elf.shndx.dynamic != .UNDEF) switch (elf.identClass()) { |
| 5437 | 5792 | .NONE, _ => unreachable, |
| 5438 | 5793 | inline else => |ct_class| { |
| ... | ... | @@ -5616,7 +5971,7 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5616 | 5971 | if (dynamic_indices.pltgot) |index| try elf.addSymbolRelocAssumeCapacity( |
| 5617 | 5972 | dynamic_ni, |
| 5618 | 5973 | @sizeOf(ElfN.Addr) * (2 * index + 1), |
| 5619 | | .local(elf.shndx.got_plt.get(elf).lsi), |
| 5974 | .local((if (got_plt) elf.shndx.got_plt else elf.shndx.plt).get(elf).lsi), |
| 5620 | 5975 | 0, |
| 5621 | 5976 | dsorel, |
| 5622 | 5977 | ); |
| ... | ... | @@ -5938,33 +6293,141 @@ fn addRelocAssumeCapacity( |
| 5938 | 6293 | .@"64_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64), |
| 5939 | 6294 | .@"32_PCREL" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32), |
| 5940 | 6295 | |
| 5941 | | .PCALA_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32_lo12), |
| 5942 | | .PCALA_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32_hi20), |
| 5943 | | .PCALA64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_hi12), |
| 5944 | | .PCALA64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64_lo20), |
| 6296 | .PCALA_LO12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_abs32_lo12), |
| 6297 | .PCALA_HI20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel32_hi20), |
| 6298 | .PCALA64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel64_hi12), |
| 6299 | .PCALA64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_rel64_lo20), |
| 5945 | 6300 | |
| 5946 | | .B16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel18), |
| 5947 | | .B21 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel23), |
| 5948 | | .B26 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .branch_rel28), |
| 5949 | | .CALL36 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .call_rel38), |
| 6301 | .B16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel18), |
| 6302 | .B21 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel23), |
| 6303 | .B26 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_branch_rel28), |
| 6304 | .CALL36 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_call_rel38), |
| 5950 | 6305 | |
| 5951 | 6306 | // Relocations targeting a TLS symbol |
| 5952 | | .TLS_LE_LO12, .TLS_LE_LO12_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_lo12), |
| 5953 | | .TLS_LE_HI20, .TLS_LE_HI20_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32_hi20), |
| 5954 | | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_lo20), |
| 5955 | | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64_hi12), |
| 6307 | .TLS_LE_LO12, .TLS_LE_LO12_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff32_lo12), |
| 6308 | .TLS_LE_HI20, .TLS_LE_HI20_R => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff32_hi20), |
| 6309 | .TLS_LE64_LO20 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff64_lo20), |
| 6310 | .TLS_LE64_HI12 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .larch_tpoff64_hi12), |
| 5956 | 6311 | .TLS_LE_ADD_R => {}, // TODO: relaxation is not yet implemented |
| 5957 | 6312 | |
| 5958 | 6313 | // Relocations targeting a GOT entry |
| 5959 | | .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12), |
| 5960 | | .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel32_hi20), |
| 5961 | | .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_lo20), |
| 5962 | | .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .rel64_hi12), |
| 5963 | | |
| 5964 | | .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_lo12), |
| 5965 | | .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs32_hi20), |
| 5966 | | .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_lo20), |
| 5967 | | .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .abs64_hi12), |
| 6314 | .GOT_PC_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_lo12), |
| 6315 | .GOT_PC_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel32_hi20), |
| 6316 | .GOT64_PC_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel64_lo20), |
| 6317 | .GOT64_PC_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_rel64_hi12), |
| 6318 | |
| 6319 | .GOT_LO12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_lo12), |
| 6320 | .GOT_HI20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs32_hi20), |
| 6321 | .GOT64_LO20 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs64_lo20), |
| 6322 | .GOT64_HI12 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .larch_abs64_hi12), |
| 6323 | }, |
| 6324 | .SPARCV9 => switch (@"type".SPARC) { |
| 6325 | _, |
| 6326 | .NONE, |
| 6327 | .COPY, |
| 6328 | .GLOB_DAT, |
| 6329 | .JMP_SLOT, |
| 6330 | .RELATIVE, |
| 6331 | .IRELATIVE, |
| 6332 | => std.debug.panic("TODO: error for illegal or unsupported input relocation, {t}", .{@"type".SPARC}), |
| 6333 | |
| 6334 | inline .WDISP22, |
| 6335 | .HI22, |
| 6336 | .@"22", |
| 6337 | .@"13", |
| 6338 | .LO10, |
| 6339 | .HIPLT22, |
| 6340 | .LOPLT10, |
| 6341 | .PCPLT22, |
| 6342 | .PCPLT10, |
| 6343 | .@"10", |
| 6344 | .@"11", |
| 6345 | .OLO10, |
| 6346 | .HH22, |
| 6347 | .HM10, |
| 6348 | .LM22, |
| 6349 | .PC_HH22, |
| 6350 | .PC_HM10, |
| 6351 | .PC_LM22, |
| 6352 | .WDISP16, |
| 6353 | .WDISP19, |
| 6354 | .@"7", |
| 6355 | .@"5", |
| 6356 | .@"6", |
| 6357 | .HIX22, |
| 6358 | .LOX10, |
| 6359 | .REGISTER, |
| 6360 | .TLS_GD_HI22, |
| 6361 | .TLS_GD_LO10, |
| 6362 | .TLS_IE_HI22, |
| 6363 | .TLS_IE_LO10, |
| 6364 | .TLS_DTPMOD32, |
| 6365 | .TLS_DTPMOD64, |
| 6366 | .H34, |
| 6367 | .WDISP10, |
| 6368 | => |t| @panic("TODO: " ++ @tagName(t)), |
| 6369 | |
| 6370 | // Relocations targeting a symbol |
| 6371 | .@"8" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs8), |
| 6372 | .@"16" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16), |
| 6373 | .@"32" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32), |
| 6374 | .DISP8 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel8), |
| 6375 | .DISP16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel16), |
| 6376 | .DISP32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel32), |
| 6377 | .WDISP30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_wdisp30), |
| 6378 | .PC10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_pc10), |
| 6379 | .PC22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_pc22), |
| 6380 | .WPLT30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_wplt30), |
| 6381 | .UA32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs32), |
| 6382 | .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs32), |
| 6383 | .PCPLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltrel32), |
| 6384 | .@"64" => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64), |
| 6385 | .DISP64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .rel64), |
| 6386 | .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .pltabs64), |
| 6387 | .H44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_h44), |
| 6388 | .M44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_m44), |
| 6389 | .L44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_l44), |
| 6390 | .UA64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs64), |
| 6391 | .UA16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .abs16), |
| 6392 | .TLS_GD_CALL, .TLS_LDM_CALL => try elf.addSymbolRelocAssumeCapacity(node, offset, try elf.externSymbolInner(.{ |
| 6393 | .lib_name = null, |
| 6394 | .name = "__tls_get_addr", |
| 6395 | .type = .FUNC, |
| 6396 | }), addend, .sparc_wplt30), |
| 6397 | .SIZE32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size32), |
| 6398 | .SIZE64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .size64), |
| 6399 | |
| 6400 | // Relocations targeting a TLS symbol |
| 6401 | .TLS_LDO_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_ldo_hix22), |
| 6402 | .TLS_LDO_LOX10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_ldo_lox10), |
| 6403 | .TLS_LE_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_le_hix22), |
| 6404 | .TLS_LE_LOX10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .sparc_le_lox10), |
| 6405 | .TLS_DTPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .dtpoff32), |
| 6406 | .TLS_DTPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .dtpoff64), |
| 6407 | .TLS_TPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff32), |
| 6408 | .TLS_TPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .tpoff64), |
| 6409 | // We currently do no relaxation, so nothing to do for these. |
| 6410 | .TLS_GD_ADD, |
| 6411 | .TLS_LDM_ADD, |
| 6412 | .TLS_LDO_ADD, |
| 6413 | .TLS_IE_LD, |
| 6414 | .TLS_IE_LDX, |
| 6415 | .TLS_IE_ADD, |
| 6416 | => {}, |
| 6417 | |
| 6418 | // Relocations targeting a GOT entry |
| 6419 | .GOT10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_10), |
| 6420 | .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_13), |
| 6421 | .GOT22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_22), |
| 6422 | .TLS_LDM_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .sparc_ldm_hi22), |
| 6423 | .TLS_LDM_LO10 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .sparc_ldm_lo10), |
| 6424 | // These need similar handling to `R_X86_64_GOTOFF64`. No compiler seems to emit them though. |
| 6425 | .GOTDATA_HIX22 => @panic("TODO: R_SPARC_GOTDATA_HIX22"), |
| 6426 | .GOTDATA_LOX10 => @panic("TODO: R_SPARC_GOTDATA_LOX10"), |
| 6427 | .GOTDATA_OP_HIX22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_op_hix22), |
| 6428 | .GOTDATA_OP_LOX10 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .sparc_op_lox10), |
| 6429 | // We currently do no relaxation, so nothing to do for this one. |
| 6430 | .GOTDATA_OP => {}, |
| 5968 | 6431 | }, |
| 5969 | 6432 | }, |
| 5970 | 6433 | } |
| ... | ... | @@ -6008,29 +6471,46 @@ fn addSymbolRelocAssumeCapacity( |
| 6008 | 6471 | }, |
| 6009 | 6472 | .abs64 => .@"64", |
| 6010 | 6473 | .abs32 => .@"32", |
| 6474 | .abs16 => unreachable, |
| 6475 | .abs8 => unreachable, |
| 6011 | 6476 | .abs32s => .@"32S", |
| 6012 | 6477 | .rel64 => .PC64, |
| 6013 | 6478 | .rel32 => .PC32, |
| 6014 | | .pltrel64 => break :r .none, |
| 6015 | | .pltrel32 => break :r .none, |
| 6479 | .rel16 => unreachable, |
| 6480 | .rel8 => unreachable, |
| 6481 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| 6016 | 6482 | .dtpoff64 => .DTPOFF64, |
| 6017 | 6483 | .dtpoff32 => .DTPOFF32, |
| 6018 | 6484 | .tpoff64 => .TPOFF64, |
| 6019 | 6485 | .tpoff32 => .TPOFF32, |
| 6020 | 6486 | .size64 => .SIZE64, |
| 6021 | 6487 | .size32 => .SIZE32, |
| 6022 | | .abs32_lo12, |
| 6023 | | .rel32_hi20, |
| 6024 | | .rel64_lo20, |
| 6025 | | .rel64_hi12, |
| 6026 | | .branch_rel18, |
| 6027 | | .branch_rel23, |
| 6028 | | .branch_rel28, |
| 6029 | | .call_rel38, |
| 6030 | | .tpoff32_lo12, |
| 6031 | | .tpoff32_hi20, |
| 6032 | | .tpoff64_lo20, |
| 6033 | | .tpoff64_hi12, |
| 6488 | |
| 6489 | .larch_abs32_lo12, |
| 6490 | .larch_rel32_hi20, |
| 6491 | .larch_rel64_lo20, |
| 6492 | .larch_rel64_hi12, |
| 6493 | .larch_branch_rel18, |
| 6494 | .larch_branch_rel23, |
| 6495 | .larch_branch_rel28, |
| 6496 | .larch_call_rel38, |
| 6497 | .larch_tpoff32_lo12, |
| 6498 | .larch_tpoff32_hi20, |
| 6499 | .larch_tpoff64_lo20, |
| 6500 | .larch_tpoff64_hi12, |
| 6501 | => unreachable, |
| 6502 | |
| 6503 | .sparc_wdisp30, |
| 6504 | .sparc_pc10, |
| 6505 | .sparc_pc22, |
| 6506 | .sparc_wplt30, |
| 6507 | .sparc_h44, |
| 6508 | .sparc_m44, |
| 6509 | .sparc_l44, |
| 6510 | .sparc_ldo_hix22, |
| 6511 | .sparc_ldo_lox10, |
| 6512 | .sparc_le_hix22, |
| 6513 | .sparc_le_lox10, |
| 6034 | 6514 | => unreachable, |
| 6035 | 6515 | } }, |
| 6036 | 6516 | .LOONGARCH => .{ .LOONGARCH = switch (@"type") { |
| ... | ... | @@ -6041,26 +6521,95 @@ fn addSymbolRelocAssumeCapacity( |
| 6041 | 6521 | }, |
| 6042 | 6522 | .abs64 => .@"64", |
| 6043 | 6523 | .abs32 => .@"32", |
| 6044 | | .abs32s, .size64, .size32 => unreachable, |
| 6524 | .abs32s => unreachable, |
| 6525 | .abs16 => unreachable, |
| 6526 | .abs8 => unreachable, |
| 6045 | 6527 | .rel64 => .@"64_PCREL", |
| 6046 | 6528 | .rel32 => .@"32_PCREL", |
| 6047 | | .pltrel64, .pltrel32 => break :r .none, |
| 6529 | .rel16 => unreachable, |
| 6530 | .rel8 => unreachable, |
| 6531 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| 6048 | 6532 | .dtpoff64 => .TLS_DTPREL64, |
| 6049 | 6533 | .dtpoff32 => .TLS_DTPREL32, |
| 6050 | 6534 | .tpoff64 => .TLS_TPREL64, |
| 6051 | 6535 | .tpoff32 => .TLS_TPREL32, |
| 6052 | | .abs32_lo12 => .PCALA_LO12, |
| 6053 | | .rel32_hi20 => .PCALA_HI20, |
| 6054 | | .rel64_lo20 => .PCALA64_LO20, |
| 6055 | | .rel64_hi12 => .PCALA64_HI12, |
| 6056 | | .branch_rel18 => .B16, |
| 6057 | | .branch_rel23 => .B21, |
| 6058 | | .branch_rel28 => .B26, |
| 6059 | | .call_rel38 => .CALL36, |
| 6060 | | .tpoff32_lo12 => .TLS_LE_LO12, |
| 6061 | | .tpoff32_hi20 => .TLS_LE_HI20, |
| 6062 | | .tpoff64_lo20 => .TLS_LE64_LO20, |
| 6063 | | .tpoff64_hi12 => .TLS_LE64_HI12, |
| 6536 | .size64 => unreachable, |
| 6537 | .size32 => unreachable, |
| 6538 | |
| 6539 | .larch_abs32_lo12 => .PCALA_LO12, |
| 6540 | .larch_rel32_hi20 => .PCALA_HI20, |
| 6541 | .larch_rel64_lo20 => .PCALA64_LO20, |
| 6542 | .larch_rel64_hi12 => .PCALA64_HI12, |
| 6543 | .larch_branch_rel18 => .B16, |
| 6544 | .larch_branch_rel23 => .B21, |
| 6545 | .larch_branch_rel28 => .B26, |
| 6546 | .larch_call_rel38 => .CALL36, |
| 6547 | .larch_tpoff32_lo12 => .TLS_LE_LO12, |
| 6548 | .larch_tpoff32_hi20 => .TLS_LE_HI20, |
| 6549 | .larch_tpoff64_lo20 => .TLS_LE64_LO20, |
| 6550 | .larch_tpoff64_hi12 => .TLS_LE64_HI12, |
| 6551 | |
| 6552 | .sparc_wdisp30, |
| 6553 | .sparc_pc10, |
| 6554 | .sparc_pc22, |
| 6555 | .sparc_wplt30, |
| 6556 | .sparc_h44, |
| 6557 | .sparc_m44, |
| 6558 | .sparc_l44, |
| 6559 | .sparc_ldo_hix22, |
| 6560 | .sparc_ldo_lox10, |
| 6561 | .sparc_le_hix22, |
| 6562 | .sparc_le_lox10, |
| 6563 | => unreachable, |
| 6564 | } }, |
| 6565 | .SPARCV9 => .{ .SPARC = switch (@"type") { |
| 6566 | .write_rela => unreachable, |
| 6567 | .dsorel64, .dsorel32 => { |
| 6568 | assert(target.unwrap() == .local); |
| 6569 | break :r .none; |
| 6570 | }, |
| 6571 | .abs64 => .@"64", |
| 6572 | .abs32 => .@"32", |
| 6573 | .abs32s => unreachable, |
| 6574 | .abs16 => .@"16", |
| 6575 | .abs8 => .@"8", |
| 6576 | .rel64 => .DISP64, |
| 6577 | .rel32 => .DISP32, |
| 6578 | .rel16 => .DISP16, |
| 6579 | .rel8 => .DISP8, |
| 6580 | .pltabs64, .pltabs32, .pltrel64, .pltrel32 => break :r .none, |
| 6581 | .dtpoff64 => .TLS_DTPOFF64, |
| 6582 | .dtpoff32 => .TLS_DTPOFF32, |
| 6583 | .tpoff64 => .TLS_TPOFF64, |
| 6584 | .tpoff32 => .TLS_TPOFF32, |
| 6585 | .size64 => .SIZE64, |
| 6586 | .size32 => .SIZE32, |
| 6587 | |
| 6588 | .larch_abs32_lo12, |
| 6589 | .larch_rel32_hi20, |
| 6590 | .larch_rel64_lo20, |
| 6591 | .larch_rel64_hi12, |
| 6592 | .larch_branch_rel18, |
| 6593 | .larch_branch_rel23, |
| 6594 | .larch_branch_rel28, |
| 6595 | .larch_call_rel38, |
| 6596 | .larch_tpoff32_lo12, |
| 6597 | .larch_tpoff32_hi20, |
| 6598 | .larch_tpoff64_lo20, |
| 6599 | .larch_tpoff64_hi12, |
| 6600 | => unreachable, |
| 6601 | |
| 6602 | .sparc_wdisp30 => .WDISP30, |
| 6603 | .sparc_pc10 => .PC10, |
| 6604 | .sparc_pc22 => .PC22, |
| 6605 | .sparc_wplt30 => .WPLT30, |
| 6606 | .sparc_h44 => .H44, |
| 6607 | .sparc_m44 => .M44, |
| 6608 | .sparc_l44 => .L44, |
| 6609 | .sparc_ldo_hix22 => .TLS_LDO_HIX22, |
| 6610 | .sparc_ldo_lox10 => .TLS_LDO_LOX10, |
| 6611 | .sparc_le_hix22 => .TLS_LE_HIX22, |
| 6612 | .sparc_le_lox10 => .TLS_LE_LOX10, |
| 6064 | 6613 | } }, |
| 6065 | 6614 | }; |
| 6066 | 6615 | |
| ... | ... | @@ -6221,8 +6770,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6221 | 6770 | } |
| 6222 | 6771 | const reloc_type: MachineRelocType = switch (elf.ehdrField(.machine)) { |
| 6223 | 6772 | else => |machine| @panic(@tagName(machine)), |
| 6224 | | .X86_64 => .{ .X86_64 = .TPOFF64 }, |
| 6225 | 6773 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_TPREL64 else .TLS_TPREL32 }, |
| 6774 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_TPOFF64 else .TLS_TPOFF32 }, |
| 6775 | .X86_64 => .{ .X86_64 = .TPOFF64 }, |
| 6226 | 6776 | }; |
| 6227 | 6777 | break :val switch (sym_id.unwrap()) { |
| 6228 | 6778 | // For global symbols, just target the right dynsym with no addend. |
| ... | ... | @@ -6270,8 +6820,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6270 | 6820 | .dynamic => .{ .reloc = .{ |
| 6271 | 6821 | .type = switch (elf.ehdrField(.machine)) { |
| 6272 | 6822 | else => |machine| @panic(@tagName(machine)), |
| 6273 | | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6274 | 6823 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| 6824 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| 6825 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6275 | 6826 | }, |
| 6276 | 6827 | .dynsym_index = switch (elf.classifySymbolValue(sym)) { |
| 6277 | 6828 | .static, .static_relative => 0, |
| ... | ... | @@ -6288,8 +6839,9 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { |
| 6288 | 6839 | .dynamic => .{ .reloc = .{ |
| 6289 | 6840 | .type = switch (elf.ehdrField(.machine)) { |
| 6290 | 6841 | else => |machine| @panic(@tagName(machine)), |
| 6291 | | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6292 | 6842 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| 6843 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPMOD64 else .TLS_DTPMOD32 }, |
| 6844 | .X86_64 => .{ .X86_64 = .DTPMOD64 }, |
| 6293 | 6845 | }, |
| 6294 | 6846 | .dynsym_index = 0, |
| 6295 | 6847 | .addend = 0, |
| ... | ... | @@ -7341,6 +7893,17 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad |
| 7341 | 7893 | }, |
| 7342 | 7894 | } |
| 7343 | 7895 | }, |
| 7896 | .SPARCV9 => switch (which) { |
| 7897 | .plt => { |
| 7898 | // Update the offsets of the relocation entries in `.rela.plt`. |
| 7899 | const rela_plt_shndx = elf.shndx.rela_plt; |
| 7900 | for (0..elf.plt.count()) |plt_index| { |
| 7901 | if (elf.pltEntryIsDead(plt_index)) continue; |
| 7902 | rela_plt_shndx.relaAdjustOffset(elf, @enumFromInt(plt_index), old_addr, addr); |
| 7903 | } |
| 7904 | }, |
| 7905 | .plt_sec, .got_plt => unreachable, |
| 7906 | }, |
| 7344 | 7907 | } |
| 7345 | 7908 | } |
| 7346 | 7909 | |