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 #include "llvm/ADT/Twine.h" 15 #include "llvm/BinaryFormat/COFF.h" 16 #include "llvm/BinaryFormat/ELF.h" 17 #include "llvm/BinaryFormat/MachO.h" 18 #include "llvm/BinaryFormat/Wasm.h" 19 #include "llvm/Object/ELFObjectFile.h" 20 #include "llvm/Object/ELFTypes.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Object/SymbolicFile.h" 23 #include "llvm/Support/Casting.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/TargetParser/Triple.h" 27 #include <cassert> 28 #include <vector> 29 30 namespace llvm { 31 namespace object { 32 33 static int64_t getELFAddend(RelocationRef R) { 34 Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); 35 handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { 36 report_fatal_error(Twine(EI.message())); 37 }); 38 return *AddendOrErr; 39 } 40 41 static bool supportsX86_64(uint64_t Type) { 42 switch (Type) { 43 case ELF::R_X86_64_NONE: 44 case ELF::R_X86_64_64: 45 case ELF::R_X86_64_DTPOFF32: 46 case ELF::R_X86_64_DTPOFF64: 47 case ELF::R_X86_64_PC32: 48 case ELF::R_X86_64_PC64: 49 case ELF::R_X86_64_32: 50 case ELF::R_X86_64_32S: 51 return true; 52 default: 53 return false; 54 } 55 } 56 57 static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 58 uint64_t LocData, int64_t Addend) { 59 switch (Type) { 60 case ELF::R_X86_64_NONE: 61 return LocData; 62 case ELF::R_X86_64_64: 63 case ELF::R_X86_64_DTPOFF32: 64 case ELF::R_X86_64_DTPOFF64: 65 return S + Addend; 66 case ELF::R_X86_64_PC32: 67 case ELF::R_X86_64_PC64: 68 return S + Addend - Offset; 69 case ELF::R_X86_64_32: 70 case ELF::R_X86_64_32S: 71 return (S + Addend) & 0xFFFFFFFF; 72 default: 73 llvm_unreachable("Invalid relocation type"); 74 } 75 } 76 77 static bool supportsAArch64(uint64_t Type) { 78 switch (Type) { 79 case ELF::R_AARCH64_ABS32: 80 case ELF::R_AARCH64_ABS64: 81 case ELF::R_AARCH64_PREL16: 82 case ELF::R_AARCH64_PREL32: 83 case ELF::R_AARCH64_PREL64: 84 return true; 85 default: 86 return false; 87 } 88 } 89 90 static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S, 91 uint64_t /*LocData*/, int64_t Addend) { 92 switch (Type) { 93 case ELF::R_AARCH64_ABS32: 94 return (S + Addend) & 0xFFFFFFFF; 95 case ELF::R_AARCH64_ABS64: 96 return S + Addend; 97 case ELF::R_AARCH64_PREL16: 98 return (S + Addend - Offset) & 0xFFFF; 99 case ELF::R_AARCH64_PREL32: 100 return (S + Addend - Offset) & 0xFFFFFFFF; 101 case ELF::R_AARCH64_PREL64: 102 return S + Addend - Offset; 103 default: 104 llvm_unreachable("Invalid relocation type"); 105 } 106 } 107 108 static bool supportsBPF(uint64_t Type) { 109 switch (Type) { 110 case ELF::R_BPF_64_ABS32: 111 case ELF::R_BPF_64_ABS64: 112 return true; 113 default: 114 return false; 115 } 116 } 117 118 static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S, 119 uint64_t LocData, int64_t /*Addend*/) { 120 switch (Type) { 121 case ELF::R_BPF_64_ABS32: 122 return (S + LocData) & 0xFFFFFFFF; 123 case ELF::R_BPF_64_ABS64: 124 return S + LocData; 125 default: 126 llvm_unreachable("Invalid relocation type"); 127 } 128 } 129 130 static bool supportsMips64(uint64_t Type) { 131 switch (Type) { 132 case ELF::R_MIPS_32: 133 case ELF::R_MIPS_64: 134 case ELF::R_MIPS_TLS_DTPREL64: 135 case ELF::R_MIPS_PC32: 136 return true; 137 default: 138 return false; 139 } 140 } 141 142 static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S, 143 uint64_t /*LocData*/, int64_t Addend) { 144 switch (Type) { 145 case ELF::R_MIPS_32: 146 return (S + Addend) & 0xFFFFFFFF; 147 case ELF::R_MIPS_64: 148 return S + Addend; 149 case ELF::R_MIPS_TLS_DTPREL64: 150 return S + Addend - 0x8000; 151 case ELF::R_MIPS_PC32: 152 return S + Addend - Offset; 153 default: 154 llvm_unreachable("Invalid relocation type"); 155 } 156 } 157 158 static bool supportsMSP430(uint64_t Type) { 159 switch (Type) { 160 case ELF::R_MSP430_32: 161 case ELF::R_MSP430_16_BYTE: 162 return true; 163 default: 164 return false; 165 } 166 } 167 168 static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S, 169 uint64_t /*LocData*/, int64_t Addend) { 170 switch (Type) { 171 case ELF::R_MSP430_32: 172 return (S + Addend) & 0xFFFFFFFF; 173 case ELF::R_MSP430_16_BYTE: 174 return (S + Addend) & 0xFFFF; 175 default: 176 llvm_unreachable("Invalid relocation type"); 177 } 178 } 179 180 static bool supportsPPC64(uint64_t Type) { 181 switch (Type) { 182 case ELF::R_PPC64_ADDR32: 183 case ELF::R_PPC64_ADDR64: 184 case ELF::R_PPC64_REL32: 185 case ELF::R_PPC64_REL64: 186 return true; 187 default: 188 return false; 189 } 190 } 191 192 static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S, 193 uint64_t /*LocData*/, int64_t Addend) { 194 switch (Type) { 195 case ELF::R_PPC64_ADDR32: 196 return (S + Addend) & 0xFFFFFFFF; 197 case ELF::R_PPC64_ADDR64: 198 return S + Addend; 199 case ELF::R_PPC64_REL32: 200 return (S + Addend - Offset) & 0xFFFFFFFF; 201 case ELF::R_PPC64_REL64: 202 return S + Addend - Offset; 203 default: 204 llvm_unreachable("Invalid relocation type"); 205 } 206 } 207 208 static bool supportsSystemZ(uint64_t Type) { 209 switch (Type) { 210 case ELF::R_390_32: 211 case ELF::R_390_64: 212 return true; 213 default: 214 return false; 215 } 216 } 217 218 static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S, 219 uint64_t /*LocData*/, int64_t Addend) { 220 switch (Type) { 221 case ELF::R_390_32: 222 return (S + Addend) & 0xFFFFFFFF; 223 case ELF::R_390_64: 224 return S + Addend; 225 default: 226 llvm_unreachable("Invalid relocation type"); 227 } 228 } 229 230 static bool supportsSparc64(uint64_t Type) { 231 switch (Type) { 232 case ELF::R_SPARC_32: 233 case ELF::R_SPARC_64: 234 case ELF::R_SPARC_UA32: 235 case ELF::R_SPARC_UA64: 236 return true; 237 default: 238 return false; 239 } 240 } 241 242 static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S, 243 uint64_t /*LocData*/, int64_t Addend) { 244 switch (Type) { 245 case ELF::R_SPARC_32: 246 case ELF::R_SPARC_64: 247 case ELF::R_SPARC_UA32: 248 case ELF::R_SPARC_UA64: 249 return S + Addend; 250 default: 251 llvm_unreachable("Invalid relocation type"); 252 } 253 } 254 255 /// Returns true if \c Obj is an AMDGPU code object based solely on the value 256 /// of e_machine. 257 /// 258 /// AMDGPU code objects with an e_machine of EF_AMDGPU_MACH_NONE do not 259 /// identify their arch as either r600 or amdgcn, but we can still handle 260 /// their relocations. When we identify an ELF object with an UnknownArch, 261 /// we use isAMDGPU to check for this case. 262 static bool isAMDGPU(const ObjectFile &Obj) { 263 if (const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) 264 return ELFObj->getEMachine() == ELF::EM_AMDGPU; 265 return false; 266 } 267 268 static bool supportsAmdgpu(uint64_t Type) { 269 switch (Type) { 270 case ELF::R_AMDGPU_ABS32: 271 case ELF::R_AMDGPU_ABS64: 272 return true; 273 default: 274 return false; 275 } 276 } 277 278 static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S, 279 uint64_t /*LocData*/, int64_t Addend) { 280 switch (Type) { 281 case ELF::R_AMDGPU_ABS32: 282 case ELF::R_AMDGPU_ABS64: 283 return S + Addend; 284 default: 285 llvm_unreachable("Invalid relocation type"); 286 } 287 } 288 289 static bool supportsX86(uint64_t Type) { 290 switch (Type) { 291 case ELF::R_386_NONE: 292 case ELF::R_386_32: 293 case ELF::R_386_PC32: 294 return true; 295 default: 296 return false; 297 } 298 } 299 300 static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S, 301 uint64_t LocData, int64_t /*Addend*/) { 302 switch (Type) { 303 case ELF::R_386_NONE: 304 return LocData; 305 case ELF::R_386_32: 306 return S + LocData; 307 case ELF::R_386_PC32: 308 return S - Offset + LocData; 309 default: 310 llvm_unreachable("Invalid relocation type"); 311 } 312 } 313 314 static bool supportsPPC32(uint64_t Type) { 315 switch (Type) { 316 case ELF::R_PPC_ADDR32: 317 case ELF::R_PPC_REL32: 318 return true; 319 default: 320 return false; 321 } 322 } 323 324 static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S, 325 uint64_t /*LocData*/, int64_t Addend) { 326 switch (Type) { 327 case ELF::R_PPC_ADDR32: 328 return (S + Addend) & 0xFFFFFFFF; 329 case ELF::R_PPC_REL32: 330 return (S + Addend - Offset) & 0xFFFFFFFF; 331 } 332 llvm_unreachable("Invalid relocation type"); 333 } 334 335 static bool supportsARM(uint64_t Type) { 336 switch (Type) { 337 case ELF::R_ARM_ABS32: 338 case ELF::R_ARM_REL32: 339 return true; 340 default: 341 return false; 342 } 343 } 344 345 static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S, 346 uint64_t LocData, int64_t Addend) { 347 // Support both RELA and REL relocations. The caller is responsible 348 // for supplying the correct values for LocData and Addend, i.e. 349 // Addend == 0 for REL and LocData == 0 for RELA. 350 assert((LocData == 0 || Addend == 0) && 351 "one of LocData and Addend must be 0"); 352 switch (Type) { 353 case ELF::R_ARM_ABS32: 354 return (S + LocData + Addend) & 0xFFFFFFFF; 355 case ELF::R_ARM_REL32: 356 return (S + LocData + Addend - Offset) & 0xFFFFFFFF; 357 } 358 llvm_unreachable("Invalid relocation type"); 359 } 360 361 static bool supportsAVR(uint64_t Type) { 362 switch (Type) { 363 case ELF::R_AVR_16: 364 case ELF::R_AVR_32: 365 return true; 366 default: 367 return false; 368 } 369 } 370 371 static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S, 372 uint64_t /*LocData*/, int64_t Addend) { 373 switch (Type) { 374 case ELF::R_AVR_16: 375 return (S + Addend) & 0xFFFF; 376 case ELF::R_AVR_32: 377 return (S + Addend) & 0xFFFFFFFF; 378 default: 379 llvm_unreachable("Invalid relocation type"); 380 } 381 } 382 383 static bool supportsLanai(uint64_t Type) { 384 return Type == ELF::R_LANAI_32; 385 } 386 387 static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S, 388 uint64_t /*LocData*/, int64_t Addend) { 389 if (Type == ELF::R_LANAI_32) 390 return (S + Addend) & 0xFFFFFFFF; 391 llvm_unreachable("Invalid relocation type"); 392 } 393 394 static bool supportsMips32(uint64_t Type) { 395 switch (Type) { 396 case ELF::R_MIPS_32: 397 case ELF::R_MIPS_TLS_DTPREL32: 398 return true; 399 default: 400 return false; 401 } 402 } 403 404 static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S, 405 uint64_t LocData, int64_t /*Addend*/) { 406 // FIXME: Take in account implicit addends to get correct results. 407 if (Type == ELF::R_MIPS_32) 408 return (S + LocData) & 0xFFFFFFFF; 409 if (Type == ELF::R_MIPS_TLS_DTPREL32) 410 return (S + LocData) & 0xFFFFFFFF; 411 llvm_unreachable("Invalid relocation type"); 412 } 413 414 static bool supportsSparc32(uint64_t Type) { 415 switch (Type) { 416 case ELF::R_SPARC_32: 417 case ELF::R_SPARC_UA32: 418 return true; 419 default: 420 return false; 421 } 422 } 423 424 static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S, 425 uint64_t LocData, int64_t Addend) { 426 if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32) 427 return S + Addend; 428 return LocData; 429 } 430 431 static bool supportsHexagon(uint64_t Type) { 432 return Type == ELF::R_HEX_32; 433 } 434 435 static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S, 436 uint64_t /*LocData*/, int64_t Addend) { 437 if (Type == ELF::R_HEX_32) 438 return S + Addend; 439 llvm_unreachable("Invalid relocation type"); 440 } 441 442 static bool supportsRISCV(uint64_t Type) { 443 switch (Type) { 444 case ELF::R_RISCV_NONE: 445 case ELF::R_RISCV_32: 446 case ELF::R_RISCV_32_PCREL: 447 case ELF::R_RISCV_64: 448 case ELF::R_RISCV_SET6: 449 case ELF::R_RISCV_SET8: 450 case ELF::R_RISCV_SUB6: 451 case ELF::R_RISCV_ADD8: 452 case ELF::R_RISCV_SUB8: 453 case ELF::R_RISCV_SET16: 454 case ELF::R_RISCV_ADD16: 455 case ELF::R_RISCV_SUB16: 456 case ELF::R_RISCV_SET32: 457 case ELF::R_RISCV_ADD32: 458 case ELF::R_RISCV_SUB32: 459 case ELF::R_RISCV_ADD64: 460 case ELF::R_RISCV_SUB64: 461 return true; 462 default: 463 return false; 464 } 465 } 466 467 static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S, 468 uint64_t LocData, int64_t Addend) { 469 int64_t RA = Addend; 470 uint64_t A = LocData; 471 switch (Type) { 472 case ELF::R_RISCV_NONE: 473 return LocData; 474 case ELF::R_RISCV_32: 475 return (S + RA) & 0xFFFFFFFF; 476 case ELF::R_RISCV_32_PCREL: 477 return (S + RA - Offset) & 0xFFFFFFFF; 478 case ELF::R_RISCV_64: 479 return S + RA; 480 case ELF::R_RISCV_SET6: 481 return (A & 0xC0) | ((S + RA) & 0x3F); 482 case ELF::R_RISCV_SUB6: 483 return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F); 484 case ELF::R_RISCV_SET8: 485 return (S + RA) & 0xFF; 486 case ELF::R_RISCV_ADD8: 487 return (A + (S + RA)) & 0xFF; 488 case ELF::R_RISCV_SUB8: 489 return (A - (S + RA)) & 0xFF; 490 case ELF::R_RISCV_SET16: 491 return (S + RA) & 0xFFFF; 492 case ELF::R_RISCV_ADD16: 493 return (A + (S + RA)) & 0xFFFF; 494 case ELF::R_RISCV_SUB16: 495 return (A - (S + RA)) & 0xFFFF; 496 case ELF::R_RISCV_SET32: 497 return (S + RA) & 0xFFFFFFFF; 498 case ELF::R_RISCV_ADD32: 499 return (A + (S + RA)) & 0xFFFFFFFF; 500 case ELF::R_RISCV_SUB32: 501 return (A - (S + RA)) & 0xFFFFFFFF; 502 case ELF::R_RISCV_ADD64: 503 return (A + (S + RA)); 504 case ELF::R_RISCV_SUB64: 505 return (A - (S + RA)); 506 default: 507 llvm_unreachable("Invalid relocation type"); 508 } 509 } 510 511 static bool supportsCSKY(uint64_t Type) { 512 switch (Type) { 513 case ELF::R_CKCORE_NONE: 514 case ELF::R_CKCORE_ADDR32: 515 case ELF::R_CKCORE_PCREL32: 516 return true; 517 default: 518 return false; 519 } 520 } 521 522 static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S, 523 uint64_t LocData, int64_t Addend) { 524 switch (Type) { 525 case ELF::R_CKCORE_NONE: 526 return LocData; 527 case ELF::R_CKCORE_ADDR32: 528 return (S + Addend) & 0xFFFFFFFF; 529 case ELF::R_CKCORE_PCREL32: 530 return (S + Addend - Offset) & 0xFFFFFFFF; 531 default: 532 llvm_unreachable("Invalid relocation type"); 533 } 534 } 535 536 static bool supportsLoongArch(uint64_t Type) { 537 switch (Type) { 538 case ELF::R_LARCH_NONE: 539 case ELF::R_LARCH_32: 540 case ELF::R_LARCH_32_PCREL: 541 case ELF::R_LARCH_64: 542 case ELF::R_LARCH_ADD8: 543 case ELF::R_LARCH_SUB8: 544 case ELF::R_LARCH_ADD16: 545 case ELF::R_LARCH_SUB16: 546 case ELF::R_LARCH_ADD32: 547 case ELF::R_LARCH_SUB32: 548 case ELF::R_LARCH_ADD64: 549 case ELF::R_LARCH_SUB64: 550 return true; 551 default: 552 return false; 553 } 554 } 555 556 static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S, 557 uint64_t LocData, int64_t Addend) { 558 switch (Type) { 559 case ELF::R_LARCH_NONE: 560 return LocData; 561 case ELF::R_LARCH_32: 562 return (S + Addend) & 0xFFFFFFFF; 563 case ELF::R_LARCH_32_PCREL: 564 return (S + Addend - Offset) & 0xFFFFFFFF; 565 case ELF::R_LARCH_64: 566 return S + Addend; 567 case ELF::R_LARCH_ADD8: 568 return (LocData + (S + Addend)) & 0xFF; 569 case ELF::R_LARCH_SUB8: 570 return (LocData - (S + Addend)) & 0xFF; 571 case ELF::R_LARCH_ADD16: 572 return (LocData + (S + Addend)) & 0xFFFF; 573 case ELF::R_LARCH_SUB16: 574 return (LocData - (S + Addend)) & 0xFFFF; 575 case ELF::R_LARCH_ADD32: 576 return (LocData + (S + Addend)) & 0xFFFFFFFF; 577 case ELF::R_LARCH_SUB32: 578 return (LocData - (S + Addend)) & 0xFFFFFFFF; 579 case ELF::R_LARCH_ADD64: 580 return (LocData + (S + Addend)); 581 case ELF::R_LARCH_SUB64: 582 return (LocData - (S + Addend)); 583 default: 584 llvm_unreachable("Invalid relocation type"); 585 } 586 } 587 588 static bool supportsCOFFX86(uint64_t Type) { 589 switch (Type) { 590 case COFF::IMAGE_REL_I386_SECREL: 591 case COFF::IMAGE_REL_I386_DIR32: 592 return true; 593 default: 594 return false; 595 } 596 } 597 598 static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S, 599 uint64_t LocData, int64_t /*Addend*/) { 600 switch (Type) { 601 case COFF::IMAGE_REL_I386_SECREL: 602 case COFF::IMAGE_REL_I386_DIR32: 603 return (S + LocData) & 0xFFFFFFFF; 604 default: 605 llvm_unreachable("Invalid relocation type"); 606 } 607 } 608 609 static bool supportsCOFFX86_64(uint64_t Type) { 610 switch (Type) { 611 case COFF::IMAGE_REL_AMD64_SECREL: 612 case COFF::IMAGE_REL_AMD64_ADDR64: 613 return true; 614 default: 615 return false; 616 } 617 } 618 619 static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 620 uint64_t LocData, int64_t /*Addend*/) { 621 switch (Type) { 622 case COFF::IMAGE_REL_AMD64_SECREL: 623 return (S + LocData) & 0xFFFFFFFF; 624 case COFF::IMAGE_REL_AMD64_ADDR64: 625 return S + LocData; 626 default: 627 llvm_unreachable("Invalid relocation type"); 628 } 629 } 630 631 static bool supportsCOFFARM(uint64_t Type) { 632 switch (Type) { 633 case COFF::IMAGE_REL_ARM_SECREL: 634 case COFF::IMAGE_REL_ARM_ADDR32: 635 return true; 636 default: 637 return false; 638 } 639 } 640 641 static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S, 642 uint64_t LocData, int64_t /*Addend*/) { 643 switch (Type) { 644 case COFF::IMAGE_REL_ARM_SECREL: 645 case COFF::IMAGE_REL_ARM_ADDR32: 646 return (S + LocData) & 0xFFFFFFFF; 647 default: 648 llvm_unreachable("Invalid relocation type"); 649 } 650 } 651 652 static bool supportsCOFFARM64(uint64_t Type) { 653 switch (Type) { 654 case COFF::IMAGE_REL_ARM64_SECREL: 655 case COFF::IMAGE_REL_ARM64_ADDR64: 656 return true; 657 default: 658 return false; 659 } 660 } 661 662 static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S, 663 uint64_t LocData, int64_t /*Addend*/) { 664 switch (Type) { 665 case COFF::IMAGE_REL_ARM64_SECREL: 666 return (S + LocData) & 0xFFFFFFFF; 667 case COFF::IMAGE_REL_ARM64_ADDR64: 668 return S + LocData; 669 default: 670 llvm_unreachable("Invalid relocation type"); 671 } 672 } 673 674 static bool supportsMachOX86_64(uint64_t Type) { 675 return Type == MachO::X86_64_RELOC_UNSIGNED; 676 } 677 678 static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 679 uint64_t LocData, int64_t /*Addend*/) { 680 if (Type == MachO::X86_64_RELOC_UNSIGNED) 681 return S; 682 llvm_unreachable("Invalid relocation type"); 683 } 684 685 static bool supportsWasm32(uint64_t Type) { 686 switch (Type) { 687 case wasm::R_WASM_FUNCTION_INDEX_LEB: 688 case wasm::R_WASM_TABLE_INDEX_SLEB: 689 case wasm::R_WASM_TABLE_INDEX_I32: 690 case wasm::R_WASM_MEMORY_ADDR_LEB: 691 case wasm::R_WASM_MEMORY_ADDR_SLEB: 692 case wasm::R_WASM_MEMORY_ADDR_I32: 693 case wasm::R_WASM_TYPE_INDEX_LEB: 694 case wasm::R_WASM_GLOBAL_INDEX_LEB: 695 case wasm::R_WASM_FUNCTION_OFFSET_I32: 696 case wasm::R_WASM_SECTION_OFFSET_I32: 697 case wasm::R_WASM_TAG_INDEX_LEB: 698 case wasm::R_WASM_GLOBAL_INDEX_I32: 699 case wasm::R_WASM_TABLE_NUMBER_LEB: 700 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 701 return true; 702 default: 703 return false; 704 } 705 } 706 707 static bool supportsWasm64(uint64_t Type) { 708 switch (Type) { 709 case wasm::R_WASM_MEMORY_ADDR_LEB64: 710 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 711 case wasm::R_WASM_MEMORY_ADDR_I64: 712 case wasm::R_WASM_TABLE_INDEX_SLEB64: 713 case wasm::R_WASM_TABLE_INDEX_I64: 714 case wasm::R_WASM_FUNCTION_OFFSET_I64: 715 return true; 716 default: 717 return supportsWasm32(Type); 718 } 719 } 720 721 static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S, 722 uint64_t LocData, int64_t /*Addend*/) { 723 switch (Type) { 724 case wasm::R_WASM_FUNCTION_INDEX_LEB: 725 case wasm::R_WASM_TABLE_INDEX_SLEB: 726 case wasm::R_WASM_TABLE_INDEX_I32: 727 case wasm::R_WASM_MEMORY_ADDR_LEB: 728 case wasm::R_WASM_MEMORY_ADDR_SLEB: 729 case wasm::R_WASM_MEMORY_ADDR_I32: 730 case wasm::R_WASM_TYPE_INDEX_LEB: 731 case wasm::R_WASM_GLOBAL_INDEX_LEB: 732 case wasm::R_WASM_FUNCTION_OFFSET_I32: 733 case wasm::R_WASM_SECTION_OFFSET_I32: 734 case wasm::R_WASM_TAG_INDEX_LEB: 735 case wasm::R_WASM_GLOBAL_INDEX_I32: 736 case wasm::R_WASM_TABLE_NUMBER_LEB: 737 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 738 // For wasm section, its offset at 0 -- ignoring Value 739 return LocData; 740 default: 741 llvm_unreachable("Invalid relocation type"); 742 } 743 } 744 745 static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S, 746 uint64_t LocData, int64_t Addend) { 747 switch (Type) { 748 case wasm::R_WASM_MEMORY_ADDR_LEB64: 749 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 750 case wasm::R_WASM_MEMORY_ADDR_I64: 751 case wasm::R_WASM_TABLE_INDEX_SLEB64: 752 case wasm::R_WASM_TABLE_INDEX_I64: 753 case wasm::R_WASM_FUNCTION_OFFSET_I64: 754 // For wasm section, its offset at 0 -- ignoring Value 755 return LocData; 756 default: 757 return resolveWasm32(Type, Offset, S, LocData, Addend); 758 } 759 } 760 761 std::pair<SupportsRelocation, RelocationResolver> 762 getRelocationResolver(const ObjectFile &Obj) { 763 if (Obj.isCOFF()) { 764 switch (Obj.getArch()) { 765 case Triple::x86_64: 766 return {supportsCOFFX86_64, resolveCOFFX86_64}; 767 case Triple::x86: 768 return {supportsCOFFX86, resolveCOFFX86}; 769 case Triple::arm: 770 case Triple::thumb: 771 return {supportsCOFFARM, resolveCOFFARM}; 772 case Triple::aarch64: 773 return {supportsCOFFARM64, resolveCOFFARM64}; 774 default: 775 return {nullptr, nullptr}; 776 } 777 } else if (Obj.isELF()) { 778 if (Obj.getBytesInAddress() == 8) { 779 switch (Obj.getArch()) { 780 case Triple::x86_64: 781 return {supportsX86_64, resolveX86_64}; 782 case Triple::aarch64: 783 case Triple::aarch64_be: 784 return {supportsAArch64, resolveAArch64}; 785 case Triple::bpfel: 786 case Triple::bpfeb: 787 return {supportsBPF, resolveBPF}; 788 case Triple::loongarch64: 789 return {supportsLoongArch, resolveLoongArch}; 790 case Triple::mips64el: 791 case Triple::mips64: 792 return {supportsMips64, resolveMips64}; 793 case Triple::ppc64le: 794 case Triple::ppc64: 795 return {supportsPPC64, resolvePPC64}; 796 case Triple::systemz: 797 return {supportsSystemZ, resolveSystemZ}; 798 case Triple::sparcv9: 799 return {supportsSparc64, resolveSparc64}; 800 case Triple::amdgcn: 801 return {supportsAmdgpu, resolveAmdgpu}; 802 case Triple::riscv64: 803 return {supportsRISCV, resolveRISCV}; 804 default: 805 if (isAMDGPU(Obj)) 806 return {supportsAmdgpu, resolveAmdgpu}; 807 return {nullptr, nullptr}; 808 } 809 } 810 811 // 32-bit object file 812 assert(Obj.getBytesInAddress() == 4 && 813 "Invalid word size in object file"); 814 815 switch (Obj.getArch()) { 816 case Triple::x86: 817 return {supportsX86, resolveX86}; 818 case Triple::ppcle: 819 case Triple::ppc: 820 return {supportsPPC32, resolvePPC32}; 821 case Triple::arm: 822 case Triple::armeb: 823 return {supportsARM, resolveARM}; 824 case Triple::avr: 825 return {supportsAVR, resolveAVR}; 826 case Triple::lanai: 827 return {supportsLanai, resolveLanai}; 828 case Triple::loongarch32: 829 return {supportsLoongArch, resolveLoongArch}; 830 case Triple::mipsel: 831 case Triple::mips: 832 return {supportsMips32, resolveMips32}; 833 case Triple::msp430: 834 return {supportsMSP430, resolveMSP430}; 835 case Triple::sparc: 836 return {supportsSparc32, resolveSparc32}; 837 case Triple::hexagon: 838 return {supportsHexagon, resolveHexagon}; 839 case Triple::r600: 840 return {supportsAmdgpu, resolveAmdgpu}; 841 case Triple::riscv32: 842 return {supportsRISCV, resolveRISCV}; 843 case Triple::csky: 844 return {supportsCSKY, resolveCSKY}; 845 default: 846 if (isAMDGPU(Obj)) 847 return {supportsAmdgpu, resolveAmdgpu}; 848 return {nullptr, nullptr}; 849 } 850 } else if (Obj.isMachO()) { 851 if (Obj.getArch() == Triple::x86_64) 852 return {supportsMachOX86_64, resolveMachOX86_64}; 853 return {nullptr, nullptr}; 854 } else if (Obj.isWasm()) { 855 if (Obj.getArch() == Triple::wasm32) 856 return {supportsWasm32, resolveWasm32}; 857 if (Obj.getArch() == Triple::wasm64) 858 return {supportsWasm64, resolveWasm64}; 859 return {nullptr, nullptr}; 860 } 861 862 llvm_unreachable("Invalid object file"); 863 } 864 865 uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, 866 uint64_t S, uint64_t LocData) { 867 if (const ObjectFile *Obj = R.getObject()) { 868 int64_t Addend = 0; 869 if (Obj->isELF()) { 870 auto GetRelSectionType = [&]() -> unsigned { 871 if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj)) 872 return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 873 if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj)) 874 return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 875 if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj)) 876 return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 877 auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj); 878 return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 879 }; 880 881 if (GetRelSectionType() == ELF::SHT_RELA) { 882 Addend = getELFAddend(R); 883 // RISCV relocations use both LocData and Addend. 884 if (Obj->getArch() != Triple::riscv32 && 885 Obj->getArch() != Triple::riscv64) 886 LocData = 0; 887 } 888 } 889 890 return Resolver(R.getType(), R.getOffset(), S, LocData, Addend); 891 } 892 893 // Sometimes the caller might want to use its own specific implementation of 894 // the resolver function. E.g. this is used by LLD when it resolves debug 895 // relocations and assumes that all of them have the same computation (S + A). 896 // The relocation R has no owner object in this case and we don't need to 897 // provide Type and Offset fields. It is also assumed the DataRefImpl.p 898 // contains the addend, provided by the caller. 899 return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData, 900 R.getRawDataRefImpl().p); 901 } 902 903 } // namespace object 904 } // namespace llvm 905