diff options
Diffstat (limited to 'ELF/Driver.cpp')
-rw-r--r-- | ELF/Driver.cpp | 38 |
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)); } |