//===- X86GOTPLT.cpp ------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "X86GOTPLT.h"
#include <new>
#include <llvm/Support/Casting.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MsgHandling.h>
namespace {
const uint64_t X86GOTPLTEntrySize = 4;
}
namespace mcld {
//===----------------------------------------------------------------------===//
// X86GOTPLT
//===----------------------------------------------------------------------===//
X86GOTPLT::X86GOTPLT(LDSection& pSection, SectionData& pSectionData)
: GOT(pSection, pSectionData, X86GOTPLTEntrySize), m_GOTPLTIterator()
{
GOTEntry* Entry = 0;
// Create GOT0 entries.
for (size_t i = 0; i < X86GOTPLT0Num; i++) {
Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
&m_SectionData);
if (!Entry)
fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
}
// Skip GOT0 entries.
iterator it = m_SectionData.begin();
for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
assert((it != m_SectionData.end()) &&
"Generation of GOT0 entries is incomplete!");
++it;
}
m_GOTPLTIterator = it;
}
X86GOTPLT::~X86GOTPLT()
{
}
X86GOTPLT::iterator X86GOTPLT::begin()
{
return m_SectionData.begin();
}
X86GOTPLT::const_iterator X86GOTPLT::begin() const
{
return m_SectionData.begin();
}
X86GOTPLT::iterator X86GOTPLT::end()
{
return m_SectionData.end();
}
X86GOTPLT::const_iterator X86GOTPLT::end() const
{
return m_SectionData.end();
}
void X86GOTPLT::applyGOT0(uint64_t pAddress)
{
llvm::cast<GOTEntry>
(*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
}
void X86GOTPLT::reserveEntry(size_t pNum)
{
GOTEntry* got_entry = NULL;
for (size_t i = 0; i < pNum; ++i) {
got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
if (!got_entry)
fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + getEntrySize());
}
}
void X86GOTPLT::applyAllGOTPLT(uint64_t pPLTBase,
unsigned int pPLT0Size,
unsigned int pPLT1Size)
{
iterator it = begin();
// skip GOT0
for (size_t i = 0; i < X86GOTPLT0Num; ++i)
++it;
// address of corresponding plt entry
uint64_t plt_addr = pPLTBase + pPLT0Size;
for (; it != end() ; ++it) {
llvm::cast<GOTEntry>(*it).setContent(plt_addr + 6);
plt_addr += pPLT1Size;
}
}
GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
{
return m_GOTPLTMap[&pSymbol];
}
GOTEntry* X86GOTPLT::getEntry(const ResolveInfo& pInfo, bool& pExist)
{
GOTEntry *&Entry = m_GOTPLTMap[&pInfo];
pExist = 1;
if (!Entry) {
pExist = 0;
++m_GOTPLTIterator;
assert(m_GOTPLTIterator != m_SectionData.getFragmentList().end()
&& "The number of GOT Entries and ResolveInfo doesn't match!");
Entry = llvm::cast<GOTEntry>(&(*m_GOTPLTIterator));
}
return Entry;
}
} //end mcld namespace