llvm.org GIT mirror llvm / 52688c3
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219260 91177308-0d34-0410-b5e6-96231b3b80d8 Nick Kledzik 5 years ago
3 changed file(s) with 70 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
125125 static ErrorOr>
126126 getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1);
127127
128 /// Map a subrange of the the specified file as a MemoryBuffer.
129 static ErrorOr>
130 getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
131
128132 //===--------------------------------------------------------------------===//
129133 // Provided for performance analysis.
130134 //===--------------------------------------------------------------------===//
9696 };
9797 }
9898
99 static ErrorOr>
100 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
101 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
102
99103 std::unique_ptr
100104 MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
101105 bool RequiresNullTerminator) {
164168 if (NameRef == "-")
165169 return getSTDIN();
166170 return getFile(Filename, FileSize);
171 }
172
173 ErrorOr>
174 MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
175 uint64_t Offset) {
176 return getFileAux(FilePath, -1, MapSize, Offset, false, false);
167177 }
168178
169179
231241 return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
232242 }
233243
234 static ErrorOr>
235 getFileAux(const Twine &Filename, int64_t FileSize, bool RequiresNullTerminator,
236 bool IsVolatileSize);
237244
238245 ErrorOr>
239246 MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
240247 bool RequiresNullTerminator, bool IsVolatileSize) {
241 return getFileAux(Filename, FileSize, RequiresNullTerminator,
242 IsVolatileSize);
248 return getFileAux(Filename, FileSize, FileSize, 0,
249 RequiresNullTerminator, IsVolatileSize);
243250 }
244251
245252 static ErrorOr>
248255 bool IsVolatileSize);
249256
250257 static ErrorOr>
251 getFileAux(const Twine &Filename, int64_t FileSize, bool RequiresNullTerminator,
252 bool IsVolatileSize) {
258 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
259 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
253260 int FD;
254261 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
255262 if (EC)
256263 return EC;
257264
258265 ErrorOr> Ret =
259 getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
266 getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
260267 RequiresNullTerminator, IsVolatileSize);
261268 close(FD);
262269 return Ret;
168168 testGetOpenFileSlice(true);
169169 }
170170
171 }
171
172 TEST_F(MemoryBufferTest, slice) {
173 // Create a file that is six pages long with different data on each page.
174 int FD;
175 SmallString<64> TestPath;
176 sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath);
177 raw_fd_ostream OF(FD, true, /*unbuffered=*/true);
178 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
179 OF << "12345678";
180 }
181 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
182 OF << "abcdefgh";
183 }
184 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
185 OF << "ABCDEFGH";
186 }
187 OF.close();
188
189 // Try offset of one page.
190 ErrorOr MB = MemoryBuffer::getFileSlice(TestPath.str(),
191 0x4000, 0x1000);
192 std::error_code EC = MB.getError();
193 ASSERT_FALSE(EC);
194 EXPECT_EQ(0x4000UL, MB.get()->getBufferSize());
195
196 StringRef BufData = MB.get()->getBuffer();
197 EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678"));
198 EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678"));
199 EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh"));
200 EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh"));
201 EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH"));
202 EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH"));
203
204 // Try non-page aligned.
205 ErrorOr MB2 = MemoryBuffer::getFileSlice(TestPath.str(),
206 0x3000, 0x0800);
207 EC = MB2.getError();
208 ASSERT_FALSE(EC);
209 EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize());
210
211 StringRef BufData2 = MB2.get()->getBuffer();
212 EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678"));
213 EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678"));
214 EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh"));
215 EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh"));
216
217 }
218
219
220
221 }