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