1921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//===- BranchIsland.cpp ---------------------------------------------------===// 2921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// 3921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// The MCLinker Project 4921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// 5921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// This file is distributed under the University of Illinois Open Source 6921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// License. See LICENSE.TXT for details. 7921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// 8921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//===----------------------------------------------------------------------===// 9921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/BranchIsland.h" 10921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 11921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/Fragment/AlignFragment.h" 12921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/Fragment/Stub.h" 13921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/LDSection.h" 14921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/ResolveInfo.h" 15921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 16921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <sstream> 17921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 18921832327619f7852b16f73a19504702c5a28a31Glenn Kastennamespace mcld { 19921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 20921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//============================================================================// 21921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// BranchIsland 229d014d04bd1e26b68ea979885ccbc6f131a7eda3Elliott Hughes//============================================================================// 23921832327619f7852b16f73a19504702c5a28a31Glenn KastenBranchIsland::BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex) 24921832327619f7852b16f73a19504702c5a28a31Glenn Kasten : m_Entry(pEntryFrag), 25921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_pExit(pEntryFrag.getNextNode()), 26921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_pRear(NULL), 27921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_MaxSize(pMaxSize), 28921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_Name("island-") { 29921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // island name 30921832327619f7852b16f73a19504702c5a28a31Glenn Kasten std::ostringstream index; 31921832327619f7852b16f73a19504702c5a28a31Glenn Kasten index << pIndex; 32921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_Name.append(index.str()); 33921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 34921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 35921832327619f7852b16f73a19504702c5a28a31Glenn KastenBranchIsland::~BranchIsland() { 36921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 37921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 38921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// fragment iterators of the island 39921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::iterator BranchIsland::begin() { 40921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return ++iterator(&m_Entry); 41921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 42921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 43921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::const_iterator BranchIsland::begin() const { 44921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return ++iterator(&m_Entry); 45921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 46921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 47921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::iterator BranchIsland::end() { 48921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (m_pExit != NULL) 49921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return iterator(m_pExit); 50921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_Entry.getParent()->end(); 51921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 52921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 53921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::const_iterator BranchIsland::end() const { 54921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (m_pExit != NULL) 55921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return iterator(m_pExit); 56921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_Entry.getParent()->end(); 57921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 58921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 59921832327619f7852b16f73a19504702c5a28a31Glenn Kastenuint64_t BranchIsland::offset() const { 60921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_Entry.getOffset() + m_Entry.size(); 61921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 62921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 63921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::size() const { 64921832327619f7852b16f73a19504702c5a28a31Glenn Kasten size_t size = 0x0; 65921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (numOfStubs() != 0x0) { 66921832327619f7852b16f73a19504702c5a28a31Glenn Kasten size = m_pRear->getOffset() + m_pRear->size() - 67921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_Entry.getNextNode()->getOffset(); 68921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 69921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return size; 70921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 71921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 72921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::maxSize() const { 73921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_MaxSize; 74921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 75921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 76921832327619f7852b16f73a19504702c5a28a31Glenn Kastenconst std::string& BranchIsland::name() const { 77921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_Name; 78921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 79921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 80921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::numOfStubs() const { 81921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return m_StubMap.numOfEntries(); 82921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 83921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 84921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// findStub - return true if there is a stub built from the given prototype 85921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// for the given relocation 86921832327619f7852b16f73a19504702c5a28a31Glenn KastenStub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc) { 87921832327619f7852b16f73a19504702c5a28a31Glenn Kasten Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); 88921832327619f7852b16f73a19504702c5a28a31Glenn Kasten StubMapType::iterator it = m_StubMap.find(key); 89921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (it != m_StubMap.end()) { 90921832327619f7852b16f73a19504702c5a28a31Glenn Kasten assert(it.getEntry()->value() != NULL); 91921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return it.getEntry()->value(); 92921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 93921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return NULL; 94921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 95921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 96921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// addStub - add a stub into the island 97921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool BranchIsland::addStub(const Stub* pPrototype, 98921832327619f7852b16f73a19504702c5a28a31Glenn Kasten const Relocation& pReloc, 99921832327619f7852b16f73a19504702c5a28a31Glenn Kasten Stub& pStub) { 100921832327619f7852b16f73a19504702c5a28a31Glenn Kasten bool exist = false; 101921832327619f7852b16f73a19504702c5a28a31Glenn Kasten Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); 102921832327619f7852b16f73a19504702c5a28a31Glenn Kasten StubEntryType* entry = m_StubMap.insert(key, exist); 103921832327619f7852b16f73a19504702c5a28a31Glenn Kasten if (!exist) { 104921832327619f7852b16f73a19504702c5a28a31Glenn Kasten entry->setValue(&pStub); 105921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_pRear = &pStub; 106921832327619f7852b16f73a19504702c5a28a31Glenn Kasten SectionData* sd = m_Entry.getParent(); 107921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 108921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // insert alignment fragment 109921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // TODO: check if we can reduce this alignment fragment for some cases 110921832327619f7852b16f73a19504702c5a28a31Glenn Kasten AlignFragment* align_frag = 111921832327619f7852b16f73a19504702c5a28a31Glenn Kasten new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1); 112921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->setParent(sd); 113921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sd->getFragmentList().insert(end(), align_frag); 114921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->setOffset(align_frag->getPrevNode()->getOffset() + 115921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->getPrevNode()->size()); 116921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 117921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // insert stub fragment 118921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.setParent(sd); 119921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sd->getFragmentList().insert(end(), &pStub); 120921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.setOffset(pStub.getPrevNode()->getOffset() + 121921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.getPrevNode()->size()); 122921832327619f7852b16f73a19504702c5a28a31Glenn Kasten } 123921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return !exist; 124921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 125921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 126921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid BranchIsland::addStub(Stub& pStub) { 127921832327619f7852b16f73a19504702c5a28a31Glenn Kasten bool exist = false; 128921832327619f7852b16f73a19504702c5a28a31Glenn Kasten Key key(&pStub, pStub.symInfo()->outSymbol(), 0); 129921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_StubMap.insert(key, exist); 130921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 131921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_pRear = &pStub; 132921832327619f7852b16f73a19504702c5a28a31Glenn Kasten SectionData* sd = m_Entry.getParent(); 133921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 134921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // insert alignment fragment 135921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // TODO: check if we can reduce this alignment fragment for some cases 136921832327619f7852b16f73a19504702c5a28a31Glenn Kasten AlignFragment* align_frag = 137921832327619f7852b16f73a19504702c5a28a31Glenn Kasten new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1); 138921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->setParent(sd); 139921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sd->getFragmentList().insert(end(), align_frag); 140921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->setOffset(align_frag->getPrevNode()->getOffset() + 141921832327619f7852b16f73a19504702c5a28a31Glenn Kasten align_frag->getPrevNode()->size()); 142921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 143921832327619f7852b16f73a19504702c5a28a31Glenn Kasten // insert stub fragment 144921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.setParent(sd); 145921832327619f7852b16f73a19504702c5a28a31Glenn Kasten sd->getFragmentList().insert(end(), &pStub); 146921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.setOffset(pStub.getPrevNode()->getOffset() + 147921832327619f7852b16f73a19504702c5a28a31Glenn Kasten pStub.getPrevNode()->size()); 148921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 149921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 150921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// addRelocation - add a relocation into island 151921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool BranchIsland::addRelocation(Relocation& pReloc) { 152921832327619f7852b16f73a19504702c5a28a31Glenn Kasten m_Relocations.push_back(&pReloc); 153921832327619f7852b16f73a19504702c5a28a31Glenn Kasten return true; 154921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} 155921832327619f7852b16f73a19504702c5a28a31Glenn Kasten 156921832327619f7852b16f73a19504702c5a28a31Glenn Kasten} // namespace mcld 157921832327619f7852b16f73a19504702c5a28a31Glenn Kasten