80 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- Buffer.cpp ---------------------------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "Buffer.h"
 | |
| #include "llvm/Support/FileOutputBuffer.h"
 | |
| #include "llvm/Support/FileSystem.h"
 | |
| #include "llvm/Support/MemoryBuffer.h"
 | |
| #include "llvm/Support/Process.h"
 | |
| #include <memory>
 | |
| 
 | |
| namespace llvm {
 | |
| namespace objcopy {
 | |
| 
 | |
| Buffer::~Buffer() {}
 | |
| 
 | |
| static Error createEmptyFile(StringRef FileName) {
 | |
|   // Create an empty tempfile and atomically swap it in place with the desired
 | |
|   // output file.
 | |
|   Expected<sys::fs::TempFile> Temp =
 | |
|       sys::fs::TempFile::create(FileName + ".temp-empty-%%%%%%%");
 | |
|   return Temp ? Temp->keep(FileName) : Temp.takeError();
 | |
| }
 | |
| 
 | |
| Error FileBuffer::allocate(size_t Size) {
 | |
|   // When a 0-sized file is requested, skip allocation but defer file
 | |
|   // creation/truncation until commit() to avoid side effects if something
 | |
|   // happens between allocate() and commit().
 | |
|   if (Size == 0) {
 | |
|     EmptyFile = true;
 | |
|     return Error::success();
 | |
|   }
 | |
| 
 | |
|   Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
 | |
|       FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
 | |
|   // FileOutputBuffer::create() returns an Error that is just a wrapper around
 | |
|   // std::error_code. Wrap it in FileError to include the actual filename.
 | |
|   if (!BufferOrErr)
 | |
|     return createFileError(getName(), BufferOrErr.takeError());
 | |
|   Buf = std::move(*BufferOrErr);
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Error FileBuffer::commit() {
 | |
|   if (EmptyFile)
 | |
|     return createEmptyFile(getName());
 | |
| 
 | |
|   assert(Buf && "allocate() not called before commit()!");
 | |
|   Error Err = Buf->commit();
 | |
|   // FileOutputBuffer::commit() returns an Error that is just a wrapper around
 | |
|   // std::error_code. Wrap it in FileError to include the actual filename.
 | |
|   return Err ? createFileError(getName(), std::move(Err)) : std::move(Err);
 | |
| }
 | |
| 
 | |
| uint8_t *FileBuffer::getBufferStart() {
 | |
|   return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
 | |
| }
 | |
| 
 | |
| Error MemBuffer::allocate(size_t Size) {
 | |
|   Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Error MemBuffer::commit() { return Error::success(); }
 | |
| 
 | |
| uint8_t *MemBuffer::getBufferStart() {
 | |
|   return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
 | |
| }
 | |
| 
 | |
| std::unique_ptr<WritableMemoryBuffer> MemBuffer::releaseMemoryBuffer() {
 | |
|   return std::move(Buf);
 | |
| }
 | |
| 
 | |
| } // end namespace objcopy
 | |
| } // end namespace llvm
 |