aboutsummaryrefslogtreecommitdiff
path: root/ELF/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/Driver.cpp')
-rw-r--r--ELF/Driver.cpp38
1 files changed, 27 insertions, 11 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 6a71eb3ee490..c2cfe3c4129e 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -123,13 +123,13 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
-std::vector<MemoryBufferRef>
-static getArchiveMembers(MemoryBufferRef MB) {
+std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
+ MemoryBufferRef MB) {
std::unique_ptr<Archive> File =
check(Archive::create(MB),
MB.getBufferIdentifier() + ": failed to parse archive");
- std::vector<MemoryBufferRef> V;
+ std::vector<std::pair<MemoryBufferRef, uint64_t>> V;
Error Err = Error::success();
for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
Archive::Child C =
@@ -139,7 +139,7 @@ static getArchiveMembers(MemoryBufferRef MB) {
check(C.getMemoryBufferRef(),
MB.getBufferIdentifier() +
": could not get the buffer for a child of the archive");
- V.push_back(MBRef);
+ V.push_back(std::make_pair(MBRef, C.getChildOffset()));
}
if (Err)
fatal(MB.getBufferIdentifier() + ": Archive::children failed: " +
@@ -152,8 +152,7 @@ static getArchiveMembers(MemoryBufferRef MB) {
return V;
}
-// Opens and parses a file. Path has to be resolved already.
-// Newly created memory buffers are owned by this driver.
+// Opens a file and create a file object. Path has to be resolved already.
void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
using namespace sys::fs;
@@ -171,14 +170,31 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
case file_magic::unknown:
readLinkerScript(MBRef);
return;
- case file_magic::archive:
+ case file_magic::archive: {
+ // Handle -whole-archive.
if (InWholeArchive) {
- for (MemoryBufferRef MB : getArchiveMembers(MBRef))
- Files.push_back(createObjectFile(MB, Path));
+ for (const auto &P : getArchiveMembers(MBRef))
+ Files.push_back(createObjectFile(P.first, Path, P.second));
return;
}
- Files.push_back(make<ArchiveFile>(MBRef));
+
+ std::unique_ptr<Archive> File =
+ check(Archive::create(MBRef), Path + ": failed to parse archive");
+
+ // If an archive file has no symbol table, it is likely that a user
+ // is attempting LTO and using a default ar command that doesn't
+ // understand the LLVM bitcode file. It is a pretty common error, so
+ // we'll handle it as if it had a symbol table.
+ if (!File->hasSymbolTable()) {
+ for (const auto &P : getArchiveMembers(MBRef))
+ Files.push_back(make<LazyObjectFile>(P.first, Path, P.second));
+ return;
+ }
+
+ // Handle the regular case.
+ Files.push_back(make<ArchiveFile>(std::move(File)));
return;
+ }
case file_magic::elf_shared_object:
if (Config->Relocatable) {
error("attempted static link of dynamic object " + Path);
@@ -199,7 +215,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
return;
default:
if (InLib)
- Files.push_back(make<LazyObjectFile>(MBRef));
+ Files.push_back(make<LazyObjectFile>(MBRef, "", 0));
else
Files.push_back(createObjectFile(MBRef));
}