Home | History | Annotate | Download | only in LD
      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 //============================================================================//
     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 
     35 BranchIsland::~BranchIsland() {
     36 }
     37 
     38 /// fragment iterators of the island
     39 SectionData::iterator BranchIsland::begin() {
     40   return ++iterator(&m_Entry);
     41 }
     42 
     43 SectionData::const_iterator BranchIsland::begin() const {
     44   return ++iterator(&m_Entry);
     45 }
     46 
     47 SectionData::iterator BranchIsland::end() {
     48   if (m_pExit != NULL)
     49     return iterator(m_pExit);
     50   return m_Entry.getParent()->end();
     51 }
     52 
     53 SectionData::const_iterator BranchIsland::end() const {
     54   if (m_pExit != NULL)
     55     return iterator(m_pExit);
     56   return m_Entry.getParent()->end();
     57 }
     58 
     59 uint64_t BranchIsland::offset() const {
     60   return m_Entry.getOffset() + m_Entry.size();
     61 }
     62 
     63 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 
     72 size_t BranchIsland::maxSize() const {
     73   return m_MaxSize;
     74 }
     75 
     76 const std::string& BranchIsland::name() const {
     77   return m_Name;
     78 }
     79 
     80 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
     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
     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 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
    151 bool BranchIsland::addRelocation(Relocation& pReloc) {
    152   m_Relocations.push_back(&pReloc);
    153   return true;
    154 }
    155 
    156 }  // namespace mcld
    157