StubFactory.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIsland.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
2637b74a387bb3993387029859c2d9d051c41c724eStephen HinesStubFactory::~StubFactory() {
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it)
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    delete (*it);
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid StubFactory::addPrototype(Stub* pPrototype) {
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_StubPool.push_back(pPrototype);
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// create - create a stub if needed, otherwise return NULL
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::create(Relocation& pReloc,
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          uint64_t pTargetSymValue,
416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          IRBuilder& pBuilder,
4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                          BranchIslandFactory& pBRIslandFactory) {
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // find if there is a prototype stub for the input relocation
440dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  Stub* stub = NULL;
450dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  Stub* prototype = findPrototype(pReloc, pReloc.place(), pTargetSymValue);
460dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if (prototype != NULL) {
470dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    const Fragment* frag = pReloc.targetRef().frag();
480dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    // find the islands for the input relocation
490dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    std::pair<BranchIsland*, BranchIsland*> islands =
500dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        pBRIslandFactory.getIslands(*frag);
510dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    if (islands.first == NULL) {
520dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      // early exit if we can not find the forward island.
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return NULL;
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
560dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    // find if there is such a stub in the backward island first.
570dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    if (islands.second != NULL) {
580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      stub = islands.second->findStub(prototype, pReloc);
590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    }
600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    if (stub != NULL) {
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // reset the branch target to the stub instead!
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pReloc.setSymInfo(stub->symInfo());
640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    } else {
650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      // find if there is such a stub in the forward island.
660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      stub = islands.first->findStub(prototype, pReloc);
670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      if (stub != NULL) {
680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // reset the branch target to the stub instead!
690dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        pReloc.setSymInfo(stub->symInfo());
700dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      } else {
710dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // create a stub from the prototype
720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        stub = prototype->clone();
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // build a name for stub symbol
750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        std::string name("__");
760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        name.append(pReloc.symInfo()->name())
770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            .append("_")
780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            .append(stub->name())
790dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            .append("@")
800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            .append(islands.first->name());
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
820dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // create LDSymbol for the stub
830dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        LDSymbol* symbol =
840dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                name,
860dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                ResolveInfo::Function,
870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                ResolveInfo::Define,
880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                ResolveInfo::Local,
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                stub->size(),          // size
9037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                stub->initSymValue(),  // value
910dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                FragmentRef::Create(*stub, stub->initSymValue()),
920dea6bc96bb52346737966839ac68644f7939f58Stephen Hines                ResolveInfo::Default);
930dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        stub->setSymInfo(symbol->resolveInfo());
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // add relocations of this stub (i.e., set the branch target of the
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // stub)
970dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        for (Stub::fixup_iterator it = stub->fixup_begin(),
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  ie = stub->fixup_end();
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines             it != ie;
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines             ++it) {
1010dea6bc96bb52346737966839ac68644f7939f58Stephen Hines          Relocation* reloc =
1020dea6bc96bb52346737966839ac68644f7939f58Stephen Hines              Relocation::Create((*it)->type(),
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 *(FragmentRef::Create(*stub, (*it)->offset())),
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 (*it)->addend());
1050dea6bc96bb52346737966839ac68644f7939f58Stephen Hines          reloc->setSymInfo(pReloc.symInfo());
1060dea6bc96bb52346737966839ac68644f7939f58Stephen Hines          islands.first->addRelocation(*reloc);
1070dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        }
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1090dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // add stub to the forward branch island
1100dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        islands.first->addStub(prototype, pReloc, *stub);
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1120dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        // reset the branch target of the input reloc to this stub instead!
1130dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        pReloc.setSymInfo(stub->symInfo());
1140dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      }
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1170dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return stub;
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc,
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                 uint64_t pSource,
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 uint64_t pTargetSymValue) {
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it) {
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue))
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return (*it);
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return NULL;
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
135