AArch64GOT.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- AArch64GOT.cpp -----------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "AArch64GOT.h"
10
11#include <llvm/Support/Casting.h>
12
13#include <mcld/LD/LDSection.h>
14#include <mcld/LD/LDFileFormat.h>
15#include <mcld/Support/MsgHandling.h>
16
17namespace {
18  const unsigned int AArch64GOT0Num = 3;
19} // end of anonymous namespace
20
21using namespace mcld;
22
23//===----------------------------------------------------------------------===//
24// AArch64GOT
25AArch64GOT::AArch64GOT(LDSection& pSection)
26  : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL)
27{
28}
29
30AArch64GOT::~AArch64GOT()
31{
32}
33
34void AArch64GOT::createGOT0()
35{
36  // create GOT0, and put them into m_SectionData immediately
37  for (unsigned int i = 0; i < AArch64GOT0Num; ++i)
38    new AArch64GOTEntry(0, m_SectionData);
39}
40
41bool AArch64GOT::hasGOT1() const
42{
43  return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
44}
45
46AArch64GOTEntry* AArch64GOT::createGOT()
47{
48  AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
49  m_GOT.push_back(entry);
50  return entry;
51}
52
53AArch64GOTEntry* AArch64GOT::createGOTPLT()
54{
55  AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
56  m_GOTPLT.push_back(entry);
57  return entry;
58}
59
60void AArch64GOT::finalizeSectionSize()
61{
62  uint32_t offset = 0;
63  SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList();
64  // setup GOT0 offset
65  SectionData::iterator frag, fragEnd = m_SectionData->end();
66  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
67    frag->setOffset(offset);
68    offset += frag->size();
69  }
70
71  // push GOTPLT into the SectionData and setup the offset
72  if (!m_GOTPLT.empty()) {
73    m_pGOTPLTFront = m_GOTPLT.front();
74    entry_iterator it, end = m_GOTPLT.end();
75    for (it = m_GOTPLT.begin(); it != end; ++it) {
76      AArch64GOTEntry* entry = *it;
77      frag_list.push_back(entry);
78      entry->setParent(m_SectionData);
79      entry->setOffset(offset);
80      offset += entry->size();
81
82    }
83  }
84  m_GOTPLT.clear();
85
86  // push GOT into the SectionData and setup the offset
87  if (!m_GOT.empty()) {
88    m_pGOTFront = m_GOT.front();
89    entry_iterator it, end = m_GOT.end();
90    for (it = m_GOT.begin(); it != end; ++it) {
91      AArch64GOTEntry* entry = *it;
92      frag_list.push_back(entry);
93      entry->setParent(m_SectionData);
94      entry->setOffset(offset);
95      offset += entry->size();
96    }
97  }
98  m_GOT.clear();
99
100  // set section size
101  m_Section.setSize(offset);
102}
103
104void AArch64GOT::applyGOT0(uint64_t pAddress)
105{
106  llvm::cast<AArch64GOTEntry>
107    (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
108}
109
110void AArch64GOT::applyGOTPLT(uint64_t pPLTBase)
111{
112  if (NULL == m_pGOTPLTFront)
113    return;
114
115  SectionData::iterator entry(m_pGOTPLTFront);
116  SectionData::iterator e_end;
117  if (NULL == m_pGOTFront)
118    e_end = m_SectionData->end();
119  else
120    e_end = SectionData::iterator(m_pGOTFront);
121
122  while (entry != e_end) {
123    llvm::cast<AArch64GOTEntry>(entry)->setValue(pPLTBase);
124    ++entry;
125  }
126}
127
128uint64_t AArch64GOT::emit(MemoryRegion& pRegion)
129{
130  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
131
132  AArch64GOTEntry* got = NULL;
133  uint64_t result = 0x0;
134  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
135      got = &(llvm::cast<AArch64GOTEntry>((*it)));
136      *buffer = static_cast<uint64_t>(got->getValue());
137      result += AArch64GOTEntry::EntrySize;
138  }
139  return result;
140}
141
142