122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- StubFactory.cpp ----------------------------------------------------===//
222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//                     The MCLinker Project
422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// This file is distributed under the University of Illinois Open Source
622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// License. See LICENSE.TXT for details.
722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//
822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/StubFactory.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
12b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines#include "mcld/Fragment/FragmentRef.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIsland.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string>
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory
26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
2737b74a387bb3993387029859c2d9d051c41c724eStephen HinesStubFactory::~StubFactory() {
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it)
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    delete (*it);
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid StubFactory::addPrototype(Stub* pPrototype) {
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_StubPool.push_back(pPrototype);
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// create - create a stub if needed, otherwise return NULL
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::create(Relocation& pReloc,
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          uint64_t pTargetSymValue,
426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          IRBuilder& pBuilder,
4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                          BranchIslandFactory& pBRIslandFactory) {
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // find if there is a prototype stub for the input relocation
450dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  Stub* stub = NULL;
460dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  Stub* prototype = findPrototype(pReloc, pReloc.place(), pTargetSymValue);
470dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if (prototype != NULL) {
480dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    const Fragment* frag = pReloc.targetRef().frag();
490dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    // find the islands for the input relocation
500dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    std::pair<BranchIsland*, BranchIsland*> islands =
510dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        pBRIslandFactory.getIslands(*frag);
520dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    if (islands.first == NULL) {
530dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      // early exit if we can not find the forward island.
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return NULL;
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
570dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    // find if there is such a stub in the backward island first.
580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    if (islands.second != NULL) {
590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      stub = islands.second->findStub(prototype, pReloc);
600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    }
610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
62b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    if (stub == NULL) {
630dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      // find if there is such a stub in the forward island.
640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      stub = islands.first->findStub(prototype, pReloc);
65b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      if (stub == NULL) {
660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // create a stub from the prototype
670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        stub = prototype->clone();
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
69b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        // apply fixups in this new stub
70b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        stub->applyFixup(pReloc, pBuilder, *islands.first);
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // add stub to the forward branch island
730dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        islands.first->addStub(prototype, pReloc, *stub);
740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      }
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return stub;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
80b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesStub* StubFactory::create(FragmentRef& pFragRef,
81b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                          IRBuilder& pBuilder,
82b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                          BranchIslandFactory& pBRIslandFactory) {
83b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  Stub* prototype = findPrototype(pFragRef);
84b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  if (prototype == NULL) {
85b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    return NULL;
86b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  } else {
87b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    std::pair<BranchIsland*, BranchIsland*> islands =
88b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines        pBRIslandFactory.getIslands(*(pFragRef.frag()));
89b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    // early exit if we can not find the forward island.
90b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    if (islands.first == NULL) {
91b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      return NULL;
92b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    } else {
93b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      // create a stub from the prototype
94b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      Stub* stub = prototype->clone();
95b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
96b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      // apply fixups in this new stub
97b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      stub->applyFixup(pFragRef, pBuilder, *islands.first);
98b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
99b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      // add stub to the forward branch island
100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      islands.first->addStub(*stub);
101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      return stub;
103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    }  // (islands.first == NULL)
104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  }  // if (prototype == NULL)
105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc,
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 uint64_t pSource,
111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                 uint64_t pTargetSymValue) const {
112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  for (StubPoolType::const_iterator it = m_StubPool.begin(),
113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                    ie = m_StubPool.end(); it != ie; ++it) {
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue))
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return (*it);
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return NULL;
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
120b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesStub* StubFactory::findPrototype(const FragmentRef& pFragRef) const {
121b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  for (StubPoolType::const_iterator it = m_StubPool.begin(),
122b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines                                    ie = m_StubPool.end(); it != ie; ++it) {
123b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines    if ((*it)->isMyDuty(pFragRef))
124b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines      return (*it);
125b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  }
126b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines  return NULL;
127b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines}
128b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
130