16 #include "llvm/Config/config.h"
28 #include <sys/types.h>
29 #include <system_error>
30 #if !defined(_MSC_VER) && !defined(__MINGW32__)
46 bool RequiresNullTerminator) {
47 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
48 "Buffer is not null terminated!");
49 BufferStart = BufStart;
61 memcpy(Memory, Data.
data(), Data.
size());
62 Memory[Data.
size()] = 0;
66 struct NamedBufferAlloc {
68 NamedBufferAlloc(
const Twine &
Name) : Name(Name) {}
72 void *
operator new(
size_t N,
const NamedBufferAlloc &Alloc) {
74 StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
76 char *Mem =
static_cast<char *
>(
operator new(
N + NameRef.
size() + 1));
85 MemoryBufferMem(
StringRef InputData,
bool RequiresNullTerminator) {
86 init(InputData.
begin(), InputData.
end(), RequiresNullTerminator);
89 const char *getBufferIdentifier()
const override {
91 return reinterpret_cast<const char*
>(
this + 1);
94 BufferKind getBufferKind()
const override {
95 return MemoryBuffer_Malloc;
102 uint64_t Offset,
bool RequiresNullTerminator,
bool IsVolatileSize);
104 std::unique_ptr<MemoryBuffer>
106 bool RequiresNullTerminator) {
107 auto *
Ret =
new (NamedBufferAlloc(BufferName))
108 MemoryBufferMem(InputData, RequiresNullTerminator);
109 return std::unique_ptr<MemoryBuffer>(
Ret);
112 std::unique_ptr<MemoryBuffer>
118 std::unique_ptr<MemoryBuffer>
120 std::unique_ptr<MemoryBuffer> Buf =
124 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.
data(),
129 std::unique_ptr<MemoryBuffer>
137 size_t AlignedStringLen =
139 size_t RealLen = AlignedStringLen + Size + 1;
140 char *Mem =
static_cast<char*
>(
operator new(RealLen, std::nothrow));
148 char *Buf = Mem + AlignedStringLen;
151 auto *
Ret =
new (Mem) MemoryBufferMem(
StringRef(Buf, Size),
true);
152 return std::unique_ptr<MemoryBuffer>(
Ret);
155 std::unique_ptr<MemoryBuffer>
160 memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
171 return getFile(Filename, FileSize);
177 return getFileAux(FilePath, -1, MapSize, Offset,
false,
false);
192 static uint64_t getLegalMapOffset(uint64_t Offset) {
196 static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
197 return Len + (Offset - getLegalMapOffset(Offset));
200 const char *getStart(uint64_t Len, uint64_t Offset) {
201 return MFR.
const_data() + (Offset - getLegalMapOffset(Offset));
205 MemoryBufferMMapFile(
bool RequiresNullTerminator,
int FD, uint64_t Len,
206 uint64_t Offset, std::error_code &EC)
207 : MFR(FD, sys::fs::mapped_file_region::readonly,
208 getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
210 const char *Start = getStart(Len, Offset);
211 init(Start, Start + Len, RequiresNullTerminator);
215 const char *getBufferIdentifier()
const override {
217 return reinterpret_cast<const char *
>(
this + 1);
220 BufferKind getBufferKind()
const override {
221 return MemoryBuffer_MMap;
228 const ssize_t ChunkSize = 4096*4;
234 ReadBytes =
read(FD, Buffer.
end(), ChunkSize);
235 if (ReadBytes == -1) {
236 if (errno == EINTR)
continue;
237 return std::error_code(errno, std::generic_category());
240 }
while (ReadBytes != 0);
248 bool RequiresNullTerminator,
bool IsVolatileSize) {
249 return getFileAux(Filename, FileSize, FileSize, 0,
250 RequiresNullTerminator, IsVolatileSize);
255 uint64_t MapSize, int64_t Offset,
bool RequiresNullTerminator,
256 bool IsVolatileSize);
260 uint64_t Offset,
bool RequiresNullTerminator,
bool IsVolatileSize) {
268 RequiresNullTerminator, IsVolatileSize);
277 bool RequiresNullTerminator,
279 bool IsVolatileSize) {
288 if (MapSize < 4 * 4096 || MapSize < (
unsigned)PageSize)
291 if (!RequiresNullTerminator)
299 if (FileSize ==
size_t(-1)) {
303 FileSize = Status.getSize();
308 size_t End = Offset + MapSize;
309 assert(End <= FileSize);
315 if ((FileSize & (PageSize -1)) == 0)
318 #if defined(__CYGWIN__)
322 if ((FileSize & (4096 - 1)) == 0)
331 uint64_t MapSize, int64_t Offset,
bool RequiresNullTerminator,
332 bool IsVolatileSize) {
336 if (MapSize == uint64_t(-1)) {
339 if (FileSize == uint64_t(-1)) {
353 FileSize = Status.getSize();
358 if (
shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
359 PageSize, IsVolatileSize)) {
361 std::unique_ptr<MemoryBuffer> Result(
362 new (NamedBufferAlloc(Filename))
363 MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));
365 return std::move(Result);
368 std::unique_ptr<MemoryBuffer> Buf =
376 char *BufPtr =
const_cast<char *
>(Buf->getBufferStart());
378 size_t BytesLeft = MapSize;
380 if (lseek(FD, Offset, SEEK_SET) == -1)
381 return std::error_code(errno, std::generic_category());
386 ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
388 ssize_t NumRead =
::read(FD, BufPtr, BytesLeft);
394 return std::error_code(errno, std::generic_category());
397 memset(BufPtr, 0, BytesLeft);
400 BytesLeft -= NumRead;
404 return std::move(Buf);
409 bool RequiresNullTerminator,
bool IsVolatileSize) {
411 RequiresNullTerminator, IsVolatileSize);
417 assert(MapSize != uint64_t(-1));
MemoryBufferRef getMemBufferRef() const
void init(const char *BufStart, const char *BufEnd, bool RequiresNullTerminator)
init - Initialize this MemoryBuffer as a reference to externally allocated memory, memory that we know is already null terminated.
Represents either an error or a value T.
size_t size() const
size - Get the string size.
value_type read(const void *memory)
Read a value of a particular endianness from memory.
This class provides various memory handling functions that manipulate MemoryBlock instances...
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getMemoryBufferForStream(int FD, const Twine &BufferName)
This class represents a memory mapped file.
StringRef getBuffer() const
static std::unique_ptr< MemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new MemoryBuffer of the specified size that is not initialized.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
void reserve(size_type N)
static std::unique_ptr< MemoryBuffer > getNewMemBuffer(size_t Size, StringRef BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
const char * const_data() const
Get a const view of the data.
static bool shouldUseMmap(int FD, size_t FileSize, size_t MapSize, off_t Offset, bool RequiresNullTerminator, int PageSize, bool IsVolatileSize)
file_status - Represents the result of a call to stat and friends.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset)
Map a subrange of the specified file as a MemoryBuffer.
virtual const char * getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::error_code make_error_code(BitcodeError E)
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static void CopyStringRef(char *Memory, StringRef Data)
CopyStringRef - Copies contents of a StringRef into a block of memory and null-terminates it...
initializer< Ty > init(const Ty &Val)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()
Read all of stdin into a file buffer, and return it.
The instances of the Type class are immutable: once they are created, they are never changed...
static unsigned getPageSize()
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, int64_t FileSize=-1)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
StringRef getBuffer() const
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it...
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
std::error_code ChangeStdinToBinary()
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize)
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
Provides a library for accessing information about this process and other processes on the operating ...
static cl::opt< unsigned > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in ""bytes"), cl::init(4096))
file_type
An enumeration for the file system's view of the type.
std::error_code openFileForRead(const Twine &Name, int &ResultFD)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
StringRef getBufferIdentifier() const
StringRef - Represent a constant reference to a string, i.e.
std::error_code status(const Twine &path, file_status &result)
Get file status as if by POSIX stat().
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, int64_t Offset)
Given an already-open file descriptor, map some slice of it into a MemoryBuffer.
bool empty() const
empty - Check if the string is empty.