blob: c5bb9a8d1d53c97c12da84d0328bb446e3eb7675 [file] [log] [blame]
//===- OutputRelocSection.cpp ---------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/Target/OutputRelocSection.h>
#include <llvm/Support/Casting.h>
#include <mcld/LD/LDSection.h>
#include <mcld/Support/MsgHandling.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// OutputRelocSection
//===----------------------------------------------------------------------===//
OutputRelocSection::OutputRelocSection(LDSection& pSection,
SectionData& pSectionData,
unsigned int pEntrySize)
: m_pSection(&pSection),
m_pSectionData(&pSectionData),
m_EntryBytes(pEntrySize),
m_isVisit(false),
m_ValidEntryIterator(){
}
OutputRelocSection::~OutputRelocSection()
{
}
void OutputRelocSection::reserveEntry(RelocationFactory& pRelFactory,
size_t pNum)
{
for(size_t i=0; i<pNum; i++) {
m_pSectionData->getFragmentList().push_back(pRelFactory.produceEmptyEntry());
// update section size
m_pSection->setSize(m_pSection->size() + m_EntryBytes);
}
}
Relocation* OutputRelocSection::getEntry(const ResolveInfo& pSymbol,
bool isForGOT,
bool& pExist)
{
// first time visit this function, set m_ValidEntryIterator to
// Fragments.begin()
if(!m_isVisit) {
assert( !m_pSectionData->getFragmentList().empty() &&
"DynRelSection contains no entries.");
m_ValidEntryIterator = m_pSectionData->getFragmentList().begin();
m_isVisit = true;
}
assert(m_ValidEntryIterator != m_pSectionData->end() &&
"No empty relocation entry for the incoming symbol.");
// if this relocation is used to relocate GOT (.got or .got.plt),
// check if we've gotten an entry for this symbol before. If yes,
// return the found entry in map.
// Otherwise, this relocation is used to relocate general section
// (data or text section), return an empty entry directly.
Relocation* result;
if(isForGOT) {
// get or create entry in m_SymRelMap
Relocation *&entry = m_SymRelMap[&pSymbol];
pExist = true;
if(NULL == entry) {
pExist = false;
entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
++m_ValidEntryIterator;
}
result = entry;
}
else {
pExist = false;
result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
++m_ValidEntryIterator;
}
return result;
}