• Home
  • History
  • Annotate
  • 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  
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