summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86GOT.cpp
blob: 278498935fe6a11f579463aeb891eb5114bca833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//===- impl.cpp -----------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "X86GOT.h"
#include <mcld/LD/LDFileFormat.h>
#include <llvm/Support/ErrorHandling.h>
#include <new>

namespace {
  const size_t X86GOTEntrySize = 4;
}

using namespace mcld;

//===----------------------------------------------------------------------===//
// X86GOT
X86GOT::X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
             : GOT(pSection, pSectionData, X86GOTEntrySize),
               m_GeneralGOTNum(0), m_GOTPLTNum(0), m_GeneralGOTIterator(),
               m_GOTPLTIterator(), m_LastGOT0()
{
  GOTEntry* Entry = 0;

  // Create GOT0 entries.
  for (unsigned int i = 0; i < X86GOT0Num; i++) {
    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
                                        &m_SectionData);

    if (!Entry)
      llvm::report_fatal_error("Allocating GOT0 entries failed!");

    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
  }

  // Skip GOT0 entries.
  iterator it = m_SectionData.begin();
  iterator ie = m_SectionData.end();

  for (unsigned int i = 1; i < X86GOT0Num; ++i) {
    if (it == ie)
      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");

    ++it;
  }

  m_LastGOT0 = it;
  m_GeneralGOTIterator = it;
  m_GOTPLTIterator = it;
}

X86GOT::~X86GOT()
{
}

void X86GOT::reserveEntry(size_t pNum)
{
  GOTEntry* Entry = 0;

  for (size_t i = 0; i < pNum; i++) {
    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
                                        &m_SectionData);

    if (!Entry)
      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");

    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
    ++m_GeneralGOTNum;
  }
}


GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
{
  GOTEntry *&Entry = m_GeneralGOTMap[&pInfo];
  pExist = 1;

  if (!Entry) {
    pExist = 0;

    ++m_GeneralGOTIterator;
    assert(m_GeneralGOTIterator != m_SectionData.getFragmentList().end()
           && "The number of GOT Entries and ResolveInfo doesn't match!");

    Entry = llvm::cast<GOTEntry>(&(*m_GeneralGOTIterator));
  }

  return Entry;
}

void X86GOT::applyGOT0(uint64_t pAddress)
{
  llvm::cast<GOTEntry>
    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
}

X86GOT::iterator X86GOT::begin()
{
  return m_SectionData.getFragmentList().begin();
}

X86GOT::const_iterator X86GOT::begin() const
{
  return m_SectionData.getFragmentList().begin();
}

X86GOT::iterator X86GOT::end()
{
  return m_SectionData.getFragmentList().end();
}

X86GOT::const_iterator X86GOT::end() const
{
  return m_SectionData.getFragmentList().end();
}

unsigned int X86GOT::getGOTPLTNum() const
{ return m_GOTPLTNum; }

X86GOT::iterator X86GOT::getLastGOT0()
{ return m_LastGOT0; }

const X86GOT::iterator X86GOT::getLastGOT0() const
{ return m_LastGOT0; }