summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Object/Archive.h11
-rw-r--r--llvm/lib/Object/Archive.cpp23
-rw-r--r--llvm/test/Object/archive-extract.test6
-rw-r--r--llvm/tools/llvm-ar/llvm-ar.cpp6
4 files changed, 39 insertions, 7 deletions
diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index e461564ace8..597f0d48c11 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -94,9 +94,7 @@ public:
/// \return the size in the archive header for this member.
uint64_t getRawSize() const;
- StringRef getBuffer() const {
- return StringRef(Data.data() + StartOfFile, getSize());
- }
+ ErrorOr<StringRef> getBuffer() const;
uint64_t getChildOffset() const;
ErrorOr<MemoryBufferRef> getMemoryBufferRef() const;
@@ -208,7 +206,11 @@ public:
bool hasSymbolTable() const;
child_iterator getSymbolTableChild() const { return SymbolTable; }
- StringRef getSymbolTable() const { return SymbolTable->getBuffer(); }
+ StringRef getSymbolTable() const {
+ // We know that the symbol table is not an external file,
+ // so we just assert there is no error.
+ return *SymbolTable->getBuffer();
+ }
uint32_t getNumberOfSymbols() const;
private:
@@ -217,6 +219,7 @@ private:
child_iterator FirstRegular;
unsigned Format : 2;
unsigned IsThin : 1;
+ mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};
}
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index c29e63941f2..d4821196a6c 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
using namespace llvm;
using namespace object;
@@ -115,6 +116,23 @@ uint64_t Archive::Child::getRawSize() const {
return getHeader()->getSize();
}
+ErrorOr<StringRef> Archive::Child::getBuffer() const {
+ if (!Parent->IsThin)
+ return StringRef(Data.data() + StartOfFile, getSize());
+ ErrorOr<StringRef> Name = getName();
+ if (std::error_code EC = Name.getError())
+ return EC;
+ SmallString<128> FullName =
+ Parent->getMemoryBufferRef().getBufferIdentifier();
+ sys::path::remove_filename(FullName);
+ sys::path::append(FullName, *Name);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
+ if (std::error_code EC = Buf.getError())
+ return EC;
+ Parent->ThinBuffers.push_back(std::move(*Buf));
+ return Parent->ThinBuffers.back()->getBuffer();
+}
+
Archive::Child Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
@@ -186,7 +204,10 @@ ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
if (std::error_code EC = NameOrErr.getError())
return EC;
StringRef Name = NameOrErr.get();
- return MemoryBufferRef(getBuffer(), Name);
+ ErrorOr<StringRef> Buf = getBuffer();
+ if (std::error_code EC = Buf.getError())
+ return EC;
+ return MemoryBufferRef(*Buf, Name);
}
ErrorOr<std::unique_ptr<Binary>>
diff --git a/llvm/test/Object/archive-extract.test b/llvm/test/Object/archive-extract.test
index c1ddcf71725..a77adf2cabb 100644
--- a/llvm/test/Object/archive-extract.test
+++ b/llvm/test/Object/archive-extract.test
@@ -48,3 +48,9 @@ NOTFOUND: foo.o was not found
RUN: not llvm-ar x %p/Inputs/thin.a foo.o 2>&1 | FileCheck %s --check-prefix=THINEXTRACT
THINEXTRACT: extracting from a thin archive is not supported
+
+RUN: llvm-ar p %p/Inputs/thin.a evenlen | FileCheck %s --check-prefix=EVENLEN
+EVENLEN: evenlen
+
+RUN: not llvm-ar p %p/Inputs/thin-path.a t/test2.o | FileCheck %s --check-prefix=MISSING
+MISSING: No such file or directory.
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index c87606d7826..2c9668c63b8 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -299,7 +299,9 @@ static void doPrint(StringRef Name, const object::Archive::Child &C) {
if (Verbose)
outs() << "Printing " << Name << "\n";
- StringRef Data = C.getBuffer();
+ ErrorOr<StringRef> DataOrErr = C.getBuffer();
+ failIfError(DataOrErr.getError());
+ StringRef Data = *DataOrErr;
outs().write(Data.data(), Data.size());
}
@@ -355,7 +357,7 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) {
raw_fd_ostream file(FD, false);
// Get the data and its length
- StringRef Data = C.getBuffer();
+ StringRef Data = *C.getBuffer();
// Write the data.
file.write(Data.data(), Data.size());
OpenPOWER on IntegriCloud