| //===- 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/LD/ResolveInfo.h> |
| #include <mcld/LD/LDSection.h> |
| #include <mcld/Fragment/Stub.h> |
| #include <mcld/Fragment/AlignFragment.h> |
| |
| #include <sstream> |
| |
| using 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 (NULL != m_pExit) |
| return iterator(m_pExit); |
| return m_Entry.getParent()->end(); |
| } |
| |
| SectionData::const_iterator BranchIsland::end() const |
| { |
| if (NULL != m_pExit) |
| 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 (0x0 != numOfStubs()) { |
| 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(NULL != it.getEntry()->value()); |
| 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; |
| } |
| |
| /// addRelocation - add a relocation into island |
| bool BranchIsland::addRelocation(Relocation& pReloc) |
| { |
| m_Relocations.push_back(&pReloc); |
| return true; |
| } |
| |