15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ARMRelocationFactory.cpp  ----------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h>
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLDInfo.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/Layout.h>
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFactory.h"
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFunctions.h"
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_ARM_APPLY_RELOC_FUNCS
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaotypedef RelocationFactory::Result (*ApplyFunctionType)(
3067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                               Relocation& pReloc,
3167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                               const MCLDInfo& pLDInfo,
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                               ARMRelocationFactory& pParent);
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
3667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
4467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_ARM_APPLY_RELOC_FUNC_PTRS
4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMRelocationFactory
4967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::ARMRelocationFactory(size_t pNum,
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           ARMGNULDBackend& pParent)
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : RelocationFactory(pNum),
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent) {
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::~ARMRelocationFactory()
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoRelocationFactory::Result
6167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoARMRelocationFactory::applyRelocation(Relocation& pRelocation,
6267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                      const MCLDInfo& pLDInfo)
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (type > 130) { // 131-255 doesn't noted in ARM spec
66affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    fatal(diag::unknown_relocation) << (int)type
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                    << pRelocation.symInfo()->name();
6867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return RelocationFactory::Unknown;
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const
7567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
7667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
7767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// non-member functions
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic RelocationFactory::DWord getThumbBit(const Relocation& pReloc)
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Set thumb bit if
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  RelocationFactory::DWord thumbBit =
86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        ((pReloc.symValue() & 0x1) != 0))?
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        1:0;
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return thumbBit;
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Relocation helper function              //
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Using uint64_t to make sure those complicate operations won't cause
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// undefined behavior.
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pOri_width <= 64);
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t sign_bit = 1 << (pOri_width - 1);
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (pVal ^ sign_bit) - sign_bit;
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Reverse sign bit, then subtract sign bit.
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (pA & ~pMask) | (pB & pMask) ;
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Check if symbol can use relocation R_ARM_RELATIVE
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym,
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                          const MCLDInfo& pLDInfo,
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                          const ARMRelocationFactory& pFactory)
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol is dynamic or undefine or preemptible
124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pSym.isDyn() ||
125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pSym.isUndef() ||
126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pFactory.getTarget().isSymbolPreemptible(pSym,
127affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                               pLDInfo,
128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                               pLDInfo.output()))
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  const MCLDInfo& pLDInfo,
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  ARMRelocationFactory& pParent)
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMGNULDBackend& ld_backend = pParent.getTarget();
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!exist) {
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we first get this GOT entry, we should initialize it.
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) {
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // No corresponding dynamic relocation, initialize to the symbol value.
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      got_entry.setContent(pReloc.symValue());
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else if (rsym->reserved() & ARMGNULDBackend::GOTRel) {
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // Initialize corresponding dynamic relocation.
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Relocation& rel_entry =
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if ( rsym->isLocal() ||
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // Initialize got entry to target symbol address
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        got_entry.setContent(pReloc.symValue());
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setSymInfo(0);
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        // Initialize got entry to 0 for corresponding dynamic relocation.
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        got_entry.setContent(0);
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        rel_entry.setSymInfo(rsym);
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.targetRef().assign(got_entry);
1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::reserve_entry_number_mismatch_got);
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return got_entry;
1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent)
1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getTarget().getGOT().getSection().addr();
1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_GOT(Relocation& pReloc,
1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         const MCLDInfo& pLDInfo,
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         ARMRelocationFactory& pParent)
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent);
1915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
1965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoPLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
1975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  ARMRelocationFactory& pParent)
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMGNULDBackend& ld_backend = pParent.getTarget();
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
2055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!exist) {
2065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we first get this PLT entry, we should initialize it.
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      GOTEntry& gotplt_entry =
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // Initialize corresponding dynamic relocation.
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      Relocation& rel_entry =
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.targetRef().assign(gotplt_entry);
2165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      rel_entry.setSymInfo(rsym);
2175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
219cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::reserve_entry_number_mismatch_plt);
2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return plt_entry;
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent)
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pParent.getTarget().getPLT().getSection().addr();
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Address helper_PLT(Relocation& pReloc,
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         ARMRelocationFactory& pParent)
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Get an relocation entry in .rel.dyn and set its type to pType,
2435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid helper_DynRel(Relocation& pReloc,
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ARMRelocationFactory::Type pType,
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                   ARMRelocationFactory& pParent)
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMGNULDBackend& ld_backend = pParent.getTarget();
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool exist;
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation& rel_entry =
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.setType(pType);
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  rel_entry.targetRef() = pReloc.targetRef();
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pType == llvm::ELF::R_ARM_RELATIVE)
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    rel_entry.setSymInfo(0);
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    rel_entry.setSymInfo(rsym);
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
2665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_extract_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
2675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // imm16: [19-16][11-0]
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            16);
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_insert_val_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                 ARMRelocationFactory::DWord pImm)
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // imm16: [19-16][11-0]
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget &= 0xfff0f000U;
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= pImm & 0x0fffU;
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= (pImm & 0xf000U) << 4;
2815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return pTarget;
2825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
2865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Consider the endianness problem, get the target data value from lower
288affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // and upper 16 bits
289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord val =
290affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
2935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // imm16: [19-16][26][14-12][7-0]
294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return helper_sign_extend((((val >> 4) & 0xf000U) |
295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             ((val >> 15) & 0x0800U) |
296affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             ((val >> 4) & 0x0700U) |
297affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                             (val & 0x00ffU)),
2985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            16);
2995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
3025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
3035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       ARMRelocationFactory::DWord pImm)
3045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord val;
3065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // imm16: [19-16][26][14-12][7-0]
3075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget &= 0xfbf08f00U;
3085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= (pImm & 0xf000U) << 4;
3095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= (pImm & 0x0800U) << 15;
3105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= (pImm & 0x0700U) << 4;
3115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pTarget |= (pImm & 0x00ffU);
312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // Consider the endianness problem, write back data from lower and
314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // upper 16 bits
315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return val;
3185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
3215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_offset(ARMRelocationFactory::DWord pUpper16,
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             ARMRelocationFactory::DWord pLower16)
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord s = (pUpper16 & (1U << 10)) >> 10,  // 26 bit
3255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                              u = pUpper16 & 0x3ffU,              // 25-16
3265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                              l = pLower16 & 0x7ffU,              // 10-0
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             j1 = (pLower16 & (1U << 13)) >> 13,  // 13
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             j2 = (pLower16 & (1U << 11)) >> 11;  // 11
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord i1 = j1 ^ s? 0: 1,
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                              i2 = j2 ^ s? 0: 1;
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // [31-25][24][23][22][21-12][11-1][0]
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //      0   s  i1  i2      u     l  0
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            (u << 12) | (l << 1),
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            25);
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_upper(ARMRelocationFactory::DWord pUpper16,
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            ARMRelocationFactory::DWord pOffset)
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic ARMRelocationFactory::DWord
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_thumb32_branch_lower(ARMRelocationFactory::DWord pLower16,
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                            ARMRelocationFactory::DWord pOffset)
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ((pLower16 & ~0x2fffU) |
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao          ((pOffset >> 1) & 0x7ffU));
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Return true if overflow
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_check_signed_overflow(ARMRelocationFactory::DWord pValue,
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             unsigned bits)
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t signed_val = static_cast<int32_t>(pValue);
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t max = (1 << (bits - 1)) - 1;
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  int32_t min = -(1 << (bits - 1));
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (signed_val > max || signed_val < min) {
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return true;
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  } else {
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
3705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
3755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation //
3765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
3775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_NONE
3795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result none(Relocation& pReloc,
3805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  const MCLDInfo& pLDInfo,
3815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  ARMRelocationFactory& pParent)
3825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
3845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_ABS32: (S + A) | T
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result abs32(Relocation& pReloc,
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
3895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   ARMRelocationFactory& pParent)
3905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
3935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord S = pReloc.symValue();
3955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
396affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
397affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
398affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
399affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
400affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
401affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
402affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
403affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = (S + A) | T;
404affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return ARMRelocationFactory::OK;
405affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
406affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
407affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // A local symbol may need REL Type dynamic relocation
408affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) {
4095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
4105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = (S + A) | T ;
4115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::OK;
4125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
413affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
414affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
415affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
416affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
4175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      S = helper_PLT(pReloc, pParent);
4185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      T = 0 ; // PLT is not thumb
4195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      pReloc.target() = (S + A) | T;
4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we generate a dynamic relocation (except R_ARM_RELATIVE)
4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // for a place, we should not perform static relocation on it
4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // in order to keep the addend store in the place correct.
424affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReserveRel) {
425affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
4275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
4285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        helper_DynRel(pReloc, pReloc.type(), pParent);
4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao        return ARMRelocationFactory::OK;
4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
4325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
4335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
435affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
4365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
4375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (S + A) | T;
4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_REL32: ((S + A) | T) - P
4425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result rel32(Relocation& pReloc,
4435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   const MCLDInfo& pLDInfo,
4445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                   ARMRelocationFactory& pParent)
4455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
4475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
4485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
4495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = ((pReloc.symValue() + A) | T)
4505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      - pReloc.place(pParent.getLayout());
4515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
4525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_BASE_PREL: B(S) + A - P
4555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result base_prel(Relocation& pReloc,
4565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const MCLDInfo& pLDInfo,
4575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       ARMRelocationFactory& pParent)
4585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
4605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
4615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout());
4625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
4635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
4665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result gotoff32(Relocation& pReloc,
4675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
4685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      ARMRelocationFactory& pParent)
4695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
4735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
4745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = ((S + A) | T) - GOT_ORG;
4765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
4775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
4805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result got_brel(Relocation& pReloc,
4815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
4825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      ARMRelocationFactory& pParent)
4835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
484affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(pReloc.symInfo()->reserved() &
485affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
4865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::BadReloc;
4875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
4885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
4895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
4905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
4915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
4925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
4935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
4945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_PREL: GOT(S) + A - P
4975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result got_prel(Relocation& pReloc,
4985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
4995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      ARMRelocationFactory& pParent)
5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
501affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(pReloc.symInfo()->reserved() &
502affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
5035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::BadReloc;
5045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
5085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
5095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - P;
5105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
5115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PLT32: ((S + A) | T) - P
5145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_JUMP24: ((S + A) | T) - P
5155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_CALL: ((S + A) | T) - P
5165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result call(Relocation& pReloc,
5175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  const MCLDInfo& pLDInfo,
5185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  ARMRelocationFactory& pParent)
5195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
520affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // TODO: Some issue have not been considered:
521affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // 1. Add stub when switching mode or jump target too far
522affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // 2. We assume the blx is available
5235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If target is undefined weak symbol, we only need to jump to the
525affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // next instruction unless it has PLT entry. Rewrite instruction
526affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // to NOP.
527affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->isWeak() &&
528affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pReloc.symInfo()->isUndef() &&
529affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      !pReloc.symInfo()->isDyn() &&
5305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
5315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // change target to NOP : mov r0, r0
5325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
5335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::OK;
5345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
536affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::Address S; // S depends on PLT exists or not.
5375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord   T = getThumbBit(pReloc);
5385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord   A =
5395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
5405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    + pReloc.addend();
5415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
5425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  S = pReloc.symValue();
544affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
5455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    S = helper_PLT(pReloc, pParent);
5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
549affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the jump target is thumb instruction, switch mode is needed, rewrite
550affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // the instruction to BLX
551affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (T != 0) {
552affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // cannot rewrite R_ARM_JUMP24 instruction to blx
553affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&&
554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      "Invalid instruction to rewrite to blx for switching mode.");
555affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = (pReloc.target() & 0xffffff) |
556affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                      0xfa000000 |
557affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                      (((S + A - P) & 2) << 23);
5585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
559affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
560affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
56267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (helper_check_signed_overflow(X, 26))
56367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return ARMRelocationFactory::Overflow;
5645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //                    Make sure the Imm is 0.          Result Mask.
5655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_CALL: ((S + A) | T) - P
570affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_JUMP24: (((S + A) | T) - P)
5715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_call(Relocation& pReloc,
5725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
5735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      ARMRelocationFactory& pParent)
5745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If target is undefined weak symbol, we only need to jump to the
576affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // next instruction unless it has PLT entry. Rewrite instruction
577affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // to NOP.
578affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->isWeak() &&
579affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pReloc.symInfo()->isUndef() &&
580affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      !pReloc.symInfo()->isDyn() &&
5815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = (0xe000U << 16) | 0xbf00U;
5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::OK;
5845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
586affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // get lower and upper 16 bit instructions from relocation targetData
587affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
588affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
5895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
5915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
5925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                               lower16);
5935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
5945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S;
5955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol has plt
597affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
5985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    S = helper_PLT(pReloc, pParent);
5995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
6005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
601affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
602affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    S = pReloc.symValue();
603affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
6045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
605affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  S = S + A;
6065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
607affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
608affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // CPU ARCH TAG, which should be ARMv5 or above)
609affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
610affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the jump target is not thumb, switch mode is needed, rewrite
611affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // instruction to BLX
612affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (T == 0) {
613affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for BLX, select bit 1 from relocation base address to jump target
614affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // address
615affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    S = helper_bit_select(S, P, 0x2);
616affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // rewrite instruction to BLX
617affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    lower16 &= ~0x1000U;
618affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
619affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
620affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // otherwise, the instruction should be BL
621affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    lower16 |= 0x1000U;
622affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
623affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
624affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord X = (S | T) - P;
625affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
626affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // TODO: check if we need stub when building non-shared object,
627affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // overflow or switch-mode.
6285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: Check bit size is 24(thumb2) or 22?
630affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (helper_check_signed_overflow(X, 25)) {
6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::Overflow;
6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  upper16 = helper_thumb32_branch_upper(upper16, X);
6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  lower16 = helper_thumb32_branch_lower(lower16, X);
6365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
637affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16;
638affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16;
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
640affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ARMRelocationFactory::OK;
6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_ABS_NC: (S + A) | T
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc,
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         const MCLDInfo& pLDInfo,
6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                         ARMRelocationFactory& pParent)
6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
6545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
655affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
65667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                                 *(pReloc.targetRef().frag()));
657affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
65867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  // If the flag of target section is not ALLOC, we will not scan this
65967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  // relocation but perform static relocation. (e.g., applying .debug section)
660affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
661affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
662affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
663affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      S = helper_PLT(pReloc, pParent);
664affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      T = 0 ; // PLT is not thumb
665affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
6665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
667affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
66967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  X = (S + A) | T;
67067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(
67167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                         pReloc.target() + pReloc.addend(), X);
67267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ARMRelocationFactory::OK;
6735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
6765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc,
6775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                          const MCLDInfo& pLDInfo,
6785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                          ARMRelocationFactory& pParent)
6795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
6815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
6835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
6845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
6855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
6865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = ((S + A) | T) - P;
6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_check_signed_overflow(X, 16)) {
6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::Overflow;
6915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  } else {
6925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
6935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::OK;
6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_ABS: S + A
6985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movt_abs(Relocation& pReloc,
6995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      const MCLDInfo& pLDInfo,
7005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                      ARMRelocationFactory& pParent)
7015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
7035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
7045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
7055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
7065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
7075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
708affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
709affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
710affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
711affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
712affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
713affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
714affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
715affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
716affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      S = helper_PLT(pReloc, pParent);
717affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
7185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
7195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = S + A;
7215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
7225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
7235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
7245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
7255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_PREL: S + A - P
7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result movt_prel(Relocation& pReloc,
7295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const MCLDInfo& pLDInfo,
7305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       ARMRelocationFactory& pParent)
7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
7335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
7345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
7355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
7375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = S + A - P;
7395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
7405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
7425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
7435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
7465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc,
7475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                             const MCLDInfo& pLDInfo,
7485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                             ARMRelocationFactory& pParent)
7495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
7515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
7525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
7535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
7545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
7555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
7565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
757affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
758affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
759affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
760affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
761affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
762affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
763affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
764affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
765affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      S = helper_PLT(pReloc, pParent);
766affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      T = 0; // PLT is not thumb
767affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
7685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
7695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = (S + A) | T;
770affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
771affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                           X);
772affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ARMRelocationFactory::OK;
7735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
7765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc,
7775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                              const MCLDInfo& pLDInfo,
7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                              ARMRelocationFactory& pParent)
7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
7815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
7835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
7845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
7865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = ((S + A) | T) - P;
7885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // check 16-bit overflow
790affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
791affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                           X);
792affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ARMRelocationFactory::OK;
793affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
794affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
795affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
796affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
797affc150dc44fab1911775a49636d0ce85333b634Zonr ChangARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc,
798affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                              const MCLDInfo& pLDInfo,
799affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                              ARMRelocationFactory& pParent)
800affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
801affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::Address S = pReloc.symValue();
802affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
803affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
804affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord A =
805affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
806affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ARMRelocationFactory::DWord X;
807affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
808affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  X = ((S + A) | T) - P;
809affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
810affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // check 16-bit overflow
811affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
812affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                           X);
813affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ARMRelocationFactory::OK;
8145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_ABS: S + A
8175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc,
8185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                          const MCLDInfo& pLDInfo,
8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                          ARMRelocationFactory& pParent)
8205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
8225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
8235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
8245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
8255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
8265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
827affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
828affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                                  *(pReloc.targetRef().frag()));
829affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  assert(NULL != target_sect);
830affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
831affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
832affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
833affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
834affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
835affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      S = helper_PLT(pReloc, pParent);
836affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
838affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
8395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = S + A;
8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // check 16-bit overflow
8435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_check_signed_overflow(X, 16)) {
8445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::Overflow;
8455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  } else {
8465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
8475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                             X);
8485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::OK;
8495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_PREL: S + A - P
853affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVT_BREL: S + A - B(S)
8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
8555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           const MCLDInfo& pLDInfo,
8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                           ARMRelocationFactory& pParent)
8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S = pReloc.symValue();
8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A =
8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
8625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X;
8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X = S + A - P;
8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
866affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
8675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                                             X);
868affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return ARMRelocationFactory::OK;
8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PREL31: (S + A) | T
8725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result prel31(Relocation& pReloc,
8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    const MCLDInfo& pLDInfo,
8745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                    ARMRelocationFactory& pParent)
8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord target = pReloc.target();
8775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) +
8795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                  pReloc.addend();
8805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::Address S;
8815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  S = pReloc.symValue();
8835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol has plt
884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if ( pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
8855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    S = helper_PLT(pReloc, pParent);
8865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
8875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMRelocationFactory::DWord X = (S + A) | T ;
8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
891affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (helper_check_signed_overflow(X, 31))
8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return ARMRelocationFactory::Overflow;
8935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::OK;
8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_GD32: GOT(S) + A - P
8975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_IE32: GOT(S) + A - P
8985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_LE32: S + A - tp
8995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result tls(Relocation& pReloc,
9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                 const MCLDInfo& pLDInfo,
9015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                 ARMRelocationFactory& pParent)
9025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
9035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::Unsupport;
9045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMRelocationFactory::Result unsupport(Relocation& pReloc,
9075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       const MCLDInfo& pLDInfo,
9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                                       ARMRelocationFactory& pParent)
9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
9105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return ARMRelocationFactory::Unsupport;
9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
912