[llvm] r242215 - Add support for reading members out of thin archives.

Rafael Espindola rafael.espindola at gmail.com
Tue Jul 14 15:18:43 PDT 2015


Author: rafael
Date: Tue Jul 14 17:18:43 2015
New Revision: 242215

URL: http://llvm.org/viewvc/llvm-project?rev=242215&view=rev
Log:
Add support for reading members out of thin archives.

For now the Archive owns the buffers of the thin archive members.
This makes for a simple API, but all the buffers are destructed
only when the archive is destructed. This should be fine since we
close the files after mmap so we should not hit an open file
limit.

Modified:
    llvm/trunk/include/llvm/Object/Archive.h
    llvm/trunk/lib/Object/Archive.cpp
    llvm/trunk/test/Object/archive-extract.test
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

Modified: llvm/trunk/include/llvm/Object/Archive.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Archive.h?rev=242215&r1=242214&r2=242215&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Archive.h (original)
+++ llvm/trunk/include/llvm/Object/Archive.h Tue Jul 14 17:18:43 2015
@@ -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;
 };
 
 }

Modified: llvm/trunk/lib/Object/Archive.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Archive.cpp?rev=242215&r1=242214&r2=242215&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Archive.cpp (original)
+++ llvm/trunk/lib/Object/Archive.cpp Tue Jul 14 17:18:43 2015
@@ -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() co
   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:
   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>>

Modified: llvm/trunk/test/Object/archive-extract.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/archive-extract.test?rev=242215&r1=242214&r2=242215&view=diff
==============================================================================
--- llvm/trunk/test/Object/archive-extract.test (original)
+++ llvm/trunk/test/Object/archive-extract.test Tue Jul 14 17:18:43 2015
@@ -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.

Modified: llvm/trunk/tools/llvm-ar/llvm-ar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-ar/llvm-ar.cpp?rev=242215&r1=242214&r2=242215&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Tue Jul 14 17:18:43 2015
@@ -299,7 +299,9 @@ static void doPrint(StringRef Name, cons
   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, co
     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());





More information about the llvm-commits mailing list