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