1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- Linker.cpp ---------------------------------------------------------===// 2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// The MCLinker Project 4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source 6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details. 7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===// 967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "alone/Linker.h" 11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "alone/Support/LinkerConfig.h" 1267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao#include "alone/Support/Log.h" 13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/ELF.h> 15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Module.h> 1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/IRBuilder.h> 18d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/MC/MCLDInput.h> 19d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/Linker.h> 20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/LDSection.h> 21affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/LDContext.h> 22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/Path.h> 23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 24affc150dc44fab1911775a49636d0ce85333b634Zonr Changusing namespace alone; 25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoconst char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) { 27affc150dc44fab1911775a49636d0ce85333b634Zonr Chang static const char* ErrorString[] = { 28affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kSuccess */ 29affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Successfully compiled.", 30affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kDoubleConfig */ 31affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Configure Linker twice.", 32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kDelegateLDInfo */ 33affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot get linker information", 3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao /* kFindNameSpec */ 3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao "Cannot find -lnamespec", 36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kOpenObjectFile */ 37affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot open object file", 38affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kNotConfig */ 39affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Linker::config() is not called", 40affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kNotSetUpOutput */ 41affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Linker::setOutput() is not called before add input files", 42affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kOpenOutput */ 43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot open output file", 44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kReadSections */ 45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot read sections", 46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kReadSymbols */ 47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot read symbols", 48affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kAddAdditionalSymbols */ 49affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "Cannot add standard and target symbols", 50affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /* kMaxErrorCode */ 51affc150dc44fab1911775a49636d0ce85333b634Zonr Chang "(Unknown error code)" 52affc150dc44fab1911775a49636d0ce85333b634Zonr Chang }; 53affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 54affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (pErrCode > kMaxErrorCode) { 55affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pErrCode = kMaxErrorCode; 56affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 57affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 58affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return ErrorString[ static_cast<size_t>(pErrCode) ]; 59affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 60affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===// 62affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Linker 63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===// 64affc150dc44fab1911775a49636d0ce85333b634Zonr ChangLinker::Linker() 65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL), 66d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mOutputHandler(-1) { 67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 68affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 69affc150dc44fab1911775a49636d0ce85333b634Zonr ChangLinker::Linker(const LinkerConfig& pConfig) 70d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL), 71d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mOutputHandler(-1) { 72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 73affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const std::string &triple = pConfig.getTriple(); 74affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang enum ErrorCode err = config(pConfig); 76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (kSuccess != err) { 77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ALOGE("%s (%s)", GetErrorString(err), triple.c_str()); 78affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return; 79affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 80affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return; 82affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 83affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 8467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei LiaoLinker::~Linker() { 8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete mModule; 86d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao delete mLinker; 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete mBuilder; 88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 9067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) { 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao mLDConfig = pConfig.getLDConfig(); 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (mLDConfig == NULL) { 93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kDelegateLDInfo; 9467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao } 95affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kSuccess; 96affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 9867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) { 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (mLDConfig != NULL) { 100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kDoubleConfig; 10167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao } 102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 103affc150dc44fab1911775a49636d0ce85333b634Zonr Chang extractFiles(pConfig); 104affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines mModule = new mcld::Module(mLDConfig->options().soname(), 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const_cast<mcld::LinkerScript&>(*pConfig.getLDScript())); 107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 108d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig); 109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 110d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mLinker = new mcld::Linker(); 111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines mLinker->emulate(const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()), 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines const_cast<mcld::LinkerConfig&>(*mLDConfig)); 114affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kSuccess; 116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 11867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) { 119d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::Input* input = mBuilder->ReadInput(pNameSpec); 120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (NULL == input) 12167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao return kFindNameSpec; 122d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kSuccess; 123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// addObject - Add a object file by the filename. 12667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) { 127d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath); 128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (NULL == input) 129d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kOpenObjectFile; 130d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kSuccess; 131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// addObject - Add a piece of memory. The memory is of ELF format. 13467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) { 135d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize); 136d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (NULL == input) 137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kOpenMemory; 138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kSuccess; 139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 14167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) { 142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object); 143d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text", 144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao llvm::ELF::SHT_PROGBITS, 145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR, 146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 0x1); 147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::SectionData* data = mBuilder->CreateSectionData(*sect); 148d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize); 149d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mBuilder->AppendFragment(*frag, *data); 150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kSuccess; 151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 15367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::setOutput(const std::string &pPath) { 154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mOutputPath = pPath; 155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return kSuccess; 156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 15867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liaoenum Linker::ErrorCode Linker::setOutput(int pFileHandler) { 159d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mOutputHandler = pFileHandler; 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return kSuccess; 16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 162affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoenum Linker::ErrorCode Linker::link() { 164d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mLinker->link(*mModule, *mBuilder); 165d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (!mOutputPath.empty()) { 166d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mLinker->emit(mOutputPath); 167d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kSuccess; 16867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao } 16967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao 170d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (-1 != mOutputHandler) { 171d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao mLinker->emit(mOutputHandler); 172d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kSuccess; 17367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao } 174d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return kNotSetUpOutput; 175affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 177