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