You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.5 KiB
157 lines
4.5 KiB
//===- BranchIsland.cpp ---------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "mcld/LD/BranchIsland.h"
|
|
|
|
#include "mcld/Fragment/AlignFragment.h"
|
|
#include "mcld/Fragment/Stub.h"
|
|
#include "mcld/LD/LDSection.h"
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
|
|
#include <sstream>
|
|
|
|
namespace mcld {
|
|
|
|
//============================================================================//
|
|
// BranchIsland
|
|
//============================================================================//
|
|
BranchIsland::BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex)
|
|
: m_Entry(pEntryFrag),
|
|
m_pExit(pEntryFrag.getNextNode()),
|
|
m_pRear(NULL),
|
|
m_MaxSize(pMaxSize),
|
|
m_Name("island-") {
|
|
// island name
|
|
std::ostringstream index;
|
|
index << pIndex;
|
|
m_Name.append(index.str());
|
|
}
|
|
|
|
BranchIsland::~BranchIsland() {
|
|
}
|
|
|
|
/// fragment iterators of the island
|
|
SectionData::iterator BranchIsland::begin() {
|
|
return ++iterator(&m_Entry);
|
|
}
|
|
|
|
SectionData::const_iterator BranchIsland::begin() const {
|
|
return ++iterator(&m_Entry);
|
|
}
|
|
|
|
SectionData::iterator BranchIsland::end() {
|
|
if (m_pExit != NULL)
|
|
return iterator(m_pExit);
|
|
return m_Entry.getParent()->end();
|
|
}
|
|
|
|
SectionData::const_iterator BranchIsland::end() const {
|
|
if (m_pExit != NULL)
|
|
return iterator(m_pExit);
|
|
return m_Entry.getParent()->end();
|
|
}
|
|
|
|
uint64_t BranchIsland::offset() const {
|
|
return m_Entry.getOffset() + m_Entry.size();
|
|
}
|
|
|
|
size_t BranchIsland::size() const {
|
|
size_t size = 0x0;
|
|
if (numOfStubs() != 0x0) {
|
|
size = m_pRear->getOffset() + m_pRear->size() -
|
|
m_Entry.getNextNode()->getOffset();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
size_t BranchIsland::maxSize() const {
|
|
return m_MaxSize;
|
|
}
|
|
|
|
const std::string& BranchIsland::name() const {
|
|
return m_Name;
|
|
}
|
|
|
|
size_t BranchIsland::numOfStubs() const {
|
|
return m_StubMap.numOfEntries();
|
|
}
|
|
|
|
/// findStub - return true if there is a stub built from the given prototype
|
|
/// for the given relocation
|
|
Stub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc) {
|
|
Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
|
|
StubMapType::iterator it = m_StubMap.find(key);
|
|
if (it != m_StubMap.end()) {
|
|
assert(it.getEntry()->value() != NULL);
|
|
return it.getEntry()->value();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/// addStub - add a stub into the island
|
|
bool BranchIsland::addStub(const Stub* pPrototype,
|
|
const Relocation& pReloc,
|
|
Stub& pStub) {
|
|
bool exist = false;
|
|
Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
|
|
StubEntryType* entry = m_StubMap.insert(key, exist);
|
|
if (!exist) {
|
|
entry->setValue(&pStub);
|
|
m_pRear = &pStub;
|
|
SectionData* sd = m_Entry.getParent();
|
|
|
|
// insert alignment fragment
|
|
// TODO: check if we can reduce this alignment fragment for some cases
|
|
AlignFragment* align_frag =
|
|
new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1);
|
|
align_frag->setParent(sd);
|
|
sd->getFragmentList().insert(end(), align_frag);
|
|
align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
|
|
align_frag->getPrevNode()->size());
|
|
|
|
// insert stub fragment
|
|
pStub.setParent(sd);
|
|
sd->getFragmentList().insert(end(), &pStub);
|
|
pStub.setOffset(pStub.getPrevNode()->getOffset() +
|
|
pStub.getPrevNode()->size());
|
|
}
|
|
return !exist;
|
|
}
|
|
|
|
void BranchIsland::addStub(Stub& pStub) {
|
|
bool exist = false;
|
|
Key key(&pStub, pStub.symInfo()->outSymbol(), 0);
|
|
m_StubMap.insert(key, exist);
|
|
|
|
m_pRear = &pStub;
|
|
SectionData* sd = m_Entry.getParent();
|
|
|
|
// insert alignment fragment
|
|
// TODO: check if we can reduce this alignment fragment for some cases
|
|
AlignFragment* align_frag =
|
|
new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1);
|
|
align_frag->setParent(sd);
|
|
sd->getFragmentList().insert(end(), align_frag);
|
|
align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
|
|
align_frag->getPrevNode()->size());
|
|
|
|
// insert stub fragment
|
|
pStub.setParent(sd);
|
|
sd->getFragmentList().insert(end(), &pStub);
|
|
pStub.setOffset(pStub.getPrevNode()->getOffset() +
|
|
pStub.getPrevNode()->size());
|
|
}
|
|
|
|
/// addRelocation - add a relocation into island
|
|
bool BranchIsland::addRelocation(Relocation& pReloc) {
|
|
m_Relocations.push_back(&pReloc);
|
|
return true;
|
|
}
|
|
|
|
} // namespace mcld
|