//===- 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