10b57cec5SDimitry Andric //===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the MemoryBuffer interface. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 1406c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h" 150b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 160b57cec5SDimitry Andric #include "llvm/Config/config.h" 17bdd1243dSDimitry Andric #include "llvm/Support/Alignment.h" 1881ad6265SDimitry Andric #include "llvm/Support/Errc.h" 1904eeddc0SDimitry Andric #include "llvm/Support/Error.h" 2004eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h" 210b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 220b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 230b57cec5SDimitry Andric #include "llvm/Support/Process.h" 240b57cec5SDimitry Andric #include "llvm/Support/Program.h" 250b57cec5SDimitry Andric #include "llvm/Support/SmallVectorMemoryBuffer.h" 2606c3fb27SDimitry Andric #include <algorithm> 270b57cec5SDimitry Andric #include <cassert> 280b57cec5SDimitry Andric #include <cstring> 290b57cec5SDimitry Andric #include <new> 300b57cec5SDimitry Andric #include <sys/types.h> 310b57cec5SDimitry Andric #include <system_error> 320b57cec5SDimitry Andric #if !defined(_MSC_VER) && !defined(__MINGW32__) 330b57cec5SDimitry Andric #include <unistd.h> 340b57cec5SDimitry Andric #else 350b57cec5SDimitry Andric #include <io.h> 360b57cec5SDimitry Andric #endif 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric #ifdef __MVS__ 3981ad6265SDimitry Andric #include "llvm/Support/AutoConvert.h" 4081ad6265SDimitry Andric #endif 410b57cec5SDimitry Andric using namespace llvm; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 440b57cec5SDimitry Andric // MemoryBuffer implementation itself. 450b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 460b57cec5SDimitry Andric 4781ad6265SDimitry Andric MemoryBuffer::~MemoryBuffer() = default; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// init - Initialize this MemoryBuffer as a reference to externally allocated 500b57cec5SDimitry Andric /// memory, memory that we know is already null terminated. 510b57cec5SDimitry Andric void MemoryBuffer::init(const char *BufStart, const char *BufEnd, 520b57cec5SDimitry Andric bool RequiresNullTerminator) { 530b57cec5SDimitry Andric assert((!RequiresNullTerminator || BufEnd[0] == 0) && 540b57cec5SDimitry Andric "Buffer is not null terminated!"); 550b57cec5SDimitry Andric BufferStart = BufStart; 560b57cec5SDimitry Andric BufferEnd = BufEnd; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 600b57cec5SDimitry Andric // MemoryBufferMem implementation. 610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// CopyStringRef - Copies contents of a StringRef into a block of memory and 640b57cec5SDimitry Andric /// null-terminates it. 650b57cec5SDimitry Andric static void CopyStringRef(char *Memory, StringRef Data) { 660b57cec5SDimitry Andric if (!Data.empty()) 670b57cec5SDimitry Andric memcpy(Memory, Data.data(), Data.size()); 680b57cec5SDimitry Andric Memory[Data.size()] = 0; // Null terminate string. 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric namespace { 720b57cec5SDimitry Andric struct NamedBufferAlloc { 730b57cec5SDimitry Andric const Twine &Name; 740b57cec5SDimitry Andric NamedBufferAlloc(const Twine &Name) : Name(Name) {} 750b57cec5SDimitry Andric }; 76fe6060f1SDimitry Andric } // namespace 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric void *operator new(size_t N, const NamedBufferAlloc &Alloc) { 790b57cec5SDimitry Andric SmallString<256> NameBuf; 800b57cec5SDimitry Andric StringRef NameRef = Alloc.Name.toStringRef(NameBuf); 810b57cec5SDimitry Andric 82*0fca6ea1SDimitry Andric // We use malloc() and manually handle it returning null instead of calling 83*0fca6ea1SDimitry Andric // operator new because we need all uses of NamedBufferAlloc to be 84*0fca6ea1SDimitry Andric // deallocated with a call to free() due to needing to use malloc() in 85*0fca6ea1SDimitry Andric // WritableMemoryBuffer::getNewUninitMemBuffer() to work around the out-of- 86*0fca6ea1SDimitry Andric // memory handler installed by default in LLVM. See operator delete() member 87*0fca6ea1SDimitry Andric // functions within this file for the paired call to free(). 88*0fca6ea1SDimitry Andric char *Mem = 89*0fca6ea1SDimitry Andric static_cast<char *>(std::malloc(N + sizeof(size_t) + NameRef.size() + 1)); 90*0fca6ea1SDimitry Andric if (!Mem) 91*0fca6ea1SDimitry Andric llvm::report_bad_alloc_error("Allocation failed"); 92bdd1243dSDimitry Andric *reinterpret_cast<size_t *>(Mem + N) = NameRef.size(); 93bdd1243dSDimitry Andric CopyStringRef(Mem + N + sizeof(size_t), NameRef); 940b57cec5SDimitry Andric return Mem; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric namespace { 980b57cec5SDimitry Andric /// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. 990b57cec5SDimitry Andric template<typename MB> 1000b57cec5SDimitry Andric class MemoryBufferMem : public MB { 1010b57cec5SDimitry Andric public: 1020b57cec5SDimitry Andric MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) { 1030b57cec5SDimitry Andric MemoryBuffer::init(InputData.begin(), InputData.end(), 1040b57cec5SDimitry Andric RequiresNullTerminator); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Disable sized deallocation for MemoryBufferMem, because it has 1080b57cec5SDimitry Andric /// tail-allocated data. 109*0fca6ea1SDimitry Andric void operator delete(void *p) { std::free(p); } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric StringRef getBufferIdentifier() const override { 1120b57cec5SDimitry Andric // The name is stored after the class itself. 113bdd1243dSDimitry Andric return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t), 114bdd1243dSDimitry Andric *reinterpret_cast<const size_t *>(this + 1)); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric MemoryBuffer::BufferKind getBufferKind() const override { 1180b57cec5SDimitry Andric return MemoryBuffer::MemoryBuffer_Malloc; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric }; 121fe6060f1SDimitry Andric } // namespace 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric template <typename MB> 1240b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<MB>> 125fe6060f1SDimitry Andric getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset, 126bdd1243dSDimitry Andric bool IsText, bool RequiresNullTerminator, bool IsVolatile, 127bdd1243dSDimitry Andric std::optional<Align> Alignment); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> 1300b57cec5SDimitry Andric MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, 1310b57cec5SDimitry Andric bool RequiresNullTerminator) { 1320b57cec5SDimitry Andric auto *Ret = new (NamedBufferAlloc(BufferName)) 1330b57cec5SDimitry Andric MemoryBufferMem<MemoryBuffer>(InputData, RequiresNullTerminator); 1340b57cec5SDimitry Andric return std::unique_ptr<MemoryBuffer>(Ret); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> 1380b57cec5SDimitry Andric MemoryBuffer::getMemBuffer(MemoryBufferRef Ref, bool RequiresNullTerminator) { 1390b57cec5SDimitry Andric return std::unique_ptr<MemoryBuffer>(getMemBuffer( 1400b57cec5SDimitry Andric Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator)); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<WritableMemoryBuffer>> 1440b57cec5SDimitry Andric getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName) { 14506c3fb27SDimitry Andric auto Buf = 14606c3fb27SDimitry Andric WritableMemoryBuffer::getNewUninitMemBuffer(InputData.size(), BufferName); 1470b57cec5SDimitry Andric if (!Buf) 1480b57cec5SDimitry Andric return make_error_code(errc::not_enough_memory); 14906c3fb27SDimitry Andric // Calling memcpy with null src/dst is UB, and an empty StringRef is 15006c3fb27SDimitry Andric // represented with {nullptr, 0}. 15106c3fb27SDimitry Andric llvm::copy(InputData, Buf->getBufferStart()); 1520b57cec5SDimitry Andric return std::move(Buf); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> 1560b57cec5SDimitry Andric MemoryBuffer::getMemBufferCopy(StringRef InputData, const Twine &BufferName) { 1570b57cec5SDimitry Andric auto Buf = getMemBufferCopyImpl(InputData, BufferName); 1580b57cec5SDimitry Andric if (Buf) 1590b57cec5SDimitry Andric return std::move(*Buf); 1600b57cec5SDimitry Andric return nullptr; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> 164fe6060f1SDimitry Andric MemoryBuffer::getFileOrSTDIN(const Twine &Filename, bool IsText, 165bdd1243dSDimitry Andric bool RequiresNullTerminator, 166bdd1243dSDimitry Andric std::optional<Align> Alignment) { 1670b57cec5SDimitry Andric SmallString<256> NameBuf; 1680b57cec5SDimitry Andric StringRef NameRef = Filename.toStringRef(NameBuf); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric if (NameRef == "-") 1710b57cec5SDimitry Andric return getSTDIN(); 172fe6060f1SDimitry Andric return getFile(Filename, IsText, RequiresNullTerminator, 173bdd1243dSDimitry Andric /*IsVolatile=*/false, Alignment); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> 1770b57cec5SDimitry Andric MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, 178bdd1243dSDimitry Andric uint64_t Offset, bool IsVolatile, 179bdd1243dSDimitry Andric std::optional<Align> Alignment) { 180fe6060f1SDimitry Andric return getFileAux<MemoryBuffer>(FilePath, MapSize, Offset, /*IsText=*/false, 181bdd1243dSDimitry Andric /*RequiresNullTerminator=*/false, IsVolatile, 182bdd1243dSDimitry Andric Alignment); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1860b57cec5SDimitry Andric // MemoryBuffer::getFile implementation. 1870b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric namespace { 1905ffd83dbSDimitry Andric 1915ffd83dbSDimitry Andric template <typename MB> 1925ffd83dbSDimitry Andric constexpr sys::fs::mapped_file_region::mapmode Mapmode = 1935ffd83dbSDimitry Andric sys::fs::mapped_file_region::readonly; 1945ffd83dbSDimitry Andric template <> 1955ffd83dbSDimitry Andric constexpr sys::fs::mapped_file_region::mapmode Mapmode<MemoryBuffer> = 1965ffd83dbSDimitry Andric sys::fs::mapped_file_region::readonly; 1975ffd83dbSDimitry Andric template <> 1985ffd83dbSDimitry Andric constexpr sys::fs::mapped_file_region::mapmode Mapmode<WritableMemoryBuffer> = 1995ffd83dbSDimitry Andric sys::fs::mapped_file_region::priv; 2005ffd83dbSDimitry Andric template <> 2015ffd83dbSDimitry Andric constexpr sys::fs::mapped_file_region::mapmode 2025ffd83dbSDimitry Andric Mapmode<WriteThroughMemoryBuffer> = sys::fs::mapped_file_region::readwrite; 2035ffd83dbSDimitry Andric 2040b57cec5SDimitry Andric /// Memory maps a file descriptor using sys::fs::mapped_file_region. 2050b57cec5SDimitry Andric /// 2060b57cec5SDimitry Andric /// This handles converting the offset into a legal offset on the platform. 2070b57cec5SDimitry Andric template<typename MB> 2080b57cec5SDimitry Andric class MemoryBufferMMapFile : public MB { 2090b57cec5SDimitry Andric sys::fs::mapped_file_region MFR; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric static uint64_t getLegalMapOffset(uint64_t Offset) { 2120b57cec5SDimitry Andric return Offset & ~(sys::fs::mapped_file_region::alignment() - 1); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) { 2160b57cec5SDimitry Andric return Len + (Offset - getLegalMapOffset(Offset)); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric const char *getStart(uint64_t Len, uint64_t Offset) { 2200b57cec5SDimitry Andric return MFR.const_data() + (Offset - getLegalMapOffset(Offset)); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric public: 2240b57cec5SDimitry Andric MemoryBufferMMapFile(bool RequiresNullTerminator, sys::fs::file_t FD, uint64_t Len, 2250b57cec5SDimitry Andric uint64_t Offset, std::error_code &EC) 2265ffd83dbSDimitry Andric : MFR(FD, Mapmode<MB>, getLegalMapSize(Len, Offset), 2270b57cec5SDimitry Andric getLegalMapOffset(Offset), EC) { 2280b57cec5SDimitry Andric if (!EC) { 2290b57cec5SDimitry Andric const char *Start = getStart(Len, Offset); 2300b57cec5SDimitry Andric MemoryBuffer::init(Start, Start + Len, RequiresNullTerminator); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric /// Disable sized deallocation for MemoryBufferMMapFile, because it has 2350b57cec5SDimitry Andric /// tail-allocated data. 236*0fca6ea1SDimitry Andric void operator delete(void *p) { std::free(p); } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric StringRef getBufferIdentifier() const override { 2390b57cec5SDimitry Andric // The name is stored after the class itself. 240bdd1243dSDimitry Andric return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t), 241bdd1243dSDimitry Andric *reinterpret_cast<const size_t *>(this + 1)); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric MemoryBuffer::BufferKind getBufferKind() const override { 2450b57cec5SDimitry Andric return MemoryBuffer::MemoryBuffer_MMap; 2460b57cec5SDimitry Andric } 24704eeddc0SDimitry Andric 24804eeddc0SDimitry Andric void dontNeedIfMmap() override { MFR.dontNeed(); } 2490b57cec5SDimitry Andric }; 250fe6060f1SDimitry Andric } // namespace 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<WritableMemoryBuffer>> 2530b57cec5SDimitry Andric getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName) { 25404eeddc0SDimitry Andric SmallString<sys::fs::DefaultReadChunkSize> Buffer; 25504eeddc0SDimitry Andric if (Error E = sys::fs::readNativeFileToEOF(FD, Buffer)) 25604eeddc0SDimitry Andric return errorToErrorCode(std::move(E)); 2570b57cec5SDimitry Andric return getMemBufferCopyImpl(Buffer, BufferName); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> 261fe6060f1SDimitry Andric MemoryBuffer::getFile(const Twine &Filename, bool IsText, 262bdd1243dSDimitry Andric bool RequiresNullTerminator, bool IsVolatile, 263bdd1243dSDimitry Andric std::optional<Align> Alignment) { 264fe6060f1SDimitry Andric return getFileAux<MemoryBuffer>(Filename, /*MapSize=*/-1, /*Offset=*/0, 265bdd1243dSDimitry Andric IsText, RequiresNullTerminator, IsVolatile, 266bdd1243dSDimitry Andric Alignment); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric template <typename MB> 2700b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<MB>> 2710b57cec5SDimitry Andric getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, 2720b57cec5SDimitry Andric uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, 273bdd1243dSDimitry Andric bool IsVolatile, std::optional<Align> Alignment); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric template <typename MB> 2760b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<MB>> 277fe6060f1SDimitry Andric getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset, 278bdd1243dSDimitry Andric bool IsText, bool RequiresNullTerminator, bool IsVolatile, 279bdd1243dSDimitry Andric std::optional<Align> Alignment) { 280fe6060f1SDimitry Andric Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForRead( 281fe6060f1SDimitry Andric Filename, IsText ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None); 2820b57cec5SDimitry Andric if (!FDOrErr) 2830b57cec5SDimitry Andric return errorToErrorCode(FDOrErr.takeError()); 2840b57cec5SDimitry Andric sys::fs::file_t FD = *FDOrErr; 285fe6060f1SDimitry Andric auto Ret = getOpenFileImpl<MB>(FD, Filename, /*FileSize=*/-1, MapSize, Offset, 286bdd1243dSDimitry Andric RequiresNullTerminator, IsVolatile, Alignment); 2870b57cec5SDimitry Andric sys::fs::closeFile(FD); 2880b57cec5SDimitry Andric return Ret; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric ErrorOr<std::unique_ptr<WritableMemoryBuffer>> 292bdd1243dSDimitry Andric WritableMemoryBuffer::getFile(const Twine &Filename, bool IsVolatile, 293bdd1243dSDimitry Andric std::optional<Align> Alignment) { 294fe6060f1SDimitry Andric return getFileAux<WritableMemoryBuffer>( 295fe6060f1SDimitry Andric Filename, /*MapSize=*/-1, /*Offset=*/0, /*IsText=*/false, 296bdd1243dSDimitry Andric /*RequiresNullTerminator=*/false, IsVolatile, Alignment); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric ErrorOr<std::unique_ptr<WritableMemoryBuffer>> 3000b57cec5SDimitry Andric WritableMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize, 301bdd1243dSDimitry Andric uint64_t Offset, bool IsVolatile, 302bdd1243dSDimitry Andric std::optional<Align> Alignment) { 303fe6060f1SDimitry Andric return getFileAux<WritableMemoryBuffer>( 304fe6060f1SDimitry Andric Filename, MapSize, Offset, /*IsText=*/false, 305bdd1243dSDimitry Andric /*RequiresNullTerminator=*/false, IsVolatile, Alignment); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric std::unique_ptr<WritableMemoryBuffer> 309bdd1243dSDimitry Andric WritableMemoryBuffer::getNewUninitMemBuffer(size_t Size, 310bdd1243dSDimitry Andric const Twine &BufferName, 311bdd1243dSDimitry Andric std::optional<Align> Alignment) { 3120b57cec5SDimitry Andric using MemBuffer = MemoryBufferMem<WritableMemoryBuffer>; 313bdd1243dSDimitry Andric 314bdd1243dSDimitry Andric // Use 16-byte alignment if no alignment is specified. 315bdd1243dSDimitry Andric Align BufAlign = Alignment.value_or(Align(16)); 316bdd1243dSDimitry Andric 3170b57cec5SDimitry Andric // Allocate space for the MemoryBuffer, the data and the name. It is important 3180b57cec5SDimitry Andric // that MemoryBuffer and data are aligned so PointerIntPair works with them. 3190b57cec5SDimitry Andric SmallString<256> NameBuf; 3200b57cec5SDimitry Andric StringRef NameRef = BufferName.toStringRef(NameBuf); 321bdd1243dSDimitry Andric 322bdd1243dSDimitry Andric size_t StringLen = sizeof(MemBuffer) + sizeof(size_t) + NameRef.size() + 1; 323bdd1243dSDimitry Andric size_t RealLen = StringLen + Size + 1 + BufAlign.value(); 32481ad6265SDimitry Andric if (RealLen <= Size) // Check for rollover. 32581ad6265SDimitry Andric return nullptr; 326*0fca6ea1SDimitry Andric // We use a call to malloc() rather than a call to a non-throwing operator 327*0fca6ea1SDimitry Andric // new() because LLVM unconditionally installs an out of memory new handler 328*0fca6ea1SDimitry Andric // when exceptions are disabled. This new handler intentionally crashes to 329*0fca6ea1SDimitry Andric // aid with debugging, but that makes non-throwing new calls unhelpful. 330*0fca6ea1SDimitry Andric // See MemoryBufferMem::operator delete() for the paired call to free(), and 331*0fca6ea1SDimitry Andric // llvm::install_out_of_memory_new_handler() for the installation of the 332*0fca6ea1SDimitry Andric // custom new handler. 333*0fca6ea1SDimitry Andric char *Mem = static_cast<char *>(std::malloc(RealLen)); 3340b57cec5SDimitry Andric if (!Mem) 3350b57cec5SDimitry Andric return nullptr; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // The name is stored after the class itself. 338bdd1243dSDimitry Andric *reinterpret_cast<size_t *>(Mem + sizeof(MemBuffer)) = NameRef.size(); 339bdd1243dSDimitry Andric CopyStringRef(Mem + sizeof(MemBuffer) + sizeof(size_t), NameRef); 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // The buffer begins after the name and must be aligned. 342bdd1243dSDimitry Andric char *Buf = (char *)alignAddr(Mem + StringLen, BufAlign); 3430b57cec5SDimitry Andric Buf[Size] = 0; // Null terminate buffer. 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true); 3460b57cec5SDimitry Andric return std::unique_ptr<WritableMemoryBuffer>(Ret); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric std::unique_ptr<WritableMemoryBuffer> 3500b57cec5SDimitry Andric WritableMemoryBuffer::getNewMemBuffer(size_t Size, const Twine &BufferName) { 3510b57cec5SDimitry Andric auto SB = WritableMemoryBuffer::getNewUninitMemBuffer(Size, BufferName); 3520b57cec5SDimitry Andric if (!SB) 3530b57cec5SDimitry Andric return nullptr; 3540b57cec5SDimitry Andric memset(SB->getBufferStart(), 0, Size); 3550b57cec5SDimitry Andric return SB; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric static bool shouldUseMmap(sys::fs::file_t FD, 3590b57cec5SDimitry Andric size_t FileSize, 3600b57cec5SDimitry Andric size_t MapSize, 3610b57cec5SDimitry Andric off_t Offset, 3620b57cec5SDimitry Andric bool RequiresNullTerminator, 3630b57cec5SDimitry Andric int PageSize, 3640b57cec5SDimitry Andric bool IsVolatile) { 3650b57cec5SDimitry Andric // mmap may leave the buffer without null terminator if the file size changed 3660b57cec5SDimitry Andric // by the time the last page is mapped in, so avoid it if the file size is 3670b57cec5SDimitry Andric // likely to change. 3685ffd83dbSDimitry Andric if (IsVolatile && RequiresNullTerminator) 3690b57cec5SDimitry Andric return false; 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric // We don't use mmap for small files because this can severely fragment our 3720b57cec5SDimitry Andric // address space. 3730b57cec5SDimitry Andric if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize) 3740b57cec5SDimitry Andric return false; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric if (!RequiresNullTerminator) 3770b57cec5SDimitry Andric return true; 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric // If we don't know the file size, use fstat to find out. fstat on an open 3800b57cec5SDimitry Andric // file descriptor is cheaper than stat on a random path. 3810b57cec5SDimitry Andric // FIXME: this chunk of code is duplicated, but it avoids a fstat when 3820b57cec5SDimitry Andric // RequiresNullTerminator = false and MapSize != -1. 3830b57cec5SDimitry Andric if (FileSize == size_t(-1)) { 3840b57cec5SDimitry Andric sys::fs::file_status Status; 3850b57cec5SDimitry Andric if (sys::fs::status(FD, Status)) 3860b57cec5SDimitry Andric return false; 3870b57cec5SDimitry Andric FileSize = Status.getSize(); 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // If we need a null terminator and the end of the map is inside the file, 3910b57cec5SDimitry Andric // we cannot use mmap. 3920b57cec5SDimitry Andric size_t End = Offset + MapSize; 3930b57cec5SDimitry Andric assert(End <= FileSize); 3940b57cec5SDimitry Andric if (End != FileSize) 3950b57cec5SDimitry Andric return false; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric // Don't try to map files that are exactly a multiple of the system page size 3980b57cec5SDimitry Andric // if we need a null terminator. 3990b57cec5SDimitry Andric if ((FileSize & (PageSize -1)) == 0) 4000b57cec5SDimitry Andric return false; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric #if defined(__CYGWIN__) 4030b57cec5SDimitry Andric // Don't try to map files that are exactly a multiple of the physical page size 4040b57cec5SDimitry Andric // if we need a null terminator. 4050b57cec5SDimitry Andric // FIXME: We should reorganize again getPageSize() on Win32. 4060b57cec5SDimitry Andric if ((FileSize & (4096 - 1)) == 0) 4070b57cec5SDimitry Andric return false; 4080b57cec5SDimitry Andric #endif 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric return true; 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> 4140b57cec5SDimitry Andric getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, 4150b57cec5SDimitry Andric uint64_t Offset) { 4160b57cec5SDimitry Andric Expected<sys::fs::file_t> FDOrErr = sys::fs::openNativeFileForReadWrite( 4170b57cec5SDimitry Andric Filename, sys::fs::CD_OpenExisting, sys::fs::OF_None); 4180b57cec5SDimitry Andric if (!FDOrErr) 4190b57cec5SDimitry Andric return errorToErrorCode(FDOrErr.takeError()); 4200b57cec5SDimitry Andric sys::fs::file_t FD = *FDOrErr; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric // Default is to map the full file. 4230b57cec5SDimitry Andric if (MapSize == uint64_t(-1)) { 4240b57cec5SDimitry Andric // If we don't know the file size, use fstat to find out. fstat on an open 4250b57cec5SDimitry Andric // file descriptor is cheaper than stat on a random path. 4260b57cec5SDimitry Andric if (FileSize == uint64_t(-1)) { 4270b57cec5SDimitry Andric sys::fs::file_status Status; 4280b57cec5SDimitry Andric std::error_code EC = sys::fs::status(FD, Status); 4290b57cec5SDimitry Andric if (EC) 4300b57cec5SDimitry Andric return EC; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric // If this not a file or a block device (e.g. it's a named pipe 4330b57cec5SDimitry Andric // or character device), we can't mmap it, so error out. 4340b57cec5SDimitry Andric sys::fs::file_type Type = Status.type(); 4350b57cec5SDimitry Andric if (Type != sys::fs::file_type::regular_file && 4360b57cec5SDimitry Andric Type != sys::fs::file_type::block_file) 4370b57cec5SDimitry Andric return make_error_code(errc::invalid_argument); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric FileSize = Status.getSize(); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric MapSize = FileSize; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric std::error_code EC; 4450b57cec5SDimitry Andric std::unique_ptr<WriteThroughMemoryBuffer> Result( 4460b57cec5SDimitry Andric new (NamedBufferAlloc(Filename)) 4470b57cec5SDimitry Andric MemoryBufferMMapFile<WriteThroughMemoryBuffer>(false, FD, MapSize, 4480b57cec5SDimitry Andric Offset, EC)); 4490b57cec5SDimitry Andric if (EC) 4500b57cec5SDimitry Andric return EC; 4510b57cec5SDimitry Andric return std::move(Result); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> 4550b57cec5SDimitry Andric WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) { 4560b57cec5SDimitry Andric return getReadWriteFile(Filename, FileSize, FileSize, 0); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric /// Map a subrange of the specified file as a WritableMemoryBuffer. 4600b57cec5SDimitry Andric ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> 4610b57cec5SDimitry Andric WriteThroughMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize, 4620b57cec5SDimitry Andric uint64_t Offset) { 4630b57cec5SDimitry Andric return getReadWriteFile(Filename, -1, MapSize, Offset); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric template <typename MB> 4670b57cec5SDimitry Andric static ErrorOr<std::unique_ptr<MB>> 4680b57cec5SDimitry Andric getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, 4690b57cec5SDimitry Andric uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, 470bdd1243dSDimitry Andric bool IsVolatile, std::optional<Align> Alignment) { 4710b57cec5SDimitry Andric static int PageSize = sys::Process::getPageSizeEstimate(); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric // Default is to map the full file. 4740b57cec5SDimitry Andric if (MapSize == uint64_t(-1)) { 4750b57cec5SDimitry Andric // If we don't know the file size, use fstat to find out. fstat on an open 4760b57cec5SDimitry Andric // file descriptor is cheaper than stat on a random path. 4770b57cec5SDimitry Andric if (FileSize == uint64_t(-1)) { 4780b57cec5SDimitry Andric sys::fs::file_status Status; 4790b57cec5SDimitry Andric std::error_code EC = sys::fs::status(FD, Status); 4800b57cec5SDimitry Andric if (EC) 4810b57cec5SDimitry Andric return EC; 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric // If this not a file or a block device (e.g. it's a named pipe 4840b57cec5SDimitry Andric // or character device), we can't trust the size. Create the memory 4850b57cec5SDimitry Andric // buffer by copying off the stream. 4860b57cec5SDimitry Andric sys::fs::file_type Type = Status.type(); 4870b57cec5SDimitry Andric if (Type != sys::fs::file_type::regular_file && 4880b57cec5SDimitry Andric Type != sys::fs::file_type::block_file) 4890b57cec5SDimitry Andric return getMemoryBufferForStream(FD, Filename); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric FileSize = Status.getSize(); 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric MapSize = FileSize; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator, 4970b57cec5SDimitry Andric PageSize, IsVolatile)) { 4980b57cec5SDimitry Andric std::error_code EC; 4990b57cec5SDimitry Andric std::unique_ptr<MB> Result( 5000b57cec5SDimitry Andric new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile<MB>( 5010b57cec5SDimitry Andric RequiresNullTerminator, FD, MapSize, Offset, EC)); 5020b57cec5SDimitry Andric if (!EC) 5030b57cec5SDimitry Andric return std::move(Result); 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 506fe6060f1SDimitry Andric #ifdef __MVS__ 507fe6060f1SDimitry Andric // Set codepage auto-conversion for z/OS. 508fe6060f1SDimitry Andric if (auto EC = llvm::enableAutoConversion(FD)) 509fe6060f1SDimitry Andric return EC; 510fe6060f1SDimitry Andric #endif 511fe6060f1SDimitry Andric 512bdd1243dSDimitry Andric auto Buf = 513bdd1243dSDimitry Andric WritableMemoryBuffer::getNewUninitMemBuffer(MapSize, Filename, Alignment); 5140b57cec5SDimitry Andric if (!Buf) { 5150b57cec5SDimitry Andric // Failed to create a buffer. The only way it can fail is if 5160b57cec5SDimitry Andric // new(std::nothrow) returns 0. 5170b57cec5SDimitry Andric return make_error_code(errc::not_enough_memory); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5208bcb0991SDimitry Andric // Read until EOF, zero-initialize the rest. 5218bcb0991SDimitry Andric MutableArrayRef<char> ToRead = Buf->getBuffer(); 5228bcb0991SDimitry Andric while (!ToRead.empty()) { 5238bcb0991SDimitry Andric Expected<size_t> ReadBytes = 5248bcb0991SDimitry Andric sys::fs::readNativeFileSlice(FD, ToRead, Offset); 5258bcb0991SDimitry Andric if (!ReadBytes) 5268bcb0991SDimitry Andric return errorToErrorCode(ReadBytes.takeError()); 5278bcb0991SDimitry Andric if (*ReadBytes == 0) { 5288bcb0991SDimitry Andric std::memset(ToRead.data(), 0, ToRead.size()); 5298bcb0991SDimitry Andric break; 5308bcb0991SDimitry Andric } 5318bcb0991SDimitry Andric ToRead = ToRead.drop_front(*ReadBytes); 5328bcb0991SDimitry Andric Offset += *ReadBytes; 5338bcb0991SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric return std::move(Buf); 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> 539bdd1243dSDimitry Andric MemoryBuffer::getOpenFile(sys::fs::file_t FD, const Twine &Filename, 540bdd1243dSDimitry Andric uint64_t FileSize, bool RequiresNullTerminator, 541bdd1243dSDimitry Andric bool IsVolatile, std::optional<Align> Alignment) { 5420b57cec5SDimitry Andric return getOpenFileImpl<MemoryBuffer>(FD, Filename, FileSize, FileSize, 0, 543bdd1243dSDimitry Andric RequiresNullTerminator, IsVolatile, 544bdd1243dSDimitry Andric Alignment); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 547bdd1243dSDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getOpenFileSlice( 548bdd1243dSDimitry Andric sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, 549bdd1243dSDimitry Andric bool IsVolatile, std::optional<Align> Alignment) { 5500b57cec5SDimitry Andric assert(MapSize != uint64_t(-1)); 5510b57cec5SDimitry Andric return getOpenFileImpl<MemoryBuffer>(FD, Filename, -1, MapSize, Offset, false, 552bdd1243dSDimitry Andric IsVolatile, Alignment); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() { 5560b57cec5SDimitry Andric // Read in all of the data from stdin, we cannot mmap stdin. 5570b57cec5SDimitry Andric // 5580b57cec5SDimitry Andric // FIXME: That isn't necessarily true, we should try to mmap stdin and 5590b57cec5SDimitry Andric // fallback if it fails. 560fe6060f1SDimitry Andric sys::ChangeStdinMode(sys::fs::OF_Text); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric return getMemoryBufferForStream(sys::fs::getStdinHandle(), "<stdin>"); 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> 5660b57cec5SDimitry Andric MemoryBuffer::getFileAsStream(const Twine &Filename) { 5670b57cec5SDimitry Andric Expected<sys::fs::file_t> FDOrErr = 5680b57cec5SDimitry Andric sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None); 5690b57cec5SDimitry Andric if (!FDOrErr) 5700b57cec5SDimitry Andric return errorToErrorCode(FDOrErr.takeError()); 5710b57cec5SDimitry Andric sys::fs::file_t FD = *FDOrErr; 5720b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = 5730b57cec5SDimitry Andric getMemoryBufferForStream(FD, Filename); 5740b57cec5SDimitry Andric sys::fs::closeFile(FD); 5750b57cec5SDimitry Andric return Ret; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric MemoryBufferRef MemoryBuffer::getMemBufferRef() const { 5790b57cec5SDimitry Andric StringRef Data = getBuffer(); 5800b57cec5SDimitry Andric StringRef Identifier = getBufferIdentifier(); 5810b57cec5SDimitry Andric return MemoryBufferRef(Data, Identifier); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 58481ad6265SDimitry Andric SmallVectorMemoryBuffer::~SmallVectorMemoryBuffer() = default; 585