1 //===- ARM.cpp ------------------------------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "InputFiles.h"
13 #include "SyntheticSections.h"
16 #include "llvm/Object/ELF.h"
17 #include "llvm/Support/Endian.h"
20 using namespace llvm::support::endian;
21 using namespace llvm::ELF;
23 using namespace lld::elf;
26 class ARM final : public TargetInfo {
29 RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
30 const uint8_t *Loc) const override;
31 bool isPicRel(uint32_t Type) const override;
32 uint32_t getDynRel(uint32_t Type) const override;
33 int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
34 void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
35 void writeIgotPlt(uint8_t *Buf, const SymbolBody &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(InputSectionBase *IS, uint64_t Off) const override;
40 void addPltHeaderSymbols(InputSectionBase *ISD) const override;
41 bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
42 const SymbolBody &S) const override;
43 bool inBranchRange(uint32_t RelocType, uint64_t Src,
44 uint64_t Dst) const override;
45 void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
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;
62 TrapInstr = 0xd4d4d4d4;
63 // ARM uses Variant 1 TLS
68 RelExpr ARM::getRelExpr(uint32_t Type, const SymbolBody &S,
69 const uint8_t *Loc) const {
73 case R_ARM_THM_JUMP11:
80 case R_ARM_THM_JUMP19:
81 case R_ARM_THM_JUMP24:
88 // GOT(S) + A - GOT_ORG
97 return Config->Target1Rel ? R_PC : R_ABS;
99 if (Config->Target2 == Target2Policy::Rel)
101 if (Config->Target2 == Target2Policy::Abs)
106 case R_ARM_TLS_LDM32:
108 case R_ARM_BASE_PREL:
110 // FIXME: currently B(S) assumed to be .got, this may not hold for all
113 case R_ARM_MOVW_PREL_NC:
114 case R_ARM_MOVT_PREL:
116 case R_ARM_THM_MOVW_PREL_NC:
117 case R_ARM_THM_MOVT_PREL:
126 bool ARM::isPicRel(uint32_t Type) const {
127 return (Type == R_ARM_TARGET1 && !Config->Target1Rel) ||
128 (Type == R_ARM_ABS32);
131 uint32_t ARM::getDynRel(uint32_t Type) const {
132 if (Type == R_ARM_TARGET1 && !Config->Target1Rel)
134 if (Type == R_ARM_ABS32)
136 // Keep it going with a dummy value so that we can find more reloc errors.
140 void ARM::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
141 write32le(Buf, InX::Plt->getVA());
144 void ARM::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
145 // An ARM entry is the address of the ifunc resolver function.
146 write32le(Buf, S.getVA());
149 void ARM::writePltHeader(uint8_t *Buf) const {
150 const uint8_t PltData[] = {
151 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]!
152 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2
153 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
154 0x08, 0xf0, 0xbe, 0xe5, // ldr pc, [lr, #8]
155 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
157 memcpy(Buf, PltData, sizeof(PltData));
158 uint64_t GotPlt = InX::GotPlt->getVA();
159 uint64_t L1 = InX::Plt->getVA() + 8;
160 write32le(Buf + 16, GotPlt - L1 - 8);
163 void ARM::addPltHeaderSymbols(InputSectionBase *ISD) const {
164 auto *IS = cast<InputSection>(ISD);
165 addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);
166 addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);
169 void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
170 uint64_t PltEntryAddr, int32_t Index,
171 unsigned RelOff) const {
172 // FIXME: Using simple code sequence with simple relocations.
173 // There is a more optimal sequence but it requires support for the group
174 // relocations. See ELF for the ARM Architecture Appendix A.3
175 const uint8_t PltData[] = {
176 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2
177 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
178 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip]
179 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8
181 memcpy(Buf, PltData, sizeof(PltData));
182 uint64_t L1 = PltEntryAddr + 4;
183 write32le(Buf + 12, GotPltEntryAddr - L1 - 8);
186 void ARM::addPltSymbols(InputSectionBase *ISD, uint64_t Off) const {
187 auto *IS = cast<InputSection>(ISD);
188 addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);
189 addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
192 bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
193 const SymbolBody &S) const {
194 // If S is an undefined weak symbol in an executable we don't need a Thunk.
195 // In a DSO calls to undefined symbols, including weak ones get PLT entries
196 // which may need a thunk.
197 if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() &&
200 // A state change from ARM to Thumb and vice versa must go through an
201 // interworking thunk if the relocation type is not R_ARM_CALL or
207 // Source is ARM, all PLT entries are ARM so no interworking required.
208 // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
209 if (Expr == R_PC && ((S.getVA() & 1) == 1))
212 case R_ARM_THM_JUMP19:
213 case R_ARM_THM_JUMP24:
214 // Source is Thumb, all PLT entries are ARM so interworking is required.
215 // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
216 if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0))
223 bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
235 case R_ARM_THM_JUMP19:
239 case R_ARM_THM_JUMP24:
247 // PC at Src is 2 instructions ahead, immediate of branch is signed
249 Range -= 2 * InstrSize;
253 if ((Dst & 0x1) == 0)
254 // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
255 // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
256 // destination will be 4 byte aligned.
259 // Bit 0 == 1 denotes Thumb state, it is not part of the range
262 uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;
263 return Distance <= Range;
266 void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
269 case R_ARM_BASE_PREL:
281 case R_ARM_TLS_LDM32:
282 case R_ARM_TLS_LDO32:
284 case R_ARM_TLS_TPOFF32:
285 case R_ARM_TLS_DTPOFF32:
288 case R_ARM_TLS_DTPMOD32:
292 checkInt<31>(Loc, Val, Type);
293 write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));
296 // R_ARM_CALL is used for BL and BLX instructions, depending on the
297 // value of bit 0 of Val, we must select a BL or BLX instruction
299 // If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
300 // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
301 checkInt<26>(Loc, Val, Type);
302 write32le(Loc, 0xfa000000 | // opcode
303 ((Val & 2) << 23) | // H
304 ((Val >> 2) & 0x00ffffff)); // imm24
307 if ((read32le(Loc) & 0xfe000000) == 0xfa000000)
308 // BLX (always unconditional) instruction to an ARM Target, select an
310 write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff));
311 // fall through as BL encoding is shared with B
316 checkInt<26>(Loc, Val, Type);
317 write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));
319 case R_ARM_THM_JUMP11:
320 checkInt<12>(Loc, Val, Type);
321 write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff));
323 case R_ARM_THM_JUMP19:
324 // Encoding T3: Val = S:J2:J1:imm6:imm11:0
325 checkInt<21>(Loc, Val, Type);
327 (read16le(Loc) & 0xfbc0) | // opcode cond
328 ((Val >> 10) & 0x0400) | // S
329 ((Val >> 12) & 0x003f)); // imm6
332 ((Val >> 8) & 0x0800) | // J2
333 ((Val >> 5) & 0x2000) | // J1
334 ((Val >> 1) & 0x07ff)); // imm11
337 // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the
338 // value of bit 0 of Val, we must select a BL or BLX instruction
339 if ((Val & 1) == 0) {
340 // Ensure BLX destination is 4-byte aligned. As BLX instruction may
341 // only be two byte aligned. This must be done before overflow check
342 Val = alignTo(Val, 4);
344 // Bit 12 is 0 for BLX, 1 for BL
345 write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);
346 // Fall through as rest of encoding is the same as B.W
348 case R_ARM_THM_JUMP24:
349 // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
350 // FIXME: Use of I1 and I2 require v6T2ops
351 checkInt<25>(Loc, Val, Type);
354 ((Val >> 14) & 0x0400) | // S
355 ((Val >> 12) & 0x03ff)); // imm10
357 (read16le(Loc + 2) & 0xd000) | // opcode
358 (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1
359 (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2
360 ((Val >> 1) & 0x07ff)); // imm11
362 case R_ARM_MOVW_ABS_NC:
363 case R_ARM_MOVW_PREL_NC:
364 write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) |
368 case R_ARM_MOVT_PREL:
369 checkInt<32>(Loc, Val, Type);
370 write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
371 (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff));
373 case R_ARM_THM_MOVT_ABS:
374 case R_ARM_THM_MOVT_PREL:
375 // Encoding T1: A = imm4:i:imm3:imm8
376 checkInt<32>(Loc, Val, Type);
379 ((Val >> 17) & 0x0400) | // i
380 ((Val >> 28) & 0x000f)); // imm4
382 (read16le(Loc + 2) & 0x8f00) | // opcode
383 ((Val >> 12) & 0x7000) | // imm3
384 ((Val >> 16) & 0x00ff)); // imm8
386 case R_ARM_THM_MOVW_ABS_NC:
387 case R_ARM_THM_MOVW_PREL_NC:
388 // Encoding T3: A = imm4:i:imm3:imm8
391 ((Val >> 1) & 0x0400) | // i
392 ((Val >> 12) & 0x000f)); // imm4
394 (read16le(Loc + 2) & 0x8f00) | // opcode
395 ((Val << 4) & 0x7000) | // imm3
396 (Val & 0x00ff)); // imm8
399 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
403 int64_t ARM::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const {
408 case R_ARM_BASE_PREL:
416 case R_ARM_TLS_LDM32:
417 case R_ARM_TLS_LDO32:
420 return SignExtend64<32>(read32le(Buf));
422 return SignExtend64<31>(read32le(Buf));
427 return SignExtend64<26>(read32le(Buf) << 2);
428 case R_ARM_THM_JUMP11:
429 return SignExtend64<12>(read16le(Buf) << 1);
430 case R_ARM_THM_JUMP19: {
431 // Encoding T3: A = S:J2:J1:imm10:imm6:0
432 uint16_t Hi = read16le(Buf);
433 uint16_t Lo = read16le(Buf + 2);
434 return SignExtend64<20>(((Hi & 0x0400) << 10) | // S
435 ((Lo & 0x0800) << 8) | // J2
436 ((Lo & 0x2000) << 5) | // J1
437 ((Hi & 0x003f) << 12) | // imm6
438 ((Lo & 0x07ff) << 1)); // imm11:0
441 case R_ARM_THM_JUMP24: {
442 // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
443 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
444 // FIXME: I1 and I2 require v6T2ops
445 uint16_t Hi = read16le(Buf);
446 uint16_t Lo = read16le(Buf + 2);
447 return SignExtend64<24>(((Hi & 0x0400) << 14) | // S
448 (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1
449 (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2
450 ((Hi & 0x003ff) << 12) | // imm0
451 ((Lo & 0x007ff) << 1)); // imm11:0
453 // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
454 // MOVT is in the range -32768 <= A < 32768
455 case R_ARM_MOVW_ABS_NC:
457 case R_ARM_MOVW_PREL_NC:
458 case R_ARM_MOVT_PREL: {
459 uint64_t Val = read32le(Buf) & 0x000f0fff;
460 return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
462 case R_ARM_THM_MOVW_ABS_NC:
463 case R_ARM_THM_MOVT_ABS:
464 case R_ARM_THM_MOVW_PREL_NC:
465 case R_ARM_THM_MOVT_PREL: {
466 // Encoding T3: A = imm4:i:imm3:imm8
467 uint16_t Hi = read16le(Buf);
468 uint16_t Lo = read16le(Buf + 2);
469 return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4
470 ((Hi & 0x0400) << 1) | // i
471 ((Lo & 0x7000) >> 4) | // imm3
472 (Lo & 0x00ff)); // imm8
477 TargetInfo *elf::getARMTargetInfo() {