BranchIsland.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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
18namespace mcld {
19
20//==========================
21// BranchIsland
22
23BranchIsland::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
35BranchIsland::~BranchIsland() {
36}
37
38/// fragment iterators of the island
39SectionData::iterator BranchIsland::begin() {
40  return ++iterator(&m_Entry);
41}
42
43SectionData::const_iterator BranchIsland::begin() const {
44  return ++iterator(&m_Entry);
45}
46
47SectionData::iterator BranchIsland::end() {
48  if (m_pExit != NULL)
49    return iterator(m_pExit);
50  return m_Entry.getParent()->end();
51}
52
53SectionData::const_iterator BranchIsland::end() const {
54  if (m_pExit != NULL)
55    return iterator(m_pExit);
56  return m_Entry.getParent()->end();
57}
58
59uint64_t BranchIsland::offset() const {
60  return m_Entry.getOffset() + m_Entry.size();
61}
62
63size_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
72size_t BranchIsland::maxSize() const {
73  return m_MaxSize;
74}
75
76const std::string& BranchIsland::name() const {
77  return m_Name;
78}
79
80size_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
86Stub* 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
97bool 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
127bool BranchIsland::addRelocation(Relocation& pReloc) {
128  m_Relocations.push_back(&pReloc);
129  return true;
130}
131
132}  // namespace mcld
133