llvm-objcopy-8.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. From 8cf7aa39d7c9461e2d765f6d4fa7e0925571695f Mon Sep 17 00:00:00 2001
  2. From: Jordan Rupprecht <rupprecht@google.com>
  3. Date: Tue, 22 Jan 2019 23:49:16 +0000
  4. Subject: [PATCH] [llvm-objcopy] Return Error from Buffer::allocate(),
  5. [ELF]Writer::finalize(), and [ELF]Writer::commit()
  6. Summary:
  7. This patch changes a few methods to return Error instead of manually calling error/reportError to abort. This will make it easier to extract into a library.
  8. Note that error() takes just a string (this patch also adds an overload that takes an Error), while reportError() takes string + [error/code]. To help unify things, use FileError to associate a given filename with an error. Note that this takes some special care (for now), e.g. calling reportError(FileName, <something that could be FileError>) will duplicate the filename. The goal is to eventually remove reportError() and have every error associated with a file to be a FileError, and just one error handling block at the tool level.
  9. This change was suggested in D56806. I took it a little further than suggested, but completely fixing llvm-objcopy will take a couple more patches. If this approach looks good, I'll commit this and apply similar patche(s) for the rest.
  10. This change is NFC in terms of non-error related code, although the error message changes in one context.
  11. Reviewers: alexshap, jhenderson, jakehehrlich, mstorsjo, espindola
  12. Reviewed By: alexshap, jhenderson
  13. Subscribers: llvm-commits, emaste, arichardson
  14. Differential Revision: https://reviews.llvm.org/D56930
  15. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351896 91177308-0d34-0410-b5e6-96231b3b80d8
  16. ---
  17. .../ELF/fail-no-output-directory.test | 2 +-
  18. tools/llvm-objcopy/Buffer.cpp | 20 ++++++++++++-----
  19. tools/llvm-objcopy/Buffer.h | 6 ++---
  20. tools/llvm-objcopy/COFF/Writer.cpp | 3 ++-
  21. tools/llvm-objcopy/ELF/ELFObjcopy.cpp | 18 ++++++++++-----
  22. tools/llvm-objcopy/ELF/Object.cpp | 22 ++++++++++---------
  23. tools/llvm-objcopy/ELF/Object.h | 12 +++++-----
  24. tools/llvm-objcopy/llvm-objcopy.cpp | 15 +++++++++++--
  25. tools/llvm-objcopy/llvm-objcopy.h | 1 +
  26. 9 files changed, 64 insertions(+), 35 deletions(-)
  27. diff --git a/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test b/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
  28. index f66b2e09fce..732046fa925 100644
  29. --- a/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
  30. +++ b/llvm/test/tools/llvm-objcopy/ELF/fail-no-output-directory.test
  31. @@ -1,6 +1,6 @@
  32. # RUN: yaml2obj %s > %t
  33. # RUN: not llvm-objcopy %t no/such/dir 2>&1 | FileCheck %s
  34. -# CHECK: failed to open no/such/dir:
  35. +# CHECK: error: 'no/such/dir': No such file or directory
  36. !ELF
  37. FileHeader:
  38. diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp
  39. index 2da03dee1af..1789097f276 100644
  40. --- a/llvm/tools/llvm-objcopy/Buffer.cpp
  41. +++ b/llvm/tools/llvm-objcopy/Buffer.cpp
  42. @@ -17,23 +17,31 @@ namespace objcopy {
  43. Buffer::~Buffer() {}
  44. -void FileBuffer::allocate(size_t Size) {
  45. +Error FileBuffer::allocate(size_t Size) {
  46. Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
  47. FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
  48. - handleAllErrors(BufferOrErr.takeError(), [this](const ErrorInfoBase &E) {
  49. - error("failed to open " + getName() + ": " + E.message());
  50. - });
  51. + // FileOutputBuffer::create() returns an Error that is just a wrapper around
  52. + // std::error_code. Wrap it in FileError to include the actual filename.
  53. + if (!BufferOrErr)
  54. + return createFileError(getName(), BufferOrErr.takeError());
  55. Buf = std::move(*BufferOrErr);
  56. + return Error::success();
  57. }
  58. -Error FileBuffer::commit() { return Buf->commit(); }
  59. +Error FileBuffer::commit() {
  60. + Error Err = Buf->commit();
  61. + // FileOutputBuffer::commit() returns an Error that is just a wrapper around
  62. + // std::error_code. Wrap it in FileError to include the actual filename.
  63. + return Err ? createFileError(getName(), std::move(Err)) : std::move(Err);
  64. +}
  65. uint8_t *FileBuffer::getBufferStart() {
  66. return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
  67. }
  68. -void MemBuffer::allocate(size_t Size) {
  69. +Error MemBuffer::allocate(size_t Size) {
  70. Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
  71. + return Error::success();
  72. }
  73. Error MemBuffer::commit() { return Error::success(); }
  74. diff --git a/llvm/tools/llvm-objcopy/Buffer.h b/llvm/tools/llvm-objcopy/Buffer.h
  75. index 482777fe05c..40670accac2 100644
  76. --- a/llvm/tools/llvm-objcopy/Buffer.h
  77. +++ b/llvm/tools/llvm-objcopy/Buffer.h
  78. @@ -27,7 +27,7 @@ class Buffer {
  79. public:
  80. virtual ~Buffer();
  81. - virtual void allocate(size_t Size) = 0;
  82. + virtual Error allocate(size_t Size) = 0;
  83. virtual uint8_t *getBufferStart() = 0;
  84. virtual Error commit() = 0;
  85. @@ -39,7 +39,7 @@ class FileBuffer : public Buffer {
  86. std::unique_ptr<FileOutputBuffer> Buf;
  87. public:
  88. - void allocate(size_t Size) override;
  89. + Error allocate(size_t Size) override;
  90. uint8_t *getBufferStart() override;
  91. Error commit() override;
  92. @@ -50,7 +50,7 @@ class MemBuffer : public Buffer {
  93. std::unique_ptr<WritableMemoryBuffer> Buf;
  94. public:
  95. - void allocate(size_t Size) override;
  96. + Error allocate(size_t Size) override;
  97. uint8_t *getBufferStart() override;
  98. Error commit() override;
  99. diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  100. index 4f57131d5ab..db3589bb119 100644
  101. --- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  102. +++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
  103. @@ -324,7 +324,8 @@ Error COFFWriter::write(bool IsBigObj) {
  104. if (Error E = finalize(IsBigObj))
  105. return E;
  106. - Buf.allocate(FileSize);
  107. + if (Error E = Buf.allocate(FileSize))
  108. + return E;
  109. writeHeaders(IsBigObj);
  110. writeSections();
  111. diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
  112. index a2996395c1f..2a52f1f9951 100644
  113. --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
  114. +++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
  115. @@ -176,8 +176,10 @@ static void splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
  116. DWOFile->Machine = Config.OutputArch.getValue().EMachine;
  117. FileBuffer FB(File);
  118. auto Writer = createWriter(Config, *DWOFile, FB, OutputElfType);
  119. - Writer->finalize();
  120. - Writer->write();
  121. + if (Error E = Writer->finalize())
  122. + error(std::move(E));
  123. + if (Error E = Writer->write())
  124. + error(std::move(E));
  125. }
  126. static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
  127. @@ -542,8 +544,10 @@ void executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
  128. handleArgs(Config, *Obj, Reader, OutputElfType);
  129. std::unique_ptr<Writer> Writer =
  130. createWriter(Config, *Obj, Out, OutputElfType);
  131. - Writer->finalize();
  132. - Writer->write();
  133. + if (Error E = Writer->finalize())
  134. + error(std::move(E));
  135. + if (Error E = Writer->write())
  136. + error(std::move(E));
  137. }
  138. void executeObjcopyOnBinary(const CopyConfig &Config,
  139. @@ -570,8 +574,10 @@ void executeObjcopyOnBinary(const CopyConfig &Config,
  140. handleArgs(Config, *Obj, Reader, OutputElfType);
  141. std::unique_ptr<Writer> Writer =
  142. createWriter(Config, *Obj, Out, OutputElfType);
  143. - Writer->finalize();
  144. - Writer->write();
  145. + if (Error E = Writer->finalize())
  146. + error(std::move(E));
  147. + if (Error E = Writer->write())
  148. + error(std::move(E));
  149. if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput) {
  150. linkToBuildIdDir(Config, Config.OutputFilename,
  151. Config.BuildIdLinkOutput.getValue(), BuildIdBytes);
  152. diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
  153. index fecb752a39f..ef5dc5d7951 100644
  154. --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
  155. +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
  156. @@ -1488,17 +1488,16 @@ template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
  157. NullSectionSize;
  158. }
  159. -template <class ELFT> void ELFWriter<ELFT>::write() {
  160. +template <class ELFT> Error ELFWriter<ELFT>::write() {
  161. writeEhdr();
  162. writePhdrs();
  163. writeSectionData();
  164. if (WriteSectionHeaders)
  165. writeShdrs();
  166. - if (auto E = Buf.commit())
  167. - reportError(Buf.getName(), errorToErrorCode(std::move(E)));
  168. + return Buf.commit();
  169. }
  170. -template <class ELFT> void ELFWriter<ELFT>::finalize() {
  171. +template <class ELFT> Error ELFWriter<ELFT>::finalize() {
  172. // It could happen that SectionNames has been removed and yet the user wants
  173. // a section header table output. We need to throw an error if a user tries
  174. // to do that.
  175. @@ -1582,21 +1581,22 @@ template <class ELFT> void ELFWriter<ELFT>::finalize() {
  176. Section.finalize();
  177. }
  178. - Buf.allocate(totalSize());
  179. + if (Error E = Buf.allocate(totalSize()))
  180. + return E;
  181. SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(Buf);
  182. + return Error::success();
  183. }
  184. -void BinaryWriter::write() {
  185. +Error BinaryWriter::write() {
  186. for (auto &Section : Obj.sections()) {
  187. if ((Section.Flags & SHF_ALLOC) == 0)
  188. continue;
  189. Section.accept(*SecWriter);
  190. }
  191. - if (auto E = Buf.commit())
  192. - reportError(Buf.getName(), errorToErrorCode(std::move(E)));
  193. + return Buf.commit();
  194. }
  195. -void BinaryWriter::finalize() {
  196. +Error BinaryWriter::finalize() {
  197. // TODO: Create a filter range to construct OrderedSegments from so that this
  198. // code can be deduped with assignOffsets above. This should also solve the
  199. // todo below for LayoutSections.
  200. @@ -1675,8 +1675,10 @@ void BinaryWriter::finalize() {
  201. TotalSize = std::max(TotalSize, Section->Offset + Section->Size);
  202. }
  203. - Buf.allocate(TotalSize);
  204. + if (Error E = Buf.allocate(TotalSize))
  205. + return E;
  206. SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
  207. + return Error::success();
  208. }
  209. template class ELFBuilder<ELF64LE>;
  210. diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h
  211. index 0dcb0d888bc..9e2b64be9dc 100644
  212. --- a/llvm/tools/llvm-objcopy/ELF/Object.h
  213. +++ b/llvm/tools/llvm-objcopy/ELF/Object.h
  214. @@ -193,8 +193,8 @@ protected:
  215. public:
  216. virtual ~Writer();
  217. - virtual void finalize() = 0;
  218. - virtual void write() = 0;
  219. + virtual Error finalize() = 0;
  220. + virtual Error write() = 0;
  221. Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
  222. };
  223. @@ -226,8 +226,8 @@ public:
  224. virtual ~ELFWriter() {}
  225. bool WriteSectionHeaders = true;
  226. - void finalize() override;
  227. - void write() override;
  228. + Error finalize() override;
  229. + Error write() override;
  230. ELFWriter(Object &Obj, Buffer &Buf, bool WSH)
  231. : Writer(Obj, Buf), WriteSectionHeaders(WSH) {}
  232. };
  233. @@ -240,8 +240,8 @@ private:
  234. public:
  235. ~BinaryWriter() {}
  236. - void finalize() override;
  237. - void write() override;
  238. + Error finalize() override;
  239. + Error write() override;
  240. BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
  241. };
  242. diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
  243. index d27395f2ae0..75d513546b7 100644
  244. --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
  245. +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
  246. @@ -56,6 +56,16 @@ LLVM_ATTRIBUTE_NORETURN void error(Twine Message) {
  247. exit(1);
  248. }
  249. +LLVM_ATTRIBUTE_NORETURN void error(Error E) {
  250. + assert(E);
  251. + std::string Buf;
  252. + raw_string_ostream OS(Buf);
  253. + logAllUnhandledErrors(std::move(E), OS);
  254. + OS.flush();
  255. + WithColor::error(errs(), ToolName) << Buf;
  256. + exit(1);
  257. +}
  258. +
  259. LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) {
  260. assert(EC);
  261. WithColor::error(errs(), ToolName)
  262. @@ -100,10 +110,11 @@ static Error deepWriteArchive(StringRef ArcName,
  263. // NewArchiveMember still requires them even though writeArchive does not
  264. // write them on disk.
  265. FileBuffer FB(Member.MemberName);
  266. - FB.allocate(Member.Buf->getBufferSize());
  267. + if (Error E = FB.allocate(Member.Buf->getBufferSize()))
  268. + return E;
  269. std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
  270. FB.getBufferStart());
  271. - if (auto E = FB.commit())
  272. + if (Error E = FB.commit())
  273. return E;
  274. }
  275. return Error::success();
  276. diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/tools/llvm-objcopy/llvm-objcopy.h
  277. index 46d8339576c..18a789ca1f8 100644
  278. --- a/llvm/tools/llvm-objcopy/llvm-objcopy.h
  279. +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.h
  280. @@ -19,6 +19,7 @@ namespace llvm {
  281. namespace objcopy {
  282. LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message);
  283. +LLVM_ATTRIBUTE_NORETURN extern void error(Error E);
  284. LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E);
  285. LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File,
  286. std::error_code EC);
  287. --
  288. 2.17.1