1//===- ARMRelocator.cpp  ----------------------------------------===//
2//
3//                     The MCLinker Project
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 <mcld/LinkerConfig.h>
11#include <mcld/IRBuilder.h>
12#include <llvm/ADT/Twine.h>
13#include <llvm/Support/DataTypes.h>
14#include <llvm/Support/ELF.h>
15#include <llvm/Support/Host.h>
16#include <mcld/Support/MsgHandling.h>
17#include <mcld/LD/LDSymbol.h>
18#include <mcld/LD/ELFFileFormat.h>
19#include <mcld/Object/ObjectBuilder.h>
20#include "ARMRelocator.h"
21#include "ARMRelocationFunctions.h"
22
23using namespace mcld;
24
25//=========================================//
26// Relocation helper function              //
27//=========================================//
28static Relocator::DWord getThumbBit(const Relocation& pReloc)
29{
30  // Set thumb bit if
31  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
32  Relocator::DWord thumbBit =
33       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
34        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
35        ((pReloc.symValue() & 0x1) != 0))?
36        1:0;
37  return thumbBit;
38}
39
40// Using uint64_t to make sure those complicate operations won't cause
41// undefined behavior.
42static
43uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
44{
45  assert(pOri_width <= 64);
46  if (pOri_width == 64)
47    return pVal;
48
49  uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width);
50  pVal &= mask;
51  // Reverse sign bit, then subtract sign bit.
52  uint64_t sign_bit = 1 << (pOri_width - 1);
53  return (pVal ^ sign_bit) - sign_bit;
54}
55
56static
57uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
58{
59  return (pA & ~pMask) | (pB & pMask) ;
60}
61
62// Check if symbol can use relocation R_ARM_RELATIVE
63static bool
64helper_use_relative_reloc(const ResolveInfo& pSym,
65                          const ARMRelocator& pFactory)
66{
67  // if symbol is dynamic or undefine or preemptible
68  if (pSym.isDyn() ||
69      pSym.isUndef() ||
70      pFactory.getTarget().isSymbolPreemptible(pSym))
71    return false;
72  return true;
73}
74
75// Strip LSB (THUMB bit) if "S" is a THUMB target.
76static inline void helper_clear_thumb_bit(Relocator::DWord& pValue)
77{
78  pValue &= (~0x1);
79}
80
81static
82Relocator::Address helper_get_GOT_address(ResolveInfo& pSym,
83                                          ARMRelocator& pParent)
84{
85  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(pSym);
86  assert(NULL != got_entry);
87  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
88}
89
90static
91ARMGOTEntry& helper_GOT_init(Relocation& pReloc,
92                             bool pHasRel,
93                             ARMRelocator& pParent)
94{
95  // rsym - The relocation target symbol
96  ResolveInfo* rsym = pReloc.symInfo();
97  ARMGNULDBackend& ld_backend = pParent.getTarget();
98  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
99
100  ARMGOTEntry* got_entry = ld_backend.getGOT().createGOT();
101  pParent.getSymGOTMap().record(*rsym, *got_entry);
102  // If we first get this GOT entry, we should initialize it.
103  if (!pHasRel) {
104    // No corresponding dynamic relocation, initialize to the symbol value.
105    got_entry->setValue(ARMRelocator::SymVal);
106  }
107  else {
108    // Initialize corresponding dynamic relocation.
109    Relocation& rel_entry = *ld_backend.getRelDyn().create();
110    if (rsym->isLocal() || helper_use_relative_reloc(*rsym, pParent)) {
111      // Initialize got entry to target symbol address
112      got_entry->setValue(ARMRelocator::SymVal);
113      rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
114      rel_entry.setSymInfo(NULL);
115    }
116    else {
117      // Initialize got entry to 0 for corresponding dynamic relocation.
118      got_entry->setValue(0);
119      rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
120      rel_entry.setSymInfo(rsym);
121    }
122    rel_entry.targetRef().assign(*got_entry);
123  }
124  return *got_entry;
125}
126
127static
128Relocator::Address helper_GOT_ORG(ARMRelocator& pParent)
129{
130  return pParent.getTarget().getGOT().addr();
131}
132
133static
134Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
135                                          ARMRelocator& pParent)
136{
137  ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
138  assert(NULL != plt_entry);
139  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
140}
141
142static
143ARMPLT1& helper_PLT_init(Relocation& pReloc, ARMRelocator& pParent)
144{
145  // rsym - The relocation target symbol
146  ResolveInfo* rsym = pReloc.symInfo();
147  ARMGNULDBackend& ld_backend = pParent.getTarget();
148  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
149
150  // initialize the plt and the corresponding gotplt and dyn relocation
151  ARMPLT1* plt_entry = ld_backend.getPLT().create();
152  pParent.getSymPLTMap().record(*rsym, *plt_entry);
153
154  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
155         "PLT entry not exist, but DynRel entry exist!");
156  ARMGOTEntry* gotplt_entry = ld_backend.getGOT().createGOTPLT();
157  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
158
159  Relocation& rel_entry = *ld_backend.getRelPLT().create();
160  rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
161  rel_entry.targetRef().assign(*gotplt_entry);
162  rel_entry.setSymInfo(rsym);
163
164  return *plt_entry;
165}
166
167// Get an relocation entry in .rel.dyn and set its type to pType,
168// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
169// pReloc->symInfo()
170static
171void helper_DynRel_init(Relocation& pReloc,
172                        Relocator::Type pType,
173                        ARMRelocator& pParent)
174{
175  // rsym - The relocation target symbol
176  ResolveInfo* rsym = pReloc.symInfo();
177  ARMGNULDBackend& ld_backend = pParent.getTarget();
178
179  Relocation& rel_entry = *ld_backend.getRelDyn().create();
180  rel_entry.setType(pType);
181  rel_entry.targetRef() = pReloc.targetRef();
182
183  if (pType == llvm::ELF::R_ARM_RELATIVE)
184    rel_entry.setSymInfo(NULL);
185  else
186    rel_entry.setSymInfo(rsym);
187}
188
189static Relocator::DWord
190helper_extract_movw_movt_addend(Relocator::DWord pTarget)
191{
192  // imm16: [19-16][11-0]
193  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
194                            16);
195}
196
197static Relocator::DWord
198helper_insert_val_movw_movt_inst(Relocator::DWord pTarget,
199                                 Relocator::DWord pImm)
200{
201  // imm16: [19-16][11-0]
202  pTarget &= 0xfff0f000U;
203  pTarget |= pImm & 0x0fffU;
204  pTarget |= (pImm & 0xf000U) << 4;
205  return pTarget;
206}
207
208static Relocator::DWord
209helper_extract_thumb_movw_movt_addend(Relocator::DWord pValue)
210{
211  // imm16: [19-16][26][14-12][7-0]
212  return helper_sign_extend((((pValue >> 4) & 0xf000U) |
213                             ((pValue >> 15) & 0x0800U) |
214                             ((pValue >> 4) & 0x0700U) |
215                             (pValue& 0x00ffU)),
216                            16);
217}
218
219static Relocator::DWord
220helper_insert_val_thumb_movw_movt_inst(Relocator::DWord pValue,
221                                       Relocator::DWord pImm)
222{
223  // imm16: [19-16][26][14-12][7-0]
224  pValue &= 0xfbf08f00U;
225  pValue |= (pImm & 0xf000U) << 4;
226  pValue |= (pImm & 0x0800U) << 15;
227  pValue |= (pImm & 0x0700U) << 4;
228  pValue |= (pImm & 0x00ffU);
229  return pValue;
230}
231
232static Relocator::DWord
233helper_thumb32_branch_offset(Relocator::DWord pUpper16,
234                             Relocator::DWord pLower16)
235{
236  Relocator::DWord s = (pUpper16 & (1U << 10)) >> 10,        // 26 bit
237                           u  = pUpper16 & 0x3ffU,              // 25-16
238                           l  = pLower16 & 0x7ffU,              // 10-0
239                           j1 = (pLower16 & (1U << 13)) >> 13,  // 13
240                           j2 = (pLower16 & (1U << 11)) >> 11;  // 11
241  Relocator::DWord i1 = j1 ^ s? 0: 1,
242                              i2 = j2 ^ s? 0: 1;
243
244  // [31-25][24][23][22][21-12][11-1][0]
245  //      0   s  i1  i2      u     l  0
246  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
247                            (u << 12) | (l << 1),
248                            25);
249}
250
251static Relocator::DWord
252helper_thumb32_branch_upper(Relocator::DWord pUpper16,
253                            Relocator::DWord pOffset)
254{
255  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
256  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
257}
258
259static Relocator::DWord
260helper_thumb32_branch_lower(Relocator::DWord pLower16,
261                            Relocator::DWord pOffset)
262{
263  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
264  return ((pLower16 & ~0x2fffU) |
265          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
266          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
267          ((pOffset >> 1) & 0x7ffU));
268}
269
270static Relocator::DWord
271helper_thumb32_cond_branch_offset(Relocator::DWord pUpper16,
272                                  Relocator::DWord pLower16)
273{
274  uint32_t s = (pUpper16 & 0x0400U) >> 10;
275  uint32_t j1 = (pLower16 & 0x2000U) >> 13;
276  uint32_t j2 = (pLower16 & 0x0800U) >> 11;
277  uint32_t lower = (pLower16 & 0x07ffU);
278  uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (pUpper16 & 0x003fU);
279  return helper_sign_extend((upper << 12) | (lower << 1), 21);
280}
281
282static Relocator::DWord
283helper_thumb32_cond_branch_upper(Relocator::DWord pUpper16,
284                                 Relocator::DWord pOffset)
285{
286  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
287  return (pUpper16 & 0xfbc0U) | (sign << 10) | ((pOffset & 0x0003f000U) >> 12);
288}
289
290static Relocator::DWord
291helper_thumb32_cond_branch_lower(Relocator::DWord pLower16,
292                                 Relocator::DWord pOffset)
293{
294  uint32_t j2 = (pOffset & 0x00080000U) >> 19;
295  uint32_t j1 = (pOffset & 0x00040000U) >> 18;
296  uint32_t lo = (pOffset & 0x00000ffeU) >> 1;
297  return (pLower16 & 0xd000U) | (j1 << 13) | (j2 << 11) | lo;
298}
299
300// Return true if overflow
301static bool
302helper_check_signed_overflow(Relocator::DWord pValue,
303                             unsigned bits)
304{
305  int32_t signed_val = static_cast<int32_t>(pValue);
306  int32_t max = (1 << (bits - 1)) - 1;
307  int32_t min = -(1 << (bits - 1));
308  if (signed_val > max || signed_val < min) {
309    return true;
310  } else {
311    return false;
312  }
313}
314
315
316//===--------------------------------------------------------------------===//
317// Relocation Functions and Tables
318//===--------------------------------------------------------------------===//
319DECL_ARM_APPLY_RELOC_FUNCS
320
321/// the prototype of applying function
322typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
323                                               ARMRelocator& pParent);
324
325// the table entry of applying functions
326struct ApplyFunctionTriple
327{
328  ApplyFunctionType func;
329  unsigned int type;
330  const char* name;
331};
332
333// declare the table of applying functions
334static const ApplyFunctionTriple ApplyFunctions[] = {
335  DECL_ARM_APPLY_RELOC_FUNC_PTRS
336};
337
338//===--------------------------------------------------------------------===//
339// ARMRelocator
340//===--------------------------------------------------------------------===//
341ARMRelocator::ARMRelocator(ARMGNULDBackend& pParent,
342                           const LinkerConfig& pConfig)
343  : Relocator(pConfig),
344    m_Target(pParent) {
345}
346
347ARMRelocator::~ARMRelocator()
348{
349}
350
351Relocator::Result
352ARMRelocator::applyRelocation(Relocation& pRelocation)
353{
354  Relocation::Type type = pRelocation.type();
355  if (type > 130) { // 131-255 doesn't noted in ARM spec
356    return Relocator::Unknown;
357  }
358
359  return ApplyFunctions[type].func(pRelocation, *this);
360}
361
362const char* ARMRelocator::getName(Relocator::Type pType) const
363{
364  return ApplyFunctions[pType].name;
365}
366
367Relocator::Size ARMRelocator::getSize(Relocation::Type pType) const
368{
369  return 32;
370}
371
372void ARMRelocator::addCopyReloc(ResolveInfo& pSym)
373{
374  Relocation& rel_entry = *getTarget().getRelDyn().create();
375  rel_entry.setType(llvm::ELF::R_ARM_COPY);
376  assert(pSym.outSymbol()->hasFragRef());
377  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
378  rel_entry.setSymInfo(&pSym);
379}
380
381/// defineSymbolForCopyReloc
382/// For a symbol needing copy relocation, define a copy symbol in the BSS
383/// section and all other reference to this symbol should refer to this
384/// copy.
385/// This is executed at scan relocation stage.
386LDSymbol&
387ARMRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
388                                       const ResolveInfo& pSym)
389{
390  // get or create corresponding BSS LDSection
391  LDSection* bss_sect_hdr = NULL;
392  ELFFileFormat* file_format = getTarget().getOutputFormat();
393  if (ResolveInfo::ThreadLocal == pSym.type())
394    bss_sect_hdr = &file_format->getTBSS();
395  else
396    bss_sect_hdr = &file_format->getBSS();
397
398  // get or create corresponding BSS SectionData
399  SectionData* bss_data = NULL;
400  if (bss_sect_hdr->hasSectionData())
401    bss_data = bss_sect_hdr->getSectionData();
402  else
403    bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
404
405  // Determine the alignment by the symbol value
406  // FIXME: here we use the largest alignment
407  uint32_t addralign = config().targets().bitclass() / 8;
408
409  // allocate space in BSS for the copy symbol
410  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
411  uint64_t size = ObjectBuilder::AppendFragment(*frag,
412                                                *bss_data,
413                                                addralign);
414  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
415
416  // change symbol binding to Global if it's a weak symbol
417  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
418  if (binding == ResolveInfo::Weak)
419    binding = ResolveInfo::Global;
420
421  // Define the copy symbol in the bss section and resolve it
422  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
423                      pSym.name(),
424                      (ResolveInfo::Type)pSym.type(),
425                      ResolveInfo::Define,
426                      binding,
427                      pSym.size(),  // size
428                      0x0,          // value
429                      FragmentRef::Create(*frag, 0x0),
430                      (ResolveInfo::Visibility)pSym.other());
431
432  return *cpy_sym;
433}
434
435/// checkValidReloc - When we attempt to generate a dynamic relocation for
436/// ouput file, check if the relocation is supported by dynamic linker.
437void ARMRelocator::checkValidReloc(Relocation& pReloc) const
438{
439  // If not PIC object, no relocation type is invalid
440  if (!config().isCodeIndep())
441    return;
442
443  switch(pReloc.type()) {
444    case llvm::ELF::R_ARM_RELATIVE:
445    case llvm::ELF::R_ARM_COPY:
446    case llvm::ELF::R_ARM_GLOB_DAT:
447    case llvm::ELF::R_ARM_JUMP_SLOT:
448    case llvm::ELF::R_ARM_ABS32:
449    case llvm::ELF::R_ARM_ABS32_NOI:
450    case llvm::ELF::R_ARM_PC24:
451    case llvm::ELF::R_ARM_TLS_DTPMOD32:
452    case llvm::ELF::R_ARM_TLS_DTPOFF32:
453    case llvm::ELF::R_ARM_TLS_TPOFF32:
454      break;
455
456    default:
457      error(diag::non_pic_relocation) << (int)pReloc.type()
458                                      << pReloc.symInfo()->name();
459      break;
460  }
461}
462
463bool ARMRelocator::mayHaveFunctionPointerAccess(const Relocation& pReloc) const
464{
465  switch (pReloc.type()) {
466    case llvm::ELF::R_ARM_PC24:
467    case llvm::ELF::R_ARM_THM_CALL:
468    case llvm::ELF::R_ARM_PLT32:
469    case llvm::ELF::R_ARM_CALL:
470    case llvm::ELF::R_ARM_JUMP24:
471    case llvm::ELF::R_ARM_THM_JUMP24:
472    case llvm::ELF::R_ARM_SBREL31:
473    case llvm::ELF::R_ARM_PREL31:
474    case llvm::ELF::R_ARM_THM_JUMP19:
475    case llvm::ELF::R_ARM_THM_JUMP6:
476    case llvm::ELF::R_ARM_THM_JUMP11:
477    case llvm::ELF::R_ARM_THM_JUMP8: {
478      return false;
479    }
480    default: {
481      return true;
482    }
483  }
484}
485
486void
487ARMRelocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection)
488{
489  // rsym - The relocation target symbol
490  ResolveInfo* rsym = pReloc.symInfo();
491
492  switch(pReloc.type()){
493
494    // Set R_ARM_TARGET1 to R_ARM_ABS32
495    // Ref: GNU gold 1.11 arm.cc, line 9892
496    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
497    // or --target1-rel
498    case llvm::ELF::R_ARM_TARGET1:
499       pReloc.setType(llvm::ELF::R_ARM_ABS32);
500    case llvm::ELF::R_ARM_ABS32:
501    case llvm::ELF::R_ARM_ABS32_NOI: {
502      // If buiding PIC object (shared library or PIC executable),
503      // a dynamic relocations with RELATIVE type to this location is needed.
504      // Reserve an entry in .rel.dyn
505      if (config().isCodeIndep()) {
506        helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
507        // set Rel bit
508        rsym->setReserved(rsym->reserved() | ReserveRel);
509        getTarget().checkAndSetHasTextRel(*pSection.getLink());
510      }
511      return;
512    }
513
514    case llvm::ELF::R_ARM_ABS16:
515    case llvm::ELF::R_ARM_ABS12:
516    case llvm::ELF::R_ARM_THM_ABS5:
517    case llvm::ELF::R_ARM_ABS8:
518    case llvm::ELF::R_ARM_BASE_ABS:
519    case llvm::ELF::R_ARM_MOVW_ABS_NC:
520    case llvm::ELF::R_ARM_MOVT_ABS:
521    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
522    case llvm::ELF::R_ARM_THM_MOVT_ABS: {
523      // PIC code should not contain these kinds of relocation
524      if (config().isCodeIndep()) {
525        error(diag::non_pic_relocation) << (int)pReloc.type()
526                                        << pReloc.symInfo()->name();
527      }
528      return;
529    }
530    case llvm::ELF::R_ARM_GOTOFF32:
531    case llvm::ELF::R_ARM_GOTOFF12: {
532      // FIXME: A GOT section is needed
533      return;
534    }
535
536    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
537    // Ref: GNU gold 1.11 arm.cc, line 9892
538    // FIXME: R_ARM_TARGET2 should be set by option --target2
539    case llvm::ELF::R_ARM_TARGET2:
540      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
541    case llvm::ELF::R_ARM_GOT_BREL:
542    case llvm::ELF::R_ARM_GOT_PREL: {
543      // A GOT entry is needed for these relocation type.
544      // return if we already create GOT for this symbol
545      if (rsym->reserved() & ReserveGOT)
546        return;
547
548      // If building PIC object, a dynamic relocation with
549      // type RELATIVE is needed to relocate this GOT entry.
550      if (config().isCodeIndep())
551         helper_GOT_init(pReloc, true, *this);
552      else
553         helper_GOT_init(pReloc, false, *this);
554      // set GOT bit
555      rsym->setReserved(rsym->reserved() | ReserveGOT);
556      return;
557    }
558
559    case llvm::ELF::R_ARM_BASE_PREL: {
560      // FIXME: Currently we only support R_ARM_BASE_PREL against
561      // symbol _GLOBAL_OFFSET_TABLE_
562      if (rsym != getTarget().getGOTSymbol()->resolveInfo())
563        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
564                                     << "mclinker@googlegroups.com";
565      return;
566    }
567    case llvm::ELF::R_ARM_COPY:
568    case llvm::ELF::R_ARM_GLOB_DAT:
569    case llvm::ELF::R_ARM_JUMP_SLOT:
570    case llvm::ELF::R_ARM_RELATIVE: {
571      // These are relocation type for dynamic linker, shold not
572      // appear in object file.
573      fatal(diag::dynamic_relocation) << (int)pReloc.type();
574      break;
575    }
576    default: {
577      break;
578    }
579  } // end switch
580}
581
582void ARMRelocator::scanGlobalReloc(Relocation& pReloc,
583                                   IRBuilder& pBuilder,
584                                   const LDSection& pSection)
585{
586  // rsym - The relocation target symbol
587  ResolveInfo* rsym = pReloc.symInfo();
588
589  switch(pReloc.type()) {
590
591    // Set R_ARM_TARGET1 to R_ARM_ABS32
592    // Ref: GNU gold 1.11 arm.cc, line 9892
593    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
594    // or --target1-rel
595    case llvm::ELF::R_ARM_TARGET1:
596      pReloc.setType(llvm::ELF::R_ARM_ABS32);
597    case llvm::ELF::R_ARM_ABS32:
598    case llvm::ELF::R_ARM_ABS16:
599    case llvm::ELF::R_ARM_ABS12:
600    case llvm::ELF::R_ARM_THM_ABS5:
601    case llvm::ELF::R_ARM_ABS8:
602    case llvm::ELF::R_ARM_BASE_ABS:
603    case llvm::ELF::R_ARM_MOVW_ABS_NC:
604    case llvm::ELF::R_ARM_MOVT_ABS:
605    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
606    case llvm::ELF::R_ARM_THM_MOVT_ABS:
607    case llvm::ELF::R_ARM_ABS32_NOI: {
608      // Absolute relocation type, symbol may needs PLT entry or
609      // dynamic relocation entry
610      if (getTarget().symbolNeedsPLT(*rsym)) {
611        // create plt for this symbol if it does not have one
612        if (!(rsym->reserved() & ReservePLT)){
613          // Symbol needs PLT entry, we need to reserve a PLT entry
614          // and the corresponding GOT and dynamic relocation entry
615          // in .got and .rel.plt.
616          helper_PLT_init(pReloc, *this);
617          // set PLT bit
618          rsym->setReserved(rsym->reserved() | ReservePLT);
619        }
620      }
621
622      if (getTarget().symbolNeedsDynRel(*rsym,
623                                       (rsym->reserved() & ReservePLT), true)) {
624        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
625          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
626          addCopyReloc(*cpy_sym.resolveInfo());
627        }
628        else {
629          checkValidReloc(pReloc);
630          // set Rel bit
631          if (helper_use_relative_reloc(*rsym, *this))
632            helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
633          else
634            helper_DynRel_init(pReloc, pReloc.type(), *this);
635          rsym->setReserved(rsym->reserved() | ReserveRel);
636          getTarget().checkAndSetHasTextRel(*pSection.getLink());
637        }
638      }
639      return;
640    }
641
642    case llvm::ELF::R_ARM_GOTOFF32:
643    case llvm::ELF::R_ARM_GOTOFF12: {
644      // FIXME: A GOT section is needed
645      return;
646    }
647
648    case llvm::ELF::R_ARM_BASE_PREL:
649    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
650    case llvm::ELF::R_ARM_THM_MOVW_BREL:
651    case llvm::ELF::R_ARM_THM_MOVT_BREL:
652      // FIXME: Currently we only support these relocations against
653      // symbol _GLOBAL_OFFSET_TABLE_
654      if (rsym != getTarget().getGOTSymbol()->resolveInfo()) {
655        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
656                                     << "mclinker@googlegroups.com";
657      }
658    case llvm::ELF::R_ARM_REL32:
659    case llvm::ELF::R_ARM_LDR_PC_G0:
660    case llvm::ELF::R_ARM_SBREL32:
661    case llvm::ELF::R_ARM_THM_PC8:
662    case llvm::ELF::R_ARM_MOVW_PREL_NC:
663    case llvm::ELF::R_ARM_MOVT_PREL:
664    case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
665    case llvm::ELF::R_ARM_THM_MOVT_PREL:
666    case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
667    case llvm::ELF::R_ARM_THM_PC12:
668    case llvm::ELF::R_ARM_REL32_NOI:
669    case llvm::ELF::R_ARM_ALU_PC_G0_NC:
670    case llvm::ELF::R_ARM_ALU_PC_G0:
671    case llvm::ELF::R_ARM_ALU_PC_G1_NC:
672    case llvm::ELF::R_ARM_ALU_PC_G1:
673    case llvm::ELF::R_ARM_ALU_PC_G2:
674    case llvm::ELF::R_ARM_LDR_PC_G1:
675    case llvm::ELF::R_ARM_LDR_PC_G2:
676    case llvm::ELF::R_ARM_LDRS_PC_G0:
677    case llvm::ELF::R_ARM_LDRS_PC_G1:
678    case llvm::ELF::R_ARM_LDRS_PC_G2:
679    case llvm::ELF::R_ARM_LDC_PC_G0:
680    case llvm::ELF::R_ARM_LDC_PC_G1:
681    case llvm::ELF::R_ARM_LDC_PC_G2:
682    case llvm::ELF::R_ARM_ALU_SB_G0_NC:
683    case llvm::ELF::R_ARM_ALU_SB_G0:
684    case llvm::ELF::R_ARM_ALU_SB_G1_NC:
685    case llvm::ELF::R_ARM_ALU_SB_G1:
686    case llvm::ELF::R_ARM_ALU_SB_G2:
687    case llvm::ELF::R_ARM_LDR_SB_G0:
688    case llvm::ELF::R_ARM_LDR_SB_G1:
689    case llvm::ELF::R_ARM_LDR_SB_G2:
690    case llvm::ELF::R_ARM_LDRS_SB_G0:
691    case llvm::ELF::R_ARM_LDRS_SB_G1:
692    case llvm::ELF::R_ARM_LDRS_SB_G2:
693    case llvm::ELF::R_ARM_LDC_SB_G0:
694    case llvm::ELF::R_ARM_LDC_SB_G1:
695    case llvm::ELF::R_ARM_LDC_SB_G2:
696    case llvm::ELF::R_ARM_MOVW_BREL_NC:
697    case llvm::ELF::R_ARM_MOVT_BREL:
698    case llvm::ELF::R_ARM_MOVW_BREL: {
699      // Relative addressing relocation, may needs dynamic relocation
700      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
701                                                                       false)) {
702        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
703        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
704          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
705          addCopyReloc(*cpy_sym.resolveInfo());
706        }
707        else {
708          checkValidReloc(pReloc);
709          // set Rel bit
710          //helper_DynRel_init(pReloc, pReloc.type(), *this);
711          rsym->setReserved(rsym->reserved() | ReserveRel);
712          getTarget().checkAndSetHasTextRel(*pSection.getLink());
713        }
714      }
715      return;
716    }
717
718    case llvm::ELF::R_ARM_PC24:
719    case llvm::ELF::R_ARM_THM_CALL:
720    case llvm::ELF::R_ARM_PLT32:
721    case llvm::ELF::R_ARM_CALL:
722    case llvm::ELF::R_ARM_JUMP24:
723    case llvm::ELF::R_ARM_THM_JUMP24:
724    case llvm::ELF::R_ARM_SBREL31:
725    case llvm::ELF::R_ARM_PREL31:
726    case llvm::ELF::R_ARM_THM_JUMP19:
727    case llvm::ELF::R_ARM_THM_JUMP6:
728    case llvm::ELF::R_ARM_THM_JUMP11:
729    case llvm::ELF::R_ARM_THM_JUMP8: {
730      // These are branch relocation (except PREL31)
731      // A PLT entry is needed when building shared library
732
733      // return if we already create plt for this symbol
734      if (rsym->reserved() & ReservePLT)
735        return;
736
737      // if the symbol's value can be decided at link time, then no need plt
738      if (getTarget().symbolFinalValueIsKnown(*rsym))
739        return;
740
741      // if symbol is defined in the ouput file and it's not
742      // preemptible, no need plt
743      if (rsym->isDefine() && !rsym->isDyn() &&
744          !getTarget().isSymbolPreemptible(*rsym)) {
745        return;
746      }
747
748      // Symbol needs PLT entry, we need to reserve a PLT entry
749      // and the corresponding GOT and dynamic relocation entry
750      // in .got and .rel.plt.
751      helper_PLT_init(pReloc, *this);
752      // set PLT bit
753      rsym->setReserved(rsym->reserved() | ReservePLT);
754      return;
755    }
756
757    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
758    // Ref: GNU gold 1.11 arm.cc, line 9892
759    // FIXME: R_ARM_TARGET2 should be set by option --target2
760    case llvm::ELF::R_ARM_TARGET2:
761      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
762    case llvm::ELF::R_ARM_GOT_BREL:
763    case llvm::ELF::R_ARM_GOT_ABS:
764    case llvm::ELF::R_ARM_GOT_PREL: {
765      // Symbol needs GOT entry, reserve entry in .got
766      // return if we already create GOT for this symbol
767      if (rsym->reserved() & ReserveGOT)
768        return;
769      // if the symbol cannot be fully resolved at link time, then we need a
770      // dynamic relocation
771      if (!getTarget().symbolFinalValueIsKnown(*rsym))
772        helper_GOT_init(pReloc, true, *this);
773      else
774        helper_GOT_init(pReloc, false, *this);
775      // set GOT bit
776      rsym->setReserved(rsym->reserved() | ReserveGOT);
777      return;
778    }
779
780    case llvm::ELF::R_ARM_COPY:
781    case llvm::ELF::R_ARM_GLOB_DAT:
782    case llvm::ELF::R_ARM_JUMP_SLOT:
783    case llvm::ELF::R_ARM_RELATIVE: {
784      // These are relocation type for dynamic linker, shold not
785      // appear in object file.
786      fatal(diag::dynamic_relocation) << (int)pReloc.type();
787      break;
788    }
789    default: {
790      break;
791    }
792  } // end switch
793}
794
795void ARMRelocator::scanRelocation(Relocation& pReloc,
796                                  IRBuilder& pBuilder,
797                                  Module& pModule,
798                                  LDSection& pSection,
799                                  Input& pInput)
800{
801  // rsym - The relocation target symbol
802  ResolveInfo* rsym = pReloc.symInfo();
803  assert(NULL != rsym &&
804         "ResolveInfo of relocation not set while scanRelocation");
805
806  assert(NULL != pSection.getLink());
807  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
808    return;
809
810  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
811  // entries should be created.
812  // FIXME: Below judgements concern nothing about TLS related relocation
813
814  // rsym is local
815  if (rsym->isLocal())
816    scanLocalReloc(pReloc, pSection);
817
818  // rsym is external
819  else
820    scanGlobalReloc(pReloc, pBuilder, pSection);
821
822  // check if we shoule issue undefined reference for the relocation target
823  // symbol
824  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
825    issueUndefRef(pReloc, pSection, pInput);
826}
827
828//=========================================//
829// Each relocation function implementation //
830//=========================================//
831
832// R_ARM_NONE
833ARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent)
834{
835  return Relocator::OK;
836}
837
838// R_ARM_ABS32: (S + A) | T
839ARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent)
840{
841  ResolveInfo* rsym = pReloc.symInfo();
842  Relocator::DWord T = getThumbBit(pReloc);
843  Relocator::DWord A = pReloc.target() + pReloc.addend();
844  Relocator::DWord S = pReloc.symValue();
845  if (T != 0x0)
846    helper_clear_thumb_bit(S);
847
848  // If the flag of target section is not ALLOC, we will not scan this relocation
849  // but perform static relocation. (e.g., applying .debug section)
850  if (0x0 == (llvm::ELF::SHF_ALLOC &
851      pReloc.targetRef().frag()->getParent()->getSection().flag())) {
852    pReloc.target() = (S + A) | T;
853    return Relocator::OK;
854  }
855
856  // An external symbol may need PLT and dynamic relocation
857  if (!rsym->isLocal()) {
858    if (rsym->reserved() & ARMRelocator::ReservePLT) {
859      S = helper_get_PLT_address(*rsym, pParent);
860      T = 0 ; // PLT is not thumb
861    }
862    // If we generate a dynamic relocation (except R_ARM_RELATIVE)
863    // for a place, we should not perform static relocation on it
864    // in order to keep the addend store in the place correct.
865    if ((rsym->reserved() & ARMRelocator::ReserveRel) &&
866        (!helper_use_relative_reloc(*rsym, pParent)))
867      return Relocator::OK;
868  }
869
870  // perform static relocation
871  pReloc.target() = (S + A) | T;
872  return Relocator::OK;
873}
874
875// R_ARM_REL32: ((S + A) | T) - P
876ARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent)
877{
878  // perform static relocation
879  Relocator::Address S = pReloc.symValue();
880  Relocator::DWord   T = getThumbBit(pReloc);
881  Relocator::DWord   A = pReloc.target() + pReloc.addend();
882
883  // An external symbol may need PLT (this reloc is from a stub/veneer)
884  if (!pReloc.symInfo()->isLocal()) {
885    if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
886      S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
887      T = 0;  // PLT is not thumb.
888    }
889  }
890
891  if (T != 0x0)
892    helper_clear_thumb_bit(S);
893
894  // perform relocation
895  pReloc.target() = ((S + A) | T) - pReloc.place();
896
897  return Relocator::OK;
898}
899
900// R_ARM_BASE_PREL: B(S) + A - P
901ARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent)
902{
903  // perform static relocation
904  Relocator::DWord A = pReloc.target() + pReloc.addend();
905  pReloc.target() = pReloc.symValue() + A - pReloc.place();
906  return Relocator::OK;
907}
908
909// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
910ARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent)
911{
912  Relocator::DWord T = getThumbBit(pReloc);
913  Relocator::DWord A = pReloc.target() + pReloc.addend();
914  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
915  Relocator::Address S = pReloc.symValue();
916  if (T != 0x0)
917    helper_clear_thumb_bit(S);
918
919  pReloc.target() = ((S + A) | T) - GOT_ORG;
920  return Relocator::OK;
921}
922
923// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
924ARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent)
925{
926  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT))
927    return Relocator::BadReloc;
928
929  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
930  Relocator::DWord   A = pReloc.target() + pReloc.addend();
931  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
932  // Apply relocation.
933  pReloc.target() = GOT_S + A - GOT_ORG;
934
935  // setup got entry value if needed
936  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
937  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
938    got_entry->setValue(pReloc.symValue());
939  return Relocator::OK;
940}
941
942// R_ARM_GOT_PREL: GOT(S) + A - P
943ARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent)
944{
945  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT)) {
946    return Relocator::BadReloc;
947  }
948  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
949  Relocator::DWord   A     = pReloc.target() + pReloc.addend();
950  Relocator::Address P     = pReloc.place();
951
952  // Apply relocation.
953  pReloc.target() = GOT_S + A - P;
954
955  // setup got entry value if needed
956  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
957  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
958    got_entry->setValue(pReloc.symValue());
959  return Relocator::OK;
960}
961
962// R_ARM_THM_JUMP8: S + A - P
963ARMRelocator::Result thm_jump8(Relocation& pReloc, ARMRelocator& pParent)
964{
965  Relocator::DWord P = pReloc.place();
966  Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x00ff) << 1, 8) +
967                       pReloc.addend();
968  // S depends on PLT exists or not
969  Relocator::Address S = pReloc.symValue();
970  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
971    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
972
973  Relocator::DWord X = S + A - P;
974  if (helper_check_signed_overflow(X, 9))
975    return Relocator::Overflow;
976  //                    Make sure the Imm is 0.          Result Mask.
977  pReloc.target() = (pReloc.target() & 0xFFFFFF00u) | ((X & 0x01FEu) >> 1);
978  return Relocator::OK;
979}
980
981// R_ARM_THM_JUMP11: S + A - P
982ARMRelocator::Result thm_jump11(Relocation& pReloc, ARMRelocator& pParent)
983{
984  Relocator::DWord P = pReloc.place();
985  Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x07ff) << 1, 11) +
986                       pReloc.addend();
987  // S depends on PLT exists or not
988  Relocator::Address S = pReloc.symValue();
989  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
990    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
991
992  Relocator::DWord X = S + A - P;
993  if (helper_check_signed_overflow(X, 12))
994    return Relocator::Overflow;
995  //                    Make sure the Imm is 0.          Result Mask.
996  pReloc.target() = (pReloc.target() & 0xFFFFF800u) | ((X & 0x0FFEu) >> 1);
997  return Relocator::OK;
998}
999
1000// R_ARM_THM_JUMP19: ((S + A) | T) - P
1001ARMRelocator::Result thm_jump19(Relocation& pReloc, ARMRelocator& pParent)
1002{
1003  // get lower and upper 16 bit instructions from relocation targetData
1004  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1005  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1006
1007  Relocator::DWord T = getThumbBit(pReloc);
1008  Relocator::DWord A = helper_thumb32_cond_branch_offset(upper_inst,
1009                                                                    lower_inst);
1010  Relocator::Address P = pReloc.place();
1011  Relocator::Address S;
1012  // if symbol has plt
1013  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
1014    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
1015    T = 0;  // PLT is not thumb.
1016  }
1017  else {
1018    S = pReloc.symValue();
1019    if (T != 0x0)
1020      helper_clear_thumb_bit(S);
1021  }
1022
1023  if (0x0 == T) {
1024    // FIXME: conditional branch to PLT in THUMB-2 not supported yet
1025    error(diag::unsupport_cond_branch_reloc) << (int)pReloc.type();
1026    return Relocator::BadReloc;
1027  }
1028
1029  Relocator::DWord X = ((S + A) | T) - P;
1030  if (helper_check_signed_overflow(X, 21))
1031    return Relocator::Overflow;
1032
1033  upper_inst = helper_thumb32_cond_branch_upper(upper_inst, X);
1034  lower_inst = helper_thumb32_cond_branch_lower(lower_inst, X);
1035
1036  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
1037  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
1038
1039  return Relocator::OK;
1040}
1041
1042// R_ARM_PC24: ((S + A) | T) - P
1043// R_ARM_PLT32: ((S + A) | T) - P
1044// R_ARM_JUMP24: ((S + A) | T) - P
1045// R_ARM_CALL: ((S + A) | T) - P
1046ARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent)
1047{
1048  // If target is undefined weak symbol, we only need to jump to the
1049  // next instruction unless it has PLT entry. Rewrite instruction
1050  // to NOP.
1051  if (pReloc.symInfo()->isWeak() &&
1052      pReloc.symInfo()->isUndef() &&
1053      !pReloc.symInfo()->isDyn() &&
1054      !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
1055    // change target to NOP : mov r0, r0
1056    pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
1057    return Relocator::OK;
1058  }
1059
1060  Relocator::DWord   T = getThumbBit(pReloc);
1061  Relocator::DWord   A =
1062    helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) +
1063    pReloc.addend();
1064  Relocator::Address P = pReloc.place();
1065  Relocator::Address S = pReloc.symValue();
1066  if (T != 0x0)
1067    helper_clear_thumb_bit(S);
1068
1069  // S depends on PLT exists or not
1070  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
1071    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
1072    T = 0;  // PLT is not thumb.
1073  }
1074
1075  // At this moment (after relaxation), if the jump target is thumb instruction,
1076  // switch mode is needed, rewrite the instruction to BLX
1077  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
1078  // CPU ARCH TAG, which should be ARMv5 or above)
1079  if (T != 0) {
1080    // cannot rewrite to blx for R_ARM_JUMP24
1081    if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
1082      return Relocator::BadReloc;
1083    if (pReloc.type() == llvm::ELF::R_ARM_PC24)
1084      return Relocator::BadReloc;
1085
1086    pReloc.target() = (pReloc.target() & 0xffffff) |
1087                      0xfa000000 |
1088                      (((S + A - P) & 2) << 23);
1089  }
1090
1091  Relocator::DWord X = ((S + A) | T) - P;
1092  // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
1093  if (helper_check_signed_overflow(X, 26))
1094    return Relocator::Overflow;
1095  //                    Make sure the Imm is 0.          Result Mask.
1096  pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
1097  return Relocator::OK;
1098}
1099
1100// R_ARM_THM_CALL: ((S + A) | T) - P
1101// R_ARM_THM_JUMP24: ((S + A) | T) - P
1102ARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent)
1103{
1104  // If target is undefined weak symbol, we only need to jump to the
1105  // next instruction unless it has PLT entry. Rewrite instruction
1106  // to NOP.
1107  if (pReloc.symInfo()->isWeak() &&
1108      pReloc.symInfo()->isUndef() &&
1109      !pReloc.symInfo()->isDyn() &&
1110      !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
1111    pReloc.target() = (0xe000U << 16) | 0xbf00U;
1112    return Relocator::OK;
1113  }
1114
1115  // get lower and upper 16 bit instructions from relocation targetData
1116  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1117  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1118
1119  Relocator::DWord T = getThumbBit(pReloc);
1120  Relocator::DWord A = helper_thumb32_branch_offset(upper_inst, lower_inst);
1121  Relocator::Address P = pReloc.place();
1122  Relocator::Address S;
1123
1124  // if symbol has plt
1125  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
1126    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
1127    T = 0;  // PLT is not thumb.
1128  }
1129  else {
1130    S = pReloc.symValue();
1131    if (T != 0x0)
1132      helper_clear_thumb_bit(S);
1133  }
1134
1135  S = S + A;
1136
1137  // At this moment (after relaxation), if the jump target is arm
1138  // instruction, switch mode is needed, rewrite the instruction to BLX
1139  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
1140  // CPU ARCH TAG, which should be ARMv5 or above)
1141  if (T == 0) {
1142    // cannot rewrite to blx for R_ARM_THM_JUMP24
1143    if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
1144      return Relocator::BadReloc;
1145
1146    // for BLX, select bit 1 from relocation base address to jump target
1147    // address
1148    S = helper_bit_select(S, P, 0x2);
1149    // rewrite instruction to BLX
1150    lower_inst &= ~0x1000U;
1151  }
1152  else {
1153    // otherwise, the instruction should be BL
1154    lower_inst |= 0x1000U;
1155  }
1156
1157  Relocator::DWord X = (S | T) - P;
1158
1159  // FIXME: Check bit size is 24(thumb2) or 22?
1160  if (helper_check_signed_overflow(X, 25)) {
1161    return Relocator::Overflow;
1162  }
1163
1164  upper_inst = helper_thumb32_branch_upper(upper_inst, X);
1165  lower_inst = helper_thumb32_branch_lower(lower_inst, X);
1166
1167  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
1168  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
1169
1170  return Relocator::OK;
1171}
1172
1173// R_ARM_MOVW_ABS_NC: (S + A) | T
1174ARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
1175{
1176  ResolveInfo* rsym = pReloc.symInfo();
1177  Relocator::Address S = pReloc.symValue();
1178  Relocator::DWord T = getThumbBit(pReloc);
1179  Relocator::DWord A =
1180             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1181  if (T != 0x0)
1182    helper_clear_thumb_bit(S);
1183
1184  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1185
1186  // If the flag of target section is not ALLOC, we will not scan this
1187  // relocation but perform static relocation. (e.g., applying .debug section)
1188  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1189    // use plt
1190    if (rsym->reserved() & ARMRelocator::ReservePLT) {
1191      S = helper_get_PLT_address(*rsym, pParent);
1192      T = 0 ; // PLT is not thumb
1193    }
1194  }
1195
1196  // perform static relocation
1197  Relocator::DWord X = (S + A) | T;
1198  pReloc.target() = helper_insert_val_movw_movt_inst(
1199                                         pReloc.target() + pReloc.addend(), X);
1200  return Relocator::OK;
1201}
1202
1203// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
1204ARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
1205{
1206  Relocator::Address S = pReloc.symValue();
1207  Relocator::DWord T = getThumbBit(pReloc);
1208  Relocator::DWord P = pReloc.place();
1209  Relocator::DWord A =
1210             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1211  if (T != 0x0)
1212    helper_clear_thumb_bit(S);
1213  Relocator::DWord X = ((S + A) | T) - P;
1214
1215  if (helper_check_signed_overflow(X, 16)) {
1216    return Relocator::Overflow;
1217  } else {
1218    pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1219    return Relocator::OK;
1220  }
1221}
1222
1223// R_ARM_MOVT_ABS: S + A
1224ARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent)
1225{
1226  ResolveInfo* rsym = pReloc.symInfo();
1227  Relocator::Address S = pReloc.symValue();
1228  Relocator::DWord A =
1229             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1230
1231  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1232
1233  // If the flag of target section is not ALLOC, we will not scan this relocation
1234  // but perform static relocation. (e.g., applying .debug section)
1235  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1236    // use plt
1237    if (rsym->reserved() & ARMRelocator::ReservePLT) {
1238      S = helper_get_PLT_address(*rsym, pParent);
1239    }
1240  }
1241
1242  Relocator::DWord X = S + A;
1243  X >>= 16;
1244  // perform static relocation
1245  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1246  return Relocator::OK;
1247}
1248
1249// R_ARM_MOVT_PREL: S + A - P
1250ARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent)
1251{
1252  Relocator::Address S = pReloc.symValue();
1253  Relocator::DWord P = pReloc.place();
1254  Relocator::DWord A =
1255             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1256  Relocator::DWord X = S + A - P;
1257  X >>= 16;
1258
1259  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1260  return Relocator::OK;
1261}
1262
1263// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
1264ARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
1265{
1266  ResolveInfo* rsym = pReloc.symInfo();
1267  Relocator::Address S = pReloc.symValue();
1268  Relocator::DWord T = getThumbBit(pReloc);
1269  if (T != 0x0)
1270    helper_clear_thumb_bit(S);
1271
1272  // get lower and upper 16 bit instructions from relocation targetData
1273  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1274  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1275  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1276  Relocator::DWord A =
1277                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1278
1279  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1280  // If the flag of target section is not ALLOC, we will not scan this relocation
1281  // but perform static relocation. (e.g., applying .debug section)
1282  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1283    // use plt
1284    if (rsym->reserved() & ARMRelocator::ReservePLT) {
1285      S = helper_get_PLT_address(*rsym, pParent);
1286      T = 0; // PLT is not thumb
1287    }
1288  }
1289  Relocator::DWord X = (S + A) | T;
1290
1291  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1292  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1293  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1294
1295  return Relocator::OK;
1296}
1297
1298// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
1299ARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
1300{
1301  Relocator::Address S = pReloc.symValue();
1302  Relocator::DWord T = getThumbBit(pReloc);
1303  Relocator::DWord P = pReloc.place();
1304  if (T != 0x0)
1305    helper_clear_thumb_bit(S);
1306
1307  // get lower and upper 16 bit instructions from relocation targetData
1308  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1309  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1310  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1311  Relocator::DWord A =
1312                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1313  Relocator::DWord X = ((S + A) | T) - P;
1314
1315  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1316  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1317  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1318
1319  return Relocator::OK;
1320}
1321
1322// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
1323// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
1324ARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent)
1325{
1326  Relocator::Address S = pReloc.symValue();
1327  Relocator::DWord T = getThumbBit(pReloc);
1328  Relocator::DWord P = pReloc.place();
1329  if (T != 0x0)
1330    helper_clear_thumb_bit(S);
1331
1332  // get lower and upper 16 bit instructions from relocation targetData
1333  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1334  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1335  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1336  Relocator::DWord A =
1337                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1338
1339  Relocator::DWord X = ((S + A) | T) - P;
1340
1341  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1342  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1343  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1344
1345  return Relocator::OK;
1346}
1347
1348// R_ARM_THM_MOVT_ABS: S + A
1349ARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent)
1350{
1351  ResolveInfo* rsym = pReloc.symInfo();
1352  Relocator::Address S = pReloc.symValue();
1353
1354  // get lower and upper 16 bit instructions from relocation targetData
1355  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1356  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1357  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1358  Relocator::DWord A =
1359                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1360
1361  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1362  // If the flag of target section is not ALLOC, we will not scan this
1363  // relocation but perform static relocation. (e.g., applying .debug section)
1364  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1365    // use plt
1366    if (rsym->reserved() & ARMRelocator::ReservePLT) {
1367      S = helper_get_PLT_address(*rsym, pParent);
1368    }
1369  }
1370
1371  Relocator::DWord X = S + A;
1372  X >>= 16;
1373
1374  // check 16-bit overflow
1375  if (helper_check_signed_overflow(X, 16))
1376    return Relocator::Overflow;
1377  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1378  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1379  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1380  return Relocator::OK;
1381
1382}
1383
1384// R_ARM_THM_MOVT_PREL: S + A - P
1385// R_ARM_THM_MOVT_BREL: S + A - B(S)
1386ARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent)
1387{
1388  Relocator::Address S = pReloc.symValue();
1389  Relocator::DWord P = pReloc.place();
1390
1391  // get lower and upper 16 bit instructions from relocation targetData
1392  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
1393  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1394  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1395  Relocator::DWord A =
1396                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1397  Relocator::DWord X = S + A - P;
1398  X >>= 16;
1399
1400  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1401  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1402  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1403
1404  return Relocator::OK;
1405}
1406
1407// R_ARM_PREL31: ((S + A) | T) - P
1408ARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent)
1409{
1410  Relocator::DWord target = pReloc.target();
1411  Relocator::DWord T = getThumbBit(pReloc);
1412  Relocator::DWord A = helper_sign_extend(target, 31) + pReloc.addend();
1413  Relocator::DWord P = pReloc.place();
1414  Relocator::Address S = pReloc.symValue();
1415  if (T != 0x0)
1416    helper_clear_thumb_bit(S);
1417
1418  // if symbol has plt
1419  if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
1420    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
1421    T = 0;  // PLT is not thumb.
1422  }
1423
1424  Relocator::DWord X = ((S + A) | T) - P;
1425  pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
1426  if (helper_check_signed_overflow(X, 31))
1427    return Relocator::Overflow;
1428  return Relocator::OK;
1429}
1430
1431// R_ARM_TLS_GD32: GOT(S) + A - P
1432// R_ARM_TLS_IE32: GOT(S) + A - P
1433// R_ARM_TLS_LE32: S + A - tp
1434ARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent)
1435{
1436  return Relocator::Unsupport;
1437}
1438
1439ARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent)
1440{
1441  return Relocator::Unsupport;
1442}
1443