Buffer.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. //===- Buffer.cpp ---------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "Buffer.h"
  9. #include "llvm/Support/FileOutputBuffer.h"
  10. #include "llvm/Support/FileSystem.h"
  11. #include "llvm/Support/MemoryBuffer.h"
  12. #include "llvm/Support/Process.h"
  13. #include <memory>
  14. namespace llvm {
  15. namespace objcopy {
  16. Buffer::~Buffer() {}
  17. static Error createEmptyFile(StringRef FileName) {
  18. // Create an empty tempfile and atomically swap it in place with the desired
  19. // output file.
  20. Expected<sys::fs::TempFile> Temp =
  21. sys::fs::TempFile::create(FileName + ".temp-empty-%%%%%%%");
  22. return Temp ? Temp->keep(FileName) : Temp.takeError();
  23. }
  24. Error FileBuffer::allocate(size_t Size) {
  25. // When a 0-sized file is requested, skip allocation but defer file
  26. // creation/truncation until commit() to avoid side effects if something
  27. // happens between allocate() and commit().
  28. if (Size == 0) {
  29. EmptyFile = true;
  30. return Error::success();
  31. }
  32. Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
  33. FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
  34. // FileOutputBuffer::create() returns an Error that is just a wrapper around
  35. // std::error_code. Wrap it in FileError to include the actual filename.
  36. if (!BufferOrErr)
  37. return createFileError(getName(), BufferOrErr.takeError());
  38. Buf = std::move(*BufferOrErr);
  39. return Error::success();
  40. }
  41. Error FileBuffer::commit() {
  42. if (EmptyFile)
  43. return createEmptyFile(getName());
  44. assert(Buf && "allocate() not called before commit()!");
  45. Error Err = Buf->commit();
  46. // FileOutputBuffer::commit() returns an Error that is just a wrapper around
  47. // std::error_code. Wrap it in FileError to include the actual filename.
  48. return Err ? createFileError(getName(), std::move(Err)) : std::move(Err);
  49. }
  50. uint8_t *FileBuffer::getBufferStart() {
  51. return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
  52. }
  53. Error MemBuffer::allocate(size_t Size) {
  54. Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
  55. return Error::success();
  56. }
  57. Error MemBuffer::commit() { return Error::success(); }
  58. uint8_t *MemBuffer::getBufferStart() {
  59. return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
  60. }
  61. std::unique_ptr<WritableMemoryBuffer> MemBuffer::releaseMemoryBuffer() {
  62. return std::move(Buf);
  63. }
  64. } // end namespace objcopy
  65. } // end namespace llvm