mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[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. llvm-svn: 219260
This commit is contained in:
parent
fa21d1891a
commit
8ae11e4491
@ -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.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -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 &Filename, int64_t FileSize) {
|
||||
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 Twine &BufferName) {
|
||||
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 &Filename, uint64_t FileSize,
|
||||
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;
|
||||
|
@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReopened) {
|
||||
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"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user