C++程序  |  80行  |  2.02 KB

//===- MipsGOTPLT.cpp -----------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <llvm/Support/Casting.h>
#include "MipsGOTPLT.h"

namespace {
  typedef mcld::GOT::Entry<4> GOTPLTEntry;

  const size_t MipsGOTPLT0Num = 2;
}

namespace mcld {

//===----------------------------------------------------------------------===//
// MipsGOTPLT
//===----------------------------------------------------------------------===//
MipsGOTPLT::MipsGOTPLT(LDSection& pSection)
  : GOT(pSection)
{
  // Create header's entries.
  new GOTPLTEntry(0, m_SectionData);
  new GOTPLTEntry(0, m_SectionData);
  m_Last = ++m_SectionData->begin();
}

void MipsGOTPLT::reserve(size_t pNum)
{
  for (size_t i = 0; i < pNum; i++)
    new GOTPLTEntry(0, m_SectionData);
}

uint64_t MipsGOTPLT::emit(MemoryRegion& pRegion)
{
  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());

  uint64_t result = 0;
  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
    GOTPLTEntry* got = &(llvm::cast<GOTPLTEntry>((*it)));
    *buffer = static_cast<uint32_t>(got->getValue());
    result += got->size();
  }
  return result;
}

Fragment* MipsGOTPLT::consume()
{
  ++m_Last;
  assert(m_Last != m_SectionData->end() &&
         "There is no reserved GOTPLT entries");
  return &(*m_Last);
}

bool MipsGOTPLT::hasGOT1() const
{
  return m_SectionData->size() > MipsGOTPLT0Num;
}

uint64_t MipsGOTPLT::getEntryAddr(size_t num) const
{
  return addr() + (MipsGOTPLT0Num + num) * GOTPLTEntry::EntrySize;
}

void MipsGOTPLT::applyAllGOTPLT(uint64_t pltAddr)
{
  iterator it = begin();
  llvm::cast<GOTPLTEntry>(*it++).setValue(0); // PLT lazy resolver
  llvm::cast<GOTPLTEntry>(*it++).setValue(0); // Module pointer

  for (; it != end(); ++it)
    llvm::cast<GOTPLTEntry>(*it).setValue(pltAddr);
}

} //end mcld namespace