1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- ARMRelocator.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
10f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h>
11f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h>
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h>
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
17f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LD/LDSymbol.h>
1887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/ELFFileFormat.h>
19f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Object/ObjectBuilder.h>
20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "ARMRelocator.h"
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMRelocationFunctions.h"
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//=========================================//
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Relocation helper function              //
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//=========================================//
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic Relocator::DWord getThumbBit(const Relocation& pReloc)
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Set thumb bit if
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocator::DWord thumbBit =
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
3587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ((pReloc.symValue() & 0x1) != 0))?
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        1:0;
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return thumbBit;
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Using uint64_t to make sure those complicate operations won't cause
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// undefined behavior.
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(pOri_width <= 64);
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pOri_width == 64)
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return pVal;
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width);
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pVal &= mask;
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Reverse sign bit, then subtract sign bit.
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t sign_bit = 1 << (pOri_width - 1);
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (pVal ^ sign_bit) - sign_bit;
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesuint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (pA & ~pMask) | (pB & pMask) ;
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Check if symbol can use relocation R_ARM_RELATIVE
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic bool
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym,
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                          const ARMRelocator& pFactory)
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if symbol is dynamic or undefine or preemptible
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym.isDyn() ||
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pSym.isUndef() ||
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Strip LSB (THUMB bit) if "S" is a THUMB target.
76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic inline void helper_clear_thumb_bit(Relocator::DWord& pValue)
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue &= (~0x1);
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_get_GOT_address(ResolveInfo& pSym,
83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                          ARMRelocator& pParent)
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(pSym);
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != got_entry);
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
9187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMGOTEntry& helper_GOT_init(Relocation& pReloc,
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             bool pHasRel,
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             ARMRelocator& pParent)
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGNULDBackend& ld_backend = pParent.getTarget();
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* got_entry = ld_backend.getGOT().createGOT();
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If we first get this GOT entry, we should initialize it.
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!pHasRel) {
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(ARMRelocator::SymVal);
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Initialize corresponding dynamic relocation.
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Relocation& rel_entry = *ld_backend.getRelDyn().create();
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (rsym->isLocal() || helper_use_relative_reloc(*rsym, pParent)) {
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Initialize got entry to target symbol address
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(ARMRelocator::SymVal);
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rel_entry.setSymInfo(NULL);
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else {
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Initialize got entry to 0 for corresponding dynamic relocation.
11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0);
11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rel_entry.setSymInfo(rsym);
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.targetRef().assign(*got_entry);
12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
12487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_GOT_ORG(ARMRelocator& pParent)
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOT().addr();
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Address helper_get_PLT_address(ResolveInfo& pSym,
135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                          ARMRelocator& pParent)
13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
13787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
13887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != plt_entry);
13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
14087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
14187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
14387f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT1& helper_PLT_init(Relocation& pReloc, ARMRelocator& pParent)
14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
14687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
14787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGNULDBackend& ld_backend = pParent.getTarget();
14887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
14987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize the plt and the corresponding gotplt and dyn relocation
15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMPLT1* plt_entry = ld_backend.getPLT().create();
15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
15387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "PLT entry not exist, but DynRel entry exist!");
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* gotplt_entry = ld_backend.getGOT().createGOTPLT();
15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
15887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelPLT().create();
16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef().assign(*gotplt_entry);
16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setSymInfo(rsym);
16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *plt_entry;
16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Get an relocation entry in .rel.dyn and set its type to pType,
16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// pReloc->symInfo()
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic
17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid helper_DynRel_init(Relocation& pReloc,
172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                        Relocator::Type pType,
17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                        ARMRelocator& pParent)
17487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
17587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
17787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGNULDBackend& ld_backend = pParent.getTarget();
17887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
17987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().create();
18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(pType);
18187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef() = pReloc.targetRef();
18287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
18387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pType == llvm::ELF::R_ARM_RELATIVE)
18487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(NULL);
18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(rsym);
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
18887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_extract_movw_movt_addend(Relocator::DWord pTarget)
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // imm16: [19-16][11-0]
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                            16);
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_insert_val_movw_movt_inst(Relocator::DWord pTarget,
199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                 Relocator::DWord pImm)
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // imm16: [19-16][11-0]
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pTarget &= 0xfff0f000U;
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pTarget |= pImm & 0x0fffU;
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pTarget |= (pImm & 0xf000U) << 4;
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pTarget;
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_extract_thumb_movw_movt_addend(Relocator::DWord pValue)
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // imm16: [19-16][26][14-12][7-0]
21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return helper_sign_extend((((pValue >> 4) & 0xf000U) |
21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             ((pValue >> 15) & 0x0800U) |
21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             ((pValue >> 4) & 0x0700U) |
21587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             (pValue& 0x00ffU)),
21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                            16);
21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_insert_val_thumb_movw_movt_inst(Relocator::DWord pValue,
221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       Relocator::DWord pImm)
22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // imm16: [19-16][26][14-12][7-0]
22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue &= 0xfbf08f00U;
22587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue |= (pImm & 0xf000U) << 4;
22687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue |= (pImm & 0x0800U) << 15;
22787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue |= (pImm & 0x0700U) << 4;
22887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pValue |= (pImm & 0x00ffU);
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pValue;
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_offset(Relocator::DWord pUpper16,
234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                             Relocator::DWord pLower16)
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord s = (pUpper16 & (1U << 10)) >> 10,        // 26 bit
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           u  = pUpper16 & 0x3ffU,              // 25-16
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           l  = pLower16 & 0x7ffU,              // 10-0
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           j1 = (pLower16 & (1U << 13)) >> 13,  // 13
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           j2 = (pLower16 & (1U << 11)) >> 11;  // 11
241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord i1 = j1 ^ s? 0: 1,
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                              i2 = j2 ^ s? 0: 1;
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // [31-25][24][23][22][21-12][11-1][0]
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //      0   s  i1  i2      u     l  0
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                            (u << 12) | (l << 1),
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                            25);
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
251551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_upper(Relocator::DWord pUpper16,
253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                            Relocator::DWord pOffset)
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_branch_lower(Relocator::DWord pLower16,
261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                            Relocator::DWord pOffset)
26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
26487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ((pLower16 & ~0x2fffU) |
26587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          ((pOffset >> 1) & 0x7ffU));
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_offset(Relocator::DWord pUpper16,
272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                  Relocator::DWord pLower16)
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t s = (pUpper16 & 0x0400U) >> 10;
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t j1 = (pLower16 & 0x2000U) >> 13;
27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t j2 = (pLower16 & 0x0800U) >> 11;
27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t lower = (pLower16 & 0x07ffU);
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (pUpper16 & 0x003fU);
27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return helper_sign_extend((upper << 12) | (lower << 1), 21);
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
28187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_upper(Relocator::DWord pUpper16,
284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                 Relocator::DWord pOffset)
28587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (pUpper16 & 0xfbc0U) | (sign << 10) | ((pOffset & 0x0003f000U) >> 12);
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::DWord
291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_thumb32_cond_branch_lower(Relocator::DWord pLower16,
292551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                 Relocator::DWord pOffset)
29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t j2 = (pOffset & 0x00080000U) >> 19;
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t j1 = (pOffset & 0x00040000U) >> 18;
29687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t lo = (pOffset & 0x00000ffeU) >> 1;
29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return (pLower16 & 0xd000U) | (j1 << 13) | (j2 << 11) | lo;
29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
29987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Return true if overflow
30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic bool
302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hineshelper_check_signed_overflow(Relocator::DWord pValue,
30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             unsigned bits)
30487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t signed_val = static_cast<int32_t>(pValue);
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t max = (1 << (bits - 1)) - 1;
30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t min = -(1 << (bits - 1));
30887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (signed_val > max || signed_val < min) {
30987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
31587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
31667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
31767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
31867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
3195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoDECL_ARM_APPLY_RELOC_FUNCS
3205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
32167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
322d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaotypedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
323d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                               ARMRelocator& pParent);
32467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
32567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
32667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostruct ApplyFunctionTriple
32767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
32867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  ApplyFunctionType func;
32967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
33067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
33167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
33267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
33367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
33467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaostatic const ApplyFunctionTriple ApplyFunctions[] = {
33567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  DECL_ARM_APPLY_RELOC_FUNC_PTRS
33667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
33767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
339d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// ARMRelocator
34067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::ARMRelocator(ARMGNULDBackend& pParent,
342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           const LinkerConfig& pConfig)
343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : Relocator(pConfig),
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_Target(pParent) {
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
347d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::~ARMRelocator()
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::applyRelocation(Relocation& pRelocation)
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (type > 130) { // 131-255 doesn't noted in ARM spec
356d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return Relocator::Unknown;
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
35922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return ApplyFunctions[type].func(pRelocation, *this);
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
362d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoconst char* ARMRelocator::getName(Relocator::Type pType) const
36367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
36467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  return ApplyFunctions[pType].name;
36567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size ARMRelocator::getSize(Relocation::Type pType) const
3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return 32;
3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::addCopyReloc(ResolveInfo& pSym)
373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
37487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *getTarget().getRelDyn().create();
375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setType(llvm::ELF::R_ARM_COPY);
376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setSymInfo(&pSym);
379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolForCopyReloc
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy.
385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// This is executed at scan relocation stage.
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol&
387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                       const ResolveInfo& pSym)
389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS LDSection
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSection* bss_sect_hdr = NULL;
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ELFFileFormat* file_format = getTarget().getOutputFormat();
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getBSS();
397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS SectionData
399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SectionData* bss_data = NULL;
400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (bss_sect_hdr->hasSectionData())
401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_data = bss_sect_hdr->getSectionData();
402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Determine the alignment by the symbol value
406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: here we use the largest alignment
407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // allocate space in BSS for the copy symbol
410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag,
412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                *bss_data,
413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                addralign);
414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // change symbol binding to Global if it's a weak symbol
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (binding == ResolveInfo::Weak)
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    binding = ResolveInfo::Global;
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Define the copy symbol in the bss section and resolve it
422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      pSym.name(),
424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      (ResolveInfo::Type)pSym.type(),
425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      ResolveInfo::Define,
426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      binding,
427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      pSym.size(),  // size
428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      0x0,          // value
429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      FragmentRef::Create(*frag, 0x0),
430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      (ResolveInfo::Visibility)pSym.other());
431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *cpy_sym;
433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// checkValidReloc - When we attempt to generate a dynamic relocation for
436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// ouput file, check if the relocation is supported by dynamic linker.
437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::checkValidReloc(Relocation& pReloc) const
438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // If not PIC object, no relocation type is invalid
440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!config().isCodeIndep())
441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()) {
444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_RELATIVE:
445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_COPY:
446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GLOB_DAT:
447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_JUMP_SLOT:
448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32:
449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32_NOI:
450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_PC24:
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TLS_DTPMOD32:
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TLS_DTPOFF32:
453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TLS_TPOFF32:
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      error(diag::non_pic_relocation) << (int)pReloc.type()
458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      << pReloc.symInfo()->name();
459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
463a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hinesbool ARMRelocator::mayHaveFunctionPointerAccess(const Relocation& pReloc) const
464a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines{
465a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  switch (pReloc.type()) {
466a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_PC24:
467a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_CALL:
468a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_PLT32:
469a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_CALL:
470a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_JUMP24:
471a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP24:
472a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_SBREL31:
473a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_PREL31:
474a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP19:
475a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP6:
476a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP11:
477a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP8: {
478a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines      return false;
479a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    }
480a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    default: {
481a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines      return true;
482a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    }
483a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  }
484a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines}
485a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines
486f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid
487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection)
488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()){
493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Set R_ARM_TARGET1 to R_ARM_ABS32
495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Ref: GNU gold 1.11 arm.cc, line 9892
496f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // or --target1-rel
498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TARGET1:
499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       pReloc.setType(llvm::ELF::R_ARM_ABS32);
500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32:
501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32_NOI: {
502f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If buiding PIC object (shared library or PIC executable),
503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve an entry in .rel.dyn
505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set Rel bit
508f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
511f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS16:
515f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS12:
516f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_ABS5:
517f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS8:
518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_BASE_ABS:
519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVW_ABS_NC:
520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVT_ABS:
521f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVT_ABS: {
523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // PIC code should not contain these kinds of relocation
524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        error(diag::non_pic_relocation) << (int)pReloc.type()
526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                        << pReloc.symInfo()->name();
527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
529f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
530f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOTOFF32:
531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOTOFF12: {
532f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Ref: GNU gold 1.11 arm.cc, line 9892
538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // FIXME: R_ARM_TARGET2 should be set by option --target2
539f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TARGET2:
540f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
541f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOT_BREL:
542f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOT_PREL: {
543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A GOT entry is needed for these relocation type.
544f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
54787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
548f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If building PIC object, a dynamic relocation with
549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // type RELATIVE is needed to relocate this GOT entry.
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (config().isCodeIndep())
55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         helper_GOT_init(pReloc, true, *this);
55287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         helper_GOT_init(pReloc, false, *this);
554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
556f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_BASE_PREL: {
560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: Currently we only support R_ARM_BASE_PREL against
561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // symbol _GLOBAL_OFFSET_TABLE_
562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym != getTarget().getGOTSymbol()->resolveInfo())
563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
564f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     << "mclinker@googlegroups.com";
565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_COPY:
568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GLOB_DAT:
569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_JUMP_SLOT:
570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_RELATIVE: {
571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // These are relocation type for dynamic linker, shold not
572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // appear in object file.
573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::dynamic_relocation) << (int)pReloc.type();
574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default: {
577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::scanGlobalReloc(Relocation& pReloc,
583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   IRBuilder& pBuilder,
584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                   const LDSection& pSection)
585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()) {
590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Set R_ARM_TARGET1 to R_ARM_ABS32
592f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Ref: GNU gold 1.11 arm.cc, line 9892
593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // or --target1-rel
595f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TARGET1:
596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pReloc.setType(llvm::ELF::R_ARM_ABS32);
597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32:
598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS16:
599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS12:
600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_ABS5:
601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS8:
602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_BASE_ABS:
603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVW_ABS_NC:
604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVT_ABS:
605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVT_ABS:
607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ABS32_NOI: {
608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation entry
610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // in .got and .rel.plt.
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_PLT_init(pReloc, *this);
617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
62287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (getTarget().symbolNeedsDynRel(*rsym,
62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       (rsym->reserved() & ReservePLT), true)) {
624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
627f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        else {
629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          checkValidReloc(pReloc);
630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set Rel bit
63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (helper_use_relative_reloc(*rsym, *this))
63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          else
63487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(pReloc, pReloc.type(), *this);
635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
637f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
638f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
640f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOTOFF32:
643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOTOFF12: {
644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
645f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
646f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
647f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
648f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_BASE_PREL:
649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
650f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVW_BREL:
651f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVT_BREL:
652f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: Currently we only support these relocations against
653f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // symbol _GLOBAL_OFFSET_TABLE_
654f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym != getTarget().getGOTSymbol()->resolveInfo()) {
655f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
656f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     << "mclinker@googlegroups.com";
657f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_REL32:
659f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_PC_G0:
660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_SBREL32:
661f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_PC8:
662f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVW_PREL_NC:
663f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVT_PREL:
664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
665f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_MOVT_PREL:
666f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
667f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_PC12:
668f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_REL32_NOI:
669f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_PC_G0_NC:
670f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_PC_G0:
671f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_PC_G1_NC:
672f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_PC_G1:
673f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_PC_G2:
674f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_PC_G1:
675f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_PC_G2:
676f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_PC_G0:
677f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_PC_G1:
678f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_PC_G2:
679f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_PC_G0:
680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_PC_G1:
681f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_PC_G2:
682f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_SB_G0_NC:
683f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_SB_G0:
684f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_SB_G1_NC:
685f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_SB_G1:
686f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_ALU_SB_G2:
687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_SB_G0:
688f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_SB_G1:
689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDR_SB_G2:
690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_SB_G0:
691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_SB_G1:
692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDRS_SB_G2:
693f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_SB_G0:
694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_SB_G1:
695f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_LDC_SB_G2:
696f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVW_BREL_NC:
697f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVT_BREL:
698f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_MOVW_BREL: {
699f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Relative addressing relocation, may needs dynamic relocation
70087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                                       false)) {
702f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
703f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
704f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        else {
708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          checkValidReloc(pReloc);
709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set Rel bit
71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          //helper_DynRel_init(pReloc, pReloc.type(), *this);
711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
713f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
714f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
715f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
716f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
717f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
718f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_PC24:
719f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_CALL:
720f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_PLT32:
721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_CALL:
722f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_JUMP24:
723f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP24:
724f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_SBREL31:
725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_PREL31:
726f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP19:
727f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP6:
728f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP11:
729f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_THM_JUMP8: {
730f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // These are branch relocation (except PREL31)
731f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A PLT entry is needed when building shared library
732f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
733f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create plt for this symbol
734f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & ReservePLT)
735f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
736f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
737f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
738f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
739f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
740f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
741f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if symbol is defined in the ouput file and it's not
742f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // preemptible, no need plt
743f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
744f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          !getTarget().isSymbolPreemptible(*rsym)) {
745f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
746f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
747f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
748f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs PLT entry, we need to reserve a PLT entry
749f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and the corresponding GOT and dynamic relocation entry
75087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // in .got and .rel.plt.
75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_PLT_init(pReloc, *this);
752f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set PLT bit
753f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
754f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
755f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
756f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
757f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
758f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Ref: GNU gold 1.11 arm.cc, line 9892
759f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // FIXME: R_ARM_TARGET2 should be set by option --target2
760f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_TARGET2:
761f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
762f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOT_BREL:
763f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOT_ABS:
764f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GOT_PREL: {
765f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
766f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
768f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
769f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol cannot be fully resolved at link time, then we need a
770f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (!getTarget().symbolFinalValueIsKnown(*rsym))
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, true, *this);
77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, false, *this);
775f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
776f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
777f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
778f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
779f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
780f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_COPY:
781f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_GLOB_DAT:
782f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_JUMP_SLOT:
783f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_ARM_RELATIVE: {
784f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // These are relocation type for dynamic linker, shold not
785f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // appear in object file.
786f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::dynamic_relocation) << (int)pReloc.type();
787f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
788f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
789f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default: {
790f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
791f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
792f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
793f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
794f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
795f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid ARMRelocator::scanRelocation(Relocation& pReloc,
796f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  IRBuilder& pBuilder,
797f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  Module& pModule,
79887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                  LDSection& pSection,
79987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                  Input& pInput)
800f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
801f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
802f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
803f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != rsym &&
804f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
805f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
806f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pSection.getLink());
807f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
808f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
809f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
810f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
811f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // entries should be created.
812f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: Below judgements concern nothing about TLS related relocation
813f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
814f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym is local
815f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isLocal())
816f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanLocalReloc(pReloc, pSection);
817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym is external
819f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanGlobalReloc(pReloc, pBuilder, pSection);
821f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
822f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // check if we shoule issue undefined reference for the relocation target
823f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol
824f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    issueUndefRef(pReloc, pSection, pInput);
8265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
8295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation //
8305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
8315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_NONE
833d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent)
8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
835551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_ABS32: (S + A) | T
839d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent)
8405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
842551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
843551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
844551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord S = pReloc.symValue();
845f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
846f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
8475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
848affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
849affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC &
85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.targetRef().frag()->getParent()->getSection().flag())) {
852affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = (S + A) | T;
853551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
854affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
855affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
856affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
857affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
858f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & ARMRelocator::ReservePLT) {
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      T = 0 ; // PLT is not thumb
8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
8625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // If we generate a dynamic relocation (except R_ARM_RELATIVE)
8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // for a place, we should not perform static relocation on it
8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // in order to keep the addend store in the place correct.
86587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((rsym->reserved() & ARMRelocator::ReserveRel) &&
86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (!helper_use_relative_reloc(*rsym, pParent)))
867551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::OK;
8685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
8715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (S + A) | T;
872551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_REL32: ((S + A) | T) - P
876d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent)
8775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
879551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
880551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   T = getThumbBit(pReloc);
881551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.target() + pReloc.addend();
88222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // An external symbol may need PLT (this reloc is from a stub/veneer)
88422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!pReloc.symInfo()->isLocal()) {
885f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
88722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      T = 0;  // PLT is not thumb.
88822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
88922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
89022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (T != 0x0)
89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    helper_clear_thumb_bit(S);
89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation
89522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = ((S + A) | T) - pReloc.place();
89622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
897551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_BASE_PREL: B(S) + A - P
901d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent)
9025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
9035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
904551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
90522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = pReloc.symValue() + A - pReloc.place();
906551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
910d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent)
9115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
912551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
914551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
915551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
916f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
917f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
9185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = ((S + A) | T) - GOT_ORG;
920551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
924d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent)
9255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT))
927551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
929551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
930551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.target() + pReloc.addend();
931551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
9325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
93487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // setup got entry value if needed
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(pReloc.symValue());
939551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_GOT_PREL: GOT(S) + A - P
943d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent)
9445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT)) {
946551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
9475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
948551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
949551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A     = pReloc.target() + pReloc.addend();
950551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P     = pReloc.place();
95122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
9535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - P;
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // setup got entry value if needed
95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(pReloc.symValue());
959551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
962a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines// R_ARM_THM_JUMP8: S + A - P
963a790f0a8f3175183bea088389b3e4ae41813e192Stephen HinesARMRelocator::Result thm_jump8(Relocation& pReloc, ARMRelocator& pParent)
964a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines{
965a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  Relocator::DWord P = pReloc.place();
966a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x00ff) << 1, 8) +
967a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines                       pReloc.addend();
968a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  // S depends on PLT exists or not
969a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  Relocator::Address S = pReloc.symValue();
970a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
971a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
972a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines
973a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  Relocator::DWord X = S + A - P;
974a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  if (helper_check_signed_overflow(X, 9))
975a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines    return Relocator::Overflow;
976a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  //                    Make sure the Imm is 0.          Result Mask.
977a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  pReloc.target() = (pReloc.target() & 0xFFFFFF00u) | ((X & 0x01FEu) >> 1);
978a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  return Relocator::OK;
979a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines}
980a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines
981f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_THM_JUMP11: S + A - P
982f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesARMRelocator::Result thm_jump11(Relocation& pReloc, ARMRelocator& pParent)
983f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
984551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
985551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = helper_sign_extend((pReloc.target() & 0x07ff) << 1, 11) +
986f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                       pReloc.addend();
987f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // S depends on PLT exists or not
988551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
989f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
99087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
991f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
992551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
993a790f0a8f3175183bea088389b3e4ae41813e192Stephen Hines  if (helper_check_signed_overflow(X, 12))
994551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
995f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //                    Make sure the Imm is 0.          Result Mask.
996f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.target() = (pReloc.target() & 0xFFFFF800u) | ((X & 0x0FFEu) >> 1);
997551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
998f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
999f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
100087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_ARM_THM_JUMP19: ((S + A) | T) - P
100187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMRelocator::Result thm_jump19(Relocation& pReloc, ARMRelocator& pParent)
100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines{
100387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // get lower and upper 16 bit instructions from relocation targetData
100487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
100587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
100687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1007551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1008551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = helper_thumb32_cond_branch_offset(upper_inst,
100987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                                    lower_inst);
1010551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
1011551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S;
101287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if symbol has plt
101387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
101487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
101587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    T = 0;  // PLT is not thumb.
101687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
101787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
101887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = pReloc.symValue();
101987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (T != 0x0)
102087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_clear_thumb_bit(S);
102187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
102287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
102387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0x0 == T) {
102487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // FIXME: conditional branch to PLT in THUMB-2 not supported yet
102587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    error(diag::unsupport_cond_branch_reloc) << (int)pReloc.type();
1026551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
102787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
102887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1029551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
103087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (helper_check_signed_overflow(X, 21))
1031551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
103287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  upper_inst = helper_thumb32_cond_branch_upper(upper_inst, X);
103487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  lower_inst = helper_thumb32_cond_branch_lower(lower_inst, X);
103587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
103687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
103787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
103887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1039551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
104087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
104187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1042f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_PC24: ((S + A) | T) - P
10435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_PLT32: ((S + A) | T) - P
10445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_JUMP24: ((S + A) | T) - P
10455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_CALL: ((S + A) | T) - P
1046d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent)
10475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If target is undefined weak symbol, we only need to jump to the
1049affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // next instruction unless it has PLT entry. Rewrite instruction
1050affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // to NOP.
1051affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->isWeak() &&
1052affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pReloc.symInfo()->isUndef() &&
1053affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      !pReloc.symInfo()->isDyn() &&
1054f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
10555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // change target to NOP : mov r0, r0
10565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
1057551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
10585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
10595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1060551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   T = getThumbBit(pReloc);
1061551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A =
1062f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26) +
1063f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pReloc.addend();
1064551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
1065551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1066f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1067f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
10685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1069f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // S depends on PLT exists or not
1070f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
107187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
10725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
10735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
10745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
107522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // At this moment (after relaxation), if the jump target is thumb instruction,
107622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // switch mode is needed, rewrite the instruction to BLX
107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // CPU ARCH TAG, which should be ARMv5 or above)
1079affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (T != 0) {
108022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // cannot rewrite to blx for R_ARM_JUMP24
108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
1082551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::BadReloc;
1083f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (pReloc.type() == llvm::ELF::R_ARM_PC24)
1084551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::BadReloc;
108522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1086affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = (pReloc.target() & 0xffffff) |
1087affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                      0xfa000000 |
1088affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                      (((S + A - P) & 2) << 23);
10895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1090affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1091551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
10925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
109367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (helper_check_signed_overflow(X, 26))
1094551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
10955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  //                    Make sure the Imm is 0.          Result Mask.
10965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
1097551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
10985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
10995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_CALL: ((S + A) | T) - P
1101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_ARM_THM_JUMP24: ((S + A) | T) - P
1102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent)
11035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
11045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // If target is undefined weak symbol, we only need to jump to the
1105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // next instruction unless it has PLT entry. Rewrite instruction
1106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // to NOP.
1107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pReloc.symInfo()->isWeak() &&
1108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      pReloc.symInfo()->isUndef() &&
1109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      !pReloc.symInfo()->isDyn() &&
1110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      !(pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)) {
11115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = (0xe000U << 16) | 0xbf00U;
1112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
11135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
11145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // get lower and upper 16 bit instructions from relocation targetData
111622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
111722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
11185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = helper_thumb32_branch_offset(upper_inst, lower_inst);
1121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
1122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S;
11235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol has plt
1125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
112687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
11275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
11285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
1130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    S = pReloc.symValue();
1131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (T != 0x0)
1132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      helper_clear_thumb_bit(S);
1133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
11345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  S = S + A;
11365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
113722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // At this moment (after relaxation), if the jump target is arm
113822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // instruction, switch mode is needed, rewrite the instruction to BLX
1139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
1140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // CPU ARCH TAG, which should be ARMv5 or above)
1141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (T == 0) {
114222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // cannot rewrite to blx for R_ARM_THM_JUMP24
114322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
1144551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::BadReloc;
114522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for BLX, select bit 1 from relocation base address to jump target
1147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // address
1148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    S = helper_bit_select(S, P, 0x2);
1149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // rewrite instruction to BLX
115022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    lower_inst &= ~0x1000U;
1151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
1152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  else {
1153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // otherwise, the instruction should be BL
115422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    lower_inst |= 0x1000U;
1155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
1156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = (S | T) - P;
1158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
11595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: Check bit size is 24(thumb2) or 22?
1160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (helper_check_signed_overflow(X, 25)) {
1161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
11625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
11635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
116422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  upper_inst = helper_thumb32_branch_upper(upper_inst, X);
116522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  lower_inst = helper_thumb32_branch_lower(lower_inst, X);
11665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
116722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
116822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
11695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
11715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
11725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_ABS_NC: (S + A) | T
1174d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
11755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
11765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
11835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
118422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
118522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
118667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  // If the flag of target section is not ALLOC, we will not scan this
118767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  // relocation but perform static relocation. (e.g., applying .debug section)
118822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
1190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & ARMRelocator::ReservePLT) {
119187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
1192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      T = 0 ; // PLT is not thumb
1193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
11945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
11965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
1197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = (S + A) | T;
119867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(
119967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                         pReloc.target() + pReloc.addend(), X);
1200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
12015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
12025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
1204d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
12055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
1209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
1213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
12145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (helper_check_signed_overflow(X, 16)) {
1216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
12175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  } else {
12185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
12205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
12215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
12225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_ABS: S + A
1224d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent)
12255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
12265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1228551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
12305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
123122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
123222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
1234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
123522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
1237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & ARMRelocator::ReservePLT) {
123887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
1239affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
12405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
12415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A;
12435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
12445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
12455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
12475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
12485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_MOVT_PREL: S + A - P
1250d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent)
12515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
1254551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines             helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
1256551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
12575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
12585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
1260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
12615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
12625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
1264d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
12655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
12665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
127122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
127222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get lower and upper 16 bit instructions from relocation targetData
127322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
127422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1276551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
12785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
127922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
1281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
128222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
1284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & ARMRelocator::ReservePLT) {
128587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
1286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      T = 0; // PLT is not thumb
1287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
12885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = (S + A) | T;
129022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
129122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
129422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
12965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
12975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
1299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
13005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
1304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
130622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
130722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get lower and upper 16 bit instructions from relocation targetData
130822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
130922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
13145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
131522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
131822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
1320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
1321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
1323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
1324d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent)
1325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
1326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1328551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
133122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
133222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get lower and upper 16 bit instructions from relocation targetData
133322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
133422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
1340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
134122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
134422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
13465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
13475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_ABS: S + A
1349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent)
13505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
13515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
135322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
135422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get lower and upper 16 bit instructions from relocation targetData
135522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
135622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
13605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
136122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this
1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
136422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
1365affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use plt
1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & ARMRelocator::ReservePLT) {
136787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
1368affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
13695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1370affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A;
13725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
13735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // check 16-bit overflow
1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (helper_check_signed_overflow(X, 16))
1376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
1380551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
1381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
13825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
13835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_THM_MOVT_PREL: S + A - P
1385affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// R_ARM_THM_MOVT_BREL: S + A - B(S)
1386d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent)
13875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
139022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
139122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get lower and upper 16 bit instructions from relocation targetData
139222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
139322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
1394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord val = ((upper_inst) << 16) | (lower_inst);
1395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A =
1396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
1397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
13985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  X >>= 16;
139922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
140022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  val = helper_insert_val_thumb_movw_movt_inst(val, X);
1401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = val >> 16;
1402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = val & 0xFFFFu;
140322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1404551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
14055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
14065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
140722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_ARM_PREL31: ((S + A) | T) - P
1408d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent)
14095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1410551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord target = pReloc.target();
1411551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord T = getThumbBit(pReloc);
1412551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = helper_sign_extend(target, 31) + pReloc.addend();
1413551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
1414551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
1415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (T != 0x0)
1416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_clear_thumb_bit(S);
14175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol has plt
1419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
142087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
14215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    T = 0;  // PLT is not thumb.
14225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
14235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1424551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = ((S + A) | T) - P;
14255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
1426affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (helper_check_signed_overflow(X, 31))
1427551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
1428551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
14295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
14305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_GD32: GOT(S) + A - P
14325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_IE32: GOT(S) + A - P
14335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_ARM_TLS_LE32: S + A - tp
1434d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent)
14355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1436551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Unsupport;
14375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
14385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1439d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent)
14405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1441551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Unsupport;
14425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1443