[llvm] r219260 - [Support] Add MemoryBuffer::getFileSlice()

Nick Kledzik kledzik at apple.com
Tue Oct 7 17:22:19 PDT 2014


Author: kledzik
Date: Tue Oct  7 19:22:18 2014
New Revision: 219260

URL: http://llvm.org/viewvc/llvm-project?rev=219260&view=rev
Log:
[Support] Add MemoryBuffer::getFileSlice()

mach-o supports "fat" files which are a header/table-of-contents followed by a
concatenation of mach-o files built for different architectures. Currently, 
MemoryBuffer has no easy way to map a subrange (slice) of a file which lld
will need to select a mach-o slice of a fat file. The new function provides 
an easy way to map a slice of a file into a MemoryBuffer. Test case included.

Modified:
    llvm/trunk/include/llvm/Support/MemoryBuffer.h
    llvm/trunk/lib/Support/MemoryBuffer.cpp
    llvm/trunk/unittests/Support/MemoryBufferTest.cpp

Modified: llvm/trunk/include/llvm/Support/MemoryBuffer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MemoryBuffer.h?rev=219260&r1=219259&r2=219260&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/MemoryBuffer.h (original)
+++ llvm/trunk/include/llvm/Support/MemoryBuffer.h Tue Oct  7 19:22:18 2014
@@ -126,6 +126,10 @@ public:
   static ErrorOr<std::unique_ptr<MemoryBuffer>>
   getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1);
 
+  /// Map a subrange of the the specified file as a MemoryBuffer.
+  static ErrorOr<std::unique_ptr<MemoryBuffer>>
+  getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
+
   //===--------------------------------------------------------------------===//
   // Provided for performance analysis.
   //===--------------------------------------------------------------------===//

Modified: llvm/trunk/lib/Support/MemoryBuffer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/MemoryBuffer.cpp?rev=219260&r1=219259&r2=219260&view=diff
==============================================================================
--- llvm/trunk/lib/Support/MemoryBuffer.cpp (original)
+++ llvm/trunk/lib/Support/MemoryBuffer.cpp Tue Oct  7 19:22:18 2014
@@ -97,6 +97,10 @@ public:
 };
 }
 
+static ErrorOr<std::unique_ptr<MemoryBuffer>>
+getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, 
+           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
+
 std::unique_ptr<MemoryBuffer>
 MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
                            bool RequiresNullTerminator) {
@@ -167,6 +171,12 @@ MemoryBuffer::getFileOrSTDIN(const Twine
   return getFile(Filename, FileSize);
 }
 
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, 
+                           uint64_t Offset) {
+  return getFileAux(FilePath, -1, MapSize, Offset, false, false);
+}
+
 
 //===----------------------------------------------------------------------===//
 // MemoryBuffer::getFile implementation.
@@ -232,15 +242,12 @@ getMemoryBufferForStream(int FD, const T
   return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
 }
 
-static ErrorOr<std::unique_ptr<MemoryBuffer>>
-getFileAux(const Twine &Filename, int64_t FileSize, bool RequiresNullTerminator,
-           bool IsVolatileSize);
 
 ErrorOr<std::unique_ptr<MemoryBuffer>>
 MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
                       bool RequiresNullTerminator, bool IsVolatileSize) {
-  return getFileAux(Filename, FileSize, RequiresNullTerminator,
-                    IsVolatileSize);
+  return getFileAux(Filename, FileSize, FileSize, 0,
+                    RequiresNullTerminator, IsVolatileSize);
 }
 
 static ErrorOr<std::unique_ptr<MemoryBuffer>>
@@ -249,15 +256,15 @@ getOpenFileImpl(int FD, const Twine &Fil
                 bool IsVolatileSize);
 
 static ErrorOr<std::unique_ptr<MemoryBuffer>>
-getFileAux(const Twine &Filename, int64_t FileSize, bool RequiresNullTerminator,
-           bool IsVolatileSize) {
+getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
+           uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
   int FD;
   std::error_code EC = sys::fs::openFileForRead(Filename, FD);
   if (EC)
     return EC;
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
-      getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
+      getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
                       RequiresNullTerminator, IsVolatileSize);
   close(FD);
   return Ret;

Modified: llvm/trunk/unittests/Support/MemoryBufferTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MemoryBufferTest.cpp?rev=219260&r1=219259&r2=219260&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/MemoryBufferTest.cpp (original)
+++ llvm/trunk/unittests/Support/MemoryBufferTest.cpp Tue Oct  7 19:22:18 2014
@@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReop
   testGetOpenFileSlice(true);
 }
 
+
+TEST_F(MemoryBufferTest, slice) {
+  // Create a file that is six pages long with different data on each page.
+  int FD;
+  SmallString<64> TestPath;
+  sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath);
+  raw_fd_ostream OF(FD, true, /*unbuffered=*/true);
+  for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+    OF << "12345678";
+  }
+  for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+    OF << "abcdefgh";
+  }
+  for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+    OF << "ABCDEFGH";
+  }
+  OF.close();
+
+  // Try offset of one page.
+  ErrorOr<OwningBuffer> MB = MemoryBuffer::getFileSlice(TestPath.str(),
+                                                        0x4000, 0x1000);
+  std::error_code EC = MB.getError();
+  ASSERT_FALSE(EC);
+  EXPECT_EQ(0x4000UL, MB.get()->getBufferSize());
+ 
+  StringRef BufData = MB.get()->getBuffer();
+  EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678"));
+  EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678"));
+  EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh"));
+  EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh"));
+  EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH"));
+  EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH"));
+   
+  // Try non-page aligned.
+  ErrorOr<OwningBuffer> MB2 = MemoryBuffer::getFileSlice(TestPath.str(),
+                                                         0x3000, 0x0800);
+  EC = MB2.getError();
+  ASSERT_FALSE(EC);
+  EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize());
+  
+  StringRef BufData2 = MB2.get()->getBuffer();
+  EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678"));
+  EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678"));
+  EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh"));
+  EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh"));
+ 
+}
+
+
+
 }





More information about the llvm-commits mailing list