Vendor import of lld trunk r291274:
https://llvm.org/svn/llvm-project/lld/trunk@291274
This commit is contained in:
parent
5d4d137132
commit
c09ce7fd2d
@ -25,6 +25,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
@ -98,9 +99,9 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) {
|
||||
MemoryBufferRef MBRef = *MB;
|
||||
OwningMBs.push_back(std::move(MB));
|
||||
|
||||
if (Driver->Cpio)
|
||||
Driver->Cpio->append(relativeToRoot(MBRef.getBufferIdentifier()),
|
||||
MBRef.getBuffer());
|
||||
if (Driver->Tar)
|
||||
Driver->Tar->append(relativeToRoot(MBRef.getBufferIdentifier()),
|
||||
MBRef.getBuffer());
|
||||
|
||||
return MBRef;
|
||||
}
|
||||
@ -368,7 +369,7 @@ static std::string createResponseFile(const opt::InputArgList &Args,
|
||||
case OPT_libpath:
|
||||
break;
|
||||
default:
|
||||
OS << stringize(Arg) << "\n";
|
||||
OS << toString(Arg) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,13 +459,17 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
|
||||
if (auto *Arg = Args.getLastArg(OPT_linkrepro)) {
|
||||
SmallString<64> Path = StringRef(Arg->getValue());
|
||||
sys::path::append(Path, "repro");
|
||||
ErrorOr<CpioFile *> F = CpioFile::create(Path);
|
||||
if (F)
|
||||
Cpio.reset(*F);
|
||||
else
|
||||
errs() << "/linkrepro: failed to open " << Path
|
||||
<< ".cpio: " << F.getError().message() << '\n';
|
||||
sys::path::append(Path, "repro.tar");
|
||||
|
||||
Expected<std::unique_ptr<TarWriter>> ErrOrWriter =
|
||||
TarWriter::create(Path, "repro");
|
||||
|
||||
if (ErrOrWriter) {
|
||||
Tar = std::move(*ErrOrWriter);
|
||||
} else {
|
||||
errs() << "/linkrepro: failed to open " << Path << ": "
|
||||
<< toString(ErrOrWriter.takeError()) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
|
||||
@ -683,10 +688,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
if (!Resources.empty())
|
||||
addBuffer(convertResToCOFF(Resources));
|
||||
|
||||
if (Cpio)
|
||||
Cpio->append("response.txt",
|
||||
createResponseFile(Args, FilePaths,
|
||||
ArrayRef<StringRef>(SearchPaths).slice(1)));
|
||||
if (Tar)
|
||||
Tar->append("response.txt",
|
||||
createResponseFile(Args, FilePaths,
|
||||
ArrayRef<StringRef>(SearchPaths).slice(1)));
|
||||
|
||||
// Handle /largeaddressaware
|
||||
if (Config->is64() || Args.hasArg(OPT_largeaddressaware))
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@ -74,7 +75,7 @@ private:
|
||||
ArgParser Parser;
|
||||
SymbolTable Symtab;
|
||||
|
||||
std::unique_ptr<CpioFile> Cpio; // for /linkrepro
|
||||
std::unique_ptr<llvm::TarWriter> Tar; // for /linkrepro
|
||||
|
||||
// Opens a file. Path has to be resolved already.
|
||||
MemoryBufferRef openFile(StringRef Path);
|
||||
|
@ -372,6 +372,8 @@ MachineTypes BitcodeFile::getMachineType() {
|
||||
return IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
||||
// Returns the last element of a path, which is supposed to be a filename.
|
||||
static StringRef getBasename(StringRef Path) {
|
||||
@ -382,7 +384,7 @@ static StringRef getBasename(StringRef Path) {
|
||||
}
|
||||
|
||||
// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
|
||||
std::string toString(InputFile *File) {
|
||||
std::string lld::toString(coff::InputFile *File) {
|
||||
if (!File)
|
||||
return "(internal)";
|
||||
if (File->ParentName.empty())
|
||||
@ -393,6 +395,3 @@ std::string toString(InputFile *File) {
|
||||
.str();
|
||||
return StringRef(Res).lower();
|
||||
}
|
||||
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
@ -202,10 +202,9 @@ private:
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
std::unique_ptr<LTOModule> M;
|
||||
};
|
||||
|
||||
std::string toString(InputFile *File);
|
||||
|
||||
} // namespace coff
|
||||
|
||||
std::string toString(coff::InputFile *File);
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,13 @@
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
// Returns a symbol name for an error message.
|
||||
std::string lld::toString(coff::SymbolBody &B) {
|
||||
if (Optional<std::string> S = coff::demangle(B.getName()))
|
||||
return ("\"" + *S + "\" (" + B.getName() + ")").str();
|
||||
return B.getName();
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
|
||||
@ -73,13 +80,5 @@ Defined *Undefined::getWeakAlias() {
|
||||
return D;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns a symbol name for an error message.
|
||||
std::string toString(SymbolBody &B) {
|
||||
if (Optional<std::string> S = demangle(B.getName()))
|
||||
return ("\"" + *S + "\" (" + B.getName() + ")").str();
|
||||
return B.getName();
|
||||
}
|
||||
|
||||
} // namespace coff
|
||||
} // namespace lld
|
||||
|
@ -428,10 +428,9 @@ inline Symbol *SymbolBody::symbol() {
|
||||
return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
|
||||
offsetof(Symbol, Body));
|
||||
}
|
||||
|
||||
std::string toString(SymbolBody &B);
|
||||
|
||||
} // namespace coff
|
||||
|
||||
std::string toString(coff::SymbolBody &B);
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdlib>
|
||||
@ -182,8 +183,8 @@ Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
|
||||
MemoryBufferRef MBRef = MB->getMemBufferRef();
|
||||
make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
|
||||
|
||||
if (Cpio)
|
||||
Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
|
||||
if (Tar)
|
||||
Tar->append(relativeToRoot(Path), MBRef.getBuffer());
|
||||
|
||||
return MBRef;
|
||||
}
|
||||
@ -309,14 +310,16 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
|
||||
if (const char *Path = getReproduceOption(Args)) {
|
||||
// Note that --reproduce is a debug option so you can ignore it
|
||||
// if you are trying to understand the whole picture of the code.
|
||||
ErrorOr<CpioFile *> F = CpioFile::create(Path);
|
||||
if (F) {
|
||||
Cpio.reset(*F);
|
||||
Cpio->append("response.txt", createResponseFile(Args));
|
||||
Cpio->append("version.txt", getLLDVersion() + "\n");
|
||||
} else
|
||||
error(F.getError(),
|
||||
Twine("--reproduce: failed to open ") + Path + ".cpio");
|
||||
Expected<std::unique_ptr<TarWriter>> ErrOrWriter =
|
||||
TarWriter::create(Path, path::stem(Path));
|
||||
if (ErrOrWriter) {
|
||||
Tar = std::move(*ErrOrWriter);
|
||||
Tar->append("response.txt", createResponseFile(Args));
|
||||
Tar->append("version.txt", getLLDVersion() + "\n");
|
||||
} else {
|
||||
error(Twine("--reproduce: failed to open ") + Path + ": " +
|
||||
toString(ErrOrWriter.takeError()));
|
||||
}
|
||||
}
|
||||
|
||||
readConfigs(Args);
|
||||
@ -423,7 +426,7 @@ static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) {
|
||||
if (S.startswith("0x"))
|
||||
S = S.drop_front(2);
|
||||
if (S.getAsInteger(16, VA))
|
||||
error("invalid argument: " + stringize(Arg));
|
||||
error("invalid argument: " + toString(Arg));
|
||||
return VA;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#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 {
|
||||
@ -29,7 +30,7 @@ public:
|
||||
void main(ArrayRef<const char *> Args, bool CanExitEarly);
|
||||
void addFile(StringRef Path);
|
||||
void addLibrary(StringRef Name);
|
||||
std::unique_ptr<CpioFile> Cpio; // for reproduce
|
||||
std::unique_ptr<llvm::TarWriter> Tar; // for reproduce
|
||||
|
||||
private:
|
||||
std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
|
||||
|
@ -146,7 +146,7 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) {
|
||||
<< "\n";
|
||||
break;
|
||||
default:
|
||||
OS << stringize(Arg) << "\n";
|
||||
OS << toString(Arg) << "\n";
|
||||
}
|
||||
}
|
||||
return Data.str();
|
||||
|
@ -92,12 +92,11 @@ std::string elf::ObjectFile<ELFT>::getLineInfo(InputSectionBase<ELFT> *S,
|
||||
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info);
|
||||
if (Info.Line == 0)
|
||||
return "";
|
||||
return convertToUnixPathSeparator(Info.FileName) + ":" +
|
||||
std::to_string(Info.Line);
|
||||
return Info.FileName + ":" + std::to_string(Info.Line);
|
||||
}
|
||||
|
||||
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
|
||||
std::string elf::toString(const InputFile *F) {
|
||||
std::string lld::toString(const InputFile *F) {
|
||||
if (!F)
|
||||
return "(internal)";
|
||||
if (!F->ArchiveName.empty())
|
||||
@ -525,9 +524,9 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) {
|
||||
"could not get the buffer for the member defining symbol " +
|
||||
Sym->getName());
|
||||
|
||||
if (C.getParent()->isThin() && Driver->Cpio)
|
||||
Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
|
||||
Ret.getBuffer());
|
||||
if (C.getParent()->isThin() && Driver->Tar)
|
||||
Driver->Tar->append(relativeToRoot(check(C.getFullName())),
|
||||
Ret.getBuffer());
|
||||
if (C.getParent()->isThin())
|
||||
return {Ret, 0};
|
||||
return {Ret, C.getChildOffset()};
|
||||
|
@ -35,11 +35,17 @@ class InputFile;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class InputFile;
|
||||
}
|
||||
|
||||
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
|
||||
std::string toString(const elf::InputFile *F);
|
||||
|
||||
namespace elf {
|
||||
|
||||
using llvm::object::Archive;
|
||||
|
||||
class InputFile;
|
||||
class Lazy;
|
||||
class SymbolBody;
|
||||
|
||||
@ -84,9 +90,6 @@ private:
|
||||
const Kind FileKind;
|
||||
};
|
||||
|
||||
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
|
||||
std::string toString(const InputFile *F);
|
||||
|
||||
template <typename ELFT> class ELFFileBase : public InputFile {
|
||||
public:
|
||||
typedef typename ELFT::Shdr Elf_Shdr;
|
||||
|
@ -34,7 +34,7 @@ using namespace lld::elf;
|
||||
|
||||
// Returns a string to construct an error message.
|
||||
template <class ELFT>
|
||||
std::string elf::toString(const InputSectionBase<ELFT> *Sec) {
|
||||
std::string lld::toString(const InputSectionBase<ELFT> *Sec) {
|
||||
return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str();
|
||||
}
|
||||
|
||||
@ -844,7 +844,7 @@ template class elf::MergeInputSection<ELF32BE>;
|
||||
template class elf::MergeInputSection<ELF64LE>;
|
||||
template class elf::MergeInputSection<ELF64BE>;
|
||||
|
||||
template std::string elf::toString(const InputSectionBase<ELF32LE> *);
|
||||
template std::string elf::toString(const InputSectionBase<ELF32BE> *);
|
||||
template std::string elf::toString(const InputSectionBase<ELF64LE> *);
|
||||
template std::string elf::toString(const InputSectionBase<ELF64BE> *);
|
||||
template std::string lld::toString(const InputSectionBase<ELF32LE> *);
|
||||
template std::string lld::toString(const InputSectionBase<ELF32BE> *);
|
||||
template std::string lld::toString(const InputSectionBase<ELF64LE> *);
|
||||
template std::string lld::toString(const InputSectionBase<ELF64BE> *);
|
||||
|
@ -318,10 +318,9 @@ private:
|
||||
};
|
||||
|
||||
template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
|
||||
|
||||
template <class ELFT> std::string toString(const InputSectionBase<ELFT> *);
|
||||
|
||||
} // namespace elf
|
||||
|
||||
template <class ELFT> std::string toString(const elf::InputSectionBase<ELFT> *);
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
@ -263,43 +263,13 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName) {
|
||||
// When using linker script the merge rules are different.
|
||||
// Unfortunately, linker scripts are name based. This means that expressions
|
||||
// like *(.foo*) can refer to multiple input sections that would normally be
|
||||
// placed in different output sections. We cannot put them in different
|
||||
// output sections or we would produce wrong results for
|
||||
// start = .; *(.foo.*) end = .; *(.bar)
|
||||
// and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
|
||||
// another. The problem is that there is no way to layout those output
|
||||
// sections such that the .foo sections are the only thing between the
|
||||
// start and end symbols.
|
||||
|
||||
// An extra annoyance is that we cannot simply disable merging of the contents
|
||||
// of SHF_MERGE sections, but our implementation requires one output section
|
||||
// per "kind" (string or not, which size/aligment).
|
||||
// Fortunately, creating symbols in the middle of a merge section is not
|
||||
// supported by bfd or gold, so we can just create multiple section in that
|
||||
// case.
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
|
||||
|
||||
uintX_t Alignment = 0;
|
||||
if (isa<MergeInputSection<ELFT>>(C))
|
||||
Alignment = std::max<uintX_t>(C->Alignment, C->Entsize);
|
||||
|
||||
return SectionKey<ELFT::Is64Bits>{OutsecName, /*Type*/ 0, Flags, Alignment};
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void LinkerScript<ELFT>::addSection(OutputSectionFactory<ELFT> &Factory,
|
||||
InputSectionBase<ELFT> *Sec,
|
||||
StringRef Name) {
|
||||
OutputSectionBase *OutSec;
|
||||
bool IsNew;
|
||||
std::tie(OutSec, IsNew) = Factory.create(createKey(Sec, Name), Sec);
|
||||
std::tie(OutSec, IsNew) = Factory.create(Sec, Name);
|
||||
if (IsNew)
|
||||
OutputSections->push_back(OutSec);
|
||||
OutSec->addSection(Sec);
|
||||
|
@ -534,41 +534,111 @@ static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
|
||||
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName) {
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
uintX_t Flags = getOutFlags(C);
|
||||
namespace llvm {
|
||||
template <> struct DenseMapInfo<lld::elf::SectionKey> {
|
||||
static lld::elf::SectionKey getEmptyKey();
|
||||
static lld::elf::SectionKey getTombstoneKey();
|
||||
static unsigned getHashValue(const lld::elf::SectionKey &Val);
|
||||
static bool isEqual(const lld::elf::SectionKey &LHS,
|
||||
const lld::elf::SectionKey &RHS);
|
||||
};
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
static SectionKey createKey(InputSectionBase<ELFT> *C, StringRef OutsecName) {
|
||||
// The ELF spec just says
|
||||
// ----------------------------------------------------------------
|
||||
// In the first phase, input sections that match in name, type and
|
||||
// attribute flags should be concatenated into single sections.
|
||||
// ----------------------------------------------------------------
|
||||
//
|
||||
// However, it is clear that at least some flags have to be ignored for
|
||||
// section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be
|
||||
// ignored. We should not have two output .text sections just because one was
|
||||
// in a group and another was not for example.
|
||||
//
|
||||
// It also seems that that wording was a late addition and didn't get the
|
||||
// necessary scrutiny.
|
||||
//
|
||||
// Merging sections with different flags is expected by some users. One
|
||||
// reason is that if one file has
|
||||
//
|
||||
// int *const bar __attribute__((section(".foo"))) = (int *)0;
|
||||
//
|
||||
// gcc with -fPIC will produce a read only .foo section. But if another
|
||||
// file has
|
||||
//
|
||||
// int zed;
|
||||
// int *const bar __attribute__((section(".foo"))) = (int *)&zed;
|
||||
//
|
||||
// gcc with -fPIC will produce a read write section.
|
||||
//
|
||||
// Last but not least, when using linker script the merge rules are forced by
|
||||
// the script. Unfortunately, linker scripts are name based. This means that
|
||||
// expressions like *(.foo*) can refer to multiple input sections with
|
||||
// different flags. We cannot put them in different output sections or we
|
||||
// would produce wrong results for
|
||||
//
|
||||
// start = .; *(.foo.*) end = .; *(.bar)
|
||||
//
|
||||
// and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
|
||||
// another. The problem is that there is no way to layout those output
|
||||
// sections such that the .foo sections are the only thing between the start
|
||||
// and end symbols.
|
||||
//
|
||||
// Given the above issues, we instead merge sections by name and error on
|
||||
// incompatible types and flags.
|
||||
//
|
||||
// The exception being SHF_MERGE, where we create different output sections
|
||||
// for each alignment. This makes each output section simple. In case of
|
||||
// relocatable object generation we do not try to perform merging and treat
|
||||
// SHF_MERGE sections as regular ones, but also create different output
|
||||
// sections for them to allow merging at final linking stage.
|
||||
//
|
||||
// Fortunately, creating symbols in the middle of a merge section is not
|
||||
// supported by bfd or gold, so the SHF_MERGE exception should not cause
|
||||
// problems with most linker scripts.
|
||||
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
|
||||
|
||||
// For SHF_MERGE we create different output sections for each alignment.
|
||||
// This makes each output section simple and keeps a single level mapping from
|
||||
// input to output.
|
||||
// In case of relocatable object generation we do not try to perform merging
|
||||
// and treat SHF_MERGE sections as regular ones, but also create different
|
||||
// output sections for them to allow merging at final linking stage.
|
||||
uintX_t Alignment = 0;
|
||||
if (isa<MergeInputSection<ELFT>>(C) ||
|
||||
(Config->Relocatable && (C->Flags & SHF_MERGE)))
|
||||
Alignment = std::max<uintX_t>(C->Alignment, C->Entsize);
|
||||
|
||||
return SectionKey<ELFT::Is64Bits>{OutsecName, C->Type, Flags, Alignment};
|
||||
return SectionKey{OutsecName, Flags, Alignment};
|
||||
}
|
||||
|
||||
template <class ELFT> OutputSectionFactory<ELFT>::OutputSectionFactory() {}
|
||||
|
||||
template <class ELFT> OutputSectionFactory<ELFT>::~OutputSectionFactory() {}
|
||||
|
||||
template <class ELFT>
|
||||
std::pair<OutputSectionBase *, bool>
|
||||
OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName) {
|
||||
SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
|
||||
SectionKey Key = createKey(C, OutsecName);
|
||||
return create(Key, C);
|
||||
}
|
||||
|
||||
static uint64_t getIncompatibleFlags(uint64_t Flags) {
|
||||
return Flags & (SHF_ALLOC | SHF_TLS);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
std::pair<OutputSectionBase *, bool>
|
||||
OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
|
||||
OutputSectionFactory<ELFT>::create(const SectionKey &Key,
|
||||
InputSectionBase<ELFT> *C) {
|
||||
uintX_t Flags = getOutFlags(C);
|
||||
OutputSectionBase *&Sec = Map[Key];
|
||||
if (Sec) {
|
||||
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags))
|
||||
error("Section has flags incompatible with others with the same name " +
|
||||
toString(C));
|
||||
if (Sec->Type != C->Type)
|
||||
error("Section has different type from others with the same name " +
|
||||
toString(C));
|
||||
Sec->Flags |= Flags;
|
||||
return {Sec, false};
|
||||
}
|
||||
@ -588,36 +658,22 @@ OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
|
||||
return {Sec, true};
|
||||
}
|
||||
|
||||
template <bool Is64Bits>
|
||||
typename lld::elf::SectionKey<Is64Bits>
|
||||
DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getEmptyKey() {
|
||||
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0, 0};
|
||||
SectionKey DenseMapInfo<SectionKey>::getEmptyKey() {
|
||||
return SectionKey{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0};
|
||||
}
|
||||
|
||||
template <bool Is64Bits>
|
||||
typename lld::elf::SectionKey<Is64Bits>
|
||||
DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getTombstoneKey() {
|
||||
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0,
|
||||
0};
|
||||
SectionKey DenseMapInfo<SectionKey>::getTombstoneKey() {
|
||||
return SectionKey{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0};
|
||||
}
|
||||
|
||||
template <bool Is64Bits>
|
||||
unsigned
|
||||
DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getHashValue(const Key &Val) {
|
||||
return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment);
|
||||
unsigned DenseMapInfo<SectionKey>::getHashValue(const SectionKey &Val) {
|
||||
return hash_combine(Val.Name, Val.Flags, Val.Alignment);
|
||||
}
|
||||
|
||||
template <bool Is64Bits>
|
||||
bool DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::isEqual(const Key &LHS,
|
||||
const Key &RHS) {
|
||||
bool DenseMapInfo<SectionKey>::isEqual(const SectionKey &LHS,
|
||||
const SectionKey &RHS) {
|
||||
return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
|
||||
LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
|
||||
LHS.Alignment == RHS.Alignment;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
template struct DenseMapInfo<SectionKey<true>>;
|
||||
template struct DenseMapInfo<SectionKey<false>>;
|
||||
LHS.Flags == RHS.Flags && LHS.Alignment == RHS.Alignment;
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
@ -217,12 +217,10 @@ template <class ELFT> struct Out {
|
||||
static OutputSectionBase *FiniArray;
|
||||
};
|
||||
|
||||
template <bool Is64Bits> struct SectionKey {
|
||||
typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
|
||||
struct SectionKey {
|
||||
StringRef Name;
|
||||
uint32_t Type;
|
||||
uintX_t Flags;
|
||||
uintX_t Alignment;
|
||||
uint64_t Flags;
|
||||
uint64_t Alignment;
|
||||
};
|
||||
|
||||
// This class knows how to create an output section for a given
|
||||
@ -232,16 +230,17 @@ template <bool Is64Bits> struct SectionKey {
|
||||
template <class ELFT> class OutputSectionFactory {
|
||||
typedef typename ELFT::Shdr Elf_Shdr;
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
typedef typename elf::SectionKey<ELFT::Is64Bits> Key;
|
||||
|
||||
public:
|
||||
OutputSectionFactory();
|
||||
~OutputSectionFactory();
|
||||
std::pair<OutputSectionBase *, bool> create(InputSectionBase<ELFT> *C,
|
||||
StringRef OutsecName);
|
||||
std::pair<OutputSectionBase *, bool>
|
||||
create(const SectionKey<ELFT::Is64Bits> &Key, InputSectionBase<ELFT> *C);
|
||||
std::pair<OutputSectionBase *, bool> create(const SectionKey &Key,
|
||||
InputSectionBase<ELFT> *C);
|
||||
|
||||
private:
|
||||
llvm::SmallDenseMap<Key, OutputSectionBase *> Map;
|
||||
llvm::SmallDenseMap<SectionKey, OutputSectionBase *> Map;
|
||||
};
|
||||
|
||||
template <class ELFT> uint64_t getHeaderSize() {
|
||||
@ -265,15 +264,5 @@ template <class ELFT> OutputSectionBase *Out<ELFT>::FiniArray;
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
namespace llvm {
|
||||
template <bool Is64Bits> struct DenseMapInfo<lld::elf::SectionKey<Is64Bits>> {
|
||||
typedef typename lld::elf::SectionKey<Is64Bits> Key;
|
||||
|
||||
static Key getEmptyKey();
|
||||
static Key getTombstoneKey();
|
||||
static unsigned getHashValue(const Key &Val);
|
||||
static bool isEqual(const Key &LHS, const Key &RHS);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -305,7 +305,7 @@ void elf::printTraceSymbol(Symbol *Sym) {
|
||||
}
|
||||
|
||||
// Returns a symbol for an error message.
|
||||
std::string elf::toString(const SymbolBody &B) {
|
||||
std::string lld::toString(const SymbolBody &B) {
|
||||
if (Config->Demangle)
|
||||
if (Optional<std::string> S = demangle(B.getName()))
|
||||
return *S;
|
||||
|
@ -453,10 +453,9 @@ inline Symbol *SymbolBody::symbol() {
|
||||
return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
|
||||
offsetof(Symbol, Body));
|
||||
}
|
||||
|
||||
std::string toString(const SymbolBody &B);
|
||||
|
||||
} // namespace elf
|
||||
|
||||
std::string toString(const elf::SymbolBody &B);
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
@ -44,6 +44,10 @@ using namespace llvm::object;
|
||||
using namespace llvm::support::endian;
|
||||
using namespace llvm::ELF;
|
||||
|
||||
std::string lld::toString(uint32_t Type) {
|
||||
return getELFRelocationTypeName(elf::Config->EMachine, Type);
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
@ -52,10 +56,6 @@ TargetInfo *Target;
|
||||
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
|
||||
static void or32be(uint8_t *P, int32_t V) { write32be(P, read32be(P) | V); }
|
||||
|
||||
std::string toString(uint32_t Type) {
|
||||
return getELFRelocationTypeName(Config->EMachine, Type);
|
||||
}
|
||||
|
||||
template <class ELFT> static std::string getErrorLoc(uint8_t *Loc) {
|
||||
for (InputSectionData *D : Symtab<ELFT>::X->Sections) {
|
||||
auto *IS = dyn_cast_or_null<InputSection<ELFT>>(D);
|
||||
|
@ -104,13 +104,14 @@ public:
|
||||
virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
|
||||
};
|
||||
|
||||
std::string toString(uint32_t RelType);
|
||||
uint64_t getPPC64TocBase();
|
||||
uint64_t getAArch64Page(uint64_t Expr);
|
||||
|
||||
extern TargetInfo *Target;
|
||||
TargetInfo *createTarget();
|
||||
}
|
||||
|
||||
std::string toString(uint32_t RelType);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -11,46 +11,15 @@
|
||||
#define LLD_CORE_REPRODUCE_H
|
||||
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class raw_fd_ostream;
|
||||
|
||||
namespace opt { class Arg; }
|
||||
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
|
||||
// This class creates a .cpio file for --reproduce (ELF) or /linkrepro (COFF).
|
||||
//
|
||||
// If "--reproduce foo" is given, we create a file "foo.cpio" and
|
||||
// copy all input files to the archive, along with a response file
|
||||
// to re-run the same command with the same inputs.
|
||||
// It is useful for reporting issues to LLD developers.
|
||||
//
|
||||
// Cpio as a file format is a deliberate choice. It's standardized in
|
||||
// POSIX and very easy to create. cpio command is available virtually
|
||||
// on all Unix systems. See
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07
|
||||
// for the format details.
|
||||
class CpioFile {
|
||||
public:
|
||||
static ErrorOr<CpioFile *> create(StringRef OutputPath);
|
||||
void append(StringRef Path, StringRef Data);
|
||||
|
||||
private:
|
||||
CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef Basename);
|
||||
|
||||
std::unique_ptr<llvm::raw_fd_ostream> OS;
|
||||
llvm::StringSet<> Seen;
|
||||
std::string Basename;
|
||||
};
|
||||
|
||||
// Makes a given pathname an absolute path first, and then remove
|
||||
// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
|
||||
// assuming that the current directory is "/home/john/bar".
|
||||
@ -64,7 +33,7 @@ std::string quote(StringRef S);
|
||||
std::string rewritePath(StringRef S);
|
||||
|
||||
// Returns the string form of the given argument.
|
||||
std::string stringize(llvm::opt::Arg *Arg);
|
||||
std::string toString(llvm::opt::Arg *Arg);
|
||||
|
||||
// Replaces backslashes with slashes if Windows.
|
||||
std::string convertToUnixPathSeparator(StringRef S);
|
||||
|
@ -8,66 +8,14 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Core/Reproduce.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace llvm;
|
||||
using namespace sys;
|
||||
|
||||
CpioFile::CpioFile(std::unique_ptr<raw_fd_ostream> OS, StringRef S)
|
||||
: OS(std::move(OS)), Basename(S) {}
|
||||
|
||||
ErrorOr<CpioFile *> CpioFile::create(StringRef OutputPath) {
|
||||
std::string Path = (OutputPath + ".cpio").str();
|
||||
std::error_code EC;
|
||||
auto OS = llvm::make_unique<raw_fd_ostream>(Path, EC, sys::fs::F_None);
|
||||
if (EC)
|
||||
return EC;
|
||||
return new CpioFile(std::move(OS), path::filename(OutputPath));
|
||||
}
|
||||
|
||||
static void writeMember(raw_fd_ostream &OS, StringRef Path, StringRef Data) {
|
||||
// The c_dev/c_ino pair should be unique according to the spec,
|
||||
// but no one seems to care.
|
||||
OS << "070707"; // c_magic
|
||||
OS << "000000"; // c_dev
|
||||
OS << "000000"; // c_ino
|
||||
OS << "100664"; // c_mode: C_ISREG | rw-rw-r--
|
||||
OS << "000000"; // c_uid
|
||||
OS << "000000"; // c_gid
|
||||
OS << "000001"; // c_nlink
|
||||
OS << "000000"; // c_rdev
|
||||
OS << "00000000000"; // c_mtime
|
||||
OS << format("%06o", Path.size() + 1); // c_namesize
|
||||
OS << format("%011o", Data.size()); // c_filesize
|
||||
OS << Path << '\0'; // c_name
|
||||
OS << Data; // c_filedata
|
||||
}
|
||||
|
||||
void CpioFile::append(StringRef Path, StringRef Data) {
|
||||
if (!Seen.insert(Path).second)
|
||||
return;
|
||||
|
||||
// Construct an in-archive filename so that /home/foo/bar is stored
|
||||
// as baz/home/foo/bar where baz is the basename of the output file.
|
||||
// (i.e. in that case we are creating baz.cpio.)
|
||||
SmallString<128> Fullpath;
|
||||
path::append(Fullpath, Basename, Path);
|
||||
|
||||
writeMember(*OS, convertToUnixPathSeparator(Fullpath), Data);
|
||||
|
||||
// Print the trailer and seek back.
|
||||
// This way we have a valid archive if we crash.
|
||||
uint64_t Pos = OS->tell();
|
||||
writeMember(*OS, "TRAILER!!!", "");
|
||||
OS->seek(Pos);
|
||||
}
|
||||
using namespace llvm::sys;
|
||||
|
||||
// Makes a given pathname an absolute path first, and then remove
|
||||
// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
|
||||
@ -76,7 +24,7 @@ void CpioFile::append(StringRef Path, StringRef Data) {
|
||||
// a mess with backslash-as-escape and backslash-as-path-separator.
|
||||
std::string lld::relativeToRoot(StringRef Path) {
|
||||
SmallString<128> Abs = Path;
|
||||
if (sys::fs::make_absolute(Abs))
|
||||
if (fs::make_absolute(Abs))
|
||||
return Path;
|
||||
path::remove_dots(Abs, /*remove_dot_dot=*/true);
|
||||
|
||||
@ -107,7 +55,7 @@ std::string lld::rewritePath(StringRef S) {
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string lld::stringize(opt::Arg *Arg) {
|
||||
std::string lld::toString(opt::Arg *Arg) {
|
||||
std::string K = Arg->getSpelling();
|
||||
if (Arg->getNumValues() == 0)
|
||||
return K;
|
||||
|
@ -1,6 +1,3 @@
|
||||
# cpio fails on windows with "Function not implemented".
|
||||
# REQUIRES: 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
|
||||
@ -8,7 +5,7 @@
|
||||
# RUN: cd %t.dir/build1
|
||||
# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
|
||||
# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff %t.obj repro/%:t.obj
|
||||
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
|
||||
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
|
||||
@ -16,7 +13,7 @@
|
||||
# RUN: cd %t.dir/build2
|
||||
# RUN: lld-link %t.obj /libpath:%p/Inputs /defaultlib:std32 /subsystem:console \
|
||||
# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff %t.obj repro/%:t.obj
|
||||
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
|
||||
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
|
||||
@ -24,7 +21,7 @@
|
||||
# RUN: cd %t.dir/build3
|
||||
# RUN: env LIB=%p/Inputs lld-link %t.obj /defaultlib:std32 /subsystem:console \
|
||||
# RUN: /entry:main@0 /linkrepro:. /out:%t.exe
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff %t.obj repro/%:t.obj
|
||||
# RUN: diff %p/Inputs/std32.lib repro/%:p/Inputs/std32.lib
|
||||
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
|
||||
|
18
test/ELF/incompatible-section-flags.s
Normal file
18
test/ELF/incompatible-section-flags.s
Normal file
@ -0,0 +1,18 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: not ld.lld -shared %t.o -o %t 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: error: Section has flags incompatible with others with the same name {{.*}}incompatible-section-flags.s.tmp.o:(.foo)
|
||||
// CHECK: error: Section has flags incompatible with others with the same name {{.*}}incompatible-section-flags.s.tmp.o:(.bar)
|
||||
|
||||
.section .foo, "awT", @progbits, unique, 1
|
||||
.quad 0
|
||||
|
||||
.section .foo, "aw", @progbits, unique, 2
|
||||
.quad 0
|
||||
|
||||
|
||||
.section .bar, "aw", @progbits, unique, 3
|
||||
.quad 0
|
||||
|
||||
.section .bar, "awT", @progbits, unique, 4
|
||||
.quad 0
|
10
test/ELF/incompatible-section-types.s
Normal file
10
test/ELF/incompatible-section-types.s
Normal file
@ -0,0 +1,10 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: not ld.lld -shared %t.o -o %t 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: error: Section has different type from others with the same name {{.*}}incompatible-section-types.s.tmp.o:(.foo)
|
||||
|
||||
.section .foo, "aw", @progbits, unique, 1
|
||||
.quad 0
|
||||
|
||||
.section .foo, "aw", @nobits, unique, 2
|
||||
.quad 0
|
@ -93,7 +93,7 @@
|
||||
|
||||
## Check the numetic values for PHDRS.
|
||||
# RUN: echo "PHDRS {text PT_LOAD FILEHDR PHDRS; foo 0x11223344; } \
|
||||
# RUN: SECTIONS { . = SIZEOF_HEADERS; .foo : { *(.*) } : text : foo}" > %t1.script
|
||||
# RUN: SECTIONS { . = SIZEOF_HEADERS; .foo : { *(.foo* .text*) } : text : foo}" > %t1.script
|
||||
# RUN: ld.lld -o %t2 --script %t1.script %t
|
||||
# RUN: llvm-readobj -program-headers %t2 | FileCheck --check-prefix=INT-PHDRS %s
|
||||
|
||||
|
@ -20,11 +20,10 @@
|
||||
# SEC-DEFAULT: 2 .data 00000020 {{[0-9a-f]*}} DATA
|
||||
# SEC-DEFAULT: 3 other 00000003 {{[0-9a-f]*}} DATA
|
||||
# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 6 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 7 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 8 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 9 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 5 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 7 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
# Sections are put in order specified in linker script, other than alloc
|
||||
# sections going first.
|
||||
@ -43,12 +42,11 @@
|
||||
# Idx Name Size
|
||||
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
|
||||
# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 4 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
|
||||
# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT DATA
|
||||
# SEC-ORDER: 3 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 4 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 5 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-ORDER: 6 .data 00000020 {{[0-9a-f]*}} DATA
|
||||
# SEC-ORDER: 7 .text 0000000e {{[0-9a-f]*}} TEXT DATA
|
||||
|
||||
# .text and .data have swapped names but proper sizes and types.
|
||||
# RUN: echo "SECTIONS { \
|
||||
@ -63,11 +61,10 @@
|
||||
# SEC-SWAP-NAMES: 2 .text 00000020 {{[0-9a-f]*}} DATA
|
||||
# SEC-SWAP-NAMES: 3 other 00000003 {{[0-9a-f]*}} DATA
|
||||
# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 6 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 7 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 8 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 9 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 5 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 7 .shstrtab 0000003b {{[0-9a-f]*}}
|
||||
# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
# .shstrtab from the input object file is discarded.
|
||||
# RUN: echo "SECTIONS { \
|
||||
@ -102,11 +99,10 @@
|
||||
# SEC-MULTI: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA
|
||||
# SEC-MULTI: 2 .data 00000023 {{[0-9a-f]*}} DATA
|
||||
# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS
|
||||
# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 5 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 6 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 7 .shstrtab 00000035 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 8 .strtab 00000008 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 4 .comment 00000008 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 6 .shstrtab 00000035 {{[0-9a-f]*}}
|
||||
# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
@ -118,7 +114,5 @@ _start:
|
||||
.section other,"aw"
|
||||
.short 10
|
||||
.byte 20
|
||||
.section .shstrtab,""
|
||||
.short 20
|
||||
.section .bss,"",@nobits
|
||||
.short 0
|
||||
|
@ -1,9 +1,9 @@
|
||||
# REQUIRES: x86, cpio, shell
|
||||
# REQUIRES: x86, shell
|
||||
|
||||
# Test that we don't erroneously replace \ with / on UNIX, as it's
|
||||
# legal for a filename to contain backslashes.
|
||||
# RUN: llvm-mc %s -o foo\\.o -filetype=obj -triple=x86_64-pc-linux
|
||||
# RUN: ld.lld foo\\.o --reproduce repro
|
||||
# RUN: cpio -it < repro.cpio | FileCheck %s
|
||||
# RUN: ld.lld foo\\.o --reproduce repro.tar
|
||||
# RUN: tar tf repro.tar | FileCheck %s
|
||||
|
||||
# CHECK: repro/{{.*}}/foo\.o
|
||||
# CHECK: repro/{{.*}}/foo\\.o
|
||||
|
@ -1,15 +1,14 @@
|
||||
# Extracting the cpio archive can get over the path limit on windows.
|
||||
# Extracting the tar archive can get over the path limit on windows.
|
||||
# REQUIRES: shell
|
||||
|
||||
# RUN: rm -rf %t.dir
|
||||
# RUN: mkdir -p %t.dir
|
||||
# RUN: cd %t.dir
|
||||
|
||||
# RUN: not ld.lld --reproduce repro abc -o t 2>&1 | FileCheck %s
|
||||
# RUN: not ld.lld --reproduce repro.tar abc -o t 2>&1 | FileCheck %s
|
||||
# CHECK: cannot open abc: {{N|n}}o such file or directory
|
||||
|
||||
# RUN: grep TRAILER repro.cpio
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: FileCheck --check-prefix=RSP %s < repro/response.txt
|
||||
# RSP: abc
|
||||
# RSP: -o t
|
||||
|
@ -5,8 +5,8 @@
|
||||
# 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: cd %t.dir
|
||||
# RUN: ld.lld build/foo.script -o bar --reproduce repro
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# 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/foo.o repro/%:t.dir/build/foo.o
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.dir/foo.o
|
||||
# RUN: cd %t.dir
|
||||
# RUN: llvm-ar --format=gnu rcT foo.a foo.o
|
||||
# RUN: ld.lld -m elf_x86_64 foo.a -o bar --reproduce repro
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: ld.lld -m elf_x86_64 foo.a -o bar --reproduce repro.tar
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff foo.a repro/%:t.dir/foo.a
|
||||
# RUN: diff foo.o repro/%:t.dir/foo.o
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
# REQUIRES: x86, cpio
|
||||
# REQUIRES: x86
|
||||
|
||||
# Test that a repro archive always uses / instead of \.
|
||||
# RUN: rm -rf %t.dir
|
||||
# RUN: mkdir -p %t.dir/build
|
||||
# RUN: llvm-mc %s -o %t.dir/build/foo.o -filetype=obj -triple=x86_64-pc-linux
|
||||
# RUN: cd %t.dir
|
||||
# RUN: ld.lld build/foo.o --reproduce repro
|
||||
# RUN: cpio -it < repro.cpio | FileCheck %s
|
||||
# RUN: ld.lld build/foo.o --reproduce repro.tar
|
||||
# RUN: tar tf repro.tar | FileCheck %s
|
||||
|
||||
# CHECK: repro/response.txt
|
||||
# CHECK: repro/{{.*}}/build/foo.o
|
||||
|
@ -1,11 +1,10 @@
|
||||
# REQUIRES: system-windows, x86, cpio
|
||||
# REQUIRES: system-windows, x86
|
||||
|
||||
# Test that a response.txt file always uses / instead of \.
|
||||
# RUN: rm -rf %t.dir
|
||||
# RUN: mkdir -p %t.dir/build
|
||||
# RUN: llvm-mc %s -o %t.dir/build/foo.o -filetype=obj -triple=x86_64-pc-linux
|
||||
# RUN: cd %t.dir
|
||||
# RUN: ld.lld build/foo.o --reproduce repro
|
||||
# RUN: echo "*response.txt" > list.txt
|
||||
# RUN: cpio -i --to-stdout --pattern-file=list.txt < repro.cpio | FileCheck %s
|
||||
# RUN: ld.lld build/foo.o --reproduce repro.tar
|
||||
# RUN: tar -O -x -f repro.tar repro/response.txt | FileCheck %s
|
||||
# CHECK: {{.*}}/build/foo.o
|
||||
|
@ -1,14 +1,14 @@
|
||||
# REQUIRES: x86, cpio
|
||||
# REQUIRES: x86
|
||||
|
||||
# Extracting the cpio archive can get over the path limit on windows.
|
||||
# Extracting the tar archive can get over the path limit on windows.
|
||||
# REQUIRES: shell
|
||||
|
||||
# RUN: rm -rf %t.dir
|
||||
# RUN: mkdir -p %t.dir/build1
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build1/foo.o
|
||||
# RUN: cd %t.dir
|
||||
# RUN: ld.lld --hash-style=gnu build1/foo.o -o bar -shared --as-needed --reproduce repro
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: ld.lld --hash-style=gnu build1/foo.o -o bar -shared --as-needed --reproduce repro.tar
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff build1/foo.o repro/%:t.dir/build1/foo.o
|
||||
|
||||
# RUN: FileCheck %s --check-prefix=RSP < repro/response.txt
|
||||
@ -25,8 +25,8 @@
|
||||
# RUN: mkdir -p %t.dir/build2/a/b/c
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build2/foo.o
|
||||
# RUN: cd %t.dir/build2/a/b/c
|
||||
# RUN: env LLD_REPRODUCE=repro ld.lld ./../../../foo.o -o bar -shared --as-needed
|
||||
# RUN: cpio -id < repro.cpio
|
||||
# RUN: env LLD_REPRODUCE=repro.tar ld.lld ./../../../foo.o -o bar -shared --as-needed
|
||||
# RUN: tar xf repro.tar
|
||||
# RUN: diff %t.dir/build2/foo.o repro/%:t.dir/build2/foo.o
|
||||
|
||||
# RUN: echo "{ local: *; };" > ver
|
||||
@ -34,10 +34,10 @@
|
||||
# RUN: echo > file
|
||||
# RUN: echo > file2
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o 'foo bar'
|
||||
# RUN: ld.lld --reproduce repro2 'foo bar' -L"foo bar" -Lfile -Tfile2 \
|
||||
# RUN: ld.lld --reproduce repro2.tar 'foo bar' -L"foo bar" -Lfile -Tfile2 \
|
||||
# RUN: --dynamic-list dyn -rpath file --script=file --version-script ver \
|
||||
# RUN: --dynamic-linker "some unusual/path" -soname 'foo bar' -soname='foo bar'
|
||||
# RUN: cpio -id < repro2.cpio
|
||||
# RUN: tar xf repro2.tar
|
||||
# RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt
|
||||
# RSP2: "{{.*}}foo bar"
|
||||
# RSP2-NEXT: -L "{{.*}}foo bar"
|
||||
@ -51,7 +51,7 @@
|
||||
# RSP2-NEXT: -soname="foo bar"
|
||||
# RSP2-NEXT: -soname="foo bar"
|
||||
|
||||
# RUN: cpio -it < repro2.cpio | FileCheck %s
|
||||
# RUN: tar tf repro2.tar | FileCheck %s
|
||||
# CHECK: repro2/response.txt
|
||||
# CHECK-NEXT: repro2/version.txt
|
||||
# CHECK-NEXT: repro2/{{.*}}/dyn
|
||||
|
@ -19,9 +19,9 @@ _start:
|
||||
.byte 0
|
||||
.section .data,"aw"
|
||||
.byte 0
|
||||
.section .bss.a,"",@nobits
|
||||
.section .bss.a,"aw",@nobits
|
||||
.byte 0
|
||||
.section .bss,"",@nobits
|
||||
.section .bss,"aw",@nobits
|
||||
.byte 0
|
||||
.section .foo.a,"aw"
|
||||
.byte 0
|
||||
@ -51,9 +51,8 @@ _start:
|
||||
// CHECK: 7 .data 00000002
|
||||
// CHECK: 8 .foo.a 00000001
|
||||
// CHECK: 9 .foo 00000001
|
||||
// CHECK: 10 .bss 00000001
|
||||
// CHECK: 11 .bss 00000001
|
||||
// CHECK: 12 .comment 00000008
|
||||
// CHECK: 13 .symtab 00000060
|
||||
// CHECK: 14 .shstrtab 00000075
|
||||
// CHECK: 15 .strtab 0000001d
|
||||
// CHECK: 10 .bss 00000002
|
||||
// CHECK: 11 .comment 00000008
|
||||
// CHECK: 12 .symtab 00000060
|
||||
// CHECK: 13 .shstrtab 00000075
|
||||
// CHECK: 14 .strtab 0000001d
|
||||
|
@ -6,10 +6,7 @@
|
||||
.global _start
|
||||
_start:
|
||||
|
||||
.section foobar,"",@progbits,unique,1
|
||||
.section foobar,"T",@progbits,unique,2
|
||||
.section foobar,"",@nobits,unique,3
|
||||
.section foobar,"",@nobits,unique,4
|
||||
.section foobar,"",@progbits
|
||||
|
||||
.section bar, "a"
|
||||
|
||||
@ -27,17 +24,4 @@ _start:
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
|
||||
// CHECK: Name: foobar
|
||||
// CHECK-NEXT: Type: SHT_PROGBITS
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: SHF_TLS
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
|
||||
// CHECK: Name: foobar
|
||||
// CHECK-NEXT: Type: SHT_NOBITS
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x0
|
||||
|
||||
// CHECK-NOT: Name: foobar
|
||||
|
@ -9,9 +9,9 @@
|
||||
# CHECK: error: undef.s:(.text+0x6): undefined symbol 'bar'
|
||||
# CHECK: error: undef.s:(.text+0x10): undefined symbol 'foo(int)'
|
||||
# CHECK: error: {{.*}}2.a({{.*}}.o):(.text+0x0): undefined symbol 'zed2'
|
||||
# CHECK: error: dir/undef-debug.s:3: undefined symbol 'zed3'
|
||||
# CHECK: error: dir/undef-debug.s:7: undefined symbol 'zed4'
|
||||
# CHECK: error: dir/undef-debug.s:11: undefined symbol 'zed5'
|
||||
# CHECK: error: dir{{/|\\}}undef-debug.s:3: undefined symbol 'zed3'
|
||||
# CHECK: error: dir{{/|\\}}undef-debug.s:7: undefined symbol 'zed4'
|
||||
# CHECK: error: dir{{/|\\}}undef-debug.s:11: undefined symbol 'zed5'
|
||||
|
||||
# RUN: not ld.lld %t.o %t2.a -o %t.exe -no-demangle 2>&1 | \
|
||||
# RUN: FileCheck -check-prefix=NO-DEMANGLE %s
|
||||
|
@ -258,7 +258,3 @@ cvtres = lit.util.which('cvtres', config.environment['PATH'])
|
||||
rc = lit.util.which('rc', config.environment['PATH'])
|
||||
if cvtres and rc:
|
||||
config.available_features.add('winres')
|
||||
|
||||
# Check if "cpio" command exists.
|
||||
if lit.util.which('cpio', config.environment['PATH']):
|
||||
config.available_features.add('cpio')
|
||||
|
Loading…
x
Reference in New Issue
Block a user