1 //===- BranchIsland.cpp ---------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include <mcld/LD/BranchIsland.h> 10 #include <mcld/LD/ResolveInfo.h> 11 #include <mcld/LD/LDSection.h> 12 #include <mcld/Fragment/Stub.h> 13 #include <mcld/Fragment/AlignFragment.h> 14 15 #include <sstream> 16 17 using namespace mcld; 18 19 //========================== 20 // BranchIsland 21 22 BranchIsland::BranchIsland(Fragment& pEntryFrag, 23 size_t pMaxSize, 24 size_t pIndex) 25 : m_Entry(pEntryFrag), 26 m_pExit(pEntryFrag.getNextNode()), 27 m_pRear(NULL), 28 m_MaxSize(pMaxSize), 29 m_Name("island-") 30 { 31 // island name 32 std::ostringstream index; 33 index << pIndex; 34 m_Name.append(index.str()); 35 } 36 37 BranchIsland::~BranchIsland() 38 { 39 } 40 41 /// fragment iterators of the island 42 SectionData::iterator BranchIsland::begin() 43 { 44 return ++iterator(&m_Entry); 45 } 46 47 SectionData::const_iterator BranchIsland::begin() const 48 { 49 return ++iterator(&m_Entry); 50 } 51 52 SectionData::iterator BranchIsland::end() 53 { 54 if (NULL != m_pExit) 55 return iterator(m_pExit); 56 return m_Entry.getParent()->end(); 57 } 58 59 SectionData::const_iterator BranchIsland::end() const 60 { 61 if (NULL != m_pExit) 62 return iterator(m_pExit); 63 return m_Entry.getParent()->end(); 64 } 65 66 uint64_t BranchIsland::offset() const 67 { 68 return m_Entry.getOffset() + m_Entry.size(); 69 } 70 71 size_t BranchIsland::size() const 72 { 73 size_t size = 0x0; 74 if (0x0 != numOfStubs()) { 75 size = m_pRear->getOffset() + m_pRear->size() - 76 m_Entry.getNextNode()->getOffset(); 77 } 78 return size; 79 } 80 81 size_t BranchIsland::maxSize() const 82 { 83 return m_MaxSize; 84 } 85 86 const std::string& BranchIsland::name() const 87 { 88 return m_Name; 89 } 90 91 size_t BranchIsland::numOfStubs() const 92 { 93 return m_StubMap.numOfEntries(); 94 } 95 96 /// findStub - return true if there is a stub built from the given prototype 97 /// for the given relocation 98 Stub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc) 99 { 100 Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); 101 StubMapType::iterator it = m_StubMap.find(key); 102 if (it != m_StubMap.end()) { 103 assert(NULL != it.getEntry()->value()); 104 return it.getEntry()->value(); 105 } 106 return NULL; 107 } 108 109 /// addStub - add a stub into the island 110 bool BranchIsland::addStub(const Stub* pPrototype, 111 const Relocation& pReloc, 112 Stub& pStub) 113 { 114 bool exist = false; 115 Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); 116 StubEntryType* entry = m_StubMap.insert(key, exist); 117 if (!exist) { 118 entry->setValue(&pStub); 119 m_pRear = &pStub; 120 SectionData* sd = m_Entry.getParent(); 121 122 // insert alignment fragment 123 // TODO: check if we can reduce this alignment fragment for some cases 124 AlignFragment* align_frag = new AlignFragment(pStub.alignment(), 125 0x0, 126 1u, 127 pStub.alignment() - 1); 128 align_frag->setParent(sd); 129 sd->getFragmentList().insert(end(), align_frag); 130 align_frag->setOffset(align_frag->getPrevNode()->getOffset() + 131 align_frag->getPrevNode()->size()); 132 133 // insert stub fragment 134 pStub.setParent(sd); 135 sd->getFragmentList().insert(end(), &pStub); 136 pStub.setOffset(pStub.getPrevNode()->getOffset() + 137 pStub.getPrevNode()->size()); 138 } 139 return !exist; 140 } 141 142 /// addRelocation - add a relocation into island 143 bool BranchIsland::addRelocation(Relocation& pReloc) 144 { 145 m_Relocations.push_back(&pReloc); 146 return true; 147 } 148 149