blob: bdbde232f04ad094e13e7a47f6bfe8ef19644d88 [file] [log] [blame]
/*
* Copyright 2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bcc/Support/LinkerConfig.h"
#include "bcc/Support/Log.h"
#include <llvm/Support/Signals.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/MC/MCLDFile.h>
#include <mcld/MC/MCLDDirectory.h>
#include <mcld/LD/TextDiagnosticPrinter.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/raw_ostream.h>
using namespace bcc;
LinkerConfig::LinkerConfig(const std::string &pTriple)
: mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
mDiagLineInfo(NULL), mDiagPrinter(NULL) {
initializeTarget();
initializeLDInfo();
initializeDiagnostic();
}
LinkerConfig::~LinkerConfig() {
delete mLDInfo;
if (mDiagPrinter->getNumErrors() != 0) {
// If here, the program failed ungracefully. Run the interrupt handlers to
// ensure any other cleanups (e.g., files that registered by
// RemoveFileOnSignal(...)) getting done before exit.
llvm::sys::RunInterruptHandlers();
}
mDiagPrinter->finish();
delete mDiagLineInfo;
delete mDiagPrinter;
}
bool LinkerConfig::initializeTarget() {
std::string error;
mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
if (NULL != mTarget) {
return true;
} else {
ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
mTriple.c_str(), error.c_str());
return false;
}
}
bool LinkerConfig::initializeLDInfo() {
if (NULL != mLDInfo) {
ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
mTriple.c_str());
return false;
}
mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
return true;
}
bool LinkerConfig::initializeDiagnostic() {
// Set up MsgHandler.
mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
return true;
}
void LinkerConfig::setShared(bool pEnable) {
mShared = pEnable;
return;
}
void LinkerConfig::setBsymbolic(bool pEnable) {
mLDInfo->options().setBsymbolic(pEnable);
return;
}
void LinkerConfig::setSOName(const std::string &pSOName) {
mSOName = pSOName;
return;
}
void LinkerConfig::setDyld(const std::string &pDyld) {
mLDInfo->options().setDyld(pDyld);
return;
}
void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
return;
}
void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
bool exist = false;
// Add wname -> __wrap_wname.
mcld::StringEntry<llvm::StringRef>* to_wrap =
mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist);
std::string to_wrap_str = "__wrap_" + pWrapSymbol;
to_wrap->setValue(to_wrap_str);
if (exist) {
mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
}
// Add __real_wname -> wname.
std::string from_real_str = "__real_" + pWrapSymbol;
mcld::StringEntry<llvm::StringRef>* from_real =
mLDInfo->scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(pWrapSymbol);
if (exist) {
mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
}
return;
}
void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
bool exist = false;
// Add pname -> pname_portable.
mcld::StringEntry<llvm::StringRef>* to_port =
mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
std::string to_port_str = pPortableSymbol + "_portable";
to_port->setValue(to_port_str);
if (exist) {
mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
}
// Add __real_pname -> pname.
std::string from_real_str = "__real_" + pPortableSymbol;
mcld::StringEntry<llvm::StringRef>* from_real =
mLDInfo->scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(pPortableSymbol);
if (exist) {
mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
}
return;
}
void LinkerConfig::addSearchDir(const std::string &pDirPath) {
// SearchDirs will remove the created MCLDDirectory.
mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
if (sd->isInSysroot()) {
sd->setSysroot(mLDInfo->options().sysroot());
}
if (exists(sd->path()) && is_directory(sd->path())) {
mLDInfo->options().directories().add(*sd);
} else {
mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
}
return;
}