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_PC64: 34 case ELF::R_X86_64_32: 35 case ELF::R_X86_64_32S: 36 return true; 37 default: 38 return false; 39 } 40 } 41 42 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) { 43 switch (R.getType()) { 44 case ELF::R_X86_64_NONE: 45 return A; 46 case ELF::R_X86_64_64: 47 case ELF::R_X86_64_DTPOFF32: 48 case ELF::R_X86_64_DTPOFF64: 49 return S + getELFAddend(R); 50 case ELF::R_X86_64_PC32: 51 case ELF::R_X86_64_PC64: 52 return S + getELFAddend(R) - R.getOffset(); 53 case ELF::R_X86_64_32: 54 case ELF::R_X86_64_32S: 55 return (S + getELFAddend(R)) & 0xFFFFFFFF; 56 default: 57 llvm_unreachable("Invalid relocation type"); 58 } 59 } 60 61 static bool supportsAArch64(uint64_t Type) { 62 switch (Type) { 63 case ELF::R_AARCH64_ABS32: 64 case ELF::R_AARCH64_ABS64: 65 return true; 66 default: 67 return false; 68 } 69 } 70 71 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { 72 switch (R.getType()) { 73 case ELF::R_AARCH64_ABS32: 74 return (S + getELFAddend(R)) & 0xFFFFFFFF; 75 case ELF::R_AARCH64_ABS64: 76 return S + getELFAddend(R); 77 default: 78 llvm_unreachable("Invalid relocation type"); 79 } 80 } 81 82 static bool supportsBPF(uint64_t Type) { 83 switch (Type) { 84 case ELF::R_BPF_64_32: 85 case ELF::R_BPF_64_64: 86 return true; 87 default: 88 return false; 89 } 90 } 91 92 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { 93 switch (R.getType()) { 94 case ELF::R_BPF_64_32: 95 return (S + A) & 0xFFFFFFFF; 96 case ELF::R_BPF_64_64: 97 return S + A; 98 default: 99 llvm_unreachable("Invalid relocation type"); 100 } 101 } 102 103 static bool supportsMips64(uint64_t Type) { 104 switch (Type) { 105 case ELF::R_MIPS_32: 106 case ELF::R_MIPS_64: 107 case ELF::R_MIPS_TLS_DTPREL64: 108 case ELF::R_MIPS_PC32: 109 return true; 110 default: 111 return false; 112 } 113 } 114 115 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) { 116 switch (R.getType()) { 117 case ELF::R_MIPS_32: 118 return (S + getELFAddend(R)) & 0xFFFFFFFF; 119 case ELF::R_MIPS_64: 120 return S + getELFAddend(R); 121 case ELF::R_MIPS_TLS_DTPREL64: 122 return S + getELFAddend(R) - 0x8000; 123 case ELF::R_MIPS_PC32: 124 return S + getELFAddend(R) - R.getOffset(); 125 default: 126 llvm_unreachable("Invalid relocation type"); 127 } 128 } 129 130 static bool supportsPPC64(uint64_t Type) { 131 switch (Type) { 132 case ELF::R_PPC64_ADDR32: 133 case ELF::R_PPC64_ADDR64: 134 return true; 135 default: 136 return false; 137 } 138 } 139 140 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { 141 switch (R.getType()) { 142 case ELF::R_PPC64_ADDR32: 143 return (S + getELFAddend(R)) & 0xFFFFFFFF; 144 case ELF::R_PPC64_ADDR64: 145 return S + getELFAddend(R); 146 default: 147 llvm_unreachable("Invalid relocation type"); 148 } 149 } 150 151 static bool supportsSystemZ(uint64_t Type) { 152 switch (Type) { 153 case ELF::R_390_32: 154 case ELF::R_390_64: 155 return true; 156 default: 157 return false; 158 } 159 } 160 161 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) { 162 switch (R.getType()) { 163 case ELF::R_390_32: 164 return (S + getELFAddend(R)) & 0xFFFFFFFF; 165 case ELF::R_390_64: 166 return S + getELFAddend(R); 167 default: 168 llvm_unreachable("Invalid relocation type"); 169 } 170 } 171 172 static bool supportsSparc64(uint64_t Type) { 173 switch (Type) { 174 case ELF::R_SPARC_32: 175 case ELF::R_SPARC_64: 176 case ELF::R_SPARC_UA32: 177 case ELF::R_SPARC_UA64: 178 return true; 179 default: 180 return false; 181 } 182 } 183 184 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) { 185 switch (R.getType()) { 186 case ELF::R_SPARC_32: 187 case ELF::R_SPARC_64: 188 case ELF::R_SPARC_UA32: 189 case ELF::R_SPARC_UA64: 190 return S + getELFAddend(R); 191 default: 192 llvm_unreachable("Invalid relocation type"); 193 } 194 } 195 196 static bool supportsAmdgpu(uint64_t Type) { 197 switch (Type) { 198 case ELF::R_AMDGPU_ABS32: 199 case ELF::R_AMDGPU_ABS64: 200 return true; 201 default: 202 return false; 203 } 204 } 205 206 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) { 207 switch (R.getType()) { 208 case ELF::R_AMDGPU_ABS32: 209 case ELF::R_AMDGPU_ABS64: 210 return S + getELFAddend(R); 211 default: 212 llvm_unreachable("Invalid relocation type"); 213 } 214 } 215 216 static bool supportsX86(uint64_t Type) { 217 switch (Type) { 218 case ELF::R_386_NONE: 219 case ELF::R_386_32: 220 case ELF::R_386_PC32: 221 return true; 222 default: 223 return false; 224 } 225 } 226 227 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { 228 switch (R.getType()) { 229 case ELF::R_386_NONE: 230 return A; 231 case ELF::R_386_32: 232 return S + A; 233 case ELF::R_386_PC32: 234 return S - R.getOffset() + A; 235 default: 236 llvm_unreachable("Invalid relocation type"); 237 } 238 } 239 240 static bool supportsPPC32(uint64_t Type) { 241 return Type == ELF::R_PPC_ADDR32; 242 } 243 244 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { 245 if (R.getType() == ELF::R_PPC_ADDR32) 246 return (S + getELFAddend(R)) & 0xFFFFFFFF; 247 llvm_unreachable("Invalid relocation type"); 248 } 249 250 static bool supportsARM(uint64_t Type) { 251 return Type == ELF::R_ARM_ABS32; 252 } 253 254 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) { 255 if (R.getType() == ELF::R_ARM_ABS32) 256 return (S + A) & 0xFFFFFFFF; 257 llvm_unreachable("Invalid relocation type"); 258 } 259 260 static bool supportsAVR(uint64_t Type) { 261 switch (Type) { 262 case ELF::R_AVR_16: 263 case ELF::R_AVR_32: 264 return true; 265 default: 266 return false; 267 } 268 } 269 270 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) { 271 switch (R.getType()) { 272 case ELF::R_AVR_16: 273 return (S + getELFAddend(R)) & 0xFFFF; 274 case ELF::R_AVR_32: 275 return (S + getELFAddend(R)) & 0xFFFFFFFF; 276 default: 277 llvm_unreachable("Invalid relocation type"); 278 } 279 } 280 281 static bool supportsLanai(uint64_t Type) { 282 return Type == ELF::R_LANAI_32; 283 } 284 285 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) { 286 if (R.getType() == ELF::R_LANAI_32) 287 return (S + getELFAddend(R)) & 0xFFFFFFFF; 288 llvm_unreachable("Invalid relocation type"); 289 } 290 291 static bool supportsMips32(uint64_t Type) { 292 switch (Type) { 293 case ELF::R_MIPS_32: 294 case ELF::R_MIPS_TLS_DTPREL32: 295 return true; 296 default: 297 return false; 298 } 299 } 300 301 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) { 302 // FIXME: Take in account implicit addends to get correct results. 303 uint32_t Rel = R.getType(); 304 if (Rel == ELF::R_MIPS_32) 305 return (S + A) & 0xFFFFFFFF; 306 if (Rel == ELF::R_MIPS_TLS_DTPREL32) 307 return (S + A) & 0xFFFFFFFF; 308 llvm_unreachable("Invalid relocation type"); 309 } 310 311 static bool supportsSparc32(uint64_t Type) { 312 switch (Type) { 313 case ELF::R_SPARC_32: 314 case ELF::R_SPARC_UA32: 315 return true; 316 default: 317 return false; 318 } 319 } 320 321 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) { 322 uint32_t Rel = R.getType(); 323 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) 324 return S + getELFAddend(R); 325 return A; 326 } 327 328 static bool supportsHexagon(uint64_t Type) { 329 return Type == ELF::R_HEX_32; 330 } 331 332 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) { 333 if (R.getType() == ELF::R_HEX_32) 334 return S + getELFAddend(R); 335 llvm_unreachable("Invalid relocation type"); 336 } 337 338 static bool supportsRISCV(uint64_t Type) { 339 switch (Type) { 340 case ELF::R_RISCV_NONE: 341 case ELF::R_RISCV_32: 342 case ELF::R_RISCV_32_PCREL: 343 case ELF::R_RISCV_64: 344 case ELF::R_RISCV_SET6: 345 case ELF::R_RISCV_SUB6: 346 case ELF::R_RISCV_ADD8: 347 case ELF::R_RISCV_SUB8: 348 case ELF::R_RISCV_ADD16: 349 case ELF::R_RISCV_SUB16: 350 case ELF::R_RISCV_ADD32: 351 case ELF::R_RISCV_SUB32: 352 case ELF::R_RISCV_ADD64: 353 case ELF::R_RISCV_SUB64: 354 return true; 355 default: 356 return false; 357 } 358 } 359 360 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) { 361 int64_t RA = getELFAddend(R); 362 switch (R.getType()) { 363 case ELF::R_RISCV_NONE: 364 return A; 365 case ELF::R_RISCV_32: 366 return (S + RA) & 0xFFFFFFFF; 367 case ELF::R_RISCV_32_PCREL: 368 return (S + RA - R.getOffset()) & 0xFFFFFFFF; 369 case ELF::R_RISCV_64: 370 return S + RA; 371 case ELF::R_RISCV_SET6: 372 return (A & 0xC0) | ((S + RA) & 0x3F); 373 case ELF::R_RISCV_SUB6: 374 return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F); 375 case ELF::R_RISCV_ADD8: 376 return (A + (S + RA)) & 0xFF; 377 case ELF::R_RISCV_SUB8: 378 return (A - (S + RA)) & 0xFF; 379 case ELF::R_RISCV_ADD16: 380 return (A + (S + RA)) & 0xFFFF; 381 case ELF::R_RISCV_SUB16: 382 return (A - (S + RA)) & 0xFFFF; 383 case ELF::R_RISCV_ADD32: 384 return (A + (S + RA)) & 0xFFFFFFFF; 385 case ELF::R_RISCV_SUB32: 386 return (A - (S + RA)) & 0xFFFFFFFF; 387 case ELF::R_RISCV_ADD64: 388 return (A + (S + RA)); 389 case ELF::R_RISCV_SUB64: 390 return (A - (S + RA)); 391 default: 392 llvm_unreachable("Invalid relocation type"); 393 } 394 } 395 396 static bool supportsCOFFX86(uint64_t Type) { 397 switch (Type) { 398 case COFF::IMAGE_REL_I386_SECREL: 399 case COFF::IMAGE_REL_I386_DIR32: 400 return true; 401 default: 402 return false; 403 } 404 } 405 406 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) { 407 switch (R.getType()) { 408 case COFF::IMAGE_REL_I386_SECREL: 409 case COFF::IMAGE_REL_I386_DIR32: 410 return (S + A) & 0xFFFFFFFF; 411 default: 412 llvm_unreachable("Invalid relocation type"); 413 } 414 } 415 416 static bool supportsCOFFX86_64(uint64_t Type) { 417 switch (Type) { 418 case COFF::IMAGE_REL_AMD64_SECREL: 419 case COFF::IMAGE_REL_AMD64_ADDR64: 420 return true; 421 default: 422 return false; 423 } 424 } 425 426 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) { 427 switch (R.getType()) { 428 case COFF::IMAGE_REL_AMD64_SECREL: 429 return (S + A) & 0xFFFFFFFF; 430 case COFF::IMAGE_REL_AMD64_ADDR64: 431 return S + A; 432 default: 433 llvm_unreachable("Invalid relocation type"); 434 } 435 } 436 437 static bool supportsCOFFARM(uint64_t Type) { 438 switch (Type) { 439 case COFF::IMAGE_REL_ARM_SECREL: 440 case COFF::IMAGE_REL_ARM_ADDR32: 441 return true; 442 default: 443 return false; 444 } 445 } 446 447 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) { 448 switch (R.getType()) { 449 case COFF::IMAGE_REL_ARM_SECREL: 450 case COFF::IMAGE_REL_ARM_ADDR32: 451 return (S + A) & 0xFFFFFFFF; 452 default: 453 llvm_unreachable("Invalid relocation type"); 454 } 455 } 456 457 static bool supportsCOFFARM64(uint64_t Type) { 458 switch (Type) { 459 case COFF::IMAGE_REL_ARM64_SECREL: 460 case COFF::IMAGE_REL_ARM64_ADDR64: 461 return true; 462 default: 463 return false; 464 } 465 } 466 467 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) { 468 switch (R.getType()) { 469 case COFF::IMAGE_REL_ARM64_SECREL: 470 return (S + A) & 0xFFFFFFFF; 471 case COFF::IMAGE_REL_ARM64_ADDR64: 472 return S + A; 473 default: 474 llvm_unreachable("Invalid relocation type"); 475 } 476 } 477 478 static bool supportsMachOX86_64(uint64_t Type) { 479 return Type == MachO::X86_64_RELOC_UNSIGNED; 480 } 481 482 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) { 483 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) 484 return S; 485 llvm_unreachable("Invalid relocation type"); 486 } 487 488 static bool supportsWasm32(uint64_t Type) { 489 switch (Type) { 490 case wasm::R_WASM_FUNCTION_INDEX_LEB: 491 case wasm::R_WASM_TABLE_INDEX_SLEB: 492 case wasm::R_WASM_TABLE_INDEX_I32: 493 case wasm::R_WASM_MEMORY_ADDR_LEB: 494 case wasm::R_WASM_MEMORY_ADDR_SLEB: 495 case wasm::R_WASM_MEMORY_ADDR_I32: 496 case wasm::R_WASM_TYPE_INDEX_LEB: 497 case wasm::R_WASM_GLOBAL_INDEX_LEB: 498 case wasm::R_WASM_FUNCTION_OFFSET_I32: 499 case wasm::R_WASM_SECTION_OFFSET_I32: 500 case wasm::R_WASM_EVENT_INDEX_LEB: 501 case wasm::R_WASM_GLOBAL_INDEX_I32: 502 return true; 503 default: 504 return false; 505 } 506 } 507 508 static bool supportsWasm64(uint64_t Type) { 509 switch (Type) { 510 case wasm::R_WASM_MEMORY_ADDR_LEB64: 511 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 512 case wasm::R_WASM_MEMORY_ADDR_I64: 513 return true; 514 default: 515 return supportsWasm32(Type); 516 } 517 } 518 519 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { 520 switch (R.getType()) { 521 case wasm::R_WASM_FUNCTION_INDEX_LEB: 522 case wasm::R_WASM_TABLE_INDEX_SLEB: 523 case wasm::R_WASM_TABLE_INDEX_I32: 524 case wasm::R_WASM_MEMORY_ADDR_LEB: 525 case wasm::R_WASM_MEMORY_ADDR_SLEB: 526 case wasm::R_WASM_MEMORY_ADDR_I32: 527 case wasm::R_WASM_TYPE_INDEX_LEB: 528 case wasm::R_WASM_GLOBAL_INDEX_LEB: 529 case wasm::R_WASM_FUNCTION_OFFSET_I32: 530 case wasm::R_WASM_SECTION_OFFSET_I32: 531 case wasm::R_WASM_EVENT_INDEX_LEB: 532 case wasm::R_WASM_GLOBAL_INDEX_I32: 533 // For wasm section, its offset at 0 -- ignoring Value 534 return A; 535 default: 536 llvm_unreachable("Invalid relocation type"); 537 } 538 } 539 540 static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) { 541 switch (R.getType()) { 542 case wasm::R_WASM_MEMORY_ADDR_LEB64: 543 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 544 case wasm::R_WASM_MEMORY_ADDR_I64: 545 // For wasm section, its offset at 0 -- ignoring Value 546 return A; 547 default: 548 return resolveWasm32(R, S, A); 549 } 550 } 551 552 std::pair<bool (*)(uint64_t), RelocationResolver> 553 getRelocationResolver(const ObjectFile &Obj) { 554 if (Obj.isCOFF()) { 555 switch (Obj.getArch()) { 556 case Triple::x86_64: 557 return {supportsCOFFX86_64, resolveCOFFX86_64}; 558 case Triple::x86: 559 return {supportsCOFFX86, resolveCOFFX86}; 560 case Triple::arm: 561 case Triple::thumb: 562 return {supportsCOFFARM, resolveCOFFARM}; 563 case Triple::aarch64: 564 return {supportsCOFFARM64, resolveCOFFARM64}; 565 default: 566 return {nullptr, nullptr}; 567 } 568 } else if (Obj.isELF()) { 569 if (Obj.getBytesInAddress() == 8) { 570 switch (Obj.getArch()) { 571 case Triple::x86_64: 572 return {supportsX86_64, resolveX86_64}; 573 case Triple::aarch64: 574 case Triple::aarch64_be: 575 return {supportsAArch64, resolveAArch64}; 576 case Triple::bpfel: 577 case Triple::bpfeb: 578 return {supportsBPF, resolveBPF}; 579 case Triple::mips64el: 580 case Triple::mips64: 581 return {supportsMips64, resolveMips64}; 582 case Triple::ppc64le: 583 case Triple::ppc64: 584 return {supportsPPC64, resolvePPC64}; 585 case Triple::systemz: 586 return {supportsSystemZ, resolveSystemZ}; 587 case Triple::sparcv9: 588 return {supportsSparc64, resolveSparc64}; 589 case Triple::amdgcn: 590 return {supportsAmdgpu, resolveAmdgpu}; 591 case Triple::riscv64: 592 return {supportsRISCV, resolveRISCV}; 593 default: 594 return {nullptr, nullptr}; 595 } 596 } 597 598 // 32-bit object file 599 assert(Obj.getBytesInAddress() == 4 && 600 "Invalid word size in object file"); 601 602 switch (Obj.getArch()) { 603 case Triple::x86: 604 return {supportsX86, resolveX86}; 605 case Triple::ppc: 606 return {supportsPPC32, resolvePPC32}; 607 case Triple::arm: 608 case Triple::armeb: 609 return {supportsARM, resolveARM}; 610 case Triple::avr: 611 return {supportsAVR, resolveAVR}; 612 case Triple::lanai: 613 return {supportsLanai, resolveLanai}; 614 case Triple::mipsel: 615 case Triple::mips: 616 return {supportsMips32, resolveMips32}; 617 case Triple::sparc: 618 return {supportsSparc32, resolveSparc32}; 619 case Triple::hexagon: 620 return {supportsHexagon, resolveHexagon}; 621 case Triple::riscv32: 622 return {supportsRISCV, resolveRISCV}; 623 default: 624 return {nullptr, nullptr}; 625 } 626 } else if (Obj.isMachO()) { 627 if (Obj.getArch() == Triple::x86_64) 628 return {supportsMachOX86_64, resolveMachOX86_64}; 629 return {nullptr, nullptr}; 630 } else if (Obj.isWasm()) { 631 if (Obj.getArch() == Triple::wasm32) 632 return {supportsWasm32, resolveWasm32}; 633 if (Obj.getArch() == Triple::wasm64) 634 return {supportsWasm64, resolveWasm64}; 635 return {nullptr, nullptr}; 636 } 637 638 llvm_unreachable("Invalid object file"); 639 } 640 641 } // namespace object 642 } // namespace llvm 643