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