Files
clang-p2996/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
Shankar Easwaran 9af77a2cab [lld][ELF][All Archs] Addend is used by dynamic relocations
only if they are relative. This removes the FIXME when the
relocations are being emitted and checks if the relocation
is relative and only then populates the addend information.

I couldnt add a testcase for this as llvm-readobj lacks     
functionality of printing dynamic relocations.              

When the functionality is added, remove the commented lines
from elf/ifunc.test to test functionality.

llvm-svn: 182077
2013-05-17 05:10:30 +00:00

170 lines
4.8 KiB
C++

//===- lib/ReaderWriter/ELF/ELFTargetInfo.cpp -----------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "TargetHandler.h"
#include "Targets.h"
#include "lld/Core/Instrumentation.h"
#include "lld/Passes/LayoutPass.h"
#include "lld/ReaderWriter/ReaderLinkerScript.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
namespace lld {
ELFTargetInfo::ELFTargetInfo(llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
: _outputFileType(elf::ET_EXEC),
_triple(triple),
_targetHandler(std::move(targetHandler)),
_baseAddress(0),
_isStaticExecutable(false),
_outputYAML(false),
_noInhibitExec(false),
_mergeCommonStrings(false),
_runLayoutPass(true),
_useShlibUndefines(false) {}
bool ELFTargetInfo::is64Bits() const {
return getTriple().isArch64Bit();
}
bool ELFTargetInfo::isLittleEndian() const {
// TODO: Do this properly. It is not defined purely by arch.
return true;
}
void ELFTargetInfo::addPasses(PassManager &pm) const {
if (_runLayoutPass)
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
}
uint16_t ELFTargetInfo::getOutputMachine() const {
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");
}
}
bool ELFTargetInfo::validate(raw_ostream &diagnostics) {
if (_outputFileType == elf::ET_EXEC &&
_entrySymbolName.empty()) {
_entrySymbolName = "_start";
}
if (_inputFiles.empty()) {
diagnostics << "No input files\n";
return true;
}
_elfReader = createReaderELF(*this);
_yamlReader = createReaderYAML(*this);
_linkerScriptReader.reset(new ReaderLinkerScript(*this));
_writer = _outputYAML ? createWriterYAML(*this) : createWriterELF(*this);
return false;
}
bool ELFTargetInfo::isDynamic() const {
switch (_outputFileType) {
case llvm::ELF::ET_EXEC:
return !_isStaticExecutable;
case llvm::ELF::ET_DYN:
return true;
}
return false;
}
bool ELFTargetInfo::isRelativeReloc(const Reference &) const { return false; }
error_code
ELFTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
std::vector<std::unique_ptr<File> > &result) const {
error_code ec = _elfReader->parseFile(mb, result);
if (ec) {
// Not an ELF file, check file extension to see if it might be yaml
StringRef path = mb->getBufferIdentifier();
if (path.endswith(".objtxt"))
ec = _yamlReader->parseFile(mb, result);
if (ec)
// Not a yaml file, assume it is a linkerscript
ec = _linkerScriptReader->parseFile(mb, result);
}
return ec;
}
Writer &ELFTargetInfo::writer() const {
return *_writer;
}
std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(llvm::Triple triple) {
switch (triple.getArch()) {
case llvm::Triple::x86:
return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(triple));
case llvm::Triple::x86_64:
return std::unique_ptr<
ELFTargetInfo>(new lld::elf::X86_64TargetInfo(triple));
case llvm::Triple::hexagon:
return std::unique_ptr<
ELFTargetInfo>(new lld::elf::HexagonTargetInfo(triple));
case llvm::Triple::ppc:
return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(triple));
default:
return nullptr;
}
}
bool ELFTargetInfo::appendLibrary(StringRef libName) {
bool foundFile = false;
StringRef pathref;
for (StringRef dir : _inputSearchPaths) {
// Search for dynamic library
if (!_isStaticExecutable) {
SmallString<128> dynlibPath;
dynlibPath.assign(dir);
llvm::sys::path::append(dynlibPath, Twine("lib") + libName + ".so");
pathref = dynlibPath.str();
if (llvm::sys::fs::exists(pathref)) {
foundFile = true;
}
}
// Search for static libraries too
if (!foundFile) {
SmallString<128> archivefullPath;
archivefullPath.assign(dir);
llvm::sys::path::append(archivefullPath, Twine("lib") + libName + ".a");
pathref = archivefullPath.str();
if (llvm::sys::fs::exists(pathref)) {
foundFile = true;
}
}
if (foundFile) {
unsigned pathlen = pathref.size();
char *x = _extraStrings.Allocate<char>(pathlen);
memcpy(x, pathref.data(), pathlen);
appendInputFile(StringRef(x, pathlen));
return false;
}
}
return true;
}
} // end namespace lld