1//===- StubFactory.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/StubFactory.h" 10 11#include "mcld/IRBuilder.h" 12#include "mcld/Fragment/FragmentRef.h" 13#include "mcld/Fragment/Relocation.h" 14#include "mcld/Fragment/Stub.h" 15#include "mcld/LD/BranchIsland.h" 16#include "mcld/LD/BranchIslandFactory.h" 17#include "mcld/LD/LDSymbol.h" 18#include "mcld/LD/ResolveInfo.h" 19 20#include <string> 21 22namespace mcld { 23 24//===----------------------------------------------------------------------===// 25// StubFactory 26//===----------------------------------------------------------------------===// 27StubFactory::~StubFactory() { 28 for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 29 it != ie; 30 ++it) 31 delete (*it); 32} 33 34/// addPrototype - register a stub prototype 35void StubFactory::addPrototype(Stub* pPrototype) { 36 m_StubPool.push_back(pPrototype); 37} 38 39/// create - create a stub if needed, otherwise return NULL 40Stub* StubFactory::create(Relocation& pReloc, 41 uint64_t pTargetSymValue, 42 IRBuilder& pBuilder, 43 BranchIslandFactory& pBRIslandFactory) { 44 // find if there is a prototype stub for the input relocation 45 Stub* stub = NULL; 46 Stub* prototype = findPrototype(pReloc, pReloc.place(), pTargetSymValue); 47 if (prototype != NULL) { 48 const Fragment* frag = pReloc.targetRef().frag(); 49 // find the islands for the input relocation 50 std::pair<BranchIsland*, BranchIsland*> islands = 51 pBRIslandFactory.getIslands(*frag); 52 if (islands.first == NULL) { 53 // early exit if we can not find the forward island. 54 return NULL; 55 } 56 57 // find if there is such a stub in the backward island first. 58 if (islands.second != NULL) { 59 stub = islands.second->findStub(prototype, pReloc); 60 } 61 62 if (stub == NULL) { 63 // find if there is such a stub in the forward island. 64 stub = islands.first->findStub(prototype, pReloc); 65 if (stub == NULL) { 66 // create a stub from the prototype 67 stub = prototype->clone(); 68 69 // apply fixups in this new stub 70 stub->applyFixup(pReloc, pBuilder, *islands.first); 71 72 // add stub to the forward branch island 73 islands.first->addStub(prototype, pReloc, *stub); 74 } 75 } 76 } 77 return stub; 78} 79 80Stub* StubFactory::create(FragmentRef& pFragRef, 81 IRBuilder& pBuilder, 82 BranchIslandFactory& pBRIslandFactory) { 83 Stub* prototype = findPrototype(pFragRef); 84 if (prototype == NULL) { 85 return NULL; 86 } else { 87 std::pair<BranchIsland*, BranchIsland*> islands = 88 pBRIslandFactory.getIslands(*(pFragRef.frag())); 89 // early exit if we can not find the forward island. 90 if (islands.first == NULL) { 91 return NULL; 92 } else { 93 // create a stub from the prototype 94 Stub* stub = prototype->clone(); 95 96 // apply fixups in this new stub 97 stub->applyFixup(pFragRef, pBuilder, *islands.first); 98 99 // add stub to the forward branch island 100 islands.first->addStub(*stub); 101 102 return stub; 103 } // (islands.first == NULL) 104 } // if (prototype == NULL) 105} 106 107/// findPrototype - find if there is a registered stub prototype for the given 108/// relocation 109Stub* StubFactory::findPrototype(const Relocation& pReloc, 110 uint64_t pSource, 111 uint64_t pTargetSymValue) const { 112 for (StubPoolType::const_iterator it = m_StubPool.begin(), 113 ie = m_StubPool.end(); it != ie; ++it) { 114 if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue)) 115 return (*it); 116 } 117 return NULL; 118} 119 120Stub* StubFactory::findPrototype(const FragmentRef& pFragRef) const { 121 for (StubPoolType::const_iterator it = m_StubPool.begin(), 122 ie = m_StubPool.end(); it != ie; ++it) { 123 if ((*it)->isMyDuty(pFragRef)) 124 return (*it); 125 } 126 return NULL; 127} 128 129} // namespace mcld 130