• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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