LLVM: lib/Support/MemoryBuffer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

16#include "llvm/Config/config.h"

25#include

26#include

27#include

28#include

29#include <sys/types.h>

30#include <system_error>

31#if !defined(_MSC_VER) && !defined(__MINGW32__)

32#include <unistd.h>

33#else

34#include <io.h>

35#endif

36

37#ifdef __MVS__

39#endif

40using namespace llvm;

41

42

43

44

45

47

48

49

51 bool RequiresNullTerminator) {

52 assert((!RequiresNullTerminator || BufEnd[0] == 0) &&

53 "Buffer is not null terminated!");

54 BufferStart = BufStart;

55 BufferEnd = BufEnd;

56}

57

58

59

60

61

62

63

65 if (Data.empty())

67 Memory[Data.size()] = 0;

68}

69

70namespace {

71struct NamedBufferAlloc {

74};

75}

76

77void *operator new(size_t N, const NamedBufferAlloc &Alloc) {

80

81

82

83

84

85

86

87 char *Mem =

88 static_cast<char *>(std::malloc(N + sizeof(size_t) + NameRef.size() + 1));

89 if (!Mem)

91 *reinterpret_cast<size_t *>(Mem + N) = NameRef.size();

93 return Mem;

94}

95

96namespace {

97

98template

99class MemoryBufferMem : public MB {

100public:

101 MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {

103 RequiresNullTerminator);

104 }

105

106

107

108 void operator delete(void *p) { std::free(p); }

109

110 StringRef getBufferIdentifier() const override {

111

112 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),

113 *reinterpret_cast<const size_t *>(this + 1));

114 }

115

118 }

119};

120}

121

122template

125 bool IsText, bool RequiresNullTerminator, bool IsVolatile,

126 std::optional Alignment);

127

128std::unique_ptr

130 bool RequiresNullTerminator) {

131 auto *Ret = new (NamedBufferAlloc(BufferName))

132 MemoryBufferMem(InputData, RequiresNullTerminator);

133 return std::unique_ptr(Ret);

134}

135

136std::unique_ptr

138 return std::unique_ptr(getMemBuffer(

139 Ref.getBuffer(), Ref.getBufferIdentifier(), RequiresNullTerminator));

140}

141

144 auto Buf =

146 if (!Buf)

148

149

150 llvm::copy(InputData, Buf->getBufferStart());

151 return std::move(Buf);

152}

153

154std::unique_ptr

157 if (Buf)

158 return std::move(*Buf);

159 return nullptr;

160}

161

164 bool RequiresNullTerminator,

165 std::optional Alignment) {

167 StringRef NameRef = Filename.toStringRef(NameBuf);

168

169 if (NameRef == "-")

171 return getFile(Filename, IsText, RequiresNullTerminator,

172 false, Alignment);

173}

174

178 std::optional Alignment) {

179 return getFileAux(FilePath, MapSize, Offset, false,

180 false, IsVolatile,

181 Alignment);

182}

183

184

185

186

187

188namespace {

189

190template

193template <>

196template <>

199template <>

202

203

204

205

206template

207class MemoryBufferMMapFile : public MB {

209

212 }

213

215 return Len + (Offset - getLegalMapOffset(Offset));

216 }

217

220 }

221

222public:

225 : MFR(FD, Mapmode, getLegalMapSize(Len, Offset),

226 getLegalMapOffset(Offset), EC) {

227 if (!EC) {

228 const char *Start = getStart(Len, Offset);

230 }

231 }

232

233

234

235 void operator delete(void *p) { std::free(p); }

236

237 StringRef getBufferIdentifier() const override {

238

239 return StringRef(reinterpret_cast<const char *>(this + 1) + sizeof(size_t),

240 *reinterpret_cast<const size_t *>(this + 1));

241 }

242

245 }

246

247 void dontNeedIfMmap() override { MFR.dontNeed(); }

248};

249}

250

257}

258

261 bool RequiresNullTerminator, bool IsVolatile,

262 std::optional Alignment) {

263 return getFileAux(Filename, -1, 0,

264 IsText, RequiresNullTerminator, IsVolatile,

265 Alignment);

266}

267

268template

271 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,

272 bool IsVolatile, std::optional Alignment);

273

274template

277 bool IsText, bool RequiresNullTerminator, bool IsVolatile,

278 std::optional Alignment) {

281 if (!FDOrErr)

284 auto Ret = getOpenFileImpl(FD, Filename, -1, MapSize, Offset,

285 RequiresNullTerminator, IsVolatile, Alignment);

287 return Ret;

288}

289

292 std::optional Alignment) {

293 return getFileAux(

294 Filename, -1, 0, false,

295 false, IsVolatile, Alignment);

296}

297

301 std::optional Alignment) {

302 return getFileAux(

303 Filename, MapSize, Offset, false,

304 false, IsVolatile, Alignment);

305}

306

307std::unique_ptr

309 const Twine &BufferName,

310 std::optional Alignment) {

311 using MemBuffer = MemoryBufferMem;

312

313

314 Align BufAlign = Alignment.value_or(Align(16));

315

316

317

320

321 size_t StringLen = sizeof(MemBuffer) + sizeof(size_t) + NameRef.size() + 1;

322 size_t RealLen = StringLen + Size + 1 + BufAlign.value();

323 if (RealLen <= Size)

324 return nullptr;

325

326

327

328

329

330

331

332 char *Mem = static_cast<char *>(std::malloc(RealLen));

333 if (!Mem)

334 return nullptr;

335

336

337 *reinterpret_cast<size_t *>(Mem + sizeof(MemBuffer)) = NameRef.size();

338 CopyStringRef(Mem + sizeof(MemBuffer) + sizeof(size_t), NameRef);

339

340

341 char *Buf = (char *)alignAddr(Mem + StringLen, BufAlign);

342 Buf[Size] = 0;

343

344 auto *Ret = new (Mem) MemBuffer(StringRef(Buf, Size), true);

345 return std::unique_ptr(Ret);

346}

347

348std::unique_ptr

351 if (!SB)

352 return nullptr;

353 memset(SB->getBufferStart(), 0, Size);

354 return SB;

355}

356

358 size_t FileSize,

359 size_t MapSize,

361 bool RequiresNullTerminator,

363 bool IsVolatile) {

364#if defined(__MVS__)

365

366 return false;

367#endif

368

369

370

371

372 if (IsVolatile && RequiresNullTerminator)

373 return false;

374

375

376

377 if (MapSize < 4 * 4096 || MapSize < (unsigned)PageSize)

378 return false;

379

380 if (!RequiresNullTerminator)

381 return true;

382

383

384

385

386

387 if (FileSize == size_t(-1)) {

390 return false;

391 FileSize = Status.getSize();

392 }

393

394

395

398 if (End != FileSize)

399 return false;

400

401

402

403 if ((FileSize & (PageSize -1)) == 0)

404 return false;

405

406#if defined(__CYGWIN__)

407

408

409

410 if ((FileSize & (4096 - 1)) == 0)

411 return false;

412#endif

413

414 return true;

415}

416

422 if (!FDOrErr)

425

426

427 if (MapSize == uint64_t(-1)) {

428

429

430 if (FileSize == uint64_t(-1)) {

433 if (EC)

434 return EC;

435

436

437

442

443 FileSize = Status.getSize();

444 }

445 MapSize = FileSize;

446 }

447

448 std::error_code EC;

449 std::unique_ptr Result(

450 new (NamedBufferAlloc(Filename))

451 MemoryBufferMMapFile(false, FD, MapSize,

453 if (EC)

454 return EC;

455 return std::move(Result);

456}

457

461}

462

463

468}

469

470template

473 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,

474 bool IsVolatile, std::optional Alignment) {

476

477

478 if (MapSize == uint64_t(-1)) {

479

480

481 if (FileSize == uint64_t(-1)) {

484 if (EC)

485 return EC;

486

487

488

489

494

495 FileSize = Status.getSize();

496 }

497 MapSize = FileSize;

498 }

499

502 std::error_code EC;

503 std::unique_ptr Result(

504 new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(

505 RequiresNullTerminator, FD, MapSize, Offset, EC));

506 if (!EC)

507 return std::move(Result);

508 }

509

510#ifdef __MVS__

511 ErrorOr NeedConversion = needzOSConversion(Filename.str().c_str(), FD);

512 if (std::error_code EC = NeedConversion.getError())

513 return EC;

514

515

516

517

518

519 if (Offset == 0 && MapSize == FileSize && *NeedConversion)

521#endif

522

523 auto Buf =

525 if (!Buf) {

526

527

529 }

530

531

533 while (!ToRead.empty()) {

536 if (!ReadBytes)

538 if (*ReadBytes == 0) {

539 std::memset(ToRead.data(), 0, ToRead.size());

540 break;

541 }

542 ToRead = ToRead.drop_front(*ReadBytes);

543 Offset += *ReadBytes;

544 }

545

546 return std::move(Buf);

547}

548

551 uint64_t FileSize, bool RequiresNullTerminator,

552 bool IsVolatile, std::optional Alignment) {

553 return getOpenFileImpl(FD, Filename, FileSize, FileSize, 0,

554 RequiresNullTerminator, IsVolatile,

555 Alignment);

556}

557

560 bool IsVolatile, std::optional Alignment) {

562 return getOpenFileImpl(FD, Filename, -1, MapSize, Offset, false,

563 IsVolatile, Alignment);

564}

565

567

568

569

570

572

574}

575

580 if (!FDOrErr)

586 return Ret;

587}

588

593}

594

static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)

static bool shouldUseMmap(sys::fs::file_t FD, size_t FileSize, size_t MapSize, off_t Offset, bool RequiresNullTerminator, int PageSize, bool IsVolatile)

static ErrorOr< std::unique_ptr< MB > > getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsText, bool RequiresNullTerminator, bool IsVolatile, std::optional< Align > Alignment)

static ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize, uint64_t Offset)

static ErrorOr< std::unique_ptr< MB > > getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator, bool IsVolatile, std::optional< Align > Alignment)

static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemBufferCopyImpl(StringRef InputData, const Twine &BufferName)

static void CopyStringRef(char *Memory, StringRef Data)

CopyStringRef - Copies contents of a StringRef into a block of memory and null-terminates it.

static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getMemoryBufferForStream(sys::fs::file_t FD, const Twine &BufferName)

Provides a library for accessing information about this process and other processes on the operating ...

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallString class.

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

Represents either an error or a value T.

std::error_code getError() const

Lightweight error class with error context and mandatory checking.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Given an already-open file descriptor, read the file and return a MemoryBuffer.

static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)

Open the specified memory range as a MemoryBuffer.

BufferKind

The kind of memory backing used to support the MemoryBuffer.

virtual StringRef getBufferIdentifier() const

Return an identifier for this buffer, typically the filename it was read from.

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.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Given an already-open file descriptor, map some slice of it into a MemoryBuffer.

void init(const char *BufStart, const char *BufEnd, bool RequiresNullTerminator)

init - Initialize this MemoryBuffer as a reference to externally allocated memory,...

StringRef getBuffer() const

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileAsStream(const Twine &Filename)

Read all of the specified file into a MemoryBuffer as a stream (i.e.

MemoryBufferRef getMemBufferRef() const

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Map a subrange of the specified file as a MemoryBuffer.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...

static ErrorOr< std::unique_ptr< MemoryBuffer > > getSTDIN()

Read all of stdin into a file buffer, and return it.

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

MutableArrayRef< T > drop_front(size_t N=1) const

Drop the first N elements of the array.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

~SmallVectorMemoryBuffer() override

StringRef - Represent a constant reference to a string, i.e.

constexpr size_t size() const

size - Get the string size.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

StringRef toStringRef(SmallVectorImpl< char > &Out) const

This returns the twine as a single StringRef if it can be represented as such.

The instances of the Type class are immutable: once they are created, they are never changed.

static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")

Allocate a new zero-initialized MemoryBuffer of the specified size.

static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getFile(const Twine &Filename, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

static std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)

Allocate a new MemoryBuffer of the specified size that is not initialized.

static ErrorOr< std::unique_ptr< WritableMemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)

Map a subrange of the specified file as a WritableMemoryBuffer.

static ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1)

static ErrorOr< std::unique_ptr< WriteThroughMemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset)

Map a subrange of the specified file as a ReadWriteMemoryBuffer.

This class provides various memory handling functions that manipulate MemoryBlock instances.

static unsigned getPageSizeEstimate()

Get the process's estimated page size.

Represents the result of a call to sys::fs::status().

This class represents a memory mapped file.

@ priv

May modify via data, but changes are lost on destruction.

@ readonly

May only access map via const_data as read only.

@ readwrite

May access map via data and modify it. Written to path.

const char * const_data() const

Get a const view of the data.

Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl< char > &Buffer, ssize_t ChunkSize=DefaultReadChunkSize)

Reads from FileHandle until EOF, appending to Buffer in chunks of size ChunkSize.

std::error_code closeFile(file_t &F)

Close the file object.

Expected< size_t > readNativeFileSlice(file_t FileHandle, MutableArrayRef< char > Buf, uint64_t Offset)

Reads Buf.size() bytes from FileHandle at offset Offset into Buf.

std::error_code status(const Twine &path, file_status &result, bool follow=true)

Get file status as if by POSIX stat().

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

@ OF_TextWithCRLF

The file should be opened in text mode and use a carriage linefeed '\r '.

file_type

An enumeration for the file system's view of the type.

@ CD_OpenExisting

CD_OpenExisting - When opening a file:

Expected< file_t > openNativeFileForReadWrite(const Twine &Name, CreationDisposition Disp, OpenFlags Flags, unsigned Mode=0666)

Opens the file with the given name in a write-only or read-write mode, returning its open file descri...

Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)

Opens the file with the given name in a read-only mode, returning its open file descriptor.

file_t getStdinHandle()

Return an open handle to standard in.

std::error_code ChangeStdinMode(fs::OpenFlags Flags)

This is an optimization pass for GlobalISel generic memory operations.

std::error_code make_error_code(BitcodeError E)

@ Ref

The access may reference the value stored in memory.

OutputIt copy(R &&Range, OutputIt Out)

std::error_code errorToErrorCode(Error Err)

Helper for converting an ECError to a std::error_code.

void report_bad_alloc_error(const char *Reason, bool GenCrashDiag=true)

Reports a bad alloc error, calling any user defined bad alloc error handler.

uintptr_t alignAddr(const void *Addr, Align Alignment)

Aligns Addr to Alignment bytes, rounding up.

This struct is a compact representation of a valid (non-zero power of two) alignment.

uint64_t value() const

This is a hole in the type system and should not be abused.