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
BranchIsland(Fragment & pEntryFrag,size_t pMaxSize,size_t pIndex)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
~BranchIsland()37 BranchIsland::~BranchIsland()
38 {
39 }
40
41 /// fragment iterators of the island
begin()42 SectionData::iterator BranchIsland::begin()
43 {
44 return ++iterator(&m_Entry);
45 }
46
begin() const47 SectionData::const_iterator BranchIsland::begin() const
48 {
49 return ++iterator(&m_Entry);
50 }
51
end()52 SectionData::iterator BranchIsland::end()
53 {
54 if (NULL != m_pExit)
55 return iterator(m_pExit);
56 return m_Entry.getParent()->end();
57 }
58
end() const59 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
offset() const66 uint64_t BranchIsland::offset() const
67 {
68 return m_Entry.getOffset() + m_Entry.size();
69 }
70
size() const71 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
maxSize() const81 size_t BranchIsland::maxSize() const
82 {
83 return m_MaxSize;
84 }
85
name() const86 const std::string& BranchIsland::name() const
87 {
88 return m_Name;
89 }
90
numOfStubs() const91 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
findStub(const Stub * pPrototype,const Relocation & pReloc)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
addStub(const Stub * pPrototype,const Relocation & pReloc,Stub & pStub)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
addRelocation(Relocation & pReloc)143 bool BranchIsland::addRelocation(Relocation& pReloc)
144 {
145 m_Relocations.push_back(&pReloc);
146 return true;
147 }
148
149