ARM.cpp revision 327952
1//===- ARM.cpp ------------------------------------------------------------===// 2// 3// The LLVM Linker 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "InputFiles.h" 11#include "Symbols.h" 12#include "SyntheticSections.h" 13#include "Target.h" 14#include "Thunks.h" 15#include "lld/Common/ErrorHandler.h" 16#include "llvm/Object/ELF.h" 17#include "llvm/Support/Endian.h" 18 19using namespace llvm; 20using namespace llvm::support::endian; 21using namespace llvm::ELF; 22using namespace lld; 23using namespace lld::elf; 24 25namespace { 26class ARM final : public TargetInfo { 27public: 28 ARM(); 29 uint32_t calcEFlags() const override; 30 RelExpr getRelExpr(RelType Type, const Symbol &S, 31 const uint8_t *Loc) const override; 32 bool isPicRel(RelType Type) const override; 33 RelType getDynRel(RelType Type) const override; 34 int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; 35 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; 36 void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; 37 void writePltHeader(uint8_t *Buf) const override; 38 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 39 int32_t Index, unsigned RelOff) const override; 40 void addPltSymbols(InputSection &IS, uint64_t Off) const override; 41 void addPltHeaderSymbols(InputSection &ISD) const override; 42 bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, 43 uint64_t BranchAddr, const Symbol &S) const override; 44 bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; 45 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; 46}; 47} // namespace 48 49ARM::ARM() { 50 CopyRel = R_ARM_COPY; 51 RelativeRel = R_ARM_RELATIVE; 52 IRelativeRel = R_ARM_IRELATIVE; 53 GotRel = R_ARM_GLOB_DAT; 54 PltRel = R_ARM_JUMP_SLOT; 55 TlsGotRel = R_ARM_TLS_TPOFF32; 56 TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; 57 TlsOffsetRel = R_ARM_TLS_DTPOFF32; 58 GotEntrySize = 4; 59 GotPltEntrySize = 4; 60 PltEntrySize = 16; 61 PltHeaderSize = 32; 62 TrapInstr = 0xd4d4d4d4; 63 // ARM uses Variant 1 TLS 64 TcbSize = 8; 65 NeedsThunks = true; 66 67 // The placing of pre-created ThunkSections is controlled by the 68 // ThunkSectionSpacing parameter. The aim is to place the 69 // ThunkSection such that all branches from the InputSections prior to the 70 // ThunkSection can reach a Thunk placed at the end of the ThunkSection. 71 // Graphically: 72 // | up to ThunkSectionSpacing .text input sections | 73 // | ThunkSection | 74 // | up to ThunkSectionSpacing .text input sections | 75 // | ThunkSection | 76 77 // Pre-created ThunkSections are spaced roughly 16MiB apart on ARM. This is to 78 // match the most common expected case of a Thumb 2 encoded BL, BLX or B.W 79 // ARM B, BL, BLX range +/- 32MiB 80 // Thumb B.W, BL, BLX range +/- 16MiB 81 // Thumb B<cc>.W range +/- 1MiB 82 // If a branch cannot reach a pre-created ThunkSection a new one will be 83 // created so we can handle the rare cases of a Thumb 2 conditional branch. 84 // We intentionally use a lower size for ThunkSectionSpacing than the maximum 85 // branch range so the end of the ThunkSection is more likely to be within 86 // range of the branch instruction that is furthest away. The value we shorten 87 // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 88 // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to 89 // one of the Thunks going out of range. 90 91 // FIXME: lld assumes that the Thumb BL and BLX encoding permits the J1 and 92 // J2 bits to be used to extend the branch range. On earlier Architectures 93 // such as ARMv4, ARMv5 and ARMv6 (except ARMv6T2) the range is +/- 4MiB. If 94 // support for the earlier encodings is added then when they are used the 95 // ThunkSectionSpacing will need lowering. 96 ThunkSectionSpacing = 0x1000000 - 0x30000; 97} 98 99uint32_t ARM::calcEFlags() const { 100 // We don't currently use any features incompatible with EF_ARM_EABI_VER5, 101 // but we don't have any firm guarantees of conformance. Linux AArch64 102 // kernels (as of 2016) require an EABI version to be set. 103 return EF_ARM_EABI_VER5; 104} 105 106RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, 107 const uint8_t *Loc) const { 108 switch (Type) { 109 case R_ARM_THM_JUMP11: 110 return R_PC; 111 case R_ARM_CALL: 112 case R_ARM_JUMP24: 113 case R_ARM_PC24: 114 case R_ARM_PLT32: 115 case R_ARM_PREL31: 116 case R_ARM_THM_JUMP19: 117 case R_ARM_THM_JUMP24: 118 case R_ARM_THM_CALL: 119 return R_PLT_PC; 120 case R_ARM_GOTOFF32: 121 // (S + A) - GOT_ORG 122 return R_GOTREL; 123 case R_ARM_GOT_BREL: 124 // GOT(S) + A - GOT_ORG 125 return R_GOT_OFF; 126 case R_ARM_GOT_PREL: 127 case R_ARM_TLS_IE32: 128 // GOT(S) + A - P 129 return R_GOT_PC; 130 case R_ARM_SBREL32: 131 return R_ARM_SBREL; 132 case R_ARM_TARGET1: 133 return Config->Target1Rel ? R_PC : R_ABS; 134 case R_ARM_TARGET2: 135 if (Config->Target2 == Target2Policy::Rel) 136 return R_PC; 137 if (Config->Target2 == Target2Policy::Abs) 138 return R_ABS; 139 return R_GOT_PC; 140 case R_ARM_TLS_GD32: 141 return R_TLSGD_PC; 142 case R_ARM_TLS_LDM32: 143 return R_TLSLD_PC; 144 case R_ARM_BASE_PREL: 145 // B(S) + A - P 146 // FIXME: currently B(S) assumed to be .got, this may not hold for all 147 // platforms. 148 return R_GOTONLY_PC; 149 case R_ARM_MOVW_PREL_NC: 150 case R_ARM_MOVT_PREL: 151 case R_ARM_REL32: 152 case R_ARM_THM_MOVW_PREL_NC: 153 case R_ARM_THM_MOVT_PREL: 154 return R_PC; 155 case R_ARM_NONE: 156 return R_NONE; 157 case R_ARM_TLS_LE32: 158 return R_TLS; 159 default: 160 return R_ABS; 161 } 162} 163 164bool ARM::isPicRel(RelType Type) const { 165 return (Type == R_ARM_TARGET1 && !Config->Target1Rel) || 166 (Type == R_ARM_ABS32); 167} 168 169RelType ARM::getDynRel(RelType Type) const { 170 if (Type == R_ARM_TARGET1 && !Config->Target1Rel) 171 return R_ARM_ABS32; 172 if (Type == R_ARM_ABS32) 173 return Type; 174 // Keep it going with a dummy value so that we can find more reloc errors. 175 return R_ARM_ABS32; 176} 177 178void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const { 179 write32le(Buf, InX::Plt->getVA()); 180} 181 182void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { 183 // An ARM entry is the address of the ifunc resolver function. 184 write32le(Buf, S.getVA()); 185} 186 187// Long form PLT Header that does not have any restrictions on the displacement 188// of the .plt from the .plt.got. 189static void writePltHeaderLong(uint8_t *Buf) { 190 const uint8_t PltData[] = { 191 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! 192 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 193 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr 194 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8] 195 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 196 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 197 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 198 0xd4, 0xd4, 0xd4, 0xd4}; 199 memcpy(Buf, PltData, sizeof(PltData)); 200 uint64_t GotPlt = InX::GotPlt->getVA(); 201 uint64_t L1 = InX::Plt->getVA() + 8; 202 write32le(Buf + 16, GotPlt - L1 - 8); 203} 204 205// The default PLT header requires the .plt.got to be within 128 Mb of the 206// .plt in the positive direction. 207void ARM::writePltHeader(uint8_t *Buf) const { 208 // Use a similar sequence to that in writePlt(), the difference is the calling 209 // conventions mean we use lr instead of ip. The PLT entry is responsible for 210 // saving lr on the stack, the dynamic loader is responsible for reloading 211 // it. 212 const uint32_t PltData[] = { 213 0xe52de004, // L1: str lr, [sp,#-4]! 214 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4) 215 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4) 216 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4) 217 }; 218 219 uint64_t Offset = InX::GotPlt->getVA() - InX::Plt->getVA() - 4; 220 if (!llvm::isUInt<27>(Offset)) { 221 // We cannot encode the Offset, use the long form. 222 writePltHeaderLong(Buf); 223 return; 224 } 225 write32le(Buf + 0, PltData[0]); 226 write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff)); 227 write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff)); 228 write32le(Buf + 12, PltData[3] | (Offset & 0xfff)); 229 write32le(Buf + 16, TrapInstr); // Pad to 32-byte boundary 230 write32le(Buf + 20, TrapInstr); 231 write32le(Buf + 24, TrapInstr); 232 write32le(Buf + 28, TrapInstr); 233} 234 235void ARM::addPltHeaderSymbols(InputSection &IS) const { 236 addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); 237 addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); 238} 239 240// Long form PLT entries that do not have any restrictions on the displacement 241// of the .plt from the .plt.got. 242static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr, 243 uint64_t PltEntryAddr, int32_t Index, 244 unsigned RelOff) { 245 const uint8_t PltData[] = { 246 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 247 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc 248 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip] 249 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8 250 }; 251 memcpy(Buf, PltData, sizeof(PltData)); 252 uint64_t L1 = PltEntryAddr + 4; 253 write32le(Buf + 12, GotPltEntryAddr - L1 - 8); 254} 255 256// The default PLT entries require the .plt.got to be within 128 Mb of the 257// .plt in the positive direction. 258void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 259 uint64_t PltEntryAddr, int32_t Index, 260 unsigned RelOff) const { 261 // The PLT entry is similar to the example given in Appendix A of ELF for 262 // the Arm Architecture. Instead of using the Group Relocations to find the 263 // optimal rotation for the 8-bit immediate used in the add instructions we 264 // hard code the most compact rotations for simplicity. This saves a load 265 // instruction over the long plt sequences. 266 const uint32_t PltData[] = { 267 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8 268 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8 269 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8 270 }; 271 272 uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8; 273 if (!llvm::isUInt<27>(Offset)) { 274 // We cannot encode the Offset, use the long form. 275 writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff); 276 return; 277 } 278 write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff)); 279 write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff)); 280 write32le(Buf + 8, PltData[2] | (Offset & 0xfff)); 281 write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary 282} 283 284void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const { 285 addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); 286 addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); 287} 288 289bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, 290 uint64_t BranchAddr, const Symbol &S) const { 291 // If S is an undefined weak symbol and does not have a PLT entry then it 292 // will be resolved as a branch to the next instruction. 293 if (S.isUndefWeak() && !S.isInPlt()) 294 return false; 295 // A state change from ARM to Thumb and vice versa must go through an 296 // interworking thunk if the relocation type is not R_ARM_CALL or 297 // R_ARM_THM_CALL. 298 switch (Type) { 299 case R_ARM_PC24: 300 case R_ARM_PLT32: 301 case R_ARM_JUMP24: 302 // Source is ARM, all PLT entries are ARM so no interworking required. 303 // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). 304 if (Expr == R_PC && ((S.getVA() & 1) == 1)) 305 return true; 306 LLVM_FALLTHROUGH; 307 case R_ARM_CALL: { 308 uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); 309 return !inBranchRange(Type, BranchAddr, Dst); 310 } 311 case R_ARM_THM_JUMP19: 312 case R_ARM_THM_JUMP24: 313 // Source is Thumb, all PLT entries are ARM so interworking is required. 314 // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). 315 if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) 316 return true; 317 LLVM_FALLTHROUGH; 318 case R_ARM_THM_CALL: { 319 uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); 320 return !inBranchRange(Type, BranchAddr, Dst); 321 } 322 } 323 return false; 324} 325 326bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { 327 uint64_t Range; 328 uint64_t InstrSize; 329 330 switch (Type) { 331 case R_ARM_PC24: 332 case R_ARM_PLT32: 333 case R_ARM_JUMP24: 334 case R_ARM_CALL: 335 Range = 0x2000000; 336 InstrSize = 4; 337 break; 338 case R_ARM_THM_JUMP19: 339 Range = 0x100000; 340 InstrSize = 2; 341 break; 342 case R_ARM_THM_JUMP24: 343 case R_ARM_THM_CALL: 344 Range = 0x1000000; 345 InstrSize = 2; 346 break; 347 default: 348 return true; 349 } 350 // PC at Src is 2 instructions ahead, immediate of branch is signed 351 if (Src > Dst) 352 Range -= 2 * InstrSize; 353 else 354 Range += InstrSize; 355 356 if ((Dst & 0x1) == 0) 357 // Destination is ARM, if ARM caller then Src is already 4-byte aligned. 358 // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure 359 // destination will be 4 byte aligned. 360 Src &= ~0x3; 361 else 362 // Bit 0 == 1 denotes Thumb state, it is not part of the range 363 Dst &= ~0x1; 364 365 uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src; 366 return Distance <= Range; 367} 368 369void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { 370 switch (Type) { 371 case R_ARM_ABS32: 372 case R_ARM_BASE_PREL: 373 case R_ARM_GLOB_DAT: 374 case R_ARM_GOTOFF32: 375 case R_ARM_GOT_BREL: 376 case R_ARM_GOT_PREL: 377 case R_ARM_REL32: 378 case R_ARM_RELATIVE: 379 case R_ARM_SBREL32: 380 case R_ARM_TARGET1: 381 case R_ARM_TARGET2: 382 case R_ARM_TLS_GD32: 383 case R_ARM_TLS_IE32: 384 case R_ARM_TLS_LDM32: 385 case R_ARM_TLS_LDO32: 386 case R_ARM_TLS_LE32: 387 case R_ARM_TLS_TPOFF32: 388 case R_ARM_TLS_DTPOFF32: 389 write32le(Loc, Val); 390 break; 391 case R_ARM_TLS_DTPMOD32: 392 write32le(Loc, 1); 393 break; 394 case R_ARM_PREL31: 395 checkInt<31>(Loc, Val, Type); 396 write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); 397 break; 398 case R_ARM_CALL: 399 // R_ARM_CALL is used for BL and BLX instructions, depending on the 400 // value of bit 0 of Val, we must select a BL or BLX instruction 401 if (Val & 1) { 402 // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. 403 // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' 404 checkInt<26>(Loc, Val, Type); 405 write32le(Loc, 0xfa000000 | // opcode 406 ((Val & 2) << 23) | // H 407 ((Val >> 2) & 0x00ffffff)); // imm24 408 break; 409 } 410 if ((read32le(Loc) & 0xfe000000) == 0xfa000000) 411 // BLX (always unconditional) instruction to an ARM Target, select an 412 // unconditional BL. 413 write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff)); 414 // fall through as BL encoding is shared with B 415 LLVM_FALLTHROUGH; 416 case R_ARM_JUMP24: 417 case R_ARM_PC24: 418 case R_ARM_PLT32: 419 checkInt<26>(Loc, Val, Type); 420 write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); 421 break; 422 case R_ARM_THM_JUMP11: 423 checkInt<12>(Loc, Val, Type); 424 write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); 425 break; 426 case R_ARM_THM_JUMP19: 427 // Encoding T3: Val = S:J2:J1:imm6:imm11:0 428 checkInt<21>(Loc, Val, Type); 429 write16le(Loc, 430 (read16le(Loc) & 0xfbc0) | // opcode cond 431 ((Val >> 10) & 0x0400) | // S 432 ((Val >> 12) & 0x003f)); // imm6 433 write16le(Loc + 2, 434 0x8000 | // opcode 435 ((Val >> 8) & 0x0800) | // J2 436 ((Val >> 5) & 0x2000) | // J1 437 ((Val >> 1) & 0x07ff)); // imm11 438 break; 439 case R_ARM_THM_CALL: 440 // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the 441 // value of bit 0 of Val, we must select a BL or BLX instruction 442 if ((Val & 1) == 0) { 443 // Ensure BLX destination is 4-byte aligned. As BLX instruction may 444 // only be two byte aligned. This must be done before overflow check 445 Val = alignTo(Val, 4); 446 } 447 // Bit 12 is 0 for BLX, 1 for BL 448 write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); 449 // Fall through as rest of encoding is the same as B.W 450 LLVM_FALLTHROUGH; 451 case R_ARM_THM_JUMP24: 452 // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 453 // FIXME: Use of I1 and I2 require v6T2ops 454 checkInt<25>(Loc, Val, Type); 455 write16le(Loc, 456 0xf000 | // opcode 457 ((Val >> 14) & 0x0400) | // S 458 ((Val >> 12) & 0x03ff)); // imm10 459 write16le(Loc + 2, 460 (read16le(Loc + 2) & 0xd000) | // opcode 461 (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1 462 (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2 463 ((Val >> 1) & 0x07ff)); // imm11 464 break; 465 case R_ARM_MOVW_ABS_NC: 466 case R_ARM_MOVW_PREL_NC: 467 write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) | 468 (Val & 0x0fff)); 469 break; 470 case R_ARM_MOVT_ABS: 471 case R_ARM_MOVT_PREL: 472 checkInt<32>(Loc, Val, Type); 473 write32le(Loc, (read32le(Loc) & ~0x000f0fff) | 474 (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); 475 break; 476 case R_ARM_THM_MOVT_ABS: 477 case R_ARM_THM_MOVT_PREL: 478 // Encoding T1: A = imm4:i:imm3:imm8 479 checkInt<32>(Loc, Val, Type); 480 write16le(Loc, 481 0xf2c0 | // opcode 482 ((Val >> 17) & 0x0400) | // i 483 ((Val >> 28) & 0x000f)); // imm4 484 write16le(Loc + 2, 485 (read16le(Loc + 2) & 0x8f00) | // opcode 486 ((Val >> 12) & 0x7000) | // imm3 487 ((Val >> 16) & 0x00ff)); // imm8 488 break; 489 case R_ARM_THM_MOVW_ABS_NC: 490 case R_ARM_THM_MOVW_PREL_NC: 491 // Encoding T3: A = imm4:i:imm3:imm8 492 write16le(Loc, 493 0xf240 | // opcode 494 ((Val >> 1) & 0x0400) | // i 495 ((Val >> 12) & 0x000f)); // imm4 496 write16le(Loc + 2, 497 (read16le(Loc + 2) & 0x8f00) | // opcode 498 ((Val << 4) & 0x7000) | // imm3 499 (Val & 0x00ff)); // imm8 500 break; 501 default: 502 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); 503 } 504} 505 506int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const { 507 switch (Type) { 508 default: 509 return 0; 510 case R_ARM_ABS32: 511 case R_ARM_BASE_PREL: 512 case R_ARM_GOTOFF32: 513 case R_ARM_GOT_BREL: 514 case R_ARM_GOT_PREL: 515 case R_ARM_REL32: 516 case R_ARM_TARGET1: 517 case R_ARM_TARGET2: 518 case R_ARM_TLS_GD32: 519 case R_ARM_TLS_LDM32: 520 case R_ARM_TLS_LDO32: 521 case R_ARM_TLS_IE32: 522 case R_ARM_TLS_LE32: 523 return SignExtend64<32>(read32le(Buf)); 524 case R_ARM_PREL31: 525 return SignExtend64<31>(read32le(Buf)); 526 case R_ARM_CALL: 527 case R_ARM_JUMP24: 528 case R_ARM_PC24: 529 case R_ARM_PLT32: 530 return SignExtend64<26>(read32le(Buf) << 2); 531 case R_ARM_THM_JUMP11: 532 return SignExtend64<12>(read16le(Buf) << 1); 533 case R_ARM_THM_JUMP19: { 534 // Encoding T3: A = S:J2:J1:imm10:imm6:0 535 uint16_t Hi = read16le(Buf); 536 uint16_t Lo = read16le(Buf + 2); 537 return SignExtend64<20>(((Hi & 0x0400) << 10) | // S 538 ((Lo & 0x0800) << 8) | // J2 539 ((Lo & 0x2000) << 5) | // J1 540 ((Hi & 0x003f) << 12) | // imm6 541 ((Lo & 0x07ff) << 1)); // imm11:0 542 } 543 case R_ARM_THM_CALL: 544 case R_ARM_THM_JUMP24: { 545 // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 546 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) 547 // FIXME: I1 and I2 require v6T2ops 548 uint16_t Hi = read16le(Buf); 549 uint16_t Lo = read16le(Buf + 2); 550 return SignExtend64<24>(((Hi & 0x0400) << 14) | // S 551 (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1 552 (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2 553 ((Hi & 0x003ff) << 12) | // imm0 554 ((Lo & 0x007ff) << 1)); // imm11:0 555 } 556 // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and 557 // MOVT is in the range -32768 <= A < 32768 558 case R_ARM_MOVW_ABS_NC: 559 case R_ARM_MOVT_ABS: 560 case R_ARM_MOVW_PREL_NC: 561 case R_ARM_MOVT_PREL: { 562 uint64_t Val = read32le(Buf) & 0x000f0fff; 563 return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff)); 564 } 565 case R_ARM_THM_MOVW_ABS_NC: 566 case R_ARM_THM_MOVT_ABS: 567 case R_ARM_THM_MOVW_PREL_NC: 568 case R_ARM_THM_MOVT_PREL: { 569 // Encoding T3: A = imm4:i:imm3:imm8 570 uint16_t Hi = read16le(Buf); 571 uint16_t Lo = read16le(Buf + 2); 572 return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4 573 ((Hi & 0x0400) << 1) | // i 574 ((Lo & 0x7000) >> 4) | // imm3 575 (Lo & 0x00ff)); // imm8 576 } 577 } 578} 579 580TargetInfo *elf::getARMTargetInfo() { 581 static ARM Target; 582 return &Target; 583} 584