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