122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- StubFactory.cpp ----------------------------------------------------===// 222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// The MCLinker Project 422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// This file is distributed under the University of Illinois Open Source 622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// License. See LICENSE.TXT for details. 722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/StubFactory.h> 106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/IRBuilder.h> 1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/BranchIslandFactory.h> 1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/BranchIsland.h> 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSymbol.h> 1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/ResolveInfo.h> 1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Stub.h> 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Relocation.h> 1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentRef.h> 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string> 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 21d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaousing namespace mcld; 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory 25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStubFactory::~StubFactory() 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao it != ie; ++it) 3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete(*it); 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid StubFactory::addPrototype(Stub* pPrototype) 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_StubPool.push_back(pPrototype); 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// create - create a stub if needed, otherwise return NULL 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::create(Relocation& pReloc, 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pTargetSymValue, 426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao BranchIslandFactory& pBRIslandFactory) 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // find if there is a prototype stub for the input relocation 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Stub* prototype = findPrototype(pReloc, 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.place(), 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pTargetSymValue); 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != prototype) { 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // find the island for the input relocation 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao BranchIsland* island = pBRIslandFactory.find(*(pReloc.targetRef().frag())); 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == island) { 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao island = pBRIslandFactory.produce(*(pReloc.targetRef().frag())); 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // find if there is such a stub in the island already 5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL != island); 5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Stub* stub = island->findStub(prototype, pReloc); 5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL != stub) { 6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reset the branch target to the stub instead! 6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.setSymInfo(stub->symInfo()); 6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create a stub from the prototype 6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao stub = prototype->clone(); 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // build a name for stub symbol 6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao std::string name("__"); 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao name.append(pReloc.symInfo()->name()); 7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao name.append("_"); 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao name.append(stub->name()); 7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao name.append("@"); 7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao name.append(island->name()); 7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create LDSymbol for the stub 7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSymbol* symbol = 776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines name, 7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo::Function, 8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo::Define, 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo::Local, 8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao stub->size(), // size 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao stub->initSymValue(), // value 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao FragmentRef::Create(*stub, stub->initSymValue()), 8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo::Default); 8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao stub->setSymInfo(symbol->resolveInfo()); 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // add relocations of this stub (i.e., set the branch target of the stub) 8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (Stub::fixup_iterator it = stub->fixup_begin(), 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ie = stub->fixup_end(); it != ie; ++it) { 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 92d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao Relocation* reloc = Relocation::Create((*it)->type(), 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *(FragmentRef::Create(*stub, (*it)->offset())), 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (*it)->addend()); 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao reloc->setSymInfo(pReloc.symInfo()); 9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao island->addRelocation(*reloc); 9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // add stub to the branch island 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao island->addStub(prototype, pReloc, *stub); 10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reset the branch target of the input reloc to this stub instead! 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.setSymInfo(stub->symInfo()); 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return stub; 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return NULL; 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation 11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc, 11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pSource, 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pTargetSymValue) 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao it != ie; ++it) { 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue)) 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (*it); 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return NULL; 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 124