summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/Buffer.cpp
diff options
context:
space:
mode:
authorJordan Rupprecht <rupprecht@google.com>2019-01-28 15:02:40 +0000
committerJordan Rupprecht <rupprecht@google.com>2019-01-28 15:02:40 +0000
commitb2702d6a45016b24bed936901c183a5b1851858a (patch)
treeac94a272963be35296887161473b2821f3d0534a /llvm/tools/llvm-objcopy/Buffer.cpp
parent6c5dfcb89edf93eb50356dc39ea0ea2dcbba906f (diff)
downloadbcm5719-llvm-b2702d6a45016b24bed936901c183a5b1851858a.tar.gz
bcm5719-llvm-b2702d6a45016b24bed936901c183a5b1851858a.zip
[llvm-objcopy] Fix crash when writing empty binary output
Summary: When using llvm-objcopy -O binary and the resulting file will be empty (e.g. removing the only section that would be written, or using --only-keep with a section that doesn't exist/isn't SHF_ALLOC), we crash because FileOutputBuffer expects Size > 0. Add a regression test, and change Buffer to open/truncate the output file in this case. Reviewers: alexshap, jhenderson, jakehehrlich, espindola Reviewed By: alexshap, jhenderson Subscribers: jfb, llvm-commits, emaste, arichardson Differential Revision: https://reviews.llvm.org/D56806 llvm-svn: 352371
Diffstat (limited to 'llvm/tools/llvm-objcopy/Buffer.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/Buffer.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp
index 1789097f276..7af9d912eda 100644
--- a/llvm/tools/llvm-objcopy/Buffer.cpp
+++ b/llvm/tools/llvm-objcopy/Buffer.cpp
@@ -9,7 +9,9 @@
#include "Buffer.h"
#include "llvm-objcopy.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 {
@@ -17,7 +19,23 @@ 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
@@ -29,6 +47,10 @@ Error FileBuffer::allocate(size_t Size) {
}
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.
OpenPOWER on IntegriCloud