summaryrefslogtreecommitdiffstats
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/InputFiles.cpp27
-rw-r--r--lld/ELF/InputFiles.h14
-rw-r--r--lld/ELF/SymbolTable.cpp6
-rw-r--r--lld/ELF/Symbols.cpp6
4 files changed, 38 insertions, 15 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index e3266f17634..269d060eec9 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -471,13 +471,14 @@ template <class ELFT> void ArchiveFile::parse() {
}
// Returns a buffer pointing to a member file containing a given symbol.
-MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
+std::pair<MemoryBufferRef, uint64_t>
+ArchiveFile::getMember(const Archive::Symbol *Sym) {
Archive::Child C =
check(Sym->getMember(),
"could not get the member for symbol " + Sym->getName());
if (!Seen.insert(C.getChildOffset()).second)
- return MemoryBufferRef();
+ return {MemoryBufferRef(), 0};
MemoryBufferRef Ret =
check(C.getMemoryBufferRef(),
@@ -487,8 +488,9 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
if (C.getParent()->isThin() && Driver->Cpio)
Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
Ret.getBuffer());
-
- return Ret;
+ if (C.getParent()->isThin())
+ return {Ret, 0};
+ return {Ret, C.getChildOffset()};
}
template <class ELFT>
@@ -713,7 +715,18 @@ static Symbol *createBitcodeSymbol(const DenseSet<const Comdat *> &KeptComdats,
template <class ELFT>
void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) {
- Obj = check(lto::InputFile::create(MB));
+
+ // Here we pass a new MemoryBufferRef which is identified by ArchiveName
+ // (the fully resolved path of the archive) + member name + offset of the
+ // member in the archive.
+ // ThinLTO uses the MemoryBufferRef identifier to access its internal
+ // data structures and if two archives define two members with the same name,
+ // this causes a collision which result in only one of the objects being
+ // taken into consideration at LTO time (which very likely causes undefined
+ // symbols later in the link stage).
+ Obj = check(lto::InputFile::create(MemoryBufferRef(
+ MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier() +
+ utostr(OffsetInArchive)))));
DenseSet<const Comdat *> KeptComdats;
for (const auto &P : Obj->getComdatSymbolTable()) {
StringRef N = Saver.save(P.first());
@@ -803,10 +816,12 @@ static bool isBitcode(MemoryBufferRef MB) {
return identify_magic(MB.getBuffer()) == file_magic::bitcode;
}
-InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName) {
+InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,
+ uint64_t OffsetInArchive) {
InputFile *F =
isBitcode(MB) ? new BitcodeFile(MB) : createELFFile<ObjectFile>(MB);
F->ArchiveName = ArchiveName;
+ F->OffsetInArchive = OffsetInArchive;
return F;
}
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index c489bd60948..9d4fa0e1211 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -66,6 +66,12 @@ public:
// string for creating error messages.
StringRef ArchiveName;
+ // If this file is in an archive, the member contains the offset of
+ // the file in the archive. Otherwise, it's just zero. We store this
+ // field so that we can pass it to lib/LTO in order to disambiguate
+ // between objects.
+ uint64_t OffsetInArchive;
+
// If this is an architecture-specific file, the following members
// have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
ELFKind EKind = ELFNoneKind;
@@ -239,10 +245,11 @@ public:
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
template <class ELFT> void parse();
- // Returns a memory buffer for a given symbol. An empty memory buffer
+ // Returns a memory buffer for a given symbol and the offset in the archive
+ // for the member. An empty memory buffer and an offset of zero
// is returned if we have already returned the same memory buffer.
// (So that we don't instantiate same members more than once.)
- MemoryBufferRef getMember(const Archive::Symbol *Sym);
+ std::pair<MemoryBufferRef, uint64_t> getMember(const Archive::Symbol *Sym);
private:
std::unique_ptr<Archive> File;
@@ -324,7 +331,8 @@ private:
std::vector<uint8_t> ELFData;
};
-InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "");
+InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",
+ uint64_t OffsetInArchive = 0);
InputFile *createSharedFile(MemoryBufferRef MB);
} // namespace elf
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 339f99c07fe..976f8d858ba 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -508,9 +508,9 @@ void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type);
return;
}
- MemoryBufferRef MBRef = F->getMember(&Sym);
- if (!MBRef.getBuffer().empty())
- addFile(createObjectFile(MBRef, F->getName()));
+ std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym);
+ if (!MBInfo.first.getBuffer().empty())
+ addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second));
}
template <class ELFT>
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index f235dd6d8c4..e813ca147a0 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -245,13 +245,13 @@ LazyObject::LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type)
}
InputFile *LazyArchive::fetch() {
- MemoryBufferRef MBRef = file()->getMember(&Sym);
+ std::pair<MemoryBufferRef, uint64_t> MBInfo = file()->getMember(&Sym);
// getMember returns an empty buffer if the member was already
// read from the library.
- if (MBRef.getBuffer().empty())
+ if (MBInfo.first.getBuffer().empty())
return nullptr;
- return createObjectFile(MBRef, file()->getName());
+ return createObjectFile(MBInfo.first, file()->getName(), MBInfo.second);
}
InputFile *LazyObject::fetch() {
OpenPOWER on IntegriCloud