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//===----------------------------------------------------------------------===//
922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/StubFactory.h>
106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/IRBuilder.h>
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/BranchIslandFactory.h>
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/BranchIsland.h>
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSymbol.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/ResolveInfo.h>
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Stub.h>
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Relocation.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentRef.h>
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
21d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaousing namespace mcld;
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStubFactory::~StubFactory()
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       it != ie; ++it)
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    delete(*it);
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid StubFactory::addPrototype(Stub* pPrototype)
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
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,
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          BranchIslandFactory& pBRIslandFactory)
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // find if there is a prototype stub for the input relocation
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Stub* prototype = findPrototype(pReloc,
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  pReloc.place(),
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  pTargetSymValue);
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != prototype) {
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // find the island for the input relocation
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    BranchIsland* island = pBRIslandFactory.find(*(pReloc.targetRef().frag()));
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == island) {
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      island = pBRIslandFactory.produce(*(pReloc.targetRef().frag()));
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // find if there is such a stub in the island already
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(NULL != island);
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Stub* stub = island->findStub(prototype, pReloc);
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL != stub) {
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // reset the branch target to the stub instead!
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pReloc.setSymInfo(stub->symInfo());
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // create a stub from the prototype
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      stub = prototype->clone();
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // build a name for stub symbol
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      std::string name("__");
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      name.append(pReloc.symInfo()->name());
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      name.append("_");
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      name.append(stub->name());
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      name.append("@");
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      name.append(island->name());
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // create LDSymbol for the stub
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      LDSymbol* symbol =
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                               name,
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               ResolveInfo::Function,
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               ResolveInfo::Define,
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               ResolveInfo::Local,
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               stub->size(), // size
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               stub->initSymValue(), // value
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               FragmentRef::Create(*stub, stub->initSymValue()),
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                               ResolveInfo::Default);
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      stub->setSymInfo(symbol->resolveInfo());
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // add relocations of this stub (i.e., set the branch target of the stub)
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      for (Stub::fixup_iterator it = stub->fixup_begin(),
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao             ie = stub->fixup_end(); it != ie; ++it) {
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
92d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        Relocation* reloc = Relocation::Create((*it)->type(),
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 *(FragmentRef::Create(*stub, (*it)->offset())),
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 (*it)->addend());
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        reloc->setSymInfo(pReloc.symInfo());
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        island->addRelocation(*reloc);
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // add stub to the branch island
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      island->addStub(prototype, pReloc, *stub);
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // reset the branch target of the input reloc to this stub instead!
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pReloc.setSymInfo(stub->symInfo());
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return stub;
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return NULL;
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc,
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 uint64_t pSource,
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 uint64_t pTargetSymValue)
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao       it != ie; ++it) {
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue))
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return (*it);
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return NULL;
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
124