1551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===- AArch64Relocator.cpp  ----------------------------------------------===//
2551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
3551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//                     The MCLinker Project
4551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
5551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// This file is distributed under the University of Illinois Open Source
6551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// License. See LICENSE.TXT for details.
7551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
8551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
9551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64Relocator.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64RelocationFunctions.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "AArch64RelocationHelpers.h"
20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
21551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/ADT/Twine.h>
22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/DataTypes.h>
23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/ELF.h>
24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/Host.h>
25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
27551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
28551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
29551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Relocation Functions and Tables
30551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
31551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesDECL_AARCH64_APPLY_RELOC_FUNCS
32551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
33551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// the prototype of applying function
34551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinestypedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
35551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                               AArch64Relocator& pParent);
36551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
37551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// the table entry of applying functions
38551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesclass ApplyFunctionEntry {
3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines public:
40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ApplyFunctionEntry() {}
41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ApplyFunctionEntry(ApplyFunctionType pFunc,
42551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const char* pName,
43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     size_t pSize = 0)
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      : func(pFunc), name(pName), size(pSize) {}
45551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ApplyFunctionType func;
46551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  const char* name;
47551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  size_t size;
48551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines};
49551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinestypedef std::map<Relocator::Type, ApplyFunctionEntry> ApplyFunctionMap;
50551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic const ApplyFunctionMap::value_type ApplyFunctionList[] = {
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    DECL_AARCH64_APPLY_RELOC_FUNC_PTRS(ApplyFunctionMap::value_type,
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       ApplyFunctionEntry)};
54551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// declare the table of applying functions
56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic ApplyFunctionMap ApplyFunctions(ApplyFunctionList,
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       ApplyFunctionList +
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           sizeof(ApplyFunctionList) /
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                               sizeof(ApplyFunctionList[0]));
60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64Relocator
63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::AArch64Relocator(AArch64GNULDBackend& pParent,
65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                   const LinkerConfig& pConfig)
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : Relocator(pConfig), m_Target(pParent) {
67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
6937b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64Relocator::~AArch64Relocator() {
70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
7237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result AArch64Relocator::applyRelocation(Relocation& pRelocation) {
73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation::Type type = pRelocation.type();
74b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  // valid types are 0x0, 0x100-1032, and R_AARCH64_REWRITE_INSN
75b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if ((type < 0x100 || type > 1032) &&
76b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      (type != 0x0) &&
77b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      (type != R_AARCH64_REWRITE_INSN)) {
78551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Unknown;
79551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(ApplyFunctions.find(type) != ApplyFunctions.end());
81551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ApplyFunctions[type].func(pRelocation, *this);
82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* AArch64Relocator::getName(Relocator::Type pType) const {
85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(ApplyFunctions.find(pType) != ApplyFunctions.end());
86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ApplyFunctions[pType].name;
87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
8937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size AArch64Relocator::getSize(Relocation::Type pType) const {
90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ApplyFunctions[pType].size;
91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::addCopyReloc(ResolveInfo& pSym) {
94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation& rel_entry = *getTarget().getRelaDyn().create();
95a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  rel_entry.setType(llvm::ELF::R_AARCH64_COPY);
96551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
97551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
98551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  rel_entry.setSymInfo(&pSym);
99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
101551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// defineSymbolForCopyReloc
102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// section and all other reference to this symbol should refer to this
104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// copy.
105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// This is executed at scan relocation stage.
106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesLDSymbol& AArch64Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                     const ResolveInfo& pSym) {
108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // get or create corresponding BSS LDSection
109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection* bss_sect_hdr = NULL;
110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ELFFileFormat* file_format = getTarget().getOutputFormat();
111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_sect_hdr = &file_format->getBSS();
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // get or create corresponding BSS SectionData
117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData* bss_data = NULL;
118551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (bss_sect_hdr->hasSectionData())
119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_data = bss_sect_hdr->getSectionData();
120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Determine the alignment by the symbol value
124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // FIXME: here we use the largest alignment
125551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
126551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // allocate space in BSS for the copy symbol
128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_data, addralign);
130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
131551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
132551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // change symbol binding to Global if it's a weak symbol
133551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (binding == ResolveInfo::Weak)
135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    binding = ResolveInfo::Global;
136551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Define the copy symbol in the bss section and resolve it
138551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.name(),
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Type)pSym.type(),
14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      binding,
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.size(),  // size
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,          // value
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Create(*frag, 0x0),
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Visibility)pSym.other());
147551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
148551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return *cpy_sym;
149551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
150551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::scanLocalReloc(Relocation& pReloc,
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const LDSection& pSection) {
153551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym - The relocation target symbol
154551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
156551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS64:
157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If buiding PIC object (shared library or PIC executable),
158551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
159551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Reserve an entry in .rel.dyn
160551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep()) {
161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set Rel bit
162551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
163551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
164551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set up the dyn rel directly
165551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        Relocation& reloc = helper_DynRela_init(rsym,
166551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                *pReloc.targetRef().frag(),
167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                pReloc.targetRef().offset(),
168a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                                llvm::ELF::R_AARCH64_RELATIVE,
169551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                *this);
170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getRelRelMap().record(pReloc, reloc);
171551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
173551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
174551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS32:
175551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS16:
176551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If buiding PIC object (shared library or PIC executable),
177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Reserve an entry in .rel.dyn
179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep()) {
180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set up the dyn rel directly
181551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        Relocation& reloc = helper_DynRela_init(rsym,
18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                *pReloc.targetRef().frag(),
18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                pReloc.targetRef().offset(),
18437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                pReloc.type(),
18537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                *this);
186551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getRelRelMap().record(pReloc, reloc);
187551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set Rel bit
188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
191551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
192551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
193551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_GOT_PAGE:
194551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: {
195551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
196551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create GOT for this symbol
197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReserveGOT)
198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If building PIC object, a dynamic relocation with
200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // type RELATIVE is needed to relocate this GOT entry.
201551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep())
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_GOT_init(pReloc, true, *this);
203551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      else
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_GOT_init(pReloc, false, *this);
205551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set GOT bit
206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
211551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      break;
212551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
214551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanGlobalReloc(Relocation& pReloc,
216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       IRBuilder& pBuilder,
21737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       const LDSection& pSection) {
218551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym - The relocation target symbol
219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
22037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS64:
222551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS32:
223551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS16:
224551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
225551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation entry
226551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
230551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
231551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
235551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
237551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), true)) {
241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // symbol needs dynamic relocation entry, set up the dynrel entry
242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
243551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
244551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
24537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set Rel bit and the dyn rel
247551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
248551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
249551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() &&
250551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines              helper_use_relative_reloc(*rsym, *this)) {
25104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines            Relocation& reloc =
25204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                helper_DynRela_init(rsym,
25304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                    *pReloc.targetRef().frag(),
25404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                    pReloc.targetRef().offset(),
25504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                    llvm::ELF::R_AARCH64_RELATIVE,
25604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                    *this);
257551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            getRelRelMap().record(pReloc, reloc);
25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            Relocation& reloc = helper_DynRela_init(rsym,
260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *pReloc.targetRef().frag(),
261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    pReloc.targetRef().offset(),
262551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    pReloc.type(),
263551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *this);
264551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            getRelRelMap().record(pReloc, reloc);
265551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          }
266551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
269551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL64:
271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL32:
272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL16:
273551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
274551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
27637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
277551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
278551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
279551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
280551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
281551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
285551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
286551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Only PC relative relocation against dynamic symbol needs a
287551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation.  Only dynamic copy relocation is allowed
288551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // and PC relative relocation will be resolved to the local copy.
289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // All other dynamic relocations may lead to run-time relocation
290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // overflow.
291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().isDynamicSymbol(*rsym) &&
29237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          getTarget()
29337b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), false) &&
295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
296551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
297551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        addCopyReloc(*cpy_sym.resolveInfo());
298551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
299551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
300551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_CONDBR19:
302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_JUMP26:
303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_CALL26: {
304551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create plt for this symbol
305551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReservePLT)
306551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
307551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
308551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
309551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
312551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if symbol is defined in the ouput file and it's not
313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // preemptible, no need plt
314551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
31537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !getTarget().isSymbolPreemptible(*rsym)) {
316551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
317551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
318551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs PLT entry, we need to reserve a PLT entry
320551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // and the corresponding GOT and dynamic relocation entry
321551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // in .got and .rel.plt.
322551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      helper_PLT_init(pReloc, *this);
323551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set PLT bit
324551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
325551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
328a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_LO21:
329551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21:
330a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
33137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
33237b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
33337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), false)) {
334551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
337551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
338551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
340551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
34137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
342551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
343551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
344551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
346551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
347551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
348551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
349551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
350551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
351551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_GOT_PAGE:
353551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: {
354551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
355551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create GOT for this symbol
356551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReserveGOT)
357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if the symbol cannot be fully resolved at link time, then we need a
359551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation
360551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (!getTarget().symbolFinalValueIsKnown(*rsym))
361551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        helper_GOT_init(pReloc, true, *this);
362551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      else
363551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        helper_GOT_init(pReloc, false, *this);
364551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set GOT bit
365551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
366551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
367551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
368551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
369551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
370551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      break;
371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
372551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
373551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
374551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanRelocation(Relocation& pReloc,
375551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      IRBuilder& pBuilder,
376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      Module& pModule,
377551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      LDSection& pSection,
37837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Input& pInput) {
379551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
38037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(rsym != NULL &&
381551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
382551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
38337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pSection.getLink() != NULL);
38437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
385551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return;
386551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
387551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // entries should be created.
389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // FIXME: Below judgements concern nothing about TLS related relocation
390551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
391551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym is local
392551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isLocal())
393551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    scanLocalReloc(pReloc, pSection);
394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym is external
395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
396551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    scanGlobalReloc(pReloc, pBuilder, pSection);
397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
398551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // check if we shoule issue undefined reference for the relocation target
399551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // symbol
400551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
401551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    issueUndefRef(pReloc, pSection, pInput);
402551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
403551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
404b0d0eb206527b43c771933602e147bbd7b471082Stephen Hinesbool
405b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesAArch64Relocator::mayHaveFunctionPointerAccess(const Relocation& pReloc) const {
406b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  switch (pReloc.type()) {
407b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21:
408b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21_NC:
409b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_AARCH64_ADD_ABS_LO12_NC:
410b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_AARCH64_ADR_GOT_PAGE:
411b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: {
412b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      return true;
413b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    }
414b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    default: {
415b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (pReloc.symInfo()->isLocal()) {
416b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        // Do not fold any local symbols if building a shared object.
417b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        return (config().codeGenType() == LinkerConfig::DynObj);
418b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      } else {
419b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        // Do not fold any none global defualt symbols if building a shared
420b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        // object.
421b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        return ((config().codeGenType() == LinkerConfig::DynObj) &&
422b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                (pReloc.symInfo()->visibility() != ResolveInfo::Default));
423b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      }
424b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    }
425b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  }
426b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return false;
427b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
428b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
42937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t AArch64Relocator::getDebugStringOffset(Relocation& pReloc) const {
43037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.type() != llvm::ELF::R_AARCH64_ABS32)
43137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    error(diag::unsupport_reloc_for_debug_string)
43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        << getName(pReloc.type()) << "mclinker@googlegroups.com";
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
43437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section)
435fda4bbd63841e8ae3418637b24b7416f6bf56ca6Stephen McGroarty    return pReloc.target() + pReloc.addend();
43637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else
43737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
43837b74a387bb3993387029859c2d9d051c41c724eStephen Hines               pReloc.target() + pReloc.addend();
43937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
44037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
44137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64Relocator::applyDebugStringOffset(Relocation& pReloc,
44237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                              uint32_t pOffset) {
44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  pReloc.target() = pOffset;
44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
446551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
447551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Each relocation function implementation
448551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
449551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
450551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_NONE
45137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, AArch64Relocator& pParent) {
452551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
453551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
454551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
45537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, AArch64Relocator& pParent) {
45637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return Relocator::Unsupported;
457551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
458551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
459551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS64: S + A
460551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS32: S + A
461551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS16: S + A
46237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, AArch64Relocator& pParent) {
463551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
464551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
465551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord S = pReloc.symValue();
466551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
46737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool has_dyn_rel = (dyn_rel != NULL);
468551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
469551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
470551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this
471551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
472551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
473551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = S + A;
474551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
475551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
476551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // A local symbol may need RELATIVE Type dynamic relocation
477551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isLocal() && has_dyn_rel) {
478551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rel->setAddend(S + A);
479551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
480551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
481551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // An external symbol may need PLT and dynamic relocation
482551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!rsym->isLocal()) {
483551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (rsym->reserved() & AArch64Relocator::ReservePLT) {
484551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      S = helper_get_PLT_address(*rsym, pParent);
485551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
486551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // If we generate a dynamic relocation (except R_AARCH64_64_RELATIVE)
487551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // for a place, we should not perform static relocation on it
488551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // in order to keep the addend store in the place correct.
489551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (has_dyn_rel) {
490551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() &&
491a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          llvm::ELF::R_AARCH64_RELATIVE == dyn_rel->type()) {
492551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        dyn_rel->setAddend(S + A);
49337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else {
494551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        dyn_rel->setAddend(A);
495551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
496551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
497551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
498551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
499551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
500551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // perform static relocation
501551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = S + A;
502551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
503551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
504551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
505551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL64: S + A - P
506551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL32: S + A - P
507551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL16: S + A - P
50837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, AArch64Relocator& pParent) {
509551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
510551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
51137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.addend();
51237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord P = pReloc.place();
513551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
514551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type())
51537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    A += pReloc.target() & get_mask(pParent.getSize(pReloc.type()));
516551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
517551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    A += pReloc.target();
518551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
519551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
520551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this
521551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
522551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
523551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // if plt entry exists, the S value is the plt entry address
524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (!rsym->isLocal()) {
525551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & AArch64Relocator::ReservePLT) {
526551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        S = helper_get_PLT_address(*rsym, pParent);
527551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
528551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
529551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
530551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
531551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
532551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = X;
533551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
534551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type() &&
535551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      helper_check_signed_overflow(X, pParent.getSize(pReloc.type())))
536551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
537551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
538551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
539551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
540551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADD_ABS_LO12_NC: S + A
54137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result add_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) {
542551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address value = 0x0;
543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.addend();
545551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
546551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  value = helper_get_page_offset(S + A);
547551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_add_imm(pReloc.target(), value);
548551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
550551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
551551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
552a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// R_AARCH64_ADR_PREL_LO21: S + A - P
553a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen HinesRelocator::Result adr_prel_lo21(Relocation& pReloc, AArch64Relocator& pParent) {
554a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
555a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  Relocator::Address S = pReloc.symValue();
556a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // if plt entry exists, the S value is the plt entry address
557a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  if (rsym->reserved() & AArch64Relocator::ReservePLT) {
558a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    S = helper_get_PLT_address(*rsym, pParent);
559a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
560a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  Relocator::DWord A = pReloc.addend();
561a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  Relocator::DWord P = pReloc.place();
562a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  Relocator::DWord X = S + A - P;
563a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
564a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  pReloc.target() = helper_reencode_adr_imm(pReloc.target(), X);
565a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
566a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  return Relocator::OK;
567a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
568a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
569551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21: ((PG(S + A) - PG(P)) >> 12)
570551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21_NC: ((PG(S + A) - PG(P)) >> 12)
57137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result adr_prel_pg_hi21(Relocation& pReloc,
57237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   AArch64Relocator& pParent) {
573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
574551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
575551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // if plt entry exists, the S value is the plt entry address
576551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->reserved() & AArch64Relocator::ReservePLT) {
577551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*rsym, pParent);
578551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
579551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
58037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord P = pReloc.place();
58137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord X =
58237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_get_page_address(S + A) - helper_get_page_address(P);
583551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12));
585551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
586551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
587551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
588551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
589551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CALL26: S + A - P
590551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_JUMP26: S + A - P
59137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result call(Relocation& pReloc, AArch64Relocator& pParent) {
592551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If target is undefined weak symbol, we only need to jump to the
593551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // next instruction unless it has PLT entry. Rewrite instruction
594551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // to NOP.
59537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
596551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !pReloc.symInfo()->isDyn() &&
597551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) {
598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // change target to NOP
599551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = 0xd503201f;
600551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
601551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
602551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
60437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.addend();
605551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
606551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
607551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // S depends on PLT exists or not
608551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)
609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
610551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
611551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
612551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // TODO: check overflow..
613551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
614551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_branch_offset_26(pReloc.target(), X >> 2);
615551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
616551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
617551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
618551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
619551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CONDBR19: S + A - P
62037b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result condbr(Relocation& pReloc, AArch64Relocator& pParent) {
621551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If target is undefined weak symbol, we only need to jump to the
622551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // next instruction unless it has PLT entry. Rewrite instruction
623551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // to NOP.
62437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !pReloc.symInfo()->isDyn() &&
626551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) {
627551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // change target to NOP
628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = 0xd503201f;
629551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
630551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
631551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
632551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
63337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.addend();
634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
635551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
636551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // S depends on PLT exists or not
637551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)
638551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
639551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
641551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // TODO: check overflow..
642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
643551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_cond_branch_ofs_19(pReloc.target(), X >> 2);
644551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
645551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
646551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
647551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
648551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_GOT_PAGE: Page(G(GDAT(S+A))) - Page(P)
64937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result adr_got_page(Relocation& pReloc, AArch64Relocator& pParent) {
650551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) {
651551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
652551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
653551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
654551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
655551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
656551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord X =
65837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_get_page_address(GOT_S + A) - helper_get_page_address(P);
659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
660551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12));
661551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
662551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup got entry value if needed
663551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
66437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (got_entry != NULL && AArch64Relocator::SymVal == got_entry->getValue())
665551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    got_entry->setValue(pReloc.symValue());
666551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup relocation addend if needed
667551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc);
66837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((dyn_rela != NULL) && (AArch64Relocator::SymVal == dyn_rela->addend())) {
669551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rela->setAddend(pReloc.symValue());
670551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
671551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
672551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
673551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
674551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LD64_GOT_LO12_NC: G(GDAT(S+A))
67537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result ld64_got_lo12(Relocation& pReloc, AArch64Relocator& pParent) {
676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) {
677551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
678551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
679551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
680551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
681551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_offset(GOT_S + A);
683551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
684551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3));
685551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
686551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup got entry value if needed
687551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
68837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (got_entry != NULL && AArch64Relocator::SymVal == got_entry->getValue())
689551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    got_entry->setValue(pReloc.symValue());
690551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
691551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup relocation addend if needed
692551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc);
69337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((dyn_rela != NULL) && (AArch64Relocator::SymVal == dyn_rela->addend())) {
694551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rela->setAddend(pReloc.symValue());
695551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
696551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
697551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
698551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
699551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
700551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST8_ABS_LO12_NC: S + A
701551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST16_ABS_LO12_NC: S + A
702551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST32_ABS_LO12_NC: S + A
703551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST64_ABS_LO12_NC: S + A
704551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST128_ABS_LO12_NC: S + A
70537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result ldst_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent) {
706551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
707551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
708551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_offset(S + A);
709551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
71037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
71137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::R_AARCH64_LDST8_ABS_LO12_NC:
71237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), X);
71337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
71437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::R_AARCH64_LDST16_ABS_LO12_NC:
71537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 1));
71637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::R_AARCH64_LDST32_ABS_LO12_NC:
71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 2));
71937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
72037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::R_AARCH64_LDST64_ABS_LO12_NC:
72137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3));
72237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
72337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::R_AARCH64_LDST128_ABS_LO12_NC:
72437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 4));
72537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
726551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
72737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
728551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
729551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
730551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
731551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
733