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
10551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LinkerConfig.h>
11551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/IRBuilder.h>
12551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/Support/MsgHandling.h>
13551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LD/LDSymbol.h>
14551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/LD/ELFFileFormat.h>
15551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <mcld/Object/ObjectBuilder.h>
16551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
17551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/ADT/Twine.h>
18551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/DataTypes.h>
19551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/ELF.h>
20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include <llvm/Support/Host.h>
21551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64Relocator.h"
23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64RelocationFunctions.h"
24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64RelocationHelpers.h"
25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
26551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesusing namespace 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 {
39551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinespublic:
40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ApplyFunctionEntry() {}
41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ApplyFunctionEntry(ApplyFunctionType pFunc,
42551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     const char* pName,
43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                     size_t pSize = 0)
44551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen 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[] = {
52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  DECL_AARCH64_APPLY_RELOC_FUNC_PTRS(ApplyFunctionMap::value_type,
53551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                     ApplyFunctionEntry)
54551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines};
55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// declare the table of applying functions
57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesstatic ApplyFunctionMap ApplyFunctions(ApplyFunctionList,
58551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    ApplyFunctionList + sizeof(ApplyFunctionList)/sizeof(ApplyFunctionList[0]));
59551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64Relocator
62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::AArch64Relocator(AArch64GNULDBackend& pParent,
64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                   const LinkerConfig& pConfig)
65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  : Relocator(pConfig),
66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    m_Target(pParent) {
67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
69551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::~AArch64Relocator()
70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
72551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result AArch64Relocator::applyRelocation(Relocation& pRelocation)
74551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
75551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation::Type type = pRelocation.type();
76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // valid types are 0x0, 0x100-0x239
77551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if ((type < 0x100 || type > 0x239) && (type != 0x0)) {
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
84551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesconst char* AArch64Relocator::getName(Relocator::Type pType) const
85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(ApplyFunctions.find(pType) != ApplyFunctions.end());
87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ApplyFunctions[pType].name;
88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
89551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Size AArch64Relocator::getSize(Relocation::Type pType) const
91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ApplyFunctions[pType].size;
93551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
95551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::addCopyReloc(ResolveInfo& pSym)
96551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
97551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation& rel_entry = *getTarget().getRelaDyn().create();
98551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  rel_entry.setType(R_AARCH64_COPY);
99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
101551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  rel_entry.setSymInfo(&pSym);
102551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// defineSymbolForCopyReloc
105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// section and all other reference to this symbol should refer to this
107551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// copy.
108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines/// This is executed at scan relocation stage.
109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesLDSymbol& AArch64Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                     const ResolveInfo& pSym)
111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // get or create corresponding BSS LDSection
113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection* bss_sect_hdr = NULL;
114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ELFFileFormat* file_format = getTarget().getOutputFormat();
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
118551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_sect_hdr = &file_format->getBSS();
119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // get or create corresponding BSS SectionData
121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData* bss_data = NULL;
122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (bss_sect_hdr->hasSectionData())
123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_data = bss_sect_hdr->getSectionData();
124551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
125551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
126551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Determine the alignment by the symbol value
128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // FIXME: here we use the largest alignment
129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
131551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // allocate space in BSS for the copy symbol
132551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
133551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_data, addralign);
134551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
135551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
136551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // change symbol binding to Global if it's a weak symbol
137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
138551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (binding == ResolveInfo::Weak)
139551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    binding = ResolveInfo::Global;
140551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
141551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Define the copy symbol in the bss section and resolve it
142551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
143551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          pSym.name(),
144551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          (ResolveInfo::Type)pSym.type(),
145551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          ResolveInfo::Define,
146551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          binding,
147551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          pSym.size(),  // size
148551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          0x0,          // value
149551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          FragmentRef::Create(*frag, 0x0),
150551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                          (ResolveInfo::Visibility)pSym.other());
151551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
152551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return *cpy_sym;
153551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
154551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
155551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid
156551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64Relocator::scanLocalReloc(Relocation& pReloc, const LDSection& pSection)
157551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
158551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym - The relocation target symbol
159551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
160551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  switch(pReloc.type()) {
161551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS64:
162551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If buiding PIC object (shared library or PIC executable),
163551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
164551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Reserve an entry in .rel.dyn
165551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep()) {
166551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set Rel bit
167551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
168551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
169551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set up the dyn rel directly
170551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        Relocation& reloc = helper_DynRela_init(rsym,
171551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                *pReloc.targetRef().frag(),
172551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                pReloc.targetRef().offset(),
173551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                R_AARCH64_RELATIVE,
174551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                *this);
175551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getRelRelMap().record(pReloc, reloc);
176551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
177551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
178551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
179551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS32:
180551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS16:
181551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If buiding PIC object (shared library or PIC executable),
182551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
183551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Reserve an entry in .rel.dyn
184551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep()) {
185551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set up the dyn rel directly
186551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        Relocation& reloc = helper_DynRela_init(rsym,
187551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                            *pReloc.targetRef().frag(),
188551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                            pReloc.targetRef().offset(), pReloc.type(), *this);
189551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getRelRelMap().record(pReloc, reloc);
190551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // set Rel bit
191551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
192551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
193551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
194551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
195551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
196551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_GOT_PAGE:
197551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: {
198551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
199551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create GOT for this symbol
200551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReserveGOT)
201551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
202551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // If building PIC object, a dynamic relocation with
203551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // type RELATIVE is needed to relocate this GOT entry.
204551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (config().isCodeIndep())
205551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines         helper_GOT_init(pReloc, true, *this);
206551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      else
207551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines         helper_GOT_init(pReloc, false, *this);
208551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set GOT bit
209551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
210551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
211551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
212551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
213551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
214551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      break;
215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
217551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
218551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanGlobalReloc(Relocation& pReloc,
219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       IRBuilder& pBuilder,
220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                       const LDSection& pSection)
221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
222551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym - The relocation target symbol
223551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
224551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  switch(pReloc.type()) {
225551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS64:
226551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS32:
227551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ABS16:
228551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
229551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation entry
230551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
231551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
232551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
233551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
234551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
235551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
236551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
237551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
238551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
239551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
240551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
241551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
242551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
243551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                                        true)) {
244551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // symbol needs dynamic relocation entry, set up the dynrel entry
245551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
246551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
247551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
248551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
249551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        else {
250551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set Rel bit and the dyn rel
251551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
252551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
253551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() &&
254551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines              helper_use_relative_reloc(*rsym, *this)) {
255551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            Relocation& reloc = helper_DynRela_init(rsym,
256551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *pReloc.targetRef().frag(),
257551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    pReloc.targetRef().offset(),
258551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    R_AARCH64_RELATIVE,
259551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *this);
260551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            getRelRelMap().record(pReloc, reloc);
261551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          }
262551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          else {
263551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            Relocation& reloc = helper_DynRela_init(rsym,
264551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *pReloc.targetRef().frag(),
265551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    pReloc.targetRef().offset(),
266551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    pReloc.type(),
267551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                    *this);
268551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines            getRelRelMap().record(pReloc, reloc);
269551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          }
270551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
271551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
272551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
273551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
274551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL64:
275551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL32:
276551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_PREL16:
277551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
278551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
279551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
280551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
281551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
282551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
283551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
284551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
285551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
286551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
287551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
288551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
289551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
290551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Only PC relative relocation against dynamic symbol needs a
291551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation.  Only dynamic copy relocation is allowed
292551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // and PC relative relocation will be resolved to the local copy.
293551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // All other dynamic relocations may lead to run-time relocation
294551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // overflow.
295551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().isDynamicSymbol(*rsym) &&
296551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().symbolNeedsDynRel(*rsym,
297551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                        (rsym->reserved() & ReservePLT),
298551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                        false) &&
299551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
300551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
301551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        addCopyReloc(*cpy_sym.resolveInfo());
302551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
303551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
304551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
305551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_CONDBR19:
306551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_JUMP26:
307551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_CALL26: {
308551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create plt for this symbol
309551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReservePLT)
310551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
311551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
312551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
313551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
314551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
315551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
316551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if symbol is defined in the ouput file and it's not
317551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // preemptible, no need plt
318551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
319551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines         !getTarget().isSymbolPreemptible(*rsym)) {
320551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
321551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
322551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
323551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs PLT entry, we need to reserve a PLT entry
324551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // and the corresponding GOT and dynamic relocation entry
325551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // in .got and .rel.plt.
326551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      helper_PLT_init(pReloc, *this);
327551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set PLT bit
328551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
329551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
330551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
331551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
332551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_PREL_PG_HI21:
333551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case R_AARCH64_ADR_PREL_PG_HI21_NC:
334551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym,
335551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                        (rsym->reserved() & ReservePLT),
336551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                        false)) {
337551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
338551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
339551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo());
340551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
341551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
342551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
343551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        // create plt for this symbol if it does not have one
344551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
345551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // Symbol needs PLT entry, we need a PLT entry
346551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // and the corresponding GOT and dynamic relocation entry
347551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // in .got and .rel.plt.
348551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          helper_PLT_init(pReloc, *this);
349551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          // set PLT bit
350551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
351551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        }
352551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
353551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
354551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
355551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_ADR_GOT_PAGE:
356551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    case llvm::ELF::R_AARCH64_LD64_GOT_LO12_NC: {
357551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
358551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // return if we already create GOT for this symbol
359551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & ReserveGOT)
360551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return;
361551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // if the symbol cannot be fully resolved at link time, then we need a
362551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // dynamic relocation
363551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (!getTarget().symbolFinalValueIsKnown(*rsym))
364551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        helper_GOT_init(pReloc, true, *this);
365551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      else
366551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        helper_GOT_init(pReloc, false, *this);
367551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      // set GOT bit
368551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
369551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return;
370551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
371551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
372551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
373551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      break;
374551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
375551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
376551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
377551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid AArch64Relocator::scanRelocation(Relocation& pReloc,
378551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      IRBuilder& pBuilder,
379551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      Module& pModule,
380551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      LDSection& pSection,
381551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                      Input& pInput)
382551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
383551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
384551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(NULL != rsym &&
385551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
386551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
387551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(NULL != pSection.getLink());
388551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
389551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return;
390551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
391551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
392551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // entries should be created.
393551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // FIXME: Below judgements concern nothing about TLS related relocation
394551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
395551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym is local
396551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isLocal())
397551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    scanLocalReloc(pReloc, pSection);
398551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // rsym is external
399551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
400551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    scanGlobalReloc(pReloc, pBuilder, pSection);
401551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
402551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // check if we shoule issue undefined reference for the relocation target
403551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // symbol
404551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
405551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    issueUndefRef(pReloc, pSection, pInput);
406551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
407551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
408551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
409551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// Each relocation function implementation
410551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
411551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
412551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_NONE
413551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result none(Relocation& pReloc, AArch64Relocator& pParent)
414551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
415551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
416551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
417551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
418551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result unsupport(Relocation& pReloc, AArch64Relocator& pParent)
419551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
420551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::Unsupport;
421551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
422551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
423551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS64: S + A
424551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS32: S + A
425551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ABS16: S + A
426551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result abs(Relocation& pReloc, AArch64Relocator& pParent)
427551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
428551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
429551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
430551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord S = pReloc.symValue();
431551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
432551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  bool has_dyn_rel = (NULL != dyn_rel);
433551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
434551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
435551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this
436551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
437551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
438551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = S + A;
439551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
440551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
441551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // A local symbol may need RELATIVE Type dynamic relocation
442551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->isLocal() && has_dyn_rel) {
443551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rel->setAddend(S + A);
444551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
445551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
446551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // An external symbol may need PLT and dynamic relocation
447551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!rsym->isLocal()) {
448551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (rsym->reserved() & AArch64Relocator::ReservePLT) {
449551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      S = helper_get_PLT_address(*rsym, pParent);
450551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
451551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // If we generate a dynamic relocation (except R_AARCH64_64_RELATIVE)
452551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // for a place, we should not perform static relocation on it
453551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // in order to keep the addend store in the place correct.
454551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (has_dyn_rel) {
455551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() &&
456551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          R_AARCH64_RELATIVE == dyn_rel->type()) {
457551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        dyn_rel->setAddend(S + A);
458551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
459551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      else {
460551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        dyn_rel->setAddend(A);
461551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
462551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
463551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
464551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
465551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
466551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // perform static relocation
467551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = S + A;
468551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
469551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
470551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
471551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL64: S + A - P
472551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL32: S + A - P
473551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_PREL16: S + A - P
474551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result rel(Relocation& pReloc, AArch64Relocator& pParent)
475551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
476551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
477551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
478551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.addend();
479551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   P = pReloc.place();
480551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
481551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type())
482551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    A +=  pReloc.target() & get_mask(pParent.getSize(pReloc.type()));
483551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
484551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    A += pReloc.target();
485551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
486551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
487551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this
488551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
489551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
490551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // if plt entry exists, the S value is the plt entry address
491551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    if (!rsym->isLocal()) {
492551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      if (rsym->reserved() & AArch64Relocator::ReservePLT) {
493551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        S = helper_get_PLT_address(*rsym, pParent);
494551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      }
495551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
496551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
497551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
498551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
499551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = X;
500551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
501551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (llvm::ELF::R_AARCH64_PREL64 != pReloc.type() &&
502551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      helper_check_signed_overflow(X, pParent.getSize(pReloc.type())))
503551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
504551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
505551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
506551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
507551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADD_ABS_LO12_NC: S + A
508551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result add_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent)
509551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
510551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address value = 0x0;
511551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
512551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.addend();
513551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
514551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  value = helper_get_page_offset(S + A);
515551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_add_imm(pReloc.target(), value);
516551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
517551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
518551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
519551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
520551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21: ((PG(S + A) - PG(P)) >> 12)
521551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_PREL_PG_HI21_NC: ((PG(S + A) - PG(P)) >> 12)
522551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result
523551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesadr_prel_pg_hi21(Relocation& pReloc, AArch64Relocator& pParent)
524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
525551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
526551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
527551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // if plt entry exists, the S value is the plt entry address
528551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (rsym->reserved() & AArch64Relocator::ReservePLT) {
529551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*rsym, pParent);
530551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
531551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
532551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord P = pReloc.place() ;
533551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_address(S + A) -
534551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                       helper_get_page_address(P);
535551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
536551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12));
537551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
538551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
539551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
540551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
541551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CALL26: S + A - P
542551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_JUMP26: S + A - P
543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result call(Relocation& pReloc, AArch64Relocator& pParent)
544551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
545551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If target is undefined weak symbol, we only need to jump to the
546551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // next instruction unless it has PLT entry. Rewrite instruction
547551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // to NOP.
548551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->isWeak() &&
549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      pReloc.symInfo()->isUndef() &&
550551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !pReloc.symInfo()->isDyn() &&
551551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) {
552551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // change target to NOP
553551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = 0xd503201f;
554551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
555551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
556551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
557551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
558551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.addend();
559551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
560551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
561551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // S depends on PLT exists or not
562551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)
563551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
564551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
565551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
566551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // TODO: check overflow..
567551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
568551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_branch_offset_26(pReloc.target(), X >> 2);
569551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
570551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
571551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
572551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_CONDBR19: S + A - P
574551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result condbr(Relocation& pReloc, AArch64Relocator& pParent)
575551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
576551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // If target is undefined weak symbol, we only need to jump to the
577551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // next instruction unless it has PLT entry. Rewrite instruction
578551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // to NOP.
579551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->isWeak() &&
580551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      pReloc.symInfo()->isUndef() &&
581551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !pReloc.symInfo()->isDyn() &&
582551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      !(pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)) {
583551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // change target to NOP
584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    pReloc.target() = 0xd503201f;
585551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
586551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
587551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
588551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
589551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord   A = pReloc.addend();
590551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
591551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
592551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // S depends on PLT exists or not
593551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pReloc.symInfo()->reserved() & AArch64Relocator::ReservePLT)
594551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
595551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
596551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = S + A - P;
597551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // TODO: check overflow..
598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
599551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_cond_branch_ofs_19(pReloc.target(), X >> 2);
600551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
601551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
602551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
604551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_ADR_GOT_PAGE: Page(G(GDAT(S+A))) - Page(P)
605551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result adr_got_page(Relocation& pReloc, AArch64Relocator& pParent)
606551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
607551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) {
608551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
610551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
611551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
612551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
613551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
614551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_address(GOT_S + A) -
615551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                       helper_get_page_address(P);
616551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
617551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_adr_imm(pReloc.target(), (X >> 12));
618551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
619551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup got entry value if needed
620551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
621551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue())
622551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    got_entry->setValue(pReloc.symValue());
623551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup relocation addend if needed
624551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc);
625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) {
626551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rela->setAddend(pReloc.symValue());
627551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
629551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
630551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
631551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LD64_GOT_LO12_NC: G(GDAT(S+A))
632551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result ld64_got_lo12(Relocation& pReloc, AArch64Relocator& pParent)
633551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!(pReloc.symInfo()->reserved() & AArch64Relocator::ReserveGOT)) {
635551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
636551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
637551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
638551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(*pReloc.symInfo(), pParent);
639551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_offset(GOT_S + A);
641551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), (X >> 3));
643551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
644551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup got entry value if needed
645551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
646551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (NULL != got_entry && AArch64Relocator::SymVal == got_entry->getValue())
647551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    got_entry->setValue(pReloc.symValue());
648551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
649551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup relocation addend if needed
650551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* dyn_rela = pParent.getRelRelMap().lookUp(pReloc);
651551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if ((NULL != dyn_rela) && (AArch64Relocator::SymVal == dyn_rela->addend())) {
652551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    dyn_rela->setAddend(pReloc.symValue());
653551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
654551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
655551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
656551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
657551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
658551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST8_ABS_LO12_NC: S + A
659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST16_ABS_LO12_NC: S + A
660551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST32_ABS_LO12_NC: S + A
661551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST64_ABS_LO12_NC: S + A
662551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// R_AARCH64_LDST128_ABS_LO12_NC: S + A
663551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesRelocator::Result ldst_abs_lo12(Relocation& pReloc, AArch64Relocator& pParent)
664551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
665551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
666551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord A = pReloc.addend();
667551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::DWord X = helper_get_page_offset(S + A);
668551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
669551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  switch(pReloc.type()) {
670551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines     case llvm::ELF::R_AARCH64_LDST8_ABS_LO12_NC:
671551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(), X);
672551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
673551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines     case llvm::ELF::R_AARCH64_LDST16_ABS_LO12_NC:
674551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(),
675551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                      (X >> 1));
676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
677551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines     case llvm::ELF::R_AARCH64_LDST32_ABS_LO12_NC:
678551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(),
679551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                      (X >> 2));
680551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
681551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines     case llvm::ELF::R_AARCH64_LDST64_ABS_LO12_NC:
682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(),
683551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                      (X >> 3));
684551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
685551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines     case llvm::ELF::R_AARCH64_LDST128_ABS_LO12_NC:
686551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       pReloc.target() = helper_reencode_ldst_pos_imm(pReloc.target(),
687551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                      (X >> 4));
688551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
689551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    default:
690551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines       break;
691551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
692551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
693551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
694551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
695