1921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//===- BranchIsland.cpp ---------------------------------------------------===//
2921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//
3921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//                     The MCLinker Project
4921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//
5921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// This file is distributed under the University of Illinois Open Source
6921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// License. See LICENSE.TXT for details.
7921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//
8921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//===----------------------------------------------------------------------===//
9921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/BranchIsland.h"
10921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
11921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/Fragment/AlignFragment.h"
12921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/Fragment/Stub.h"
13921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/LDSection.h"
14921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include "mcld/LD/ResolveInfo.h"
15921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
16921832327619f7852b16f73a19504702c5a28a31Glenn Kasten#include <sstream>
17921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
18921832327619f7852b16f73a19504702c5a28a31Glenn Kastennamespace mcld {
19921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
20921832327619f7852b16f73a19504702c5a28a31Glenn Kasten//============================================================================//
21921832327619f7852b16f73a19504702c5a28a31Glenn Kasten// BranchIsland
229d014d04bd1e26b68ea979885ccbc6f131a7eda3Elliott Hughes//============================================================================//
23921832327619f7852b16f73a19504702c5a28a31Glenn KastenBranchIsland::BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex)
24921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    : m_Entry(pEntryFrag),
25921832327619f7852b16f73a19504702c5a28a31Glenn Kasten      m_pExit(pEntryFrag.getNextNode()),
26921832327619f7852b16f73a19504702c5a28a31Glenn Kasten      m_pRear(NULL),
27921832327619f7852b16f73a19504702c5a28a31Glenn Kasten      m_MaxSize(pMaxSize),
28921832327619f7852b16f73a19504702c5a28a31Glenn Kasten      m_Name("island-") {
29921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  // island name
30921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  std::ostringstream index;
31921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  index << pIndex;
32921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  m_Name.append(index.str());
33921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
34921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
35921832327619f7852b16f73a19504702c5a28a31Glenn KastenBranchIsland::~BranchIsland() {
36921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
37921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
38921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// fragment iterators of the island
39921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::iterator BranchIsland::begin() {
40921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return ++iterator(&m_Entry);
41921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
42921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
43921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::const_iterator BranchIsland::begin() const {
44921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return ++iterator(&m_Entry);
45921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
46921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
47921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::iterator BranchIsland::end() {
48921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  if (m_pExit != NULL)
49921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    return iterator(m_pExit);
50921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_Entry.getParent()->end();
51921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
52921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
53921832327619f7852b16f73a19504702c5a28a31Glenn KastenSectionData::const_iterator BranchIsland::end() const {
54921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  if (m_pExit != NULL)
55921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    return iterator(m_pExit);
56921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_Entry.getParent()->end();
57921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
58921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
59921832327619f7852b16f73a19504702c5a28a31Glenn Kastenuint64_t BranchIsland::offset() const {
60921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_Entry.getOffset() + m_Entry.size();
61921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
62921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
63921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::size() const {
64921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  size_t size = 0x0;
65921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  if (numOfStubs() != 0x0) {
66921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    size = m_pRear->getOffset() + m_pRear->size() -
67921832327619f7852b16f73a19504702c5a28a31Glenn Kasten           m_Entry.getNextNode()->getOffset();
68921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  }
69921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return size;
70921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
71921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
72921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::maxSize() const {
73921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_MaxSize;
74921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
75921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
76921832327619f7852b16f73a19504702c5a28a31Glenn Kastenconst std::string& BranchIsland::name() const {
77921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_Name;
78921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
79921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
80921832327619f7852b16f73a19504702c5a28a31Glenn Kastensize_t BranchIsland::numOfStubs() const {
81921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return m_StubMap.numOfEntries();
82921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
83921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
84921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// findStub - return true if there is a stub built from the given prototype
85921832327619f7852b16f73a19504702c5a28a31Glenn Kasten///            for the given relocation
86921832327619f7852b16f73a19504702c5a28a31Glenn KastenStub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc) {
87921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
88921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  StubMapType::iterator it = m_StubMap.find(key);
89921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  if (it != m_StubMap.end()) {
90921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    assert(it.getEntry()->value() != NULL);
91921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    return it.getEntry()->value();
92921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  }
93921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return NULL;
94921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
95921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
96921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// addStub - add a stub into the island
97921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool BranchIsland::addStub(const Stub* pPrototype,
98921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                           const Relocation& pReloc,
99921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                           Stub& pStub) {
100921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  bool exist = false;
101921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
102921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  StubEntryType* entry = m_StubMap.insert(key, exist);
103921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  if (!exist) {
104921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    entry->setValue(&pStub);
105921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    m_pRear = &pStub;
106921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    SectionData* sd = m_Entry.getParent();
107921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
108921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    // insert alignment fragment
109921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    // TODO: check if we can reduce this alignment fragment for some cases
110921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    AlignFragment* align_frag =
111921832327619f7852b16f73a19504702c5a28a31Glenn Kasten        new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1);
112921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    align_frag->setParent(sd);
113921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    sd->getFragmentList().insert(end(), align_frag);
114921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
115921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                          align_frag->getPrevNode()->size());
116921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
117921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    // insert stub fragment
118921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    pStub.setParent(sd);
119921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    sd->getFragmentList().insert(end(), &pStub);
120921832327619f7852b16f73a19504702c5a28a31Glenn Kasten    pStub.setOffset(pStub.getPrevNode()->getOffset() +
121921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                    pStub.getPrevNode()->size());
122921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  }
123921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return !exist;
124921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
125921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
126921832327619f7852b16f73a19504702c5a28a31Glenn Kastenvoid BranchIsland::addStub(Stub& pStub) {
127921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  bool exist = false;
128921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  Key key(&pStub, pStub.symInfo()->outSymbol(), 0);
129921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  m_StubMap.insert(key, exist);
130921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
131921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  m_pRear = &pStub;
132921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  SectionData* sd = m_Entry.getParent();
133921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
134921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  // insert alignment fragment
135921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  // TODO: check if we can reduce this alignment fragment for some cases
136921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  AlignFragment* align_frag =
137921832327619f7852b16f73a19504702c5a28a31Glenn Kasten      new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1);
138921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  align_frag->setParent(sd);
139921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  sd->getFragmentList().insert(end(), align_frag);
140921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
141921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                        align_frag->getPrevNode()->size());
142921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
143921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  // insert stub fragment
144921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  pStub.setParent(sd);
145921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  sd->getFragmentList().insert(end(), &pStub);
146921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  pStub.setOffset(pStub.getPrevNode()->getOffset() +
147921832327619f7852b16f73a19504702c5a28a31Glenn Kasten                  pStub.getPrevNode()->size());
148921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
149921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
150921832327619f7852b16f73a19504702c5a28a31Glenn Kasten/// addRelocation - add a relocation into island
151921832327619f7852b16f73a19504702c5a28a31Glenn Kastenbool BranchIsland::addRelocation(Relocation& pReloc) {
152921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  m_Relocations.push_back(&pReloc);
153921832327619f7852b16f73a19504702c5a28a31Glenn Kasten  return true;
154921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}
155921832327619f7852b16f73a19504702c5a28a31Glenn Kasten
156921832327619f7852b16f73a19504702c5a28a31Glenn Kasten}  // namespace mcld
157921832327619f7852b16f73a19504702c5a28a31Glenn Kasten