1 //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the MemoryBuffer interface. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/MemoryBuffer.h" 15 #include "llvm/ADT/OwningPtr.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/Support/MathExtras.h" 18 #include "llvm/Support/Errno.h" 19 #include "llvm/Support/Path.h" 20 #include "llvm/Support/Process.h" 21 #include "llvm/Support/Program.h" 22 #include "llvm/Support/system_error.h" 23 #include <cassert> 24 #include <cstdio> 25 #include <cstring> 26 #include <cerrno> 27 #include <new> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #if !defined(_MSC_VER) && !defined(__MINGW32__) 31 #include <unistd.h> 32 #include <sys/uio.h> 33 #else 34 #include <io.h> 35 #endif 36 #include <fcntl.h> 37 using namespace llvm; 38 39 namespace { const llvm::error_code success; } 40 41 //===----------------------------------------------------------------------===// 42 // MemoryBuffer implementation itself. 43 //===----------------------------------------------------------------------===// 44 45 MemoryBuffer::~MemoryBuffer() { } 46 47 /// init - Initialize this MemoryBuffer as a reference to externally allocated 48 /// memory, memory that we know is already null terminated. 49 void MemoryBuffer::init(const char *BufStart, const char *BufEnd, 50 bool RequiresNullTerminator) { 51 assert((!RequiresNullTerminator || BufEnd[0] == 0) && 52 "Buffer is not null terminated!"); 53 BufferStart = BufStart; 54 BufferEnd = BufEnd; 55 } 56 57 //===----------------------------------------------------------------------===// 58 // MemoryBufferMem implementation. 59 //===----------------------------------------------------------------------===// 60 61 /// CopyStringRef - Copies contents of a StringRef into a block of memory and 62 /// null-terminates it. 63 static void CopyStringRef(char *Memory, StringRef Data) { 64 memcpy(Memory, Data.data(), Data.size()); 65 Memory[Data.size()] = 0; // Null terminate string. 66 } 67 68 /// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it. 69 template <typename T> 70 static T *GetNamedBuffer(StringRef Buffer, StringRef Name, 71 bool RequiresNullTerminator) { 72 char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1)); 73 CopyStringRef(Mem + sizeof(T), Name); 74 return new (Mem) T(Buffer, RequiresNullTerminator); 75 } 76 77 namespace { 78 /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. 79 class MemoryBufferMem : public MemoryBuffer { 80 public: 81 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) { 82 init(InputData.begin(), InputData.end(), RequiresNullTerminator); 83 } 84 85 virtual const char *getBufferIdentifier() const { 86 // The name is stored after the class itself. 87 return reinterpret_cast<const char*>(this + 1); 88 } 89 90 virtual BufferKind getBufferKind() const { 91 return MemoryBuffer_Malloc; 92 } 93 }; 94 } 95 96 /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note 97 /// that InputData must be a null terminated if RequiresNullTerminator is true! 98 MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, 99 StringRef BufferName, 100 bool RequiresNullTerminator) { 101 return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName, 102 RequiresNullTerminator); 103 } 104 105 /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, 106 /// copying the contents and taking ownership of it. This has no requirements 107 /// on EndPtr[0]. 108 MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, 109 StringRef BufferName) { 110 MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName); 111 if (!Buf) return 0; 112 memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(), 113 InputData.size()); 114 return Buf; 115 } 116 117 /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size 118 /// that is not initialized. Note that the caller should initialize the 119 /// memory allocated by this method. The memory is owned by the MemoryBuffer 120 /// object. 121 MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, 122 StringRef BufferName) { 123 // Allocate space for the MemoryBuffer, the data and the name. It is important 124 // that MemoryBuffer and data are aligned so PointerIntPair works with them. 125 size_t AlignedStringLen = 126 RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, 127 sizeof(void*)); // TODO: Is sizeof(void*) enough? 128 size_t RealLen = AlignedStringLen + Size + 1; 129 char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow)); 130 if (!Mem) return 0; 131 132 // The name is stored after the class itself. 133 CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName); 134 135 // The buffer begins after the name and must be aligned. 136 char *Buf = Mem + AlignedStringLen; 137 Buf[Size] = 0; // Null terminate buffer. 138 139 return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true); 140 } 141 142 /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that 143 /// is completely initialized to zeros. Note that the caller should 144 /// initialize the memory allocated by this method. The memory is owned by 145 /// the MemoryBuffer object. 146 MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { 147 MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); 148 if (!SB) return 0; 149 memset(const_cast<char*>(SB->getBufferStart()), 0, Size); 150 return SB; 151 } 152 153 154 /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin 155 /// if the Filename is "-". If an error occurs, this returns null and fills 156 /// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN) 157 /// returns an empty buffer. 158 error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename, 159 OwningPtr<MemoryBuffer> &result, 160 int64_t FileSize) { 161 if (Filename == "-") 162 return getSTDIN(result); 163 return getFile(Filename, result, FileSize); 164 } 165 166 error_code MemoryBuffer::getFileOrSTDIN(const char *Filename, 167 OwningPtr<MemoryBuffer> &result, 168 int64_t FileSize) { 169 if (strcmp(Filename, "-") == 0) 170 return getSTDIN(result); 171 return getFile(Filename, result, FileSize); 172 } 173 174 //===----------------------------------------------------------------------===// 175 // MemoryBuffer::getFile implementation. 176 //===----------------------------------------------------------------------===// 177 178 namespace { 179 /// MemoryBufferMMapFile - This represents a file that was mapped in with the 180 /// sys::Path::MapInFilePages method. When destroyed, it calls the 181 /// sys::Path::UnMapFilePages method. 182 class MemoryBufferMMapFile : public MemoryBufferMem { 183 public: 184 MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator) 185 : MemoryBufferMem(Buffer, RequiresNullTerminator) { } 186 187 ~MemoryBufferMMapFile() { 188 static int PageSize = sys::Process::GetPageSize(); 189 190 uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart()); 191 size_t Size = getBufferSize(); 192 uintptr_t RealStart = Start & ~(PageSize - 1); 193 size_t RealSize = Size + (Start - RealStart); 194 195 sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart), 196 RealSize); 197 } 198 199 virtual BufferKind getBufferKind() const { 200 return MemoryBuffer_MMap; 201 } 202 }; 203 } 204 205 error_code MemoryBuffer::getFile(StringRef Filename, 206 OwningPtr<MemoryBuffer> &result, 207 int64_t FileSize, 208 bool RequiresNullTerminator) { 209 // Ensure the path is null terminated. 210 SmallString<256> PathBuf(Filename.begin(), Filename.end()); 211 return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize, 212 RequiresNullTerminator); 213 } 214 215 error_code MemoryBuffer::getFile(const char *Filename, 216 OwningPtr<MemoryBuffer> &result, 217 int64_t FileSize, 218 bool RequiresNullTerminator) { 219 int OpenFlags = O_RDONLY; 220 #ifdef O_BINARY 221 OpenFlags |= O_BINARY; // Open input file in binary mode on win32. 222 #endif 223 int FD = ::open(Filename, OpenFlags); 224 if (FD == -1) 225 return error_code(errno, posix_category()); 226 227 error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize, 228 0, RequiresNullTerminator); 229 close(FD); 230 return ret; 231 } 232 233 static bool shouldUseMmap(int FD, 234 size_t FileSize, 235 size_t MapSize, 236 off_t Offset, 237 bool RequiresNullTerminator, 238 int PageSize) { 239 // We don't use mmap for small files because this can severely fragment our 240 // address space. 241 if (MapSize < 4096*4) 242 return false; 243 244 if (!RequiresNullTerminator) 245 return true; 246 247 248 // If we don't know the file size, use fstat to find out. fstat on an open 249 // file descriptor is cheaper than stat on a random path. 250 // FIXME: this chunk of code is duplicated, but it avoids a fstat when 251 // RequiresNullTerminator = false and MapSize != -1. 252 if (FileSize == size_t(-1)) { 253 struct stat FileInfo; 254 // TODO: This should use fstat64 when available. 255 if (fstat(FD, &FileInfo) == -1) { 256 return error_code(errno, posix_category()); 257 } 258 FileSize = FileInfo.st_size; 259 } 260 261 // If we need a null terminator and the end of the map is inside the file, 262 // we cannot use mmap. 263 size_t End = Offset + MapSize; 264 assert(End <= FileSize); 265 if (End != FileSize) 266 return false; 267 268 // Don't try to map files that are exactly a multiple of the system page size 269 // if we need a null terminator. 270 if ((FileSize & (PageSize -1)) == 0) 271 return false; 272 273 return true; 274 } 275 276 error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, 277 OwningPtr<MemoryBuffer> &result, 278 size_t FileSize, size_t MapSize, 279 off_t Offset, 280 bool RequiresNullTerminator) { 281 static int PageSize = sys::Process::GetPageSize(); 282 283 // Default is to map the full file. 284 if (MapSize == size_t(-1)) { 285 // If we don't know the file size, use fstat to find out. fstat on an open 286 // file descriptor is cheaper than stat on a random path. 287 if (FileSize == size_t(-1)) { 288 struct stat FileInfo; 289 // TODO: This should use fstat64 when available. 290 if (fstat(FD, &FileInfo) == -1) { 291 return error_code(errno, posix_category()); 292 } 293 FileSize = FileInfo.st_size; 294 } 295 MapSize = FileSize; 296 } 297 298 if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, 299 PageSize)) { 300 off_t RealMapOffset = Offset & ~(PageSize - 1); 301 off_t Delta = Offset - RealMapOffset; 302 size_t RealMapSize = MapSize + Delta; 303 304 if (const char *Pages = sys::Path::MapInFilePages(FD, 305 RealMapSize, 306 RealMapOffset)) { 307 result.reset(GetNamedBuffer<MemoryBufferMMapFile>( 308 StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator)); 309 return success; 310 } 311 } 312 313 MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename); 314 if (!Buf) { 315 // Failed to create a buffer. The only way it can fail is if 316 // new(std::nothrow) returns 0. 317 return make_error_code(errc::not_enough_memory); 318 } 319 320 OwningPtr<MemoryBuffer> SB(Buf); 321 char *BufPtr = const_cast<char*>(SB->getBufferStart()); 322 323 size_t BytesLeft = MapSize; 324 if (lseek(FD, Offset, SEEK_SET) == -1) 325 return error_code(errno, posix_category()); 326 327 while (BytesLeft) { 328 ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); 329 if (NumRead == -1) { 330 if (errno == EINTR) 331 continue; 332 // Error while reading. 333 return error_code(errno, posix_category()); 334 } else if (NumRead == 0) { 335 // We hit EOF early, truncate and terminate buffer. 336 Buf->BufferEnd = BufPtr; 337 *BufPtr = 0; 338 result.swap(SB); 339 return success; 340 } 341 BytesLeft -= NumRead; 342 BufPtr += NumRead; 343 } 344 345 result.swap(SB); 346 return success; 347 } 348 349 //===----------------------------------------------------------------------===// 350 // MemoryBuffer::getSTDIN implementation. 351 //===----------------------------------------------------------------------===// 352 353 error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) { 354 // Read in all of the data from stdin, we cannot mmap stdin. 355 // 356 // FIXME: That isn't necessarily true, we should try to mmap stdin and 357 // fallback if it fails. 358 sys::Program::ChangeStdinToBinary(); 359 360 const ssize_t ChunkSize = 4096*4; 361 SmallString<ChunkSize> Buffer; 362 ssize_t ReadBytes; 363 // Read into Buffer until we hit EOF. 364 do { 365 Buffer.reserve(Buffer.size() + ChunkSize); 366 ReadBytes = read(0, Buffer.end(), ChunkSize); 367 if (ReadBytes == -1) { 368 if (errno == EINTR) continue; 369 return error_code(errno, posix_category()); 370 } 371 Buffer.set_size(Buffer.size() + ReadBytes); 372 } while (ReadBytes != 0); 373 374 result.reset(getMemBufferCopy(Buffer, "<stdin>")); 375 return success; 376 } 377