MipsGOTPLT.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
1//===- MipsGOTPLT.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 "MipsGOTPLT.h"
10
11#include <llvm/Support/Casting.h>
12
13namespace {
14typedef mcld::GOT::Entry<4> GOTPLTEntry;
15
16const size_t MipsGOTPLT0Num = 2;
17}
18
19namespace mcld {
20
21//===----------------------------------------------------------------------===//
22// MipsGOTPLT
23//===----------------------------------------------------------------------===//
24MipsGOTPLT::MipsGOTPLT(LDSection& pSection) : GOT(pSection) {
25  // Create header's entries.
26  new GOTPLTEntry(0, m_SectionData);
27  new GOTPLTEntry(0, m_SectionData);
28  m_Last = ++m_SectionData->begin();
29}
30
31void MipsGOTPLT::reserve(size_t pNum) {
32  for (size_t i = 0; i < pNum; ++i)
33    new GOTPLTEntry(0, m_SectionData);
34}
35
36uint64_t MipsGOTPLT::emit(MemoryRegion& pRegion) {
37  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
38
39  uint64_t result = 0;
40  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
41    GOTPLTEntry* got = &(llvm::cast<GOTPLTEntry>((*it)));
42    *buffer = static_cast<uint32_t>(got->getValue());
43    result += got->size();
44  }
45  return result;
46}
47
48Fragment* MipsGOTPLT::consume() {
49  ++m_Last;
50  assert(m_Last != m_SectionData->end() &&
51         "There is no reserved GOTPLT entries");
52  return &(*m_Last);
53}
54
55bool MipsGOTPLT::hasGOT1() const {
56  return m_SectionData->size() > MipsGOTPLT0Num;
57}
58
59uint64_t MipsGOTPLT::getEntryAddr(size_t num) const {
60  return addr() + (MipsGOTPLT0Num + num) * GOTPLTEntry::EntrySize;
61}
62
63void MipsGOTPLT::applyAllGOTPLT(uint64_t pltAddr) {
64  iterator it = begin();
65  llvm::cast<GOTPLTEntry>(*it++).setValue(0);  // PLT lazy resolver
66  llvm::cast<GOTPLTEntry>(*it++).setValue(0);  // Module pointer
67
68  for (; it != end(); ++it)
69    llvm::cast<GOTPLTEntry>(*it).setValue(pltAddr);
70}
71
72}  // namespace mcld
73