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