Vendor import of lld trunk r291476:
https://llvm.org/svn/llvm-project/lld/trunk@291476
This commit is contained in:
parent
b8a5e9d616
commit
5d23c01cc5
@ -26,6 +26,7 @@
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdlib>
|
||||
@ -51,6 +52,7 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
|
||||
ErrorCount = 0;
|
||||
ErrorOS = &Error;
|
||||
Argv0 = Args[0];
|
||||
Tar = nullptr;
|
||||
|
||||
Config = make<Configuration>();
|
||||
Driver = make<LinkerDriver>();
|
||||
@ -170,25 +172,6 @@ void LinkerDriver::addFile(StringRef Path) {
|
||||
}
|
||||
}
|
||||
|
||||
Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
|
||||
if (Config->Verbose)
|
||||
outs() << Path << "\n";
|
||||
|
||||
auto MBOrErr = MemoryBuffer::getFile(Path);
|
||||
if (auto EC = MBOrErr.getError()) {
|
||||
error(EC, "cannot open " + Path);
|
||||
return None;
|
||||
}
|
||||
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
|
||||
MemoryBufferRef MBRef = MB->getMemBufferRef();
|
||||
make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
|
||||
|
||||
if (Tar)
|
||||
Tar->append(relativeToRoot(Path), MBRef.getBuffer());
|
||||
|
||||
return MBRef;
|
||||
}
|
||||
|
||||
// Add a given library by searching it from input search paths.
|
||||
void LinkerDriver::addLibrary(StringRef Name) {
|
||||
if (Optional<std::string> Path = searchLibrary(Name))
|
||||
@ -313,9 +296,10 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
|
||||
Expected<std::unique_ptr<TarWriter>> ErrOrWriter =
|
||||
TarWriter::create(Path, path::stem(Path));
|
||||
if (ErrOrWriter) {
|
||||
Tar = std::move(*ErrOrWriter);
|
||||
Tar = ErrOrWriter->get();
|
||||
Tar->append("response.txt", createResponseFile(Args));
|
||||
Tar->append("version.txt", getLLDVersion() + "\n");
|
||||
make<std::unique_ptr<TarWriter>>(std::move(*ErrOrWriter));
|
||||
} else {
|
||||
error(Twine("--reproduce: failed to open ") + Path + ": " +
|
||||
toString(ErrOrWriter.takeError()));
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace lld {
|
||||
@ -30,11 +29,9 @@ public:
|
||||
void main(ArrayRef<const char *> Args, bool CanExitEarly);
|
||||
void addFile(StringRef Path);
|
||||
void addLibrary(StringRef Name);
|
||||
std::unique_ptr<llvm::TarWriter> Tar; // for reproduce
|
||||
|
||||
private:
|
||||
std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
|
||||
llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
|
||||
void readConfigs(llvm::opt::InputArgList &Args);
|
||||
void createFiles(llvm::opt::InputArgList &Args);
|
||||
void inferMachineType();
|
||||
|
@ -8,7 +8,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InputFiles.h"
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "LinkerScript.h"
|
||||
@ -26,6 +25,7 @@
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -36,6 +36,8 @@ using namespace llvm::sys::fs;
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
TarWriter *elf::Tar;
|
||||
|
||||
namespace {
|
||||
// In ELF object file all section addresses are zero. If we have multiple
|
||||
// .text sections (when using -ffunction-section or comdat group) then
|
||||
@ -53,6 +55,24 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
Optional<MemoryBufferRef> elf::readFile(StringRef Path) {
|
||||
if (Config->Verbose)
|
||||
outs() << Path << "\n";
|
||||
|
||||
auto MBOrErr = MemoryBuffer::getFile(Path);
|
||||
if (auto EC = MBOrErr.getError()) {
|
||||
error(EC, "cannot open " + Path);
|
||||
return None;
|
||||
}
|
||||
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
|
||||
MemoryBufferRef MBRef = MB->getMemBufferRef();
|
||||
make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
|
||||
|
||||
if (Tar)
|
||||
Tar->append(relativeToRoot(Path), MBRef.getBuffer());
|
||||
return MBRef;
|
||||
}
|
||||
|
||||
template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() {
|
||||
std::unique_ptr<object::ObjectFile> Obj =
|
||||
check(object::ObjectFile::createObjectFile(this->MB),
|
||||
@ -398,6 +418,14 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
|
||||
if (Config->Strip != StripPolicy::None && Name.startswith(".debug"))
|
||||
return &InputSection<ELFT>::Discarded;
|
||||
|
||||
// The linkonce feature is a sort of proto-comdat. Some glibc i386 object
|
||||
// files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce
|
||||
// sections. Drop those sections to avoid duplicate symbol errors.
|
||||
// FIXME: This is glibc PR20543, we should remove this hack once that has been
|
||||
// fixed for a while.
|
||||
if (Name.startswith(".gnu.linkonce."))
|
||||
return &InputSection<ELFT>::Discarded;
|
||||
|
||||
// The linker merges EH (exception handling) frames and creates a
|
||||
// .eh_frame_hdr section for runtime. So we handle them with a special
|
||||
// class. For relocatable outputs, they are just passed through.
|
||||
@ -524,9 +552,8 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) {
|
||||
"could not get the buffer for the member defining symbol " +
|
||||
Sym->getName());
|
||||
|
||||
if (C.getParent()->isThin() && Driver->Tar)
|
||||
Driver->Tar->append(relativeToRoot(check(C.getFullName())),
|
||||
Ret.getBuffer());
|
||||
if (C.getParent()->isThin() && Tar)
|
||||
Tar->append(relativeToRoot(check(C.getFullName())), Ret.getBuffer());
|
||||
if (C.getParent()->isThin())
|
||||
return {Ret, 0};
|
||||
return {Ret, C.getChildOffset()};
|
||||
@ -651,6 +678,8 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
|
||||
VersymIndex = Versym->vs_index;
|
||||
++Versym;
|
||||
}
|
||||
bool Hidden = VersymIndex & VERSYM_HIDDEN;
|
||||
VersymIndex = VersymIndex & ~VERSYM_HIDDEN;
|
||||
|
||||
StringRef Name = check(Sym.getName(this->StringTable));
|
||||
if (Sym.isUndefined()) {
|
||||
@ -658,15 +687,23 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Versym) {
|
||||
// Ignore local symbols and non-default versions.
|
||||
if (VersymIndex == VER_NDX_LOCAL || (VersymIndex & VERSYM_HIDDEN))
|
||||
continue;
|
||||
}
|
||||
// Ignore local symbols.
|
||||
if (Versym && VersymIndex == VER_NDX_LOCAL)
|
||||
continue;
|
||||
|
||||
const Elf_Verdef *V =
|
||||
VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex];
|
||||
elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V);
|
||||
|
||||
if (!Hidden)
|
||||
elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V);
|
||||
|
||||
// Also add the symbol with the versioned name to handle undefined symbols
|
||||
// with explicit versions.
|
||||
if (V) {
|
||||
StringRef VerName = this->StringTable.data() + V->getAux()->vda_name;
|
||||
Name = Saver.save(Twine(Name) + "@" + VerName);
|
||||
elf::Symtab<ELFT>::X->addShared(this, Name, Sym, V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
namespace llvm {
|
||||
class DWARFDebugLine;
|
||||
class TarWriter;
|
||||
namespace lto {
|
||||
class InputFile;
|
||||
}
|
||||
@ -49,6 +50,13 @@ using llvm::object::Archive;
|
||||
class Lazy;
|
||||
class SymbolBody;
|
||||
|
||||
// If -reproduce option is given, all input files are written
|
||||
// to this tar archive.
|
||||
extern llvm::TarWriter *Tar;
|
||||
|
||||
// Opens a given file.
|
||||
llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
|
||||
|
||||
// The root class of input files.
|
||||
class InputFile {
|
||||
public:
|
||||
|
@ -56,29 +56,30 @@ using namespace lld::elf;
|
||||
LinkerScriptBase *elf::ScriptBase;
|
||||
ScriptConfiguration *elf::ScriptConfig;
|
||||
|
||||
template <class ELFT> static void addRegular(SymbolAssignment *Cmd) {
|
||||
template <class ELFT> static SymbolBody *addRegular(SymbolAssignment *Cmd) {
|
||||
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
Symbol *Sym = Symtab<ELFT>::X->addRegular(Cmd->Name, Visibility, STT_NOTYPE,
|
||||
0, 0, STB_GLOBAL, nullptr, nullptr);
|
||||
Cmd->Sym = Sym->body();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addUndefined(
|
||||
Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
|
||||
/*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
|
||||
// If we have no SECTIONS then we don't have '.' and don't call
|
||||
// assignAddresses(). We calculate symbol value immediately in this case.
|
||||
if (!ScriptConfig->HasSections)
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Cmd->Expression(0);
|
||||
replaceBody<DefinedRegular<ELFT>>(Sym, Cmd->Name, /*IsLocal=*/false,
|
||||
Visibility, STT_NOTYPE, 0, 0, nullptr,
|
||||
nullptr);
|
||||
return Sym->body();
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
|
||||
// If we have SECTIONS block then output sections haven't been created yet.
|
||||
template <class ELFT> static SymbolBody *addSynthetic(SymbolAssignment *Cmd) {
|
||||
uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
|
||||
const OutputSectionBase *Sec =
|
||||
ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addSynthetic(
|
||||
Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
|
||||
Cmd->Sym = Sym->body();
|
||||
Symbol *Sym = Symtab<ELFT>::X->addUndefined(
|
||||
Cmd->Name, /*IsLocal=*/false, STB_GLOBAL, Visibility,
|
||||
/*Type*/ 0,
|
||||
/*CanOmitFromDynSym*/ false, /*File*/ nullptr);
|
||||
|
||||
// If we already know section then we can calculate symbol value immediately.
|
||||
if (Sec)
|
||||
cast<DefinedSynthetic>(Cmd->Sym)->Value = Cmd->Expression(0) - Sec->Addr;
|
||||
replaceBody<DefinedSynthetic>(Sym, Cmd->Name, 0, Sec);
|
||||
return Sym->body();
|
||||
}
|
||||
|
||||
static bool isUnderSysroot(StringRef Path) {
|
||||
@ -90,21 +91,39 @@ static bool isUnderSysroot(StringRef Path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
|
||||
if (Cmd->Expression.IsAbsolute())
|
||||
addRegular<ELFT>(Cmd);
|
||||
else
|
||||
addSynthetic<ELFT>(Cmd);
|
||||
template <class ELFT> static void assignSymbol(SymbolAssignment *Cmd) {
|
||||
// If there are sections, then let the value be assigned later in
|
||||
// `assignAddresses`.
|
||||
if (ScriptConfig->HasSections)
|
||||
return;
|
||||
|
||||
uint64_t Value = Cmd->Expression(0);
|
||||
if (Cmd->Expression.IsAbsolute()) {
|
||||
cast<DefinedRegular<ELFT>>(Cmd->Sym)->Value = Value;
|
||||
} else {
|
||||
const OutputSectionBase *Sec = Cmd->Expression.Section();
|
||||
if (Sec)
|
||||
cast<DefinedSynthetic>(Cmd->Sym)->Value = Value - Sec->Addr;
|
||||
}
|
||||
}
|
||||
// If a symbol was in PROVIDE(), we need to define it only when
|
||||
// it is an undefined symbol.
|
||||
template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
|
||||
|
||||
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
|
||||
if (Cmd->Name == ".")
|
||||
return false;
|
||||
if (!Cmd->Provide)
|
||||
return true;
|
||||
return;
|
||||
|
||||
// If a symbol was in PROVIDE(), we need to define it only when
|
||||
// it is a referenced undefined symbol.
|
||||
SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
|
||||
return B && B->isUndefined();
|
||||
if (Cmd->Provide && (!B || B->isDefined()))
|
||||
return;
|
||||
|
||||
// Otherwise, create a new symbol if one does not exist or an
|
||||
// undefined one does exist.
|
||||
if (Cmd->Expression.IsAbsolute())
|
||||
Cmd->Sym = addRegular<ELFT>(Cmd);
|
||||
else
|
||||
Cmd->Sym = addSynthetic<ELFT>(Cmd);
|
||||
assignSymbol<ELFT>(Cmd);
|
||||
}
|
||||
|
||||
bool SymbolAssignment::classof(const BaseCommand *C) {
|
||||
@ -283,8 +302,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
||||
|
||||
// Handle symbol assignments outside of any output section.
|
||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base1.get())) {
|
||||
if (shouldDefine<ELFT>(Cmd))
|
||||
addSymbol<ELFT>(Cmd);
|
||||
addSymbol<ELFT>(Cmd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -326,8 +344,7 @@ void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
|
||||
// ".foo : { ...; bar = .; }". Handle them.
|
||||
for (const std::unique_ptr<BaseCommand> &Base : Cmd->Commands)
|
||||
if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get()))
|
||||
if (shouldDefine<ELFT>(OutCmd))
|
||||
addSymbol<ELFT>(OutCmd);
|
||||
addSymbol<ELFT>(OutCmd);
|
||||
|
||||
// Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
|
||||
// is given, input sections are aligned to that value, whether the
|
||||
@ -1143,20 +1160,21 @@ void ScriptParser::readGroup() {
|
||||
|
||||
void ScriptParser::readInclude() {
|
||||
StringRef Tok = unquote(next());
|
||||
|
||||
// https://sourceware.org/binutils/docs/ld/File-Commands.html:
|
||||
// The file will be searched for in the current directory, and in any
|
||||
// directory specified with the -L option.
|
||||
auto MBOrErr = MemoryBuffer::getFile(Tok);
|
||||
if (!MBOrErr)
|
||||
if (Optional<std::string> Path = findFromSearchPaths(Tok))
|
||||
MBOrErr = MemoryBuffer::getFile(*Path);
|
||||
if (!MBOrErr) {
|
||||
setError("cannot open " + Tok);
|
||||
if (sys::fs::exists(Tok)) {
|
||||
if (Optional<MemoryBufferRef> MB = readFile(Tok))
|
||||
tokenize(*MB);
|
||||
return;
|
||||
}
|
||||
MemoryBufferRef MBRef = (*MBOrErr)->getMemBufferRef();
|
||||
make<std::unique_ptr<MemoryBuffer>>(std::move(*MBOrErr)); // take MB ownership
|
||||
tokenize(MBRef);
|
||||
if (Optional<std::string> Path = findFromSearchPaths(Tok)) {
|
||||
if (Optional<MemoryBufferRef> MB = readFile(*Path))
|
||||
tokenize(*MB);
|
||||
return;
|
||||
}
|
||||
setError("cannot open " + Tok);
|
||||
}
|
||||
|
||||
void ScriptParser::readOutput() {
|
||||
|
@ -202,6 +202,10 @@ void SymbolBody::parseSymbolVersion() {
|
||||
// Truncate the symbol name so that it doesn't include the version string.
|
||||
Name = {S.data(), Pos};
|
||||
|
||||
// If this is an undefined or shared symbol it is not a definition.
|
||||
if (isUndefined() || isShared())
|
||||
return;
|
||||
|
||||
// '@@' in a symbol name means the default version.
|
||||
// It is usually the most recent one.
|
||||
bool IsDefault = (Verstr[0] == '@');
|
||||
|
@ -1,5 +1,5 @@
|
||||
macro(add_lld_library name)
|
||||
add_llvm_library(${name} ${ARGN})
|
||||
llvm_add_library(${name} ${ARGN})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "lld libraries")
|
||||
endmacro(add_lld_library)
|
||||
|
||||
|
@ -34,9 +34,6 @@ std::string rewritePath(StringRef S);
|
||||
|
||||
// Returns the string form of the given argument.
|
||||
std::string toString(llvm::opt::Arg *Arg);
|
||||
|
||||
// Replaces backslashes with slashes if Windows.
|
||||
std::string convertToUnixPathSeparator(StringRef S);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,6 @@ add_lld_library(lldConfig
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Config
|
||||
|
||||
LINK_LIBS
|
||||
LLVMSupport
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
@ -12,6 +12,6 @@ add_lld_library(lldCore
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Core
|
||||
|
||||
LINK_LIBS
|
||||
LLVMSupport
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ std::string lld::relativeToRoot(StringRef Path) {
|
||||
Res = Root.substr(2);
|
||||
|
||||
path::append(Res, path::relative_path(Abs));
|
||||
return convertToUnixPathSeparator(Res);
|
||||
return path::convert_to_slash(Res);
|
||||
}
|
||||
|
||||
// Quote a given string if it contains a space character.
|
||||
@ -64,13 +64,3 @@ std::string lld::toString(opt::Arg *Arg) {
|
||||
return K + V;
|
||||
return K + " " + V;
|
||||
}
|
||||
|
||||
std::string lld::convertToUnixPathSeparator(StringRef S) {
|
||||
#ifdef LLVM_ON_WIN32
|
||||
std::string Ret = S.str();
|
||||
std::replace(Ret.begin(), Ret.end(), '\\', '/');
|
||||
return Ret;
|
||||
#else
|
||||
return S;
|
||||
#endif
|
||||
}
|
||||
|
@ -8,15 +8,17 @@ add_lld_library(lldDriver
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/Driver
|
||||
|
||||
LINK_COMPONENTS
|
||||
Object
|
||||
Option
|
||||
Support
|
||||
|
||||
LINK_LIBS
|
||||
lldConfig
|
||||
lldMachO
|
||||
lldCore
|
||||
lldReaderWriter
|
||||
lldYAML
|
||||
LLVMObject
|
||||
LLVMOption
|
||||
LLVMSupport
|
||||
)
|
||||
|
||||
add_dependencies(lldDriver DriverOptionsTableGen)
|
||||
|
@ -11,9 +11,11 @@ add_lld_library(lldReaderWriter
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLD_INCLUDE_DIR}/lld/ReaderWriter
|
||||
|
||||
LINK_COMPONENTS
|
||||
Object
|
||||
Support
|
||||
|
||||
LINK_LIBS
|
||||
lldCore
|
||||
lldYAML
|
||||
LLVMObject
|
||||
LLVMSupport
|
||||
)
|
||||
|
@ -18,13 +18,16 @@ add_lld_library(lldMachO
|
||||
StubsPass.cpp
|
||||
TLVPass.cpp
|
||||
WriterMachO.cpp
|
||||
|
||||
LINK_COMPONENTS
|
||||
DebugInfoDWARF
|
||||
Object
|
||||
Support
|
||||
Demangle
|
||||
|
||||
LINK_LIBS
|
||||
lldCore
|
||||
lldYAML
|
||||
LLVMDebugInfoDWARF
|
||||
LLVMObject
|
||||
LLVMSupport
|
||||
LLVMDemangle
|
||||
${PTHREAD_LIB}
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
add_lld_library(lldYAML
|
||||
ReaderWriterYAML.cpp
|
||||
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
|
||||
LINK_LIBS
|
||||
lldCore
|
||||
LLVMSupport
|
||||
)
|
||||
|
@ -1,3 +1,5 @@
|
||||
# REQUIRES: x86, shell
|
||||
|
||||
# RUN: rm -rf %t.dir
|
||||
# RUN: mkdir -p %t.dir/build1 %t.dir/build2 %t.dir/build3
|
||||
# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
|
||||
|
9
test/ELF/comdat-linkonce.s
Normal file
9
test/ELF/comdat-linkonce.s
Normal file
@ -0,0 +1,9 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o
|
||||
// RUN: ld.lld -shared %t.o %t2.o -o %t
|
||||
// RUN: ld.lld -shared %t2.o %t.o -o %t
|
||||
|
||||
.section .gnu.linkonce.t.zed
|
||||
.globl abc
|
||||
abc:
|
||||
nop
|
@ -13,14 +13,20 @@
|
||||
# RUN: symbol9 = - 4; \
|
||||
# RUN: symbol10 = 0xfedcba9876543210; \
|
||||
# RUN: symbol11 = ((0x28000 + 0x1fff) & ~(0x1000 + -1)); \
|
||||
# RUN: symbol12 = 0x1234; \
|
||||
# RUN: symbol12 += 1; \
|
||||
# RUN: bar = 0x5678; \
|
||||
# RUN: baz = 0x9abc; \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
|
||||
|
||||
# CHECK: SYMBOL TABLE:
|
||||
# CHECK-NEXT: 0000000000000000 *UND* 00000000
|
||||
# CHECK-NEXT: .text 00000000 _start
|
||||
# CHECK-NEXT: .text 00000000 foo
|
||||
# CHECK-NEXT: 0000000000000000 .text 00000000 _start
|
||||
# CHECK-NEXT: 0000000000005678 *ABS* 00000000 bar
|
||||
# CHECK-NEXT: 0000000000009abc *ABS* 00000000 baz
|
||||
# CHECK-NEXT: 0000000000000001 .text 00000000 foo
|
||||
# CHECK-NEXT: 0000000000001000 *ABS* 00000000 symbol
|
||||
# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol2
|
||||
# CHECK-NEXT: 0000000000002234 *ABS* 00000000 symbol3
|
||||
@ -32,6 +38,7 @@
|
||||
# CHECK-NEXT: fffffffffffffffc *ABS* 00000000 symbol9
|
||||
# CHECK-NEXT: fedcba9876543210 *ABS* 00000000 symbol10
|
||||
# CHECK-NEXT: 0000000000029000 *ABS* 00000000 symbol11
|
||||
# CHECK-NEXT: 0000000000001235 *ABS* 00000000 symbol12
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: symbol2 = symbol; \
|
||||
@ -46,3 +53,9 @@ _start:
|
||||
|
||||
.global foo
|
||||
foo:
|
||||
nop
|
||||
|
||||
.global bar
|
||||
bar = 0x1234
|
||||
|
||||
.comm baz,8,8
|
||||
|
@ -1,8 +1,10 @@
|
||||
# Check that the linker use a value of _gp symbol defined
|
||||
# in a linker script to calculate GOT relocations.
|
||||
|
||||
# FIXME: This test is xfailed because it depends on D27276 patch
|
||||
# that enables absolute symbols redefinition by a linker's script.
|
||||
# FIXME: This test is xfailed because there is currently a bug
|
||||
# that causes symbols defined by linker scripts to be put in the
|
||||
# wrong sections. In particular, `_gp = . + 0x100` ends up in
|
||||
# `.text` when it should be in `*ABS*`.
|
||||
# XFAIL: *
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
|
||||
|
@ -4,10 +4,13 @@
|
||||
# RUN: mkdir -p %t.dir/build
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build/foo.o
|
||||
# RUN: echo "INPUT(\"%t.dir/build/foo.o\")" > %t.dir/build/foo.script
|
||||
# RUN: echo "INCLUDE \"%t.dir/build/bar.script\"" >> %t.dir/build/foo.script
|
||||
# RUN: echo "/* empty */" > %t.dir/build/bar.script
|
||||
# RUN: cd %t.dir
|
||||
# RUN: ld.lld build/foo.script -o bar --reproduce repro.tar
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff build/foo.script repro/%:t.dir/build/foo.script
|
||||
# RUN: diff build/bar.script repro/%:t.dir/build/bar.script
|
||||
# RUN: diff build/foo.o repro/%:t.dir/build/foo.o
|
||||
|
||||
.globl _start
|
||||
|
74
test/ELF/undefined-versioned-symbol.s
Normal file
74
test/ELF/undefined-versioned-symbol.s
Normal file
@ -0,0 +1,74 @@
|
||||
// REQUIRES: x86
|
||||
// RUN: echo ".data; \
|
||||
// RUN: .quad \"basename\"; \
|
||||
// RUN: .quad \"basename@FBSD_1.0\"; \
|
||||
// RUN: .quad \"basename@FBSD_1.1\" " > %t.s
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
|
||||
// RUN: echo "FBSD_1.0 { local: *; }; FBSD_1.1 { };" > %t2.ver
|
||||
// RUN: ld.lld --shared --version-script %t2.ver %t2.o -o %t2.so
|
||||
// RUN: echo "LIBPKG_1.3 { };" > %t.ver
|
||||
// RUN: ld.lld --shared %t.o --version-script %t.ver %t2.so -o %t.so
|
||||
// RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t.so | FileCheck %s
|
||||
|
||||
// Test that each relocation points to the correct version.
|
||||
|
||||
// CHECK: Section ({{.*}}) .rela.dyn {
|
||||
// CHECK-NEXT: Relocation {
|
||||
// CHECK-NEXT: Offset: 0x2000
|
||||
// CHECK-NEXT: Type: R_X86_64_64 (1)
|
||||
// CHECK-NEXT: Symbol: basename (1)
|
||||
// CHECK-NEXT: Addend: 0x0
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Relocation {
|
||||
// CHECK-NEXT: Offset: 0x2008
|
||||
// CHECK-NEXT: Type: R_X86_64_64 (1)
|
||||
// CHECK-NEXT: Symbol: basename (2)
|
||||
// CHECK-NEXT: Addend: 0x0
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Relocation {
|
||||
// CHECK-NEXT: Offset: 0x2010
|
||||
// CHECK-NEXT: Type: R_X86_64_64 (1)
|
||||
// CHECK-NEXT: Symbol: basename (3)
|
||||
// CHECK-NEXT: Addend: 0x0
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
// CHECK: DynamicSymbols [
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name:
|
||||
// CHECK-NEXT: Value:
|
||||
// CHECK-NEXT: Size:
|
||||
// CHECK-NEXT: Binding:
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Other:
|
||||
// CHECK-NEXT: Section:
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: basename@FBSD_1.1
|
||||
// CHECK-NEXT: Value:
|
||||
// CHECK-NEXT: Size:
|
||||
// CHECK-NEXT: Binding:
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Other:
|
||||
// CHECK-NEXT: Section:
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: basename@FBSD_1.0
|
||||
// CHECK-NEXT: Value:
|
||||
// CHECK-NEXT: Size:
|
||||
// CHECK-NEXT: Binding:
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Other:
|
||||
// CHECK-NEXT: Section:
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: basename@FBSD_1.1
|
||||
|
||||
|
||||
.global "basename@FBSD_1.0"
|
||||
"basename@FBSD_1.0":
|
||||
|
||||
.global "basename@@FBSD_1.1"
|
||||
"basename@@FBSD_1.1":
|
@ -1,3 +1,7 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
||||
add_lld_tool(lld
|
||||
lld.cpp
|
||||
)
|
||||
@ -6,7 +10,6 @@ target_link_libraries(lld
|
||||
lldDriver
|
||||
lldCOFF
|
||||
lldELF
|
||||
LLVMSupport
|
||||
)
|
||||
|
||||
install(TARGETS lld
|
||||
|
Loading…
x
Reference in New Issue
Block a user