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 22 namespace mcld { 23 24 //===----------------------------------------------------------------------===// 25 // StubFactory 26 //===----------------------------------------------------------------------===// 27 StubFactory::~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 35 void StubFactory::addPrototype(Stub* pPrototype) { 36 m_StubPool.push_back(pPrototype); 37 } 38 39 /// create - create a stub if needed, otherwise return NULL 40 Stub* 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 80 Stub* 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 109 Stub* 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 120 Stub* 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