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