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 #include <mcld/IRBuilder.h> 11 #include <mcld/LD/BranchIslandFactory.h> 12 #include <mcld/LD/BranchIsland.h> 13 #include <mcld/LD/LDSymbol.h> 14 #include <mcld/LD/ResolveInfo.h> 15 #include <mcld/Fragment/Stub.h> 16 #include <mcld/Fragment/Relocation.h> 17 18 #include <string> 19 20 using namespace mcld; 21 22 //===----------------------------------------------------------------------===// 23 // StubFactory 24 //===----------------------------------------------------------------------===// 25 StubFactory::~StubFactory() 26 { 27 for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 28 it != ie; ++it) 29 delete(*it); 30 } 31 32 /// addPrototype - register a stub prototype 33 void StubFactory::addPrototype(Stub* pPrototype) 34 { 35 m_StubPool.push_back(pPrototype); 36 } 37 38 /// create - create a stub if needed, otherwise return NULL 39 Stub* StubFactory::create(Relocation& pReloc, 40 uint64_t pTargetSymValue, 41 IRBuilder& pBuilder, 42 BranchIslandFactory& pBRIslandFactory) 43 { 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 // reset the branch target to the stub instead! 64 pReloc.setSymInfo(stub->symInfo()); 65 } else { 66 // find if there is such a stub in the forward island. 67 stub = islands.first->findStub(prototype, pReloc); 68 if (stub != NULL) { 69 // reset the branch target to the stub instead! 70 pReloc.setSymInfo(stub->symInfo()); 71 } else { 72 // create a stub from the prototype 73 stub = prototype->clone(); 74 75 // build a name for stub symbol 76 std::string name("__"); 77 name.append(pReloc.symInfo()->name()) 78 .append("_") 79 .append(stub->name()) 80 .append("@") 81 .append(islands.first->name()); 82 83 // create LDSymbol for the stub 84 LDSymbol* symbol = 85 pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 86 name, 87 ResolveInfo::Function, 88 ResolveInfo::Define, 89 ResolveInfo::Local, 90 stub->size(), // size 91 stub->initSymValue(), // value 92 FragmentRef::Create(*stub, stub->initSymValue()), 93 ResolveInfo::Default); 94 stub->setSymInfo(symbol->resolveInfo()); 95 96 // add relocations of this stub (i.e., set the branch target of the stub) 97 for (Stub::fixup_iterator it = stub->fixup_begin(), 98 ie = stub->fixup_end(); it != ie; ++it) { 99 100 Relocation* reloc = 101 Relocation::Create((*it)->type(), 102 *(FragmentRef::Create(*stub, (*it)->offset())), 103 (*it)->addend()); 104 reloc->setSymInfo(pReloc.symInfo()); 105 islands.first->addRelocation(*reloc); 106 } 107 108 // add stub to the forward branch island 109 islands.first->addStub(prototype, pReloc, *stub); 110 111 // reset the branch target of the input reloc to this stub instead! 112 pReloc.setSymInfo(stub->symInfo()); 113 } 114 } 115 } 116 return stub; 117 } 118 119 /// findPrototype - find if there is a registered stub prototype for the given 120 /// relocation 121 Stub* StubFactory::findPrototype(const Relocation& pReloc, 122 uint64_t pSource, 123 uint64_t pTargetSymValue) 124 { 125 for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 126 it != ie; ++it) { 127 if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue)) 128 return (*it); 129 } 130 return NULL; 131 } 132