StubFactory.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
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//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/StubFactory.h" 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIsland.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h" 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string> 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory 25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 2637b74a387bb3993387029859c2d9d051c41c724eStephen HinesStubFactory::~StubFactory() { 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) 3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines delete (*it); 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype 3437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid StubFactory::addPrototype(Stub* pPrototype) { 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_StubPool.push_back(pPrototype); 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// create - create a stub if needed, otherwise return NULL 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::create(Relocation& pReloc, 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pTargetSymValue, 416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines BranchIslandFactory& pBRIslandFactory) { 4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // find if there is a prototype stub for the input relocation 440dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Stub* stub = NULL; 450dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Stub* prototype = findPrototype(pReloc, pReloc.place(), pTargetSymValue); 460dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (prototype != NULL) { 470dea6bc96bb52346737966839ac68644f7939f58Stephen Hines const Fragment* frag = pReloc.targetRef().frag(); 480dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find the islands for the input relocation 490dea6bc96bb52346737966839ac68644f7939f58Stephen Hines std::pair<BranchIsland*, BranchIsland*> islands = 500dea6bc96bb52346737966839ac68644f7939f58Stephen Hines pBRIslandFactory.getIslands(*frag); 510dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (islands.first == NULL) { 520dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // early exit if we can not find the forward island. 5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return NULL; 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 560dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find if there is such a stub in the backward island first. 570dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (islands.second != NULL) { 580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = islands.second->findStub(prototype, pReloc); 590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (stub != NULL) { 6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reset the branch target to the stub instead! 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pReloc.setSymInfo(stub->symInfo()); 640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } else { 650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find if there is such a stub in the forward island. 660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = islands.first->findStub(prototype, pReloc); 670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (stub != NULL) { 680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // reset the branch target to the stub instead! 690dea6bc96bb52346737966839ac68644f7939f58Stephen Hines pReloc.setSymInfo(stub->symInfo()); 700dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } else { 710dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // create a stub from the prototype 720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = prototype->clone(); 7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // build a name for stub symbol 750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines std::string name("__"); 760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines name.append(pReloc.symInfo()->name()) 770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines .append("_") 780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines .append(stub->name()) 790dea6bc96bb52346737966839ac68644f7939f58Stephen Hines .append("@") 800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines .append(islands.first->name()); 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 820dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // create LDSymbol for the stub 830dea6bc96bb52346737966839ac68644f7939f58Stephen Hines LDSymbol* symbol = 840dea6bc96bb52346737966839ac68644f7939f58Stephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines name, 860dea6bc96bb52346737966839ac68644f7939f58Stephen Hines ResolveInfo::Function, 870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines ResolveInfo::Define, 880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines ResolveInfo::Local, 8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines stub->size(), // size 9037b74a387bb3993387029859c2d9d051c41c724eStephen Hines stub->initSymValue(), // value 910dea6bc96bb52346737966839ac68644f7939f58Stephen Hines FragmentRef::Create(*stub, stub->initSymValue()), 920dea6bc96bb52346737966839ac68644f7939f58Stephen Hines ResolveInfo::Default); 930dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub->setSymInfo(symbol->resolveInfo()); 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines // add relocations of this stub (i.e., set the branch target of the 9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines // stub) 970dea6bc96bb52346737966839ac68644f7939f58Stephen Hines for (Stub::fixup_iterator it = stub->fixup_begin(), 9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines ie = stub->fixup_end(); 9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) { 1010dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Relocation* reloc = 1020dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Relocation::Create((*it)->type(), 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *(FragmentRef::Create(*stub, (*it)->offset())), 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao (*it)->addend()); 1050dea6bc96bb52346737966839ac68644f7939f58Stephen Hines reloc->setSymInfo(pReloc.symInfo()); 1060dea6bc96bb52346737966839ac68644f7939f58Stephen Hines islands.first->addRelocation(*reloc); 1070dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1090dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // add stub to the forward branch island 1100dea6bc96bb52346737966839ac68644f7939f58Stephen Hines islands.first->addStub(prototype, pReloc, *stub); 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1120dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // reset the branch target of the input reloc to this stub instead! 1130dea6bc96bb52346737966839ac68644f7939f58Stephen Hines pReloc.setSymInfo(stub->symInfo()); 1140dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 1170dea6bc96bb52346737966839ac68644f7939f58Stephen Hines return stub; 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc, 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pSource, 12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t pTargetSymValue) { 12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) { 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue)) 12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (*it); 13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return NULL; 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines 13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 135