16f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===- HexagonRelocator.cpp -----------------------------------------------===//
26f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
36f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//                     The MCLinker Project
46f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
56f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// This file is distributed under the University of Illinois Open Source
66f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// License. See LICENSE.TXT for details.
76f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
86f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "HexagonRelocator.h"
1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "HexagonRelocationFunctions.h"
1187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "HexagonEncodings.h"
126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/ADT/Twine.h>
136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/DataTypes.h>
146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ELF.h>
156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/ELFFileFormat.h>
1787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/LD/LDSymbol.h>
1887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <mcld/Support/MsgHandling.h>
196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld;
216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
2387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Relocation Helper Functions
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic Relocation &helper_DynRel_init(ResolveInfo *pSym,
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Fragment &pFrag,
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t pOffset,
29551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      Relocator::Type pType,
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      HexagonRelocator &pParent) {
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonLDBackend &ld_backend = pParent.getTarget();
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation &rela_entry = *ld_backend.getRelaDyn().create();
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rela_entry.setType(pType);
3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rela_entry.targetRef().assign(pFrag, pOffset);
3587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pType == llvm::ELF::R_HEX_RELATIVE || NULL == pSym)
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rela_entry.setSymInfo(0);
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rela_entry.setSymInfo(pSym);
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return rela_entry;
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// R_HEX_RELATIVE
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic bool helper_use_relative_reloc(const ResolveInfo &pSym,
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      const HexagonRelocator &pFactory) {
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if symbol is dynamic or undefine or preemptible
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym.isDyn() || pSym.isUndef() ||
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic HexagonGOTEntry &helper_GOT_init(Relocation &pReloc,
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                        bool pHasRel,
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                        HexagonRelocator &pParent) {
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonLDBackend &ld_backend = pParent.getTarget();
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonGOTEntry *got_entry = ld_backend.getGOT().create();
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!pHasRel) {
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(HexagonRelocator::SymVal);
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else {
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Initialize got_entry content and the corresponding dynamic relocation.
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (helper_use_relative_reloc(*rsym, pParent)) {
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_RELATIVE,
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                                       pParent);
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(HexagonRelocator::SymVal);
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else {
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_GLOB_DAT,
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                                       pParent);
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0);
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::Address helper_get_GOT_address(ResolveInfo &pSym,
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                    HexagonRelocator &pParent) {
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(pSym);
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != got_entry);
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic PLTEntryBase &helper_PLT_init(Relocation &pReloc,
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     HexagonRelocator &pParent) {
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonLDBackend &ld_backend = pParent.getTarget();
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase *plt_entry = ld_backend.getPLT().create();
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "PLT entry not exist, but DynRel entry exist!");
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonGOTEntry *gotplt_entry = ld_backend.getGOTPLT().create();
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // init the corresponding rel entry in .rela.plt
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation &rela_entry = *ld_backend.getRelaPLT().create();
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rela_entry.setType(llvm::ELF::R_HEX_JMP_SLOT);
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rela_entry.targetRef().assign(*gotplt_entry);
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rela_entry.setSymInfo(rsym);
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *plt_entry;
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                    HexagonRelocator &pParent) {
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase *plt_entry = pParent.getSymPLTMap().lookUp(pSym);
11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != plt_entry);
11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
1236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocation Functions and Tables
1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_HEXAGON_APPLY_RELOC_FUNCS
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// the prototype of applying function
128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinestypedef Relocator::Result (*ApplyFunctionType)(Relocation &pReloc,
129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                               HexagonRelocator &pParent);
1306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct ApplyFunctionTriple {
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ApplyFunctionType func;
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int type;
13587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char *name;
1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
1376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions
1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const ApplyFunctionTriple ApplyFunctions[] = {
1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
1426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstatic uint32_t findBitMask(uint32_t insn, Instruction *encodings,
14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                            int32_t numInsns) {
14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (int32_t i = 0; i < numInsns; i++) {
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      continue;
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (((insn & 0xc000) != 0) && (encodings[i].isDuplex))
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      continue;
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (((encodings[i].insnMask) & insn) == encodings[i].insnCmpMask)
153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return encodings[i].insnBitMask;
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(0);
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Should not be here, but add a return for -Werror=return-type
15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // error: control reaches end of non-void function
15887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return -1;
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#define FINDBITMASK(INSN)                                                      \
16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  findBitMask((uint32_t) INSN, insn_encodings,                                 \
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines              sizeof(insn_encodings) / sizeof(Instruction))
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
1666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// HexagonRelocator
1676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
16887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesHexagonRelocator::HexagonRelocator(HexagonLDBackend &pParent,
16987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                   const LinkerConfig &pConfig)
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    : Relocator(pConfig), m_Target(pParent) {}
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
17287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesHexagonRelocator::~HexagonRelocator() {}
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
17487f34658dec9097d987d254a990ea7f311bfc95fStephen HinesRelocator::Result HexagonRelocator::applyRelocation(Relocation &pRelocation) {
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation::Type type = pRelocation.type();
1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (type > 85) { // 86-255 relocs do not exists for Hexagon
1786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Relocator::Unknown;
1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // apply the relocation
1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ApplyFunctions[type].func(pRelocation, *this);
1836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesconst char *HexagonRelocator::getName(Relocation::Type pType) const {
1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ApplyFunctions[pType].name;
1876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
18987f34658dec9097d987d254a990ea7f311bfc95fStephen HinesRelocator::Size HexagonRelocator::getSize(Relocation::Type pType) const {
1906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return 32;
1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid HexagonRelocator::scanRelocation(Relocation &pReloc, IRBuilder &pLinker,
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Module &pModule, LDSection &pSection, Input &pInput) {
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (LinkerConfig::Object == config().codeGenType())
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != rsym &&
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (config().isCodeStatic())
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pSection.getLink());
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isLocal()) // rsym is local
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanLocalReloc(pReloc, pLinker, pModule, pSection);
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else // rsym is external
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // check if we should issue undefined reference for the relocation target
216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol
217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    issueUndefRef(pReloc, pSection, pInput);
219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
22187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid HexagonRelocator::addCopyReloc(ResolveInfo &pSym,
22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                    HexagonLDBackend &pTarget) {
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation &rel_entry = *pTarget.getRelaDyn().create();
224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setType(pTarget.getCopyRelType());
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setSymInfo(&pSym);
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid HexagonRelocator::scanLocalReloc(Relocation &pReloc, IRBuilder &pBuilder,
23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Module &pModule, LDSection &pSection) {
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
23487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_LO16:
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_HI16:
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16:
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8:
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32_6_X:
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16_X:
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_12_X:
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_11_X:
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_10_X:
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_9_X:
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8_X:
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_7_X:
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_6_X:
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(!(rsym->reserved() & ReserveRel) &&
25187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           "Cannot apply this relocation for read only section");
25287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
25387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32:
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // If buiding PIC object (shared library or PIC executable),
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // a dynamic relocations with RELATIVE type to this location is needed.
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Reserve an entry in .rel.dyn
25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (config().isCodeIndep()) {
25987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      Relocation &reloc = helper_DynRel_init(rsym,
26087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             *pReloc.targetRef().frag(),
26187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             pReloc.targetRef().offset(),
26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             llvm::ELF::R_HEX_RELATIVE,
26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             *this);
26487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // we need to set up the relocation addend at apply relocation, record the
26587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // relocation
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getRelRelMap().record(pReloc, reloc);
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set Rel bit
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveRel);
27087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getTarget().checkAndSetHasTextRel(*pSection.getLink());
27187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
27987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid HexagonRelocator::scanGlobalReloc(Relocation &pReloc, IRBuilder &pBuilder,
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       Module &pModule, LDSection &pSection) {
281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
28287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
28387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonLDBackend &ld_backend = getTarget();
28487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
28587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_LO16:
28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_HI16:
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16:
28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8:
29087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32_6_X:
29187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16_X:
29287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_12_X:
29387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_11_X:
29487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_10_X:
29587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_9_X:
29687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8_X:
29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_7_X:
29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_6_X:
29987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(!(rsym->reserved() & ReserveRel) &&
30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           "Cannot apply this relocation for read only section");
30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32:
30487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (ld_backend.symbolNeedsPLT(*rsym)) {
30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      //create PLT for this symbol if it does not have.
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (!(rsym->reserved() & ReservePLT)) {
30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_PLT_init(pReloc, *this);
30887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReservePLT);
309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (ld_backend.symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     true)) {
31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) {
31587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        LDSymbol &cpy_sym =
31687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend);
31787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        addCopyReloc(*cpy_sym.resolveInfo(), ld_backend);
31887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
31987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else {
32087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        Relocation &reloc = helper_DynRel_init(rsym,
32187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *pReloc.targetRef().frag(),
32287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               pReloc.targetRef().offset(),
32387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               llvm::ELF::R_HEX_RELATIVE,
32487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *this);
32587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // we need to set up the relocation addend at apply relocation, record the
32687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // relocation
32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getRelRelMap().record(pReloc, reloc);
32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ld_backend.checkAndSetHasTextRel(*pSection.getLink());
330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_LO16:
33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_HI16:
33687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_32:
33787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_32_6_X:
33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_16_X:
33987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_11_X:
34087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // This assumes that GOT exists
34187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
34387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_LO16:
34487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_HI16:
34587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_32:
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_16:
34787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_32_6_X:
34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_16_X:
34987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_11_X:
35087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Symbol needs GOT entry, reserve entry in .got
35187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // return if we already create GOT for this symbol
35287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (rsym->reserved() & ReserveGOT)
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
35487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // If the GOT is used in statically linked binaries,
35587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // the GOT entry is enough and no relocation is needed.
35687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (config().isCodeStatic())
35787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_GOT_init(pReloc, false, *this);
35887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    else
35987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_GOT_init(pReloc, true, *this);
36087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // set GOT bit
36187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rsym->setReserved(rsym->reserved() | ReserveGOT);
36287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
36487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B22_PCREL:
36587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B15_PCREL:
36687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B7_PCREL:
36787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B13_PCREL:
36887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B9_PCREL:
36987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B32_PCREL_X:
37087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B22_PCREL_X:
37187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B15_PCREL_X:
37287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B13_PCREL_X:
37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B9_PCREL_X:
37487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B7_PCREL_X:
37587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32_PCREL:
37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_6_PCREL_X:
37787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_PLT_B22_PCREL:
37887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (rsym->reserved() & ReservePLT)
37987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return;
38087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (ld_backend.symbolNeedsPLT(*rsym) ||
38187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) {
38287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_PLT_init(pReloc, *this);
38387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
38587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
38687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
38987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } // end of switch
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolforCopyReloc
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy.
397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// @note This is executed at `scan relocation' stage.
39887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesLDSymbol &HexagonRelocator::defineSymbolforCopyReloc(
39987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    IRBuilder &pBuilder, const ResolveInfo &pSym, HexagonLDBackend &pTarget) {
400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS LDSection
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection *bss_sect_hdr = NULL;
40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat *file_format = pTarget.getOutputFormat();
403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getBSS();
407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS SectionData
409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != bss_sect_hdr);
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData *bss_section = NULL;
411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (bss_sect_hdr->hasSectionData())
412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = bss_sect_hdr->getSectionData();
413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Determine the alignment by the symbol value
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: here we use the largest alignment
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // allocate space in BSS for the copy symbol
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment *frag = new FillFragment(0x0, 1, pSym.size());
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign);
423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // change symbol binding to Global if it's a weak symbol
42687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding) pSym.binding();
427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (binding == ResolveInfo::Weak)
428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    binding = ResolveInfo::Global;
429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Define the copy symbol in the bss section and resolve it
43187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSymbol *cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
43287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pSym.name(), (ResolveInfo::Type) pSym.type(), ResolveInfo::Define,
43387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      binding, pSym.size(), // size
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      0x0,                  // value
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      FragmentRef::Create(*frag, 0x0), (ResolveInfo::Visibility) pSym.other());
436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // output all other alias symbols if any
438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module &pModule = pBuilder.getModule();
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Module::AliasList *alias_list = pModule.getAliasList(pSym);
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL != alias_list) {
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Module::alias_iterator it, it_e = alias_list->end();
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (it = alias_list->begin(); it != it_e; ++it) {
44387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const ResolveInfo *alias = *it;
44487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (alias != &pSym && alias->isDyn()) {
445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
44687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            alias->name(), (ResolveInfo::Type) alias->type(),
44787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            ResolveInfo::Define, binding, alias->size(), // size
44887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            0x0,                                         // value
44987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            FragmentRef::Create(*frag, 0x0),
45087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            (ResolveInfo::Visibility) alias->other());
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *cpy_sym;
456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid HexagonRelocator::partialScanRelocation(Relocation &pReloc,
45987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             Module &pModule,
46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                             const LDSection &pSection) {
461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.updateAddend();
462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // if we meet a section symbol
463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
46487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    LDSymbol *input_sym = pReloc.symInfo()->outSymbol();
465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // 1. update the relocation target offset
467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    assert(input_sym->hasFragRef());
468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // 2. get the output LDSection which the symbol defined in
46987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const LDSection &out_sect =
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        input_sym->fragRef()->frag()->getParent()->getSection();
47187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ResolveInfo *sym_info =
47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
473f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // set relocation target symbol to the output section symbol's resolveInfo
474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    pReloc.setSymInfo(sym_info);
475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
477f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
4786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//=========================================//
4796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Each relocation function implementation //
4806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//=========================================//
4816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
4826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_HEX_NONE
483551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result none(Relocation &pReloc, HexagonRelocator &pParent) {
484551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
4856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
4866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//R_HEX_32 and its class of relocations use only addend and symbol value
48887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// S + A : result is unsigned truncate.
48987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Exception: R_HEX_32_6_X : unsigned verify
490551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result applyAbs(Relocation &pReloc) {
491551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
492551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t result = (uint32_t)(S + A);
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t bitMask = 0;
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t effectiveBits = 0;
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t alignment = 1;
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t shift = 0;
49887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_LO16:
50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
50287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
50387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_HI16:
50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 16;
50687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
50887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32:
51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xffffffff;
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16:
51487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x0000ffff;
51587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 2;
51687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
51787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8:
51987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x000000ff;
52087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 1;
52187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
52287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_12_X:
52487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x000007e0;
52587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
52687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32_6_X:
52887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xfff3fff;
52987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 6;
53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 26;
53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_16_X:
53487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_11_X:
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_10_X:
53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_9_X:
53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_8_X:
53887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_7_X:
53987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_6_X:
54087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
54187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
54387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
54487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // show proper error
54587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::unsupported_relocation) << (int)
54687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() << "mclinker@googlegroups.com";
5476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
5496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((shift != 0) && (result % alignment != 0))
551551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
5526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  result >>= shift;
5546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (effectiveBits) {
55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t range = 1 << effectiveBits;
55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (result > (range - 1))
558551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::Overflow;
5596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
562551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
564f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
56587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//R_HEX_B22_PCREL and its class of relocations, use
56687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// S + A - P : result is signed verify.
56787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Exception: R_HEX_B32_PCREL_X : signed truncate
56887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Another Exception: R_HEX_6_PCREL_X is unsigned truncate
569551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result applyRel(Relocation &pReloc, int64_t pResult) {
57087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t bitMask = 0;
57187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t effectiveBits = 0;
57287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t alignment = 1;
57387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t result;
57487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t shift = 0;
57587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
57787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B22_PCREL:
57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x01ff3ffe;
57987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 22;
58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
58187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
58287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B15_PCREL:
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00df20fe;
58687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 15;
58787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
58887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
59087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
59187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B7_PCREL:
59287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00001f18;
59387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 7;
59487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
59687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
59787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
59887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B13_PCREL:
59987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00202ffe;
60087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 13;
60187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B9_PCREL:
60687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x003000fe;
60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 9;
60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
61187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
61287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B32_PCREL_X:
61387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xfff3fff;
61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 6;
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
61787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B22_PCREL_X:
61887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x01ff3ffe;
61987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 22;
62087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pResult &= 0x3f;
62187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
62287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B15_PCREL_X:
62487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00df20fe;
62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 15;
62687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pResult &= 0x3f;
62787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
62887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
62987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B13_PCREL_X:
63087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00202ffe;
63187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 13;
63287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pResult &= 0x3f;
63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
63487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B9_PCREL_X:
63687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x003000fe;
63787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 9;
63887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pResult &= 0x3f;
63987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
64087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_B7_PCREL_X:
64287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00001f18;
64387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 7;
64487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pResult &= 0x3f;
64587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_32_PCREL:
64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xffffffff;
64987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 32;
65087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
65187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
65287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_6_PCREL_X:
65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // This is unique since it has a unsigned operand and its truncated
65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    result = pReloc.addend() + pReloc.symValue() - pReloc.place();
65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
657551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
65987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
66087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // show proper error
66187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::unsupported_relocation) << (int)
66287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() << "mclinker@googlegroups.com";
66387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
66587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((shift != 0) && (pResult % alignment != 0))
666551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
66887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pResult >>= shift;
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
67087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (effectiveBits) {
67187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int64_t range = 1LL << (effectiveBits - 1);
67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((pResult > (range - 1)) || (pResult < -range))
673551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::Overflow;
67487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
67687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.target() |= (uint32_t) ApplyMask<int32_t>(bitMask, pResult);
677551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
680551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocAbs(Relocation &pReloc, HexagonRelocator &pParent) {
68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
683551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc);
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool has_dyn_rel = (NULL != rel_entry);
687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
68887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if the flag of target section is not ALLOC, we eprform only static
68987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // relocation.
69087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0 == (llvm::ELF::SHF_ALLOC &
69187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            pReloc.targetRef().frag()->getParent()->getSection().flag())) {
69287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return applyAbs(pReloc);
693f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
69587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // a local symbol with .rela type relocation
69687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal() && has_dyn_rel) {
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry->setAddend(S + A);
698551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
699f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
70187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!rsym->isLocal()) {
70287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
70387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
70487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
70687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (has_dyn_rel) {
70787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (llvm::ELF::R_HEX_32 == pReloc.type() &&
70887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_use_relative_reloc(*rsym, pParent)) {
70987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rel_entry->setAddend(S + A);
71087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      } else {
71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rel_entry->setAddend(A);
712551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
715f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
716f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
71787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return applyAbs(pReloc);
718f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
719f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
720551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocPCREL(Relocation &pReloc, HexagonRelocator &pParent) {
72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo *rsym = pReloc.symInfo();
72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int64_t result;
7236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
724551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
725551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
726551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place();
7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  FragmentRef &target_fragref = pReloc.targetRef();
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Fragment *target_frag = target_fragref.frag();
73087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection &target_sect = target_frag->getParent()->getSection();
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
73287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  result = (int64_t)(S + A - P);
733f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
73487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // for relocs inside non ALLOC, just apply
73587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
73687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return applyRel(pReloc, result);
7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
738f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
73987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!rsym->isLocal()) {
74087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
74187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
74287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      result = (int64_t)(S + A - P);
74387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      applyRel(pReloc, result);
744551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::OK;
74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
746f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
747f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return applyRel(pReloc, result);
7496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
75187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_HEX_GPREL16_0 and its class : Unsigned Verify
752551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocGPREL(Relocation &pReloc, HexagonRelocator &pParent) {
753551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
754551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
755551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord GP = pParent.getTarget().getGP();
75687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
75787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t result = (uint32_t)(S + A - GP);
75887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t shift = 0;
75987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t alignment = 1;
76087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
76287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GPREL16_0:
76387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
76487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GPREL16_1:
76687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 1;
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 2;
76887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
76987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GPREL16_2:
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 2;
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GPREL16_3:
77687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 3;
77787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 8;
77887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
77987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
78087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
78187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // show proper error
78287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::unsupported_relocation) << (int)
78387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() << "mclinker@googlegroups.com";
784f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
785f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
78687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t range = 1 << 16;
787f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t bitMask = FINDBITMASK(pReloc.target());
788f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((shift != 0) && (result % alignment != 0))
790551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  result >>= shift;
7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
79487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (result < range - 1) {
79587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
796551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
798551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Overflow;
7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
800f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
801f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// R_HEX_PLT_B22_PCREL: PLT(S) + A - P
802551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocPLTB22PCREL(Relocation &pReloc,
803551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                   HexagonRelocator &pParent) {
804f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // PLT_S depends on if there is a PLT entry.
805551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address PLT_S;
806f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT))
80787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
808f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
809f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    PLT_S = pReloc.symValue();
810551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
811f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t bitMask = FINDBITMASK(pReloc.target());
812f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t result = (PLT_S + pReloc.addend() - P) >> 2;
813f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
814551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
815f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
816f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
81787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//R_HEX_GOT_LO16 and its class : (G) Signed Truncate
81887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//Exception: R_HEX_GOT_16(_X): signed verify
81987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Exception: R_HEX_GOT_11_X : unsigned truncate
820551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocGOT(Relocation &pReloc, HexagonRelocator &pParent) {
82187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) {
822551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
82387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
824f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set got entry value if needed
82687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
82787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(NULL != got_entry);
82887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (HexagonRelocator::SymVal == got_entry->getValue())
82987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(pReloc.symValue());
830f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
831551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S =
83287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                             helper_get_GOT_address(*pReloc.symInfo(), pParent);
833551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
83487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  int32_t result = (int32_t)(GOT_S - GOT);
83587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t effectiveBits = 0;
83687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t alignment = 1;
83787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t bitMask = 0;
83887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t result_u;
83987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t shift = 0;
84087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
84287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_LO16:
84387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
84487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
84587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_HI16:
84787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 16;
84987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_32:
85387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xffffffff;
85487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
85587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_16:
85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
85887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 16;
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
86087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
86187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_32_6_X:
86287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xfff3fff;
86387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 6;
86487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
86587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
86687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_16_X:
86787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    effectiveBits = 6;
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
87087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOT_11_X:
87287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    result_u = GOT_S - GOT;
87487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u);
875551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
876f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
87887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // show proper error
87987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::unsupported_relocation) << (int)
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() << "mclinker@googlegroups.com";
88187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
882f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((shift != 0) && (result % alignment != 0))
884551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
885f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  result >>= shift;
887f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (effectiveBits) {
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    int32_t range = 1 << (effectiveBits - 1);
89087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((result > range - 1) || (result < -range))
891551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::Overflow;
89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.target() |= ApplyMask<int32_t>(bitMask, result);
894551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
895f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
896f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
89787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// R_HEX_GOTREL_LO16: and its class of relocs
89887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// (S + A - GOT) : Signed Truncate
899551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result relocGOTREL(Relocation &pReloc, HexagonRelocator &pParent) {
900551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
901551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
902551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
903f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t bitMask = 0;
90587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t alignment = 1;
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t shift = 0;
90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t result = (uint32_t)(S + A - GOT);
90987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  switch (pReloc.type()) {
91187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_LO16:
91287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
91387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
91487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_HI16:
91687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x00c03fff;
91787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 16;
91887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    alignment = 4;
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
92087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_32:
92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0xffffffff;
92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_32_6_X:
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = 0x0fff3fff;
92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    shift = 6;
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_16_X:
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  case llvm::ELF::R_HEX_GOTREL_11_X:
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bitMask = FINDBITMASK(pReloc.target());
93387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    break;
93487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  default:
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // show proper error
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::unsupported_relocation) << (int)
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pReloc.type() << "mclinker@googlegroups.com";
939f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
940f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (result % alignment != 0)
942551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
94387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  result >>= shift;
94587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
94687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
947551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
948f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
949f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
950551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result unsupport(Relocation &pReloc, HexagonRelocator &pParent) {
951551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Unsupport;
952f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
953