xref: /aosp_15_r20/external/llvm/lib/Support/MemoryBuffer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker //  This file implements the MemoryBuffer interface.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Config/config.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errc.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errno.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Process.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Program.h"
24*9880d681SAndroid Build Coastguard Worker #include <cassert>
25*9880d681SAndroid Build Coastguard Worker #include <cerrno>
26*9880d681SAndroid Build Coastguard Worker #include <cstring>
27*9880d681SAndroid Build Coastguard Worker #include <new>
28*9880d681SAndroid Build Coastguard Worker #include <sys/types.h>
29*9880d681SAndroid Build Coastguard Worker #include <system_error>
30*9880d681SAndroid Build Coastguard Worker #if !defined(_MSC_VER) && !defined(__MINGW32__)
31*9880d681SAndroid Build Coastguard Worker #include <unistd.h>
32*9880d681SAndroid Build Coastguard Worker #else
33*9880d681SAndroid Build Coastguard Worker #include <io.h>
34*9880d681SAndroid Build Coastguard Worker #endif
35*9880d681SAndroid Build Coastguard Worker using namespace llvm;
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
38*9880d681SAndroid Build Coastguard Worker // MemoryBuffer implementation itself.
39*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
40*9880d681SAndroid Build Coastguard Worker 
~MemoryBuffer()41*9880d681SAndroid Build Coastguard Worker MemoryBuffer::~MemoryBuffer() { }
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker /// init - Initialize this MemoryBuffer as a reference to externally allocated
44*9880d681SAndroid Build Coastguard Worker /// memory, memory that we know is already null terminated.
init(const char * BufStart,const char * BufEnd,bool RequiresNullTerminator)45*9880d681SAndroid Build Coastguard Worker void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
46*9880d681SAndroid Build Coastguard Worker                         bool RequiresNullTerminator) {
47*9880d681SAndroid Build Coastguard Worker   assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
48*9880d681SAndroid Build Coastguard Worker          "Buffer is not null terminated!");
49*9880d681SAndroid Build Coastguard Worker   BufferStart = BufStart;
50*9880d681SAndroid Build Coastguard Worker   BufferEnd = BufEnd;
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
54*9880d681SAndroid Build Coastguard Worker // MemoryBufferMem implementation.
55*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker /// CopyStringRef - Copies contents of a StringRef into a block of memory and
58*9880d681SAndroid Build Coastguard Worker /// null-terminates it.
CopyStringRef(char * Memory,StringRef Data)59*9880d681SAndroid Build Coastguard Worker static void CopyStringRef(char *Memory, StringRef Data) {
60*9880d681SAndroid Build Coastguard Worker   if (!Data.empty())
61*9880d681SAndroid Build Coastguard Worker     memcpy(Memory, Data.data(), Data.size());
62*9880d681SAndroid Build Coastguard Worker   Memory[Data.size()] = 0; // Null terminate string.
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker namespace {
66*9880d681SAndroid Build Coastguard Worker struct NamedBufferAlloc {
67*9880d681SAndroid Build Coastguard Worker   const Twine &Name;
NamedBufferAlloc__anonf2dc34e70111::NamedBufferAlloc68*9880d681SAndroid Build Coastguard Worker   NamedBufferAlloc(const Twine &Name) : Name(Name) {}
69*9880d681SAndroid Build Coastguard Worker };
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker 
operator new(size_t N,const NamedBufferAlloc & Alloc)72*9880d681SAndroid Build Coastguard Worker void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
73*9880d681SAndroid Build Coastguard Worker   SmallString<256> NameBuf;
74*9880d681SAndroid Build Coastguard Worker   StringRef NameRef = Alloc.Name.toStringRef(NameBuf);
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   char *Mem = static_cast<char *>(operator new(N + NameRef.size() + 1));
77*9880d681SAndroid Build Coastguard Worker   CopyStringRef(Mem + N, NameRef);
78*9880d681SAndroid Build Coastguard Worker   return Mem;
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker namespace {
82*9880d681SAndroid Build Coastguard Worker /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
83*9880d681SAndroid Build Coastguard Worker class MemoryBufferMem : public MemoryBuffer {
84*9880d681SAndroid Build Coastguard Worker public:
MemoryBufferMem(StringRef InputData,bool RequiresNullTerminator)85*9880d681SAndroid Build Coastguard Worker   MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
86*9880d681SAndroid Build Coastguard Worker     init(InputData.begin(), InputData.end(), RequiresNullTerminator);
87*9880d681SAndroid Build Coastguard Worker   }
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   /// Disable sized deallocation for MemoryBufferMem, because it has
90*9880d681SAndroid Build Coastguard Worker   /// tail-allocated data.
operator delete(void * p)91*9880d681SAndroid Build Coastguard Worker   void operator delete(void *p) { ::operator delete(p); }
92*9880d681SAndroid Build Coastguard Worker 
getBufferIdentifier() const93*9880d681SAndroid Build Coastguard Worker   const char *getBufferIdentifier() const override {
94*9880d681SAndroid Build Coastguard Worker      // The name is stored after the class itself.
95*9880d681SAndroid Build Coastguard Worker     return reinterpret_cast<const char*>(this + 1);
96*9880d681SAndroid Build Coastguard Worker   }
97*9880d681SAndroid Build Coastguard Worker 
getBufferKind() const98*9880d681SAndroid Build Coastguard Worker   BufferKind getBufferKind() const override {
99*9880d681SAndroid Build Coastguard Worker     return MemoryBuffer_Malloc;
100*9880d681SAndroid Build Coastguard Worker   }
101*9880d681SAndroid Build Coastguard Worker };
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<MemoryBuffer>>
105*9880d681SAndroid Build Coastguard Worker getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
106*9880d681SAndroid Build Coastguard Worker            uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize);
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer>
getMemBuffer(StringRef InputData,StringRef BufferName,bool RequiresNullTerminator)109*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName,
110*9880d681SAndroid Build Coastguard Worker                            bool RequiresNullTerminator) {
111*9880d681SAndroid Build Coastguard Worker   auto *Ret = new (NamedBufferAlloc(BufferName))
112*9880d681SAndroid Build Coastguard Worker       MemoryBufferMem(InputData, RequiresNullTerminator);
113*9880d681SAndroid Build Coastguard Worker   return std::unique_ptr<MemoryBuffer>(Ret);
114*9880d681SAndroid Build Coastguard Worker }
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer>
getMemBuffer(MemoryBufferRef Ref,bool RequiresNullTerminator)117*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) {
118*9880d681SAndroid Build Coastguard Worker   return std::unique_ptr<MemoryBuffer>(getMemBuffer(
119*9880d681SAndroid Build Coastguard Worker       Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));
120*9880d681SAndroid Build Coastguard Worker }
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer>
getMemBufferCopy(StringRef InputData,const Twine & BufferName)123*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) {
124*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> Buf =
125*9880d681SAndroid Build Coastguard Worker       getNewUninitMemBuffer(InputData.size(), BufferName);
126*9880d681SAndroid Build Coastguard Worker   if (!Buf)
127*9880d681SAndroid Build Coastguard Worker     return nullptr;
128*9880d681SAndroid Build Coastguard Worker   memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
129*9880d681SAndroid Build Coastguard Worker          InputData.size());
130*9880d681SAndroid Build Coastguard Worker   return Buf;
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer>
getNewUninitMemBuffer(size_t Size,const Twine & BufferName)134*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getNewUninitMemBuffer(size_t Size, const Twine &BufferName) {
135*9880d681SAndroid Build Coastguard Worker   // Allocate space for the MemoryBuffer, the data and the name. It is important
136*9880d681SAndroid Build Coastguard Worker   // that MemoryBuffer and data are aligned so PointerIntPair works with them.
137*9880d681SAndroid Build Coastguard Worker   // TODO: Is 16-byte alignment enough?  We copy small object files with large
138*9880d681SAndroid Build Coastguard Worker   // alignment expectations into this buffer.
139*9880d681SAndroid Build Coastguard Worker   SmallString<256> NameBuf;
140*9880d681SAndroid Build Coastguard Worker   StringRef NameRef = BufferName.toStringRef(NameBuf);
141*9880d681SAndroid Build Coastguard Worker   size_t AlignedStringLen =
142*9880d681SAndroid Build Coastguard Worker       alignTo(sizeof(MemoryBufferMem) + NameRef.size() + 1, 16);
143*9880d681SAndroid Build Coastguard Worker   size_t RealLen = AlignedStringLen + Size + 1;
144*9880d681SAndroid Build Coastguard Worker   char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
145*9880d681SAndroid Build Coastguard Worker   if (!Mem)
146*9880d681SAndroid Build Coastguard Worker     return nullptr;
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker   // The name is stored after the class itself.
149*9880d681SAndroid Build Coastguard Worker   CopyStringRef(Mem + sizeof(MemoryBufferMem), NameRef);
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   // The buffer begins after the name and must be aligned.
152*9880d681SAndroid Build Coastguard Worker   char *Buf = Mem + AlignedStringLen;
153*9880d681SAndroid Build Coastguard Worker   Buf[Size] = 0; // Null terminate buffer.
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   auto *Ret = new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
156*9880d681SAndroid Build Coastguard Worker   return std::unique_ptr<MemoryBuffer>(Ret);
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer>
getNewMemBuffer(size_t Size,StringRef BufferName)160*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
161*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> SB = getNewUninitMemBuffer(Size, BufferName);
162*9880d681SAndroid Build Coastguard Worker   if (!SB)
163*9880d681SAndroid Build Coastguard Worker     return nullptr;
164*9880d681SAndroid Build Coastguard Worker   memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
165*9880d681SAndroid Build Coastguard Worker   return SB;
166*9880d681SAndroid Build Coastguard Worker }
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileOrSTDIN(const Twine & Filename,int64_t FileSize,bool RequiresNullTerminator)169*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize,
170*9880d681SAndroid Build Coastguard Worker                              bool RequiresNullTerminator) {
171*9880d681SAndroid Build Coastguard Worker   SmallString<256> NameBuf;
172*9880d681SAndroid Build Coastguard Worker   StringRef NameRef = Filename.toStringRef(NameBuf);
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   if (NameRef == "-")
175*9880d681SAndroid Build Coastguard Worker     return getSTDIN();
176*9880d681SAndroid Build Coastguard Worker   return getFile(Filename, FileSize, RequiresNullTerminator);
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileSlice(const Twine & FilePath,uint64_t MapSize,uint64_t Offset)180*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
181*9880d681SAndroid Build Coastguard Worker                            uint64_t Offset) {
182*9880d681SAndroid Build Coastguard Worker   return getFileAux(FilePath, -1, MapSize, Offset, false, false);
183*9880d681SAndroid Build Coastguard Worker }
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
187*9880d681SAndroid Build Coastguard Worker // MemoryBuffer::getFile implementation.
188*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker namespace {
191*9880d681SAndroid Build Coastguard Worker /// \brief Memory maps a file descriptor using sys::fs::mapped_file_region.
192*9880d681SAndroid Build Coastguard Worker ///
193*9880d681SAndroid Build Coastguard Worker /// This handles converting the offset into a legal offset on the platform.
194*9880d681SAndroid Build Coastguard Worker class MemoryBufferMMapFile : public MemoryBuffer {
195*9880d681SAndroid Build Coastguard Worker   sys::fs::mapped_file_region MFR;
196*9880d681SAndroid Build Coastguard Worker 
getLegalMapOffset(uint64_t Offset)197*9880d681SAndroid Build Coastguard Worker   static uint64_t getLegalMapOffset(uint64_t Offset) {
198*9880d681SAndroid Build Coastguard Worker     return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
199*9880d681SAndroid Build Coastguard Worker   }
200*9880d681SAndroid Build Coastguard Worker 
getLegalMapSize(uint64_t Len,uint64_t Offset)201*9880d681SAndroid Build Coastguard Worker   static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
202*9880d681SAndroid Build Coastguard Worker     return Len + (Offset - getLegalMapOffset(Offset));
203*9880d681SAndroid Build Coastguard Worker   }
204*9880d681SAndroid Build Coastguard Worker 
getStart(uint64_t Len,uint64_t Offset)205*9880d681SAndroid Build Coastguard Worker   const char *getStart(uint64_t Len, uint64_t Offset) {
206*9880d681SAndroid Build Coastguard Worker     return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
207*9880d681SAndroid Build Coastguard Worker   }
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker public:
MemoryBufferMMapFile(bool RequiresNullTerminator,int FD,uint64_t Len,uint64_t Offset,std::error_code & EC)210*9880d681SAndroid Build Coastguard Worker   MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
211*9880d681SAndroid Build Coastguard Worker                        uint64_t Offset, std::error_code &EC)
212*9880d681SAndroid Build Coastguard Worker       : MFR(FD, sys::fs::mapped_file_region::readonly,
213*9880d681SAndroid Build Coastguard Worker             getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
214*9880d681SAndroid Build Coastguard Worker     if (!EC) {
215*9880d681SAndroid Build Coastguard Worker       const char *Start = getStart(Len, Offset);
216*9880d681SAndroid Build Coastguard Worker       init(Start, Start + Len, RequiresNullTerminator);
217*9880d681SAndroid Build Coastguard Worker     }
218*9880d681SAndroid Build Coastguard Worker   }
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker   /// Disable sized deallocation for MemoryBufferMMapFile, because it has
221*9880d681SAndroid Build Coastguard Worker   /// tail-allocated data.
operator delete(void * p)222*9880d681SAndroid Build Coastguard Worker   void operator delete(void *p) { ::operator delete(p); }
223*9880d681SAndroid Build Coastguard Worker 
getBufferIdentifier() const224*9880d681SAndroid Build Coastguard Worker   const char *getBufferIdentifier() const override {
225*9880d681SAndroid Build Coastguard Worker     // The name is stored after the class itself.
226*9880d681SAndroid Build Coastguard Worker     return reinterpret_cast<const char *>(this + 1);
227*9880d681SAndroid Build Coastguard Worker   }
228*9880d681SAndroid Build Coastguard Worker 
getBufferKind() const229*9880d681SAndroid Build Coastguard Worker   BufferKind getBufferKind() const override {
230*9880d681SAndroid Build Coastguard Worker     return MemoryBuffer_MMap;
231*9880d681SAndroid Build Coastguard Worker   }
232*9880d681SAndroid Build Coastguard Worker };
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker 
235*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<MemoryBuffer>>
getMemoryBufferForStream(int FD,const Twine & BufferName)236*9880d681SAndroid Build Coastguard Worker getMemoryBufferForStream(int FD, const Twine &BufferName) {
237*9880d681SAndroid Build Coastguard Worker   const ssize_t ChunkSize = 4096*4;
238*9880d681SAndroid Build Coastguard Worker   SmallString<ChunkSize> Buffer;
239*9880d681SAndroid Build Coastguard Worker   ssize_t ReadBytes;
240*9880d681SAndroid Build Coastguard Worker   // Read into Buffer until we hit EOF.
241*9880d681SAndroid Build Coastguard Worker   do {
242*9880d681SAndroid Build Coastguard Worker     Buffer.reserve(Buffer.size() + ChunkSize);
243*9880d681SAndroid Build Coastguard Worker     ReadBytes = read(FD, Buffer.end(), ChunkSize);
244*9880d681SAndroid Build Coastguard Worker     if (ReadBytes == -1) {
245*9880d681SAndroid Build Coastguard Worker       if (errno == EINTR) continue;
246*9880d681SAndroid Build Coastguard Worker       return std::error_code(errno, std::generic_category());
247*9880d681SAndroid Build Coastguard Worker     }
248*9880d681SAndroid Build Coastguard Worker     Buffer.set_size(Buffer.size() + ReadBytes);
249*9880d681SAndroid Build Coastguard Worker   } while (ReadBytes != 0);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   return MemoryBuffer::getMemBufferCopy(Buffer, BufferName);
252*9880d681SAndroid Build Coastguard Worker }
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>>
getFile(const Twine & Filename,int64_t FileSize,bool RequiresNullTerminator,bool IsVolatileSize)256*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize,
257*9880d681SAndroid Build Coastguard Worker                       bool RequiresNullTerminator, bool IsVolatileSize) {
258*9880d681SAndroid Build Coastguard Worker   return getFileAux(Filename, FileSize, FileSize, 0,
259*9880d681SAndroid Build Coastguard Worker                     RequiresNullTerminator, IsVolatileSize);
260*9880d681SAndroid Build Coastguard Worker }
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<MemoryBuffer>>
263*9880d681SAndroid Build Coastguard Worker getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
264*9880d681SAndroid Build Coastguard Worker                 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
265*9880d681SAndroid Build Coastguard Worker                 bool IsVolatileSize);
266*9880d681SAndroid Build Coastguard Worker 
267*9880d681SAndroid Build Coastguard Worker static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFileAux(const Twine & Filename,int64_t FileSize,uint64_t MapSize,uint64_t Offset,bool RequiresNullTerminator,bool IsVolatileSize)268*9880d681SAndroid Build Coastguard Worker getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
269*9880d681SAndroid Build Coastguard Worker            uint64_t Offset, bool RequiresNullTerminator, bool IsVolatileSize) {
270*9880d681SAndroid Build Coastguard Worker   int FD;
271*9880d681SAndroid Build Coastguard Worker   std::error_code EC = sys::fs::openFileForRead(Filename, FD);
272*9880d681SAndroid Build Coastguard Worker   if (EC)
273*9880d681SAndroid Build Coastguard Worker     return EC;
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<MemoryBuffer>> Ret =
276*9880d681SAndroid Build Coastguard Worker       getOpenFileImpl(FD, Filename, FileSize, MapSize, Offset,
277*9880d681SAndroid Build Coastguard Worker                       RequiresNullTerminator, IsVolatileSize);
278*9880d681SAndroid Build Coastguard Worker   close(FD);
279*9880d681SAndroid Build Coastguard Worker   return Ret;
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker 
shouldUseMmap(int FD,size_t FileSize,size_t MapSize,off_t Offset,bool RequiresNullTerminator,int PageSize,bool IsVolatileSize)282*9880d681SAndroid Build Coastguard Worker static bool shouldUseMmap(int FD,
283*9880d681SAndroid Build Coastguard Worker                           size_t FileSize,
284*9880d681SAndroid Build Coastguard Worker                           size_t MapSize,
285*9880d681SAndroid Build Coastguard Worker                           off_t Offset,
286*9880d681SAndroid Build Coastguard Worker                           bool RequiresNullTerminator,
287*9880d681SAndroid Build Coastguard Worker                           int PageSize,
288*9880d681SAndroid Build Coastguard Worker                           bool IsVolatileSize) {
289*9880d681SAndroid Build Coastguard Worker   // mmap may leave the buffer without null terminator if the file size changed
290*9880d681SAndroid Build Coastguard Worker   // by the time the last page is mapped in, so avoid it if the file size is
291*9880d681SAndroid Build Coastguard Worker   // likely to change.
292*9880d681SAndroid Build Coastguard Worker   if (IsVolatileSize)
293*9880d681SAndroid Build Coastguard Worker     return false;
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   // We don't use mmap for small files because this can severely fragment our
296*9880d681SAndroid Build Coastguard Worker   // address space.
297*9880d681SAndroid Build Coastguard Worker   if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)
298*9880d681SAndroid Build Coastguard Worker     return false;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   if (!RequiresNullTerminator)
301*9880d681SAndroid Build Coastguard Worker     return true;
302*9880d681SAndroid Build Coastguard Worker 
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker   // If we don't know the file size, use fstat to find out.  fstat on an open
305*9880d681SAndroid Build Coastguard Worker   // file descriptor is cheaper than stat on a random path.
306*9880d681SAndroid Build Coastguard Worker   // FIXME: this chunk of code is duplicated, but it avoids a fstat when
307*9880d681SAndroid Build Coastguard Worker   // RequiresNullTerminator = false and MapSize != -1.
308*9880d681SAndroid Build Coastguard Worker   if (FileSize == size_t(-1)) {
309*9880d681SAndroid Build Coastguard Worker     sys::fs::file_status Status;
310*9880d681SAndroid Build Coastguard Worker     if (sys::fs::status(FD, Status))
311*9880d681SAndroid Build Coastguard Worker       return false;
312*9880d681SAndroid Build Coastguard Worker     FileSize = Status.getSize();
313*9880d681SAndroid Build Coastguard Worker   }
314*9880d681SAndroid Build Coastguard Worker 
315*9880d681SAndroid Build Coastguard Worker   // If we need a null terminator and the end of the map is inside the file,
316*9880d681SAndroid Build Coastguard Worker   // we cannot use mmap.
317*9880d681SAndroid Build Coastguard Worker   size_t End = Offset + MapSize;
318*9880d681SAndroid Build Coastguard Worker   assert(End <= FileSize);
319*9880d681SAndroid Build Coastguard Worker   if (End != FileSize)
320*9880d681SAndroid Build Coastguard Worker     return false;
321*9880d681SAndroid Build Coastguard Worker 
322*9880d681SAndroid Build Coastguard Worker   // Don't try to map files that are exactly a multiple of the system page size
323*9880d681SAndroid Build Coastguard Worker   // if we need a null terminator.
324*9880d681SAndroid Build Coastguard Worker   if ((FileSize & (PageSize -1)) == 0)
325*9880d681SAndroid Build Coastguard Worker     return false;
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker #if defined(__CYGWIN__)
328*9880d681SAndroid Build Coastguard Worker   // Don't try to map files that are exactly a multiple of the physical page size
329*9880d681SAndroid Build Coastguard Worker   // if we need a null terminator.
330*9880d681SAndroid Build Coastguard Worker   // FIXME: We should reorganize again getPageSize() on Win32.
331*9880d681SAndroid Build Coastguard Worker   if ((FileSize & (4096 - 1)) == 0)
332*9880d681SAndroid Build Coastguard Worker     return false;
333*9880d681SAndroid Build Coastguard Worker #endif
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker   return true;
336*9880d681SAndroid Build Coastguard Worker }
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker 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)339*9880d681SAndroid Build Coastguard Worker getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
340*9880d681SAndroid Build Coastguard Worker                 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
341*9880d681SAndroid Build Coastguard Worker                 bool IsVolatileSize) {
342*9880d681SAndroid Build Coastguard Worker   static int PageSize = sys::Process::getPageSize();
343*9880d681SAndroid Build Coastguard Worker 
344*9880d681SAndroid Build Coastguard Worker   // Default is to map the full file.
345*9880d681SAndroid Build Coastguard Worker   if (MapSize == uint64_t(-1)) {
346*9880d681SAndroid Build Coastguard Worker     // If we don't know the file size, use fstat to find out.  fstat on an open
347*9880d681SAndroid Build Coastguard Worker     // file descriptor is cheaper than stat on a random path.
348*9880d681SAndroid Build Coastguard Worker     if (FileSize == uint64_t(-1)) {
349*9880d681SAndroid Build Coastguard Worker       sys::fs::file_status Status;
350*9880d681SAndroid Build Coastguard Worker       std::error_code EC = sys::fs::status(FD, Status);
351*9880d681SAndroid Build Coastguard Worker       if (EC)
352*9880d681SAndroid Build Coastguard Worker         return EC;
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker       // If this not a file or a block device (e.g. it's a named pipe
355*9880d681SAndroid Build Coastguard Worker       // or character device), we can't trust the size. Create the memory
356*9880d681SAndroid Build Coastguard Worker       // buffer by copying off the stream.
357*9880d681SAndroid Build Coastguard Worker       sys::fs::file_type Type = Status.type();
358*9880d681SAndroid Build Coastguard Worker       if (Type != sys::fs::file_type::regular_file &&
359*9880d681SAndroid Build Coastguard Worker           Type != sys::fs::file_type::block_file)
360*9880d681SAndroid Build Coastguard Worker         return getMemoryBufferForStream(FD, Filename);
361*9880d681SAndroid Build Coastguard Worker 
362*9880d681SAndroid Build Coastguard Worker       FileSize = Status.getSize();
363*9880d681SAndroid Build Coastguard Worker     }
364*9880d681SAndroid Build Coastguard Worker     MapSize = FileSize;
365*9880d681SAndroid Build Coastguard Worker   }
366*9880d681SAndroid Build Coastguard Worker 
367*9880d681SAndroid Build Coastguard Worker   if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
368*9880d681SAndroid Build Coastguard Worker                     PageSize, IsVolatileSize)) {
369*9880d681SAndroid Build Coastguard Worker     std::error_code EC;
370*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<MemoryBuffer> Result(
371*9880d681SAndroid Build Coastguard Worker         new (NamedBufferAlloc(Filename))
372*9880d681SAndroid Build Coastguard Worker         MemoryBufferMMapFile(RequiresNullTerminator, FD, MapSize, Offset, EC));
373*9880d681SAndroid Build Coastguard Worker     if (!EC)
374*9880d681SAndroid Build Coastguard Worker       return std::move(Result);
375*9880d681SAndroid Build Coastguard Worker   }
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> Buf =
378*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
379*9880d681SAndroid Build Coastguard Worker   if (!Buf) {
380*9880d681SAndroid Build Coastguard Worker     // Failed to create a buffer. The only way it can fail is if
381*9880d681SAndroid Build Coastguard Worker     // new(std::nothrow) returns 0.
382*9880d681SAndroid Build Coastguard Worker     return make_error_code(errc::not_enough_memory);
383*9880d681SAndroid Build Coastguard Worker   }
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   char *BufPtr = const_cast<char *>(Buf->getBufferStart());
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker   size_t BytesLeft = MapSize;
388*9880d681SAndroid Build Coastguard Worker #ifndef HAVE_PREAD
389*9880d681SAndroid Build Coastguard Worker   if (lseek(FD, Offset, SEEK_SET) == -1)
390*9880d681SAndroid Build Coastguard Worker     return std::error_code(errno, std::generic_category());
391*9880d681SAndroid Build Coastguard Worker #endif
392*9880d681SAndroid Build Coastguard Worker 
393*9880d681SAndroid Build Coastguard Worker   while (BytesLeft) {
394*9880d681SAndroid Build Coastguard Worker #ifdef HAVE_PREAD
395*9880d681SAndroid Build Coastguard Worker     ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
396*9880d681SAndroid Build Coastguard Worker #else
397*9880d681SAndroid Build Coastguard Worker     ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
398*9880d681SAndroid Build Coastguard Worker #endif
399*9880d681SAndroid Build Coastguard Worker     if (NumRead == -1) {
400*9880d681SAndroid Build Coastguard Worker       if (errno == EINTR)
401*9880d681SAndroid Build Coastguard Worker         continue;
402*9880d681SAndroid Build Coastguard Worker       // Error while reading.
403*9880d681SAndroid Build Coastguard Worker       return std::error_code(errno, std::generic_category());
404*9880d681SAndroid Build Coastguard Worker     }
405*9880d681SAndroid Build Coastguard Worker     if (NumRead == 0) {
406*9880d681SAndroid Build Coastguard Worker       memset(BufPtr, 0, BytesLeft); // zero-initialize rest of the buffer.
407*9880d681SAndroid Build Coastguard Worker       break;
408*9880d681SAndroid Build Coastguard Worker     }
409*9880d681SAndroid Build Coastguard Worker     BytesLeft -= NumRead;
410*9880d681SAndroid Build Coastguard Worker     BufPtr += NumRead;
411*9880d681SAndroid Build Coastguard Worker   }
412*9880d681SAndroid Build Coastguard Worker 
413*9880d681SAndroid Build Coastguard Worker   return std::move(Buf);
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker 
416*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFile(int FD,const Twine & Filename,uint64_t FileSize,bool RequiresNullTerminator,bool IsVolatileSize)417*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
418*9880d681SAndroid Build Coastguard Worker                           bool RequiresNullTerminator, bool IsVolatileSize) {
419*9880d681SAndroid Build Coastguard Worker   return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,
420*9880d681SAndroid Build Coastguard Worker                          RequiresNullTerminator, IsVolatileSize);
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker 
423*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFileSlice(int FD,const Twine & Filename,uint64_t MapSize,int64_t Offset)424*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
425*9880d681SAndroid Build Coastguard Worker                                int64_t Offset) {
426*9880d681SAndroid Build Coastguard Worker   assert(MapSize != uint64_t(-1));
427*9880d681SAndroid Build Coastguard Worker   return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,
428*9880d681SAndroid Build Coastguard Worker                          /*IsVolatileSize*/ false);
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker 
getSTDIN()431*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
432*9880d681SAndroid Build Coastguard Worker   // Read in all of the data from stdin, we cannot mmap stdin.
433*9880d681SAndroid Build Coastguard Worker   //
434*9880d681SAndroid Build Coastguard Worker   // FIXME: That isn't necessarily true, we should try to mmap stdin and
435*9880d681SAndroid Build Coastguard Worker   // fallback if it fails.
436*9880d681SAndroid Build Coastguard Worker   sys::ChangeStdinToBinary();
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   return getMemoryBufferForStream(0, "<stdin>");
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker 
getMemBufferRef() const441*9880d681SAndroid Build Coastguard Worker MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
442*9880d681SAndroid Build Coastguard Worker   StringRef Data = getBuffer();
443*9880d681SAndroid Build Coastguard Worker   StringRef Identifier = getBufferIdentifier();
444*9880d681SAndroid Build Coastguard Worker   return MemoryBufferRef(Data, Identifier);
445*9880d681SAndroid Build Coastguard Worker }
446