ARMGOT.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
1//===- impl.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 "ARMGOT.h"
10
11#include <new>
12
13#include <llvm/Support/Casting.h>
14
15#include <mcld/LD/LDSection.h>
16#include <mcld/LD/LDFileFormat.h>
17#include <mcld/Support/MemoryRegion.h>
18#include <mcld/Support/MsgHandling.h>
19
20namespace {
21  const size_t ARMGOTEntrySize = 4;
22  const unsigned int ARMGOT0Num = 3;
23} // end of anonymous namespace
24
25using namespace mcld;
26
27//===----------------------------------------------------------------------===//
28// ARMGOT
29ARMGOT::ARMGOT(LDSection& pSection)
30  : GOT(pSection, ARMGOTEntrySize)
31{
32  // Create GOT0 entries.
33  reserve(ARMGOT0Num);
34
35  // Skip GOT0 entries.
36  for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
37    consume();
38  }
39}
40
41ARMGOT::~ARMGOT()
42{
43}
44
45bool ARMGOT::hasGOT1() const
46{
47  return (m_SectionData->size() > ARMGOT0Num);
48}
49
50void ARMGOT::reserveGOTPLT()
51{
52  Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
53  if (NULL == m_GOTPLT.front) {
54    // GOTPLT is empty
55    if (NULL == m_GOT.front) {
56      // GOT part is also empty. Since entry is the last entry, we can assign
57      // it to GOTPLT directly.
58      m_GOTPLT.front = entry;
59    }
60    else {
61      // GOTn is not empty. Shift GOTn backward by one entry.
62      m_GOTPLT.front = m_GOT.front;
63      m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
64    }
65  }
66  else {
67    // GOTPLT is not empty
68    if (NULL != m_GOT.front)
69      m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
70  }
71}
72
73void ARMGOT::reserveGOT()
74{
75  Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
76  if (NULL == m_GOT.front) {
77    // Entry must be the last entry. We can directly assign it to GOT part.
78    m_GOT.front = entry;
79  }
80}
81
82GOT::Entry* ARMGOT::consumeGOTPLT()
83{
84  assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
85
86  if (NULL == m_GOTPLT.last_used) {
87    m_GOTPLT.last_used = m_GOTPLT.front;
88  }
89  else {
90    m_GOTPLT.last_used = llvm::cast<GOT::Entry>(m_GOTPLT.last_used->getNextNode());
91    assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
92  }
93  return m_GOTPLT.last_used;
94}
95
96GOT::Entry* ARMGOT::consumeGOT()
97{
98  assert(NULL != m_GOT.front && "Consuming empty GOT section!");
99
100  if (NULL == m_GOT.last_used) {
101    m_GOT.last_used = m_GOT.front;
102  }
103  else {
104    m_GOT.last_used = llvm::cast<GOT::Entry>(m_GOT.last_used->getNextNode());
105    assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
106  }
107  return m_GOT.last_used;
108}
109
110void ARMGOT::applyGOT0(uint64_t pAddress)
111{
112  llvm::cast<Entry>
113    (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
114}
115
116void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
117{
118  if (NULL == m_GOTPLT.front)
119    return;
120
121  SectionData::iterator entry(m_GOTPLT.front);
122  SectionData::iterator e_end;
123  if (NULL == m_GOT.front)
124    e_end = m_SectionData->end();
125  else
126    e_end = SectionData::iterator(m_GOT.front);
127
128  while (entry != e_end) {
129    llvm::cast<GOT::Entry>(entry)->setContent(pPLTBase);
130    ++entry;
131  }
132}
133
134uint64_t ARMGOT::emit(MemoryRegion& pRegion)
135{
136  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
137
138  Entry* got = 0;
139  unsigned int entry_size = getEntrySize();
140  uint64_t result = 0x0;
141  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
142      got = &(llvm::cast<Entry>((*it)));
143      *buffer = static_cast<uint32_t>(got->getContent());
144      result += entry_size;
145  }
146  return result;
147}
148
149