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