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" 12b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines#include "mcld/Fragment/FragmentRef.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIsland.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h" 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <string> 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// StubFactory 26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===// 2737b74a387bb3993387029859c2d9d051c41c724eStephen HinesStubFactory::~StubFactory() { 2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end(); 2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines it != ie; 3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines ++it) 3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines delete (*it); 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// addPrototype - register a stub prototype 3537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid StubFactory::addPrototype(Stub* pPrototype) { 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, 4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines BranchIslandFactory& pBRIslandFactory) { 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // find if there is a prototype stub for the input relocation 450dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Stub* stub = NULL; 460dea6bc96bb52346737966839ac68644f7939f58Stephen Hines Stub* prototype = findPrototype(pReloc, pReloc.place(), pTargetSymValue); 470dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (prototype != NULL) { 480dea6bc96bb52346737966839ac68644f7939f58Stephen Hines const Fragment* frag = pReloc.targetRef().frag(); 490dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find the islands for the input relocation 500dea6bc96bb52346737966839ac68644f7939f58Stephen Hines std::pair<BranchIsland*, BranchIsland*> islands = 510dea6bc96bb52346737966839ac68644f7939f58Stephen Hines pBRIslandFactory.getIslands(*frag); 520dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (islands.first == NULL) { 530dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // early exit if we can not find the forward island. 5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return NULL; 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 570dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find if there is such a stub in the backward island first. 580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines if (islands.second != NULL) { 590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = islands.second->findStub(prototype, pReloc); 600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines 62b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (stub == NULL) { 630dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // find if there is such a stub in the forward island. 640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = islands.first->findStub(prototype, pReloc); 65b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (stub == NULL) { 660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // create a stub from the prototype 670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines stub = prototype->clone(); 6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 69b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // apply fixups in this new stub 70b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines stub->applyFixup(pReloc, pBuilder, *islands.first); 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines // add stub to the forward branch island 730dea6bc96bb52346737966839ac68644f7939f58Stephen Hines islands.first->addStub(prototype, pReloc, *stub); 740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines } 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines return stub; 7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 80b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesStub* StubFactory::create(FragmentRef& pFragRef, 81b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines IRBuilder& pBuilder, 82b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines BranchIslandFactory& pBRIslandFactory) { 83b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Stub* prototype = findPrototype(pFragRef); 84b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (prototype == NULL) { 85b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return NULL; 86b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 87b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines std::pair<BranchIsland*, BranchIsland*> islands = 88b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines pBRIslandFactory.getIslands(*(pFragRef.frag())); 89b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // early exit if we can not find the forward island. 90b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if (islands.first == NULL) { 91b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return NULL; 92b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } else { 93b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // create a stub from the prototype 94b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines Stub* stub = prototype->clone(); 95b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 96b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // apply fixups in this new stub 97b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines stub->applyFixup(pFragRef, pBuilder, *islands.first); 98b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 99b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines // add stub to the forward branch island 100b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines islands.first->addStub(*stub); 101b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 102b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return stub; 103b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } // (islands.first == NULL) 104b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } // if (prototype == NULL) 105b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 106b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// findPrototype - find if there is a registered stub prototype for the given 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// relocation 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoStub* StubFactory::findPrototype(const Relocation& pReloc, 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pSource, 111b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines uint64_t pTargetSymValue) const { 112b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines for (StubPoolType::const_iterator it = m_StubPool.begin(), 113b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ie = m_StubPool.end(); it != ie; ++it) { 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue)) 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return (*it); 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return NULL; 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines 120b0d0eb206527b43c771933602e147bbd7b471082Stephen HinesStub* StubFactory::findPrototype(const FragmentRef& pFragRef) const { 121b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines for (StubPoolType::const_iterator it = m_StubPool.begin(), 122b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines ie = m_StubPool.end(); it != ie; ++it) { 123b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines if ((*it)->isMyDuty(pFragRef)) 124b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return (*it); 125b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines } 126b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines return NULL; 127b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines} 128b0d0eb206527b43c771933602e147bbd7b471082Stephen Hines 12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 130