2013-08-07 06:31:59 +08:00
|
|
|
//===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
|
2013-01-22 10:15:30 +08:00
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
2013-01-22 10:15:30 +08:00
|
|
|
|
2013-10-26 07:59:06 +08:00
|
|
|
#include "ArrayOrderPass.h"
|
2013-08-31 13:27:38 +08:00
|
|
|
#include "File.h"
|
2013-01-30 06:03:39 +08:00
|
|
|
#include "TargetHandler.h"
|
|
|
|
#include "Targets.h"
|
2013-01-30 03:53:41 +08:00
|
|
|
|
2013-05-07 08:28:07 +08:00
|
|
|
#include "lld/Core/Instrumentation.h"
|
2013-02-08 04:16:12 +08:00
|
|
|
#include "lld/Passes/LayoutPass.h"
|
2013-10-29 13:12:14 +08:00
|
|
|
#include "lld/Passes/RoundTripNativePass.h"
|
|
|
|
#include "lld/Passes/RoundTripYAMLPass.h"
|
2013-01-22 10:15:30 +08:00
|
|
|
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "llvm/Support/ELF.h"
|
2013-03-01 08:03:36 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2013-04-05 02:59:24 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2013-01-22 10:15:30 +08:00
|
|
|
|
|
|
|
namespace lld {
|
2013-08-31 13:27:38 +08:00
|
|
|
|
|
|
|
class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
|
|
|
|
public:
|
|
|
|
CommandLineUndefinedAtom(const File &f, StringRef name)
|
|
|
|
: SimpleUndefinedAtom(f, name) {}
|
|
|
|
|
|
|
|
virtual CanBeNull canBeNull() const {
|
|
|
|
return CanBeNull::canBeNullAtBuildtime;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
ELFLinkingContext::ELFLinkingContext(
|
|
|
|
llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
|
2013-09-23 12:24:15 +08:00
|
|
|
: _outputELFType(elf::ET_EXEC), _triple(triple),
|
2013-08-07 06:31:59 +08:00
|
|
|
_targetHandler(std::move(targetHandler)), _baseAddress(0),
|
2013-09-23 12:24:15 +08:00
|
|
|
_isStaticExecutable(false), _noInhibitExec(false),
|
2013-08-07 06:31:59 +08:00
|
|
|
_mergeCommonStrings(false), _runLayoutPass(true),
|
2013-11-25 12:28:57 +08:00
|
|
|
_useShlibUndefines(true), _dynamicLinkerArg(false),
|
2013-09-04 00:29:02 +08:00
|
|
|
_noAllowDynamicLibraries(false), _outputMagic(OutputMagic::DEFAULT),
|
|
|
|
_sysrootPath("") {}
|
2013-04-05 02:59:24 +08:00
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); }
|
2013-04-05 02:59:24 +08:00
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
bool ELFLinkingContext::isLittleEndian() const {
|
2013-04-05 02:59:24 +08:00
|
|
|
// TODO: Do this properly. It is not defined purely by arch.
|
|
|
|
return true;
|
2013-01-22 10:15:30 +08:00
|
|
|
}
|
|
|
|
|
2013-10-29 13:12:14 +08:00
|
|
|
void ELFLinkingContext::addPasses(PassManager &pm) {
|
2013-04-05 02:59:24 +08:00
|
|
|
if (_runLayoutPass)
|
|
|
|
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
|
2013-10-26 07:59:06 +08:00
|
|
|
pm.add(std::unique_ptr<Pass>(new elf::ArrayOrderPass()));
|
2013-02-08 04:16:12 +08:00
|
|
|
}
|
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
uint16_t ELFLinkingContext::getOutputMachine() const {
|
2013-01-22 10:15:30 +08:00
|
|
|
switch (getTriple().getArch()) {
|
|
|
|
case llvm::Triple::x86:
|
|
|
|
return llvm::ELF::EM_386;
|
|
|
|
case llvm::Triple::x86_64:
|
|
|
|
return llvm::ELF::EM_X86_64;
|
|
|
|
case llvm::Triple::hexagon:
|
|
|
|
return llvm::ELF::EM_HEXAGON;
|
|
|
|
case llvm::Triple::ppc:
|
|
|
|
return llvm::ELF::EM_PPC;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unhandled arch");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-31 13:27:38 +08:00
|
|
|
StringRef ELFLinkingContext::entrySymbolName() const {
|
2013-09-23 12:24:15 +08:00
|
|
|
if (_outputELFType == elf::ET_EXEC && _entrySymbolName.empty())
|
2013-08-31 13:27:38 +08:00
|
|
|
return "_start";
|
|
|
|
return _entrySymbolName;
|
|
|
|
}
|
2013-04-05 11:50:15 +08:00
|
|
|
|
2013-08-31 13:27:38 +08:00
|
|
|
bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
2013-05-07 08:28:07 +08:00
|
|
|
_elfReader = createReaderELF(*this);
|
2013-09-23 12:24:15 +08:00
|
|
|
switch (outputFileType()) {
|
|
|
|
case LinkingContext::OutputFileType::YAML:
|
|
|
|
_writer = createWriterYAML(*this);
|
|
|
|
break;
|
|
|
|
case LinkingContext::OutputFileType::Native:
|
|
|
|
llvm_unreachable("Unimplemented");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_writer = createWriterELF(*this);
|
|
|
|
break;
|
|
|
|
}
|
2013-09-25 07:26:34 +08:00
|
|
|
return true;
|
2013-04-05 02:59:24 +08:00
|
|
|
}
|
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
bool ELFLinkingContext::isDynamic() const {
|
2013-09-23 12:24:15 +08:00
|
|
|
switch (_outputELFType) {
|
2013-04-05 02:59:24 +08:00
|
|
|
case llvm::ELF::ET_EXEC:
|
2013-05-17 01:53:34 +08:00
|
|
|
return !_isStaticExecutable;
|
2013-04-05 02:59:24 +08:00
|
|
|
case llvm::ELF::ET_DYN:
|
|
|
|
return true;
|
2013-03-01 08:03:36 +08:00
|
|
|
}
|
2013-04-05 02:59:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-03-01 08:03:36 +08:00
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
|
|
|
|
return false;
|
|
|
|
}
|
2013-05-17 13:10:30 +08:00
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
Writer &ELFLinkingContext::writer() const { return *_writer; }
|
2013-04-05 02:59:24 +08:00
|
|
|
|
2013-08-07 06:31:59 +08:00
|
|
|
std::unique_ptr<ELFLinkingContext>
|
|
|
|
ELFLinkingContext::create(llvm::Triple triple) {
|
2013-04-05 02:59:24 +08:00
|
|
|
switch (triple.getArch()) {
|
2013-01-22 10:15:30 +08:00
|
|
|
case llvm::Triple::x86:
|
2013-08-07 06:31:59 +08:00
|
|
|
return std::unique_ptr<ELFLinkingContext>(
|
|
|
|
new lld::elf::X86LinkingContext(triple));
|
2013-01-22 10:15:30 +08:00
|
|
|
case llvm::Triple::x86_64:
|
2013-08-07 06:31:59 +08:00
|
|
|
return std::unique_ptr<ELFLinkingContext>(
|
|
|
|
new lld::elf::X86_64LinkingContext(triple));
|
2013-01-22 10:15:30 +08:00
|
|
|
case llvm::Triple::hexagon:
|
2013-08-07 06:31:59 +08:00
|
|
|
return std::unique_ptr<ELFLinkingContext>(
|
|
|
|
new lld::elf::HexagonLinkingContext(triple));
|
2013-01-22 10:15:30 +08:00
|
|
|
case llvm::Triple::ppc:
|
2013-08-07 06:31:59 +08:00
|
|
|
return std::unique_ptr<ELFLinkingContext>(
|
|
|
|
new lld::elf::PPCLinkingContext(triple));
|
2013-01-22 10:15:30 +08:00
|
|
|
default:
|
2013-05-17 01:53:34 +08:00
|
|
|
return nullptr;
|
2013-01-22 10:15:30 +08:00
|
|
|
}
|
|
|
|
}
|
2013-01-28 12:15:44 +08:00
|
|
|
|
2013-11-25 11:55:34 +08:00
|
|
|
ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
|
2013-04-05 11:50:15 +08:00
|
|
|
bool foundFile = false;
|
|
|
|
StringRef pathref;
|
2013-09-26 06:12:14 +08:00
|
|
|
SmallString<128> path;
|
2013-11-25 11:55:34 +08:00
|
|
|
for (StringRef dir : _inputSearchPaths) {
|
2013-04-05 11:50:15 +08:00
|
|
|
// Search for dynamic library
|
|
|
|
if (!_isStaticExecutable) {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.clear();
|
2013-09-04 00:29:02 +08:00
|
|
|
if (dir.startswith("=/")) {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.assign(_sysrootPath);
|
|
|
|
path.append(dir.substr(1));
|
2013-09-04 00:29:02 +08:00
|
|
|
} else {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.assign(dir);
|
2013-09-04 00:29:02 +08:00
|
|
|
}
|
2013-09-26 06:12:14 +08:00
|
|
|
llvm::sys::path::append(path, Twine("lib") + libName + ".so");
|
|
|
|
pathref = path.str();
|
2013-04-05 11:50:15 +08:00
|
|
|
if (llvm::sys::fs::exists(pathref)) {
|
|
|
|
foundFile = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Search for static libraries too
|
|
|
|
if (!foundFile) {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.clear();
|
2013-09-04 00:29:02 +08:00
|
|
|
if (dir.startswith("=/")) {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.assign(_sysrootPath);
|
|
|
|
path.append(dir.substr(1));
|
2013-09-04 00:29:02 +08:00
|
|
|
} else {
|
2013-09-26 06:12:14 +08:00
|
|
|
path.assign(dir);
|
2013-09-04 00:29:02 +08:00
|
|
|
}
|
2013-09-26 06:12:14 +08:00
|
|
|
llvm::sys::path::append(path, Twine("lib") + libName + ".a");
|
|
|
|
pathref = path.str();
|
2013-04-05 11:50:15 +08:00
|
|
|
if (llvm::sys::fs::exists(pathref)) {
|
|
|
|
foundFile = true;
|
|
|
|
}
|
|
|
|
}
|
2013-08-22 06:57:10 +08:00
|
|
|
if (foundFile)
|
2013-10-08 23:43:48 +08:00
|
|
|
return StringRef(*new (_allocator) std::string(pathref));
|
2013-04-05 02:59:24 +08:00
|
|
|
}
|
2013-09-04 06:44:37 +08:00
|
|
|
if (!llvm::sys::fs::exists(libName))
|
|
|
|
return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
|
|
|
|
|
2013-09-26 06:12:14 +08:00
|
|
|
return libName;
|
2013-01-28 12:15:44 +08:00
|
|
|
}
|
|
|
|
|
2013-10-07 10:47:09 +08:00
|
|
|
std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() const {
|
2013-08-31 13:27:38 +08:00
|
|
|
if (_initialUndefinedSymbols.empty())
|
|
|
|
return nullptr;
|
|
|
|
std::unique_ptr<SimpleFile> undefinedSymFile(
|
|
|
|
new SimpleFile(*this, "command line option -u"));
|
|
|
|
for (auto undefSymStr : _initialUndefinedSymbols)
|
|
|
|
undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom(
|
|
|
|
*undefinedSymFile, undefSymStr)));
|
|
|
|
return std::move(undefinedSymFile);
|
|
|
|
}
|
|
|
|
|
2013-01-22 10:15:30 +08:00
|
|
|
} // end namespace lld
|