1 //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines utilities to resolve relocations in object files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Object/RelocationResolver.h" 14 15 namespace llvm { 16 namespace object { 17 18 static int64_t getELFAddend(RelocationRef R) { 19 Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); 20 handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { 21 report_fatal_error(EI.message()); 22 }); 23 return *AddendOrErr; 24 } 25 26 static bool supportsX86_64(uint64_t Type) { 27 switch (Type) { 28 case ELF::R_X86_64_NONE: 29 case ELF::R_X86_64_64: 30 case ELF::R_X86_64_DTPOFF32: 31 case ELF::R_X86_64_DTPOFF64: 32 case ELF::R_X86_64_PC32: 33 case ELF::R_X86_64_32: 34 case ELF::R_X86_64_32S: 35 return true; 36 default: 37 return false; 38 } 39 } 40 41 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) { 42 switch (R.getType()) { 43 case ELF::R_X86_64_NONE: 44 return A; 45 case ELF::R_X86_64_64: 46 case ELF::R_X86_64_DTPOFF32: 47 case ELF::R_X86_64_DTPOFF64: 48 return S + getELFAddend(R); 49 case ELF::R_X86_64_PC32: 50 return S + getELFAddend(R) - R.getOffset(); 51 case ELF::R_X86_64_32: 52 case ELF::R_X86_64_32S: 53 return (S + getELFAddend(R)) & 0xFFFFFFFF; 54 default: 55 llvm_unreachable("Invalid relocation type"); 56 } 57 } 58 59 static bool supportsAArch64(uint64_t Type) { 60 switch (Type) { 61 case ELF::R_AARCH64_ABS32: 62 case ELF::R_AARCH64_ABS64: 63 return true; 64 default: 65 return false; 66 } 67 } 68 69 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { 70 switch (R.getType()) { 71 case ELF::R_AARCH64_ABS32: 72 return (S + getELFAddend(R)) & 0xFFFFFFFF; 73 case ELF::R_AARCH64_ABS64: 74 return S + getELFAddend(R); 75 default: 76 llvm_unreachable("Invalid relocation type"); 77 } 78 } 79 80 static bool supportsBPF(uint64_t Type) { 81 switch (Type) { 82 case ELF::R_BPF_64_32: 83 case ELF::R_BPF_64_64: 84 return true; 85 default: 86 return false; 87 } 88 } 89 90 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { 91 switch (R.getType()) { 92 case ELF::R_BPF_64_32: 93 return S & 0xFFFFFFFF; 94 case ELF::R_BPF_64_64: 95 return S; 96 default: 97 llvm_unreachable("Invalid relocation type"); 98 } 99 } 100 101 static bool supportsMips64(uint64_t Type) { 102 switch (Type) { 103 case ELF::R_MIPS_32: 104 case ELF::R_MIPS_64: 105 case ELF::R_MIPS_TLS_DTPREL64: 106 return true; 107 default: 108 return false; 109 } 110 } 111 112 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) { 113 switch (R.getType()) { 114 case ELF::R_MIPS_32: 115 return (S + getELFAddend(R)) & 0xFFFFFFFF; 116 case ELF::R_MIPS_64: 117 return S + getELFAddend(R); 118 case ELF::R_MIPS_TLS_DTPREL64: 119 return S + getELFAddend(R) - 0x8000; 120 default: 121 llvm_unreachable("Invalid relocation type"); 122 } 123 } 124 125 static bool supportsPPC64(uint64_t Type) { 126 switch (Type) { 127 case ELF::R_PPC64_ADDR32: 128 case ELF::R_PPC64_ADDR64: 129 return true; 130 default: 131 return false; 132 } 133 } 134 135 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { 136 switch (R.getType()) { 137 case ELF::R_PPC64_ADDR32: 138 return (S + getELFAddend(R)) & 0xFFFFFFFF; 139 case ELF::R_PPC64_ADDR64: 140 return S + getELFAddend(R); 141 default: 142 llvm_unreachable("Invalid relocation type"); 143 } 144 } 145 146 static bool supportsSystemZ(uint64_t Type) { 147 switch (Type) { 148 case ELF::R_390_32: 149 case ELF::R_390_64: 150 return true; 151 default: 152 return false; 153 } 154 } 155 156 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) { 157 switch (R.getType()) { 158 case ELF::R_390_32: 159 return (S + getELFAddend(R)) & 0xFFFFFFFF; 160 case ELF::R_390_64: 161 return S + getELFAddend(R); 162 default: 163 llvm_unreachable("Invalid relocation type"); 164 } 165 } 166 167 static bool supportsSparc64(uint64_t Type) { 168 switch (Type) { 169 case ELF::R_SPARC_32: 170 case ELF::R_SPARC_64: 171 case ELF::R_SPARC_UA32: 172 case ELF::R_SPARC_UA64: 173 return true; 174 default: 175 return false; 176 } 177 } 178 179 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) { 180 switch (R.getType()) { 181 case ELF::R_SPARC_32: 182 case ELF::R_SPARC_64: 183 case ELF::R_SPARC_UA32: 184 case ELF::R_SPARC_UA64: 185 return S + getELFAddend(R); 186 default: 187 llvm_unreachable("Invalid relocation type"); 188 } 189 } 190 191 static bool supportsAmdgpu(uint64_t Type) { 192 switch (Type) { 193 case ELF::R_AMDGPU_ABS32: 194 case ELF::R_AMDGPU_ABS64: 195 return true; 196 default: 197 return false; 198 } 199 } 200 201 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) { 202 switch (R.getType()) { 203 case ELF::R_AMDGPU_ABS32: 204 case ELF::R_AMDGPU_ABS64: 205 return S + getELFAddend(R); 206 default: 207 llvm_unreachable("Invalid relocation type"); 208 } 209 } 210 211 static bool supportsX86(uint64_t Type) { 212 switch (Type) { 213 case ELF::R_386_NONE: 214 case ELF::R_386_32: 215 case ELF::R_386_PC32: 216 return true; 217 default: 218 return false; 219 } 220 } 221 222 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { 223 switch (R.getType()) { 224 case ELF::R_386_NONE: 225 return A; 226 case ELF::R_386_32: 227 return S + A; 228 case ELF::R_386_PC32: 229 return S - R.getOffset() + A; 230 default: 231 llvm_unreachable("Invalid relocation type"); 232 } 233 } 234 235 static bool supportsPPC32(uint64_t Type) { 236 return Type == ELF::R_PPC_ADDR32; 237 } 238 239 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { 240 if (R.getType() == ELF::R_PPC_ADDR32) 241 return (S + getELFAddend(R)) & 0xFFFFFFFF; 242 llvm_unreachable("Invalid relocation type"); 243 } 244 245 static bool supportsARM(uint64_t Type) { 246 return Type == ELF::R_ARM_ABS32; 247 } 248 249 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) { 250 if (R.getType() == ELF::R_ARM_ABS32) 251 return (S + A) & 0xFFFFFFFF; 252 llvm_unreachable("Invalid relocation type"); 253 } 254 255 static bool supportsAVR(uint64_t Type) { 256 switch (Type) { 257 case ELF::R_AVR_16: 258 case ELF::R_AVR_32: 259 return true; 260 default: 261 return false; 262 } 263 } 264 265 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) { 266 switch (R.getType()) { 267 case ELF::R_AVR_16: 268 return (S + getELFAddend(R)) & 0xFFFF; 269 case ELF::R_AVR_32: 270 return (S + getELFAddend(R)) & 0xFFFFFFFF; 271 default: 272 llvm_unreachable("Invalid relocation type"); 273 } 274 } 275 276 static bool supportsLanai(uint64_t Type) { 277 return Type == ELF::R_LANAI_32; 278 } 279 280 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) { 281 if (R.getType() == ELF::R_LANAI_32) 282 return (S + getELFAddend(R)) & 0xFFFFFFFF; 283 llvm_unreachable("Invalid relocation type"); 284 } 285 286 static bool supportsMips32(uint64_t Type) { 287 switch (Type) { 288 case ELF::R_MIPS_32: 289 case ELF::R_MIPS_TLS_DTPREL32: 290 return true; 291 default: 292 return false; 293 } 294 } 295 296 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) { 297 // FIXME: Take in account implicit addends to get correct results. 298 uint32_t Rel = R.getType(); 299 if (Rel == ELF::R_MIPS_32) 300 return (S + A) & 0xFFFFFFFF; 301 if (Rel == ELF::R_MIPS_TLS_DTPREL32) 302 return (S + A) & 0xFFFFFFFF; 303 llvm_unreachable("Invalid relocation type"); 304 } 305 306 static bool supportsSparc32(uint64_t Type) { 307 switch (Type) { 308 case ELF::R_SPARC_32: 309 case ELF::R_SPARC_UA32: 310 return true; 311 default: 312 return false; 313 } 314 } 315 316 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) { 317 uint32_t Rel = R.getType(); 318 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) 319 return S + getELFAddend(R); 320 return A; 321 } 322 323 static bool supportsHexagon(uint64_t Type) { 324 return Type == ELF::R_HEX_32; 325 } 326 327 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) { 328 if (R.getType() == ELF::R_HEX_32) 329 return S + getELFAddend(R); 330 llvm_unreachable("Invalid relocation type"); 331 } 332 333 static bool supportsCOFFX86(uint64_t Type) { 334 switch (Type) { 335 case COFF::IMAGE_REL_I386_SECREL: 336 case COFF::IMAGE_REL_I386_DIR32: 337 return true; 338 default: 339 return false; 340 } 341 } 342 343 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) { 344 switch (R.getType()) { 345 case COFF::IMAGE_REL_I386_SECREL: 346 case COFF::IMAGE_REL_I386_DIR32: 347 return (S + A) & 0xFFFFFFFF; 348 default: 349 llvm_unreachable("Invalid relocation type"); 350 } 351 } 352 353 static bool supportsCOFFX86_64(uint64_t Type) { 354 switch (Type) { 355 case COFF::IMAGE_REL_AMD64_SECREL: 356 case COFF::IMAGE_REL_AMD64_ADDR64: 357 return true; 358 default: 359 return false; 360 } 361 } 362 363 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) { 364 switch (R.getType()) { 365 case COFF::IMAGE_REL_AMD64_SECREL: 366 return (S + A) & 0xFFFFFFFF; 367 case COFF::IMAGE_REL_AMD64_ADDR64: 368 return S + A; 369 default: 370 llvm_unreachable("Invalid relocation type"); 371 } 372 } 373 374 static bool supportsMachOX86_64(uint64_t Type) { 375 return Type == MachO::X86_64_RELOC_UNSIGNED; 376 } 377 378 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) { 379 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) 380 return S; 381 llvm_unreachable("Invalid relocation type"); 382 } 383 384 static bool supportsWasm32(uint64_t Type) { 385 switch (Type) { 386 case wasm::R_WASM_FUNCTION_INDEX_LEB: 387 case wasm::R_WASM_TABLE_INDEX_SLEB: 388 case wasm::R_WASM_TABLE_INDEX_I32: 389 case wasm::R_WASM_MEMORY_ADDR_LEB: 390 case wasm::R_WASM_MEMORY_ADDR_SLEB: 391 case wasm::R_WASM_MEMORY_ADDR_I32: 392 case wasm::R_WASM_TYPE_INDEX_LEB: 393 case wasm::R_WASM_GLOBAL_INDEX_LEB: 394 case wasm::R_WASM_FUNCTION_OFFSET_I32: 395 case wasm::R_WASM_SECTION_OFFSET_I32: 396 case wasm::R_WASM_EVENT_INDEX_LEB: 397 return true; 398 default: 399 return false; 400 } 401 } 402 403 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { 404 switch (R.getType()) { 405 case wasm::R_WASM_FUNCTION_INDEX_LEB: 406 case wasm::R_WASM_TABLE_INDEX_SLEB: 407 case wasm::R_WASM_TABLE_INDEX_I32: 408 case wasm::R_WASM_MEMORY_ADDR_LEB: 409 case wasm::R_WASM_MEMORY_ADDR_SLEB: 410 case wasm::R_WASM_MEMORY_ADDR_I32: 411 case wasm::R_WASM_TYPE_INDEX_LEB: 412 case wasm::R_WASM_GLOBAL_INDEX_LEB: 413 case wasm::R_WASM_FUNCTION_OFFSET_I32: 414 case wasm::R_WASM_SECTION_OFFSET_I32: 415 case wasm::R_WASM_EVENT_INDEX_LEB: 416 // For wasm section, its offset at 0 -- ignoring Value 417 return A; 418 default: 419 llvm_unreachable("Invalid relocation type"); 420 } 421 } 422 423 std::pair<bool (*)(uint64_t), RelocationResolver> 424 getRelocationResolver(const ObjectFile &Obj) { 425 if (Obj.isCOFF()) { 426 if (Obj.getBytesInAddress() == 8) 427 return {supportsCOFFX86_64, resolveCOFFX86_64}; 428 return {supportsCOFFX86, resolveCOFFX86}; 429 } else if (Obj.isELF()) { 430 if (Obj.getBytesInAddress() == 8) { 431 switch (Obj.getArch()) { 432 case Triple::x86_64: 433 return {supportsX86_64, resolveX86_64}; 434 case Triple::aarch64: 435 case Triple::aarch64_be: 436 return {supportsAArch64, resolveAArch64}; 437 case Triple::bpfel: 438 case Triple::bpfeb: 439 return {supportsBPF, resolveBPF}; 440 case Triple::mips64el: 441 case Triple::mips64: 442 return {supportsMips64, resolveMips64}; 443 case Triple::ppc64le: 444 case Triple::ppc64: 445 return {supportsPPC64, resolvePPC64}; 446 case Triple::systemz: 447 return {supportsSystemZ, resolveSystemZ}; 448 case Triple::sparcv9: 449 return {supportsSparc64, resolveSparc64}; 450 case Triple::amdgcn: 451 return {supportsAmdgpu, resolveAmdgpu}; 452 default: 453 return {nullptr, nullptr}; 454 } 455 } 456 457 // 32-bit object file 458 assert(Obj.getBytesInAddress() == 4 && 459 "Invalid word size in object file"); 460 461 switch (Obj.getArch()) { 462 case Triple::x86: 463 return {supportsX86, resolveX86}; 464 case Triple::ppc: 465 return {supportsPPC32, resolvePPC32}; 466 case Triple::arm: 467 case Triple::armeb: 468 return {supportsARM, resolveARM}; 469 case Triple::avr: 470 return {supportsAVR, resolveAVR}; 471 case Triple::lanai: 472 return {supportsLanai, resolveLanai}; 473 case Triple::mipsel: 474 case Triple::mips: 475 return {supportsMips32, resolveMips32}; 476 case Triple::sparc: 477 return {supportsSparc32, resolveSparc32}; 478 case Triple::hexagon: 479 return {supportsHexagon, resolveHexagon}; 480 default: 481 return {nullptr, nullptr}; 482 } 483 } else if (Obj.isMachO()) { 484 if (Obj.getArch() == Triple::x86_64) 485 return {supportsMachOX86_64, resolveMachOX86_64}; 486 return {nullptr, nullptr}; 487 } else if (Obj.isWasm()) { 488 if (Obj.getArch() == Triple::wasm32) 489 return {supportsWasm32, resolveWasm32}; 490 return {nullptr, nullptr}; 491 } 492 493 llvm_unreachable("Invalid object file"); 494 } 495 496 } // namespace object 497 } // namespace llvm 498