Index: llvm/trunk/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test =================================================================== --- llvm/trunk/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test +++ llvm/trunk/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test @@ -1,6 +1,6 @@ # RUN: yaml2obj %s > %t # RUN: not llvm-objcopy %t no/such/dir 2>&1 | FileCheck %s -# CHECK: failed to open no/such/dir: +# CHECK: error: 'no/such/dir': No such file or directory !ELF FileHeader: Index: llvm/trunk/tools/llvm-objcopy/Buffer.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/Buffer.h +++ llvm/trunk/tools/llvm-objcopy/Buffer.h @@ -27,7 +27,7 @@ public: virtual ~Buffer(); - virtual void allocate(size_t Size) = 0; + virtual Error allocate(size_t Size) = 0; virtual uint8_t *getBufferStart() = 0; virtual Error commit() = 0; @@ -39,7 +39,7 @@ std::unique_ptr Buf; public: - void allocate(size_t Size) override; + Error allocate(size_t Size) override; uint8_t *getBufferStart() override; Error commit() override; @@ -50,7 +50,7 @@ std::unique_ptr Buf; public: - void allocate(size_t Size) override; + Error allocate(size_t Size) override; uint8_t *getBufferStart() override; Error commit() override; Index: llvm/trunk/tools/llvm-objcopy/Buffer.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/Buffer.cpp +++ llvm/trunk/tools/llvm-objcopy/Buffer.cpp @@ -17,23 +17,31 @@ Buffer::~Buffer() {} -void FileBuffer::allocate(size_t Size) { +Error FileBuffer::allocate(size_t Size) { Expected> BufferOrErr = FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable); - handleAllErrors(BufferOrErr.takeError(), [this](const ErrorInfoBase &E) { - error("failed to open " + getName() + ": " + E.message()); - }); + // 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() { return Buf->commit(); } +Error FileBuffer::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(Buf->getBufferStart()); } -void MemBuffer::allocate(size_t Size) { +Error MemBuffer::allocate(size_t Size) { Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName()); + return Error::success(); } Error MemBuffer::commit() { return Error::success(); } Index: llvm/trunk/tools/llvm-objcopy/COFF/Writer.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/COFF/Writer.cpp +++ llvm/trunk/tools/llvm-objcopy/COFF/Writer.cpp @@ -324,7 +324,8 @@ if (Error E = finalize(IsBigObj)) return E; - Buf.allocate(FileSize); + if (Error E = Buf.allocate(FileSize)) + return E; writeHeaders(IsBigObj); writeSections(); Index: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -176,8 +176,10 @@ DWOFile->Machine = Config.OutputArch.getValue().EMachine; FileBuffer FB(File); auto Writer = createWriter(Config, *DWOFile, FB, OutputElfType); - Writer->finalize(); - Writer->write(); + if (Error E = Writer->finalize()) + error(std::move(E)); + if (Error E = Writer->write()) + error(std::move(E)); } static Error dumpSectionToFile(StringRef SecName, StringRef Filename, @@ -542,8 +544,10 @@ handleArgs(Config, *Obj, Reader, OutputElfType); std::unique_ptr Writer = createWriter(Config, *Obj, Out, OutputElfType); - Writer->finalize(); - Writer->write(); + if (Error E = Writer->finalize()) + error(std::move(E)); + if (Error E = Writer->write()) + error(std::move(E)); } void executeObjcopyOnBinary(const CopyConfig &Config, @@ -570,8 +574,10 @@ handleArgs(Config, *Obj, Reader, OutputElfType); std::unique_ptr Writer = createWriter(Config, *Obj, Out, OutputElfType); - Writer->finalize(); - Writer->write(); + if (Error E = Writer->finalize()) + error(std::move(E)); + if (Error E = Writer->write()) + error(std::move(E)); if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput) { linkToBuildIdDir(Config, Config.OutputFilename, Config.BuildIdLinkOutput.getValue(), BuildIdBytes); Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.h +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.h @@ -193,8 +193,8 @@ public: virtual ~Writer(); - virtual void finalize() = 0; - virtual void write() = 0; + virtual Error finalize() = 0; + virtual Error write() = 0; Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {} }; @@ -226,8 +226,8 @@ virtual ~ELFWriter() {} bool WriteSectionHeaders = true; - void finalize() override; - void write() override; + Error finalize() override; + Error write() override; ELFWriter(Object &Obj, Buffer &Buf, bool WSH) : Writer(Obj, Buf), WriteSectionHeaders(WSH) {} }; @@ -240,8 +240,8 @@ public: ~BinaryWriter() {} - void finalize() override; - void write() override; + Error finalize() override; + Error write() override; BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {} }; Index: llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/trunk/tools/llvm-objcopy/ELF/Object.cpp @@ -1488,17 +1488,16 @@ NullSectionSize; } -template void ELFWriter::write() { +template Error ELFWriter::write() { writeEhdr(); writePhdrs(); writeSectionData(); if (WriteSectionHeaders) writeShdrs(); - if (auto E = Buf.commit()) - reportError(Buf.getName(), errorToErrorCode(std::move(E))); + return Buf.commit(); } -template void ELFWriter::finalize() { +template Error ELFWriter::finalize() { // It could happen that SectionNames has been removed and yet the user wants // a section header table output. We need to throw an error if a user tries // to do that. @@ -1582,21 +1581,22 @@ Section.finalize(); } - Buf.allocate(totalSize()); + if (Error E = Buf.allocate(totalSize())) + return E; SecWriter = llvm::make_unique>(Buf); + return Error::success(); } -void BinaryWriter::write() { +Error BinaryWriter::write() { for (auto &Section : Obj.sections()) { if ((Section.Flags & SHF_ALLOC) == 0) continue; Section.accept(*SecWriter); } - if (auto E = Buf.commit()) - reportError(Buf.getName(), errorToErrorCode(std::move(E))); + return Buf.commit(); } -void BinaryWriter::finalize() { +Error BinaryWriter::finalize() { // TODO: Create a filter range to construct OrderedSegments from so that this // code can be deduped with assignOffsets above. This should also solve the // todo below for LayoutSections. @@ -1675,8 +1675,10 @@ TotalSize = std::max(TotalSize, Section->Offset + Section->Size); } - Buf.allocate(TotalSize); + if (Error E = Buf.allocate(TotalSize)) + return E; SecWriter = llvm::make_unique(Buf); + return Error::success(); } template class ELFBuilder; Index: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h =================================================================== --- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h +++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.h @@ -19,6 +19,7 @@ namespace objcopy { LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message); +LLVM_ATTRIBUTE_NORETURN extern void error(Error E); LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E); LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, std::error_code EC); Index: llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp +++ llvm/trunk/tools/llvm-objcopy/llvm-objcopy.cpp @@ -56,6 +56,16 @@ exit(1); } +LLVM_ATTRIBUTE_NORETURN void error(Error E) { + assert(E); + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(std::move(E), OS); + OS.flush(); + WithColor::error(errs(), ToolName) << Buf; + exit(1); +} + LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) { assert(EC); WithColor::error(errs(), ToolName) @@ -100,10 +110,11 @@ // NewArchiveMember still requires them even though writeArchive does not // write them on disk. FileBuffer FB(Member.MemberName); - FB.allocate(Member.Buf->getBufferSize()); + if (Error E = FB.allocate(Member.Buf->getBufferSize())) + return E; std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(), FB.getBufferStart()); - if (auto E = FB.commit()) + if (Error E = FB.commit()) return E; } return Error::success();