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