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 #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 
     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 
     37 BranchIsland::~BranchIsland()
     38 {
     39 }
     40 
     41 /// fragment iterators of the island
     42 SectionData::iterator BranchIsland::begin()
     43 {
     44   return ++iterator(&m_Entry);
     45 }
     46 
     47 SectionData::const_iterator BranchIsland::begin() const
     48 {
     49   return ++iterator(&m_Entry);
     50 }
     51 
     52 SectionData::iterator BranchIsland::end()
     53 {
     54   if (NULL != m_pExit)
     55     return iterator(m_pExit);
     56   return m_Entry.getParent()->end();
     57 }
     58 
     59 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 
     66 uint64_t BranchIsland::offset() const
     67 {
     68   return m_Entry.getOffset() + m_Entry.size();
     69 }
     70 
     71 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 
     81 size_t BranchIsland::maxSize() const
     82 {
     83   return m_MaxSize;
     84 }
     85 
     86 const std::string& BranchIsland::name() const
     87 {
     88   return m_Name;
     89 }
     90 
     91 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
     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
    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
    143 bool BranchIsland::addRelocation(Relocation& pReloc)
    144 {
    145   m_Relocations.push_back(&pReloc);
    146   return true;
    147 }
    148 
    149