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 
126 /// addRelocation - add a relocation into island
addRelocation(Relocation & pReloc)127 bool BranchIsland::addRelocation(Relocation& pReloc) {
128   m_Relocations.push_back(&pReloc);
129   return true;
130 }
131 
132 }  // namespace mcld
133