1/* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "bcc/Linker.h" 18#include "bcc/Support/LinkerConfig.h" 19#include "bcc/Support/Log.h" 20 21#include <llvm/Support/ELF.h> 22 23#include <mcld/Module.h> 24#include <mcld/IRBuilder.h> 25#include <mcld/MC/MCLDInput.h> 26#include <mcld/Linker.h> 27#include <mcld/LD/LDSection.h> 28#include <mcld/LD/LDContext.h> 29#include <mcld/Support/Path.h> 30 31using namespace bcc; 32 33const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) { 34 static const char* ErrorString[] = { 35 /* kSuccess */ 36 "Successfully compiled.", 37 /* kDoubleConfig */ 38 "Configure Linker twice.", 39 /* kDelegateLDInfo */ 40 "Cannot get linker information", 41 /* kFindNameSpec */ 42 "Cannot find -lnamespec", 43 /* kOpenObjectFile */ 44 "Cannot open object file", 45 /* kNotConfig */ 46 "Linker::config() is not called", 47 /* kNotSetUpOutput */ 48 "Linker::setOutput() is not called before add input files", 49 /* kOpenOutput */ 50 "Cannot open output file", 51 /* kReadSections */ 52 "Cannot read sections", 53 /* kReadSymbols */ 54 "Cannot read symbols", 55 /* kAddAdditionalSymbols */ 56 "Cannot add standard and target symbols", 57 /* kMaxErrorCode */ 58 "(Unknown error code)" 59 }; 60 61 if (pErrCode > kMaxErrorCode) { 62 pErrCode = kMaxErrorCode; 63 } 64 65 return ErrorString[ static_cast<size_t>(pErrCode) ]; 66} 67 68//===----------------------------------------------------------------------===// 69// Linker 70//===----------------------------------------------------------------------===// 71Linker::Linker() 72 : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL), 73 mOutputHandler(-1) { 74} 75 76Linker::Linker(const LinkerConfig& pConfig) 77 : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL), 78 mOutputHandler(-1) { 79 80 const std::string &triple = pConfig.getTriple(); 81 82 enum ErrorCode err = config(pConfig); 83 if (kSuccess != err) { 84 ALOGE("%s (%s)", GetErrorString(err), triple.c_str()); 85 return; 86 } 87 88 return; 89} 90 91Linker::~Linker() { 92 delete mModule; 93 delete mLinker; 94 delete mBuilder; 95} 96 97enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) { 98 mLDConfig = pConfig.getLDConfig(); 99 if (mLDConfig == NULL) { 100 return kDelegateLDInfo; 101 } 102 return kSuccess; 103} 104 105enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) { 106 if (mLDConfig != NULL) { 107 return kDoubleConfig; 108 } 109 110 extractFiles(pConfig); 111 112 mModule = new mcld::Module(mLDConfig->options().soname()); 113 114 mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig); 115 116 mLinker = new mcld::Linker(); 117 118 mLinker->config(const_cast<mcld::LinkerConfig&>(*mLDConfig)); 119 120 return kSuccess; 121} 122 123enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) { 124 mcld::Input* input = mBuilder->ReadInput(pNameSpec); 125 if (NULL == input) 126 return kFindNameSpec; 127 return kSuccess; 128} 129 130/// addObject - Add a object file by the filename. 131enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) { 132 mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath); 133 if (NULL == input) 134 return kOpenObjectFile; 135 return kSuccess; 136} 137 138/// addObject - Add a piece of memory. The memory is of ELF format. 139enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) { 140 mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize); 141 if (NULL == input) 142 return kOpenMemory; 143 return kSuccess; 144} 145 146enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) { 147 mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object); 148 mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text", 149 llvm::ELF::SHT_PROGBITS, 150 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR, 151 0x1); 152 mcld::SectionData* data = mBuilder->CreateSectionData(*sect); 153 mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize); 154 mBuilder->AppendFragment(*frag, *data); 155 return kSuccess; 156} 157 158enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) { 159 mOutputPath = pPath; 160 return kSuccess; 161} 162 163enum Linker::ErrorCode Linker::setOutput(int pFileHandler) { 164 mOutputHandler = pFileHandler; 165 return kSuccess; 166} 167 168enum Linker::ErrorCode Linker::link() { 169 mLinker->link(*mModule, *mBuilder); 170 if (!mOutputPath.empty()) { 171 mLinker->emit(mOutputPath); 172 return kSuccess; 173 } 174 175 if (-1 != mOutputHandler) { 176 mLinker->emit(mOutputHandler); 177 return kSuccess; 178 } 179 return kNotSetUpOutput; 180} 181 182