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 + A) & 0xFFFFFFFF; 94 case ELF::R_BPF_64_64: 95 return S + A; 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 supportsRISCV(uint64_t Type) { 334 switch (Type) { 335 case ELF::R_RISCV_NONE: 336 case ELF::R_RISCV_32: 337 case ELF::R_RISCV_64: 338 case ELF::R_RISCV_SET6: 339 case ELF::R_RISCV_SUB6: 340 case ELF::R_RISCV_ADD8: 341 case ELF::R_RISCV_SUB8: 342 case ELF::R_RISCV_ADD16: 343 case ELF::R_RISCV_SUB16: 344 case ELF::R_RISCV_ADD32: 345 case ELF::R_RISCV_SUB32: 346 case ELF::R_RISCV_ADD64: 347 case ELF::R_RISCV_SUB64: 348 return true; 349 default: 350 return false; 351 } 352 } 353 354 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) { 355 int64_t RA = getELFAddend(R); 356 switch (R.getType()) { 357 case ELF::R_RISCV_NONE: 358 return A; 359 case ELF::R_RISCV_32: 360 return (S + RA) & 0xFFFFFFFF; 361 case ELF::R_RISCV_64: 362 return S + RA; 363 case ELF::R_RISCV_SET6: 364 return (A + (S + RA)) & 0xFF; 365 case ELF::R_RISCV_SUB6: 366 return (A - (S + RA)) & 0xFF; 367 case ELF::R_RISCV_ADD8: 368 return (A + (S + RA)) & 0xFF; 369 case ELF::R_RISCV_SUB8: 370 return (A - (S + RA)) & 0xFF; 371 case ELF::R_RISCV_ADD16: 372 return (A + (S + RA)) & 0xFFFF; 373 case ELF::R_RISCV_SUB16: 374 return (A - (S + RA)) & 0xFFFF; 375 case ELF::R_RISCV_ADD32: 376 return (A + (S + RA)) & 0xFFFFFFFF; 377 case ELF::R_RISCV_SUB32: 378 return (A - (S + RA)) & 0xFFFFFFFF; 379 case ELF::R_RISCV_ADD64: 380 return (A + (S + RA)); 381 case ELF::R_RISCV_SUB64: 382 return (A - (S + RA)); 383 default: 384 llvm_unreachable("Invalid relocation type"); 385 } 386 } 387 388 static bool supportsCOFFX86(uint64_t Type) { 389 switch (Type) { 390 case COFF::IMAGE_REL_I386_SECREL: 391 case COFF::IMAGE_REL_I386_DIR32: 392 return true; 393 default: 394 return false; 395 } 396 } 397 398 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) { 399 switch (R.getType()) { 400 case COFF::IMAGE_REL_I386_SECREL: 401 case COFF::IMAGE_REL_I386_DIR32: 402 return (S + A) & 0xFFFFFFFF; 403 default: 404 llvm_unreachable("Invalid relocation type"); 405 } 406 } 407 408 static bool supportsCOFFX86_64(uint64_t Type) { 409 switch (Type) { 410 case COFF::IMAGE_REL_AMD64_SECREL: 411 case COFF::IMAGE_REL_AMD64_ADDR64: 412 return true; 413 default: 414 return false; 415 } 416 } 417 418 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) { 419 switch (R.getType()) { 420 case COFF::IMAGE_REL_AMD64_SECREL: 421 return (S + A) & 0xFFFFFFFF; 422 case COFF::IMAGE_REL_AMD64_ADDR64: 423 return S + A; 424 default: 425 llvm_unreachable("Invalid relocation type"); 426 } 427 } 428 429 static bool supportsCOFFARM(uint64_t Type) { 430 switch (Type) { 431 case COFF::IMAGE_REL_ARM_SECREL: 432 case COFF::IMAGE_REL_ARM_ADDR32: 433 return true; 434 default: 435 return false; 436 } 437 } 438 439 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) { 440 switch (R.getType()) { 441 case COFF::IMAGE_REL_ARM_SECREL: 442 case COFF::IMAGE_REL_ARM_ADDR32: 443 return (S + A) & 0xFFFFFFFF; 444 default: 445 llvm_unreachable("Invalid relocation type"); 446 } 447 } 448 449 static bool supportsCOFFARM64(uint64_t Type) { 450 switch (Type) { 451 case COFF::IMAGE_REL_ARM64_SECREL: 452 case COFF::IMAGE_REL_ARM64_ADDR64: 453 return true; 454 default: 455 return false; 456 } 457 } 458 459 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) { 460 switch (R.getType()) { 461 case COFF::IMAGE_REL_ARM64_SECREL: 462 return (S + A) & 0xFFFFFFFF; 463 case COFF::IMAGE_REL_ARM64_ADDR64: 464 return S + A; 465 default: 466 llvm_unreachable("Invalid relocation type"); 467 } 468 } 469 470 static bool supportsMachOX86_64(uint64_t Type) { 471 return Type == MachO::X86_64_RELOC_UNSIGNED; 472 } 473 474 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) { 475 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) 476 return S; 477 llvm_unreachable("Invalid relocation type"); 478 } 479 480 static bool supportsWasm32(uint64_t Type) { 481 switch (Type) { 482 case wasm::R_WASM_FUNCTION_INDEX_LEB: 483 case wasm::R_WASM_TABLE_INDEX_SLEB: 484 case wasm::R_WASM_TABLE_INDEX_I32: 485 case wasm::R_WASM_MEMORY_ADDR_LEB: 486 case wasm::R_WASM_MEMORY_ADDR_SLEB: 487 case wasm::R_WASM_MEMORY_ADDR_I32: 488 case wasm::R_WASM_TYPE_INDEX_LEB: 489 case wasm::R_WASM_GLOBAL_INDEX_LEB: 490 case wasm::R_WASM_FUNCTION_OFFSET_I32: 491 case wasm::R_WASM_SECTION_OFFSET_I32: 492 case wasm::R_WASM_EVENT_INDEX_LEB: 493 return true; 494 default: 495 return false; 496 } 497 } 498 499 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { 500 switch (R.getType()) { 501 case wasm::R_WASM_FUNCTION_INDEX_LEB: 502 case wasm::R_WASM_TABLE_INDEX_SLEB: 503 case wasm::R_WASM_TABLE_INDEX_I32: 504 case wasm::R_WASM_MEMORY_ADDR_LEB: 505 case wasm::R_WASM_MEMORY_ADDR_SLEB: 506 case wasm::R_WASM_MEMORY_ADDR_I32: 507 case wasm::R_WASM_TYPE_INDEX_LEB: 508 case wasm::R_WASM_GLOBAL_INDEX_LEB: 509 case wasm::R_WASM_FUNCTION_OFFSET_I32: 510 case wasm::R_WASM_SECTION_OFFSET_I32: 511 case wasm::R_WASM_EVENT_INDEX_LEB: 512 // For wasm section, its offset at 0 -- ignoring Value 513 return A; 514 default: 515 llvm_unreachable("Invalid relocation type"); 516 } 517 } 518 519 std::pair<bool (*)(uint64_t), RelocationResolver> 520 getRelocationResolver(const ObjectFile &Obj) { 521 if (Obj.isCOFF()) { 522 switch (Obj.getArch()) { 523 case Triple::x86_64: 524 return {supportsCOFFX86_64, resolveCOFFX86_64}; 525 case Triple::x86: 526 return {supportsCOFFX86, resolveCOFFX86}; 527 case Triple::arm: 528 case Triple::thumb: 529 return {supportsCOFFARM, resolveCOFFARM}; 530 case Triple::aarch64: 531 return {supportsCOFFARM64, resolveCOFFARM64}; 532 default: 533 return {nullptr, nullptr}; 534 } 535 } else if (Obj.isELF()) { 536 if (Obj.getBytesInAddress() == 8) { 537 switch (Obj.getArch()) { 538 case Triple::x86_64: 539 return {supportsX86_64, resolveX86_64}; 540 case Triple::aarch64: 541 case Triple::aarch64_be: 542 return {supportsAArch64, resolveAArch64}; 543 case Triple::bpfel: 544 case Triple::bpfeb: 545 return {supportsBPF, resolveBPF}; 546 case Triple::mips64el: 547 case Triple::mips64: 548 return {supportsMips64, resolveMips64}; 549 case Triple::ppc64le: 550 case Triple::ppc64: 551 return {supportsPPC64, resolvePPC64}; 552 case Triple::systemz: 553 return {supportsSystemZ, resolveSystemZ}; 554 case Triple::sparcv9: 555 return {supportsSparc64, resolveSparc64}; 556 case Triple::amdgcn: 557 return {supportsAmdgpu, resolveAmdgpu}; 558 case Triple::riscv64: 559 return {supportsRISCV, resolveRISCV}; 560 default: 561 return {nullptr, nullptr}; 562 } 563 } 564 565 // 32-bit object file 566 assert(Obj.getBytesInAddress() == 4 && 567 "Invalid word size in object file"); 568 569 switch (Obj.getArch()) { 570 case Triple::x86: 571 return {supportsX86, resolveX86}; 572 case Triple::ppc: 573 return {supportsPPC32, resolvePPC32}; 574 case Triple::arm: 575 case Triple::armeb: 576 return {supportsARM, resolveARM}; 577 case Triple::avr: 578 return {supportsAVR, resolveAVR}; 579 case Triple::lanai: 580 return {supportsLanai, resolveLanai}; 581 case Triple::mipsel: 582 case Triple::mips: 583 return {supportsMips32, resolveMips32}; 584 case Triple::sparc: 585 return {supportsSparc32, resolveSparc32}; 586 case Triple::hexagon: 587 return {supportsHexagon, resolveHexagon}; 588 case Triple::riscv32: 589 return {supportsRISCV, resolveRISCV}; 590 default: 591 return {nullptr, nullptr}; 592 } 593 } else if (Obj.isMachO()) { 594 if (Obj.getArch() == Triple::x86_64) 595 return {supportsMachOX86_64, resolveMachOX86_64}; 596 return {nullptr, nullptr}; 597 } else if (Obj.isWasm()) { 598 if (Obj.getArch() == Triple::wasm32) 599 return {supportsWasm32, resolveWasm32}; 600 return {nullptr, nullptr}; 601 } 602 603 llvm_unreachable("Invalid object file"); 604 } 605 606 } // namespace object 607 } // namespace llvm 608