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