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/Support/LinkerConfig.h" 18#include "bcc/Support/Log.h" 19 20#include <llvm/Support/Signals.h> 21 22#include <mcld/MC/MCLDInfo.h> 23#include <mcld/MC/MCLDFile.h> 24#include <mcld/MC/MCLDDirectory.h> 25#include <mcld/LD/TextDiagnosticPrinter.h> 26#include <mcld/Support/Path.h> 27#include <mcld/Support/MsgHandling.h> 28#include <mcld/Support/raw_ostream.h> 29 30using namespace bcc; 31 32LinkerConfig::LinkerConfig(const std::string &pTriple) 33 : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL), 34 mDiagLineInfo(NULL), mDiagPrinter(NULL) { 35 36 initializeTarget(); 37 initializeLDInfo(); 38 initializeDiagnostic(); 39} 40 41LinkerConfig::~LinkerConfig() { 42 delete mLDInfo; 43 44 if (mDiagPrinter->getNumErrors() != 0) { 45 // If here, the program failed ungracefully. Run the interrupt handlers to 46 // ensure any other cleanups (e.g., files that registered by 47 // RemoveFileOnSignal(...)) getting done before exit. 48 llvm::sys::RunInterruptHandlers(); 49 } 50 mDiagPrinter->finish(); 51 52 delete mDiagLineInfo; 53 delete mDiagPrinter; 54} 55 56bool LinkerConfig::initializeTarget() { 57 std::string error; 58 mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error); 59 if (NULL != mTarget) { 60 return true; 61 } else { 62 ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n", 63 mTriple.c_str(), error.c_str()); 64 return false; 65 } 66} 67 68bool LinkerConfig::initializeLDInfo() { 69 if (NULL != mLDInfo) { 70 ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n", 71 mTriple.c_str()); 72 return false; 73 } 74 75 mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32); 76 return true; 77} 78 79bool LinkerConfig::initializeDiagnostic() { 80 // Set up MsgHandler. 81 mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple); 82 83 mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo); 84 85 mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter); 86 87 return true; 88} 89 90void LinkerConfig::setShared(bool pEnable) { 91 mShared = pEnable; 92 return; 93} 94 95void LinkerConfig::setBsymbolic(bool pEnable) { 96 mLDInfo->options().setBsymbolic(pEnable); 97 return; 98} 99 100void LinkerConfig::setSOName(const std::string &pSOName) { 101 mSOName = pSOName; 102 return; 103} 104 105void LinkerConfig::setDyld(const std::string &pDyld) { 106 mLDInfo->options().setDyld(pDyld); 107 return; 108} 109 110void LinkerConfig::setSysRoot(const std::string &pSysRoot) { 111 mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot)); 112 return; 113} 114 115void LinkerConfig::addWrap(const std::string &pWrapSymbol) { 116 bool exist = false; 117 118 // Add wname -> __wrap_wname. 119 mcld::StringEntry<llvm::StringRef>* to_wrap = 120 mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist); 121 122 std::string to_wrap_str = "__wrap_" + pWrapSymbol; 123 to_wrap->setValue(to_wrap_str); 124 125 if (exist) { 126 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str; 127 } 128 129 // Add __real_wname -> wname. 130 std::string from_real_str = "__real_" + pWrapSymbol; 131 mcld::StringEntry<llvm::StringRef>* from_real = 132 mLDInfo->scripts().renameMap().insert(from_real_str, exist); 133 from_real->setValue(pWrapSymbol); 134 135 if (exist) { 136 mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str; 137 } 138 139 return; 140} 141 142void LinkerConfig::addPortable(const std::string &pPortableSymbol) { 143 bool exist = false; 144 145 // Add pname -> pname_portable. 146 mcld::StringEntry<llvm::StringRef>* to_port = 147 mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist); 148 149 std::string to_port_str = pPortableSymbol + "_portable"; 150 to_port->setValue(to_port_str); 151 152 if (exist) { 153 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str; 154} 155 156 // Add __real_pname -> pname. 157 std::string from_real_str = "__real_" + pPortableSymbol; 158 mcld::StringEntry<llvm::StringRef>* from_real = 159 mLDInfo->scripts().renameMap().insert(from_real_str, exist); 160 161 from_real->setValue(pPortableSymbol); 162 163 if (exist) { 164 mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str; 165 } 166 167 return; 168} 169 170void LinkerConfig::addSearchDir(const std::string &pDirPath) { 171 // SearchDirs will remove the created MCLDDirectory. 172 mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath); 173 174 if (sd->isInSysroot()) { 175 sd->setSysroot(mLDInfo->options().sysroot()); 176 } 177 178 if (exists(sd->path()) && is_directory(sd->path())) { 179 mLDInfo->options().directories().add(*sd); 180 } else { 181 mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name(); 182 } 183 184 return; 185} 186