]> granicus.if.org Git - llvm/commitdiff
[llvm-objcopy] [COFF] Use Error/Expected returns instead of calling reportError....
authorMartin Storsjo <martin@martin.st>
Sun, 30 Dec 2018 20:35:43 +0000 (20:35 +0000)
committerMartin Storsjo <martin@martin.st>
Sun, 30 Dec 2018 20:35:43 +0000 (20:35 +0000)
Differential Revision: https://reviews.llvm.org/D55922

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350168 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvm-objcopy/COFF/COFFObjcopy.cpp
tools/llvm-objcopy/COFF/Reader.cpp
tools/llvm-objcopy/COFF/Reader.h
tools/llvm-objcopy/COFF/Writer.cpp
tools/llvm-objcopy/COFF/Writer.h

index 89e926af567e93181fbd99a33ac1d1ec9f4cd2c0..9ed965cc941404d982a72dede2d4da754b44c329 100644 (file)
@@ -29,10 +29,14 @@ using namespace COFF;
 void executeObjcopyOnBinary(const CopyConfig &Config,
                             object::COFFObjectFile &In, Buffer &Out) {
   COFFReader Reader(In);
-  std::unique_ptr<Object> Obj = Reader.create();
+  Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
+  if (!ObjOrErr)
+    reportError(Config.InputFilename, ObjOrErr.takeError());
+  Object *Obj = ObjOrErr->get();
   assert(Obj && "Unable to deserialize COFF object");
   COFFWriter Writer(*Obj, Out);
-  Writer.write();
+  if (Error E = Writer.write())
+    reportError(Config.OutputFilename, std::move(E));
 }
 
 } // end namespace coff
index a8a3576084cd1fa74ef82a5e3bf02d6593d78775..5d805961d6fd2c97e7a86a512552191d432814d0 100644 (file)
@@ -25,11 +25,11 @@ using namespace object;
 
 Reader::~Reader() {}
 
-void COFFReader::readExecutableHeaders(Object &Obj) const {
+Error COFFReader::readExecutableHeaders(Object &Obj) const {
   const dos_header *DH = COFFObj.getDOSHeader();
   Obj.Is64 = COFFObj.is64();
   if (!DH)
-    return;
+    return Error::success();
 
   Obj.IsPE = true;
   Obj.DosHeader = *DH;
@@ -40,12 +40,12 @@ void COFFReader::readExecutableHeaders(Object &Obj) const {
   if (COFFObj.is64()) {
     const pe32plus_header *PE32Plus = nullptr;
     if (auto EC = COFFObj.getPE32PlusHeader(PE32Plus))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     Obj.PeHeader = *PE32Plus;
   } else {
     const pe32_header *PE32 = nullptr;
     if (auto EC = COFFObj.getPE32Header(PE32))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     copyPeHeader(Obj.PeHeader, *PE32);
     // The pe32plus_header (stored in Object) lacks the BaseOfData field.
     Obj.BaseOfData = PE32->BaseOfData;
@@ -54,39 +54,40 @@ void COFFReader::readExecutableHeaders(Object &Obj) const {
   for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) {
     const data_directory *Dir;
     if (auto EC = COFFObj.getDataDirectory(I, Dir))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     Obj.DataDirectories.emplace_back(*Dir);
   }
+  return Error::success();
 }
 
-void COFFReader::readSections(Object &Obj) const {
+Error COFFReader::readSections(Object &Obj) const {
   // Section indexing starts from 1.
   for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
     const coff_section *Sec;
     if (auto EC = COFFObj.getSection(I, Sec))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     Obj.Sections.push_back(Section());
     Section &S = Obj.Sections.back();
     S.Header = *Sec;
     if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
-    S.Relocs.insert(S.Relocs.end(), Relocs.begin(), Relocs.end());
+    for (const coff_relocation &R : Relocs)
+      S.Relocs.push_back(R);
     if (auto EC = COFFObj.getSectionName(Sec, S.Name))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     if (Sec->hasExtendedRelocations())
-      reportError(
-          COFFObj.getFileName(),
-          make_error<StringError>("Extended relocations not supported yet",
-                                  object_error::parse_failed));
+      return make_error<StringError>("Extended relocations not supported yet",
+                                     object_error::parse_failed);
   }
+  return Error::success();
 }
 
-void COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
+Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
   for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
     Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
     if (!SymOrErr)
-      reportError(COFFObj.getFileName(), SymOrErr.takeError());
+      return SymOrErr.takeError();
     COFFSymbolRef SymRef = *SymOrErr;
 
     Obj.Symbols.push_back(Symbol());
@@ -99,15 +100,16 @@ void COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
       copySymbol(Sym.Sym,
                  *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
     if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name))
-      reportError(COFFObj.getFileName(), std::move(EC));
+      return errorCodeToError(EC);
     Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
     assert((Sym.AuxData.size() %
             (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
     I += 1 + SymRef.getNumberOfAuxSymbols();
   }
+  return Error::success();
 }
 
-std::unique_ptr<Object> COFFReader::create() const {
+Expected<std::unique_ptr<Object>> COFFReader::create() const {
   auto Obj = llvm::make_unique<Object>();
 
   const coff_file_header *CFH = nullptr;
@@ -119,9 +121,8 @@ std::unique_ptr<Object> COFFReader::create() const {
     Obj->CoffFileHeader = *CFH;
   } else {
     if (!CBFH)
-      reportError(COFFObj.getFileName(),
-                  make_error<StringError>("No COFF file header returned",
-                                          object_error::parse_failed));
+      return make_error<StringError>("No COFF file header returned",
+                                     object_error::parse_failed);
     // Only copying the few fields from the bigobj header that we need
     // and won't recreate in the end.
     Obj->CoffFileHeader.Machine = CBFH->Machine;
@@ -129,11 +130,14 @@ std::unique_ptr<Object> COFFReader::create() const {
     IsBigObj = true;
   }
 
-  readExecutableHeaders(*Obj);
-  readSections(*Obj);
-  readSymbols(*Obj, IsBigObj);
+  if (Error E = readExecutableHeaders(*Obj))
+    return std::move(E);
+  if (Error E = readSections(*Obj))
+    return std::move(E);
+  if (Error E = readSymbols(*Obj, IsBigObj))
+    return std::move(E);
 
-  return Obj;
+  return std::move(Obj);
 }
 
 } // end namespace coff
index c81a9751f1804cd83f60f2ab93bdcca46a191b8a..f2b7f78a90822055efd1538dd7f551d189c577fe 100644 (file)
@@ -13,6 +13,7 @@
 #include "Buffer.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
+#include "llvm/Support/Error.h"
 
 namespace llvm {
 namespace objcopy {
@@ -25,19 +26,19 @@ using object::COFFObjectFile;
 class Reader {
 public:
   virtual ~Reader();
-  virtual std::unique_ptr<Object> create() const = 0;
+  virtual Expected<std::unique_ptr<Object>> create() const = 0;
 };
 
 class COFFReader : public Reader {
   const COFFObjectFile &COFFObj;
 
-  void readExecutableHeaders(Object &Obj) const;
-  void readSections(Object &Obj) const;
-  void readSymbols(Object &Obj, bool IsBigObj) const;
+  Error readExecutableHeaders(Object &Obj) const;
+  Error readSections(Object &Obj) const;
+  Error readSymbols(Object &Obj, bool IsBigObj) const;
 
 public:
   explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {}
-  std::unique_ptr<Object> create() const override;
+  Expected<std::unique_ptr<Object>> create() const override;
 };
 
 } // end namespace coff
index 5a461e43a5551874f89e7b1d2b5c98bc38117060..388c62cbdc67e1a09bdcfe6756a4df21e654ab08 100644 (file)
@@ -247,7 +247,7 @@ template <class SymbolTy> void COFFWriter::writeSymbolStringTables() {
   }
 }
 
-void COFFWriter::write(bool IsBigObj) {
+Error COFFWriter::write(bool IsBigObj) {
   finalize(IsBigObj);
 
   Buf.allocate(FileSize);
@@ -260,31 +260,30 @@ void COFFWriter::write(bool IsBigObj) {
     writeSymbolStringTables<coff_symbol16>();
 
   if (Obj.IsPE)
-    patchDebugDirectory();
+    if (Error E = patchDebugDirectory())
+      return E;
 
-  if (auto E = Buf.commit())
-    reportError(Buf.getName(), errorToErrorCode(std::move(E)));
+  return Buf.commit();
 }
 
 // Locate which sections contain the debug directories, iterate over all
 // the debug_directory structs in there, and set the PointerToRawData field
 // in all of them, according to their new physical location in the file.
-void COFFWriter::patchDebugDirectory() {
+Error COFFWriter::patchDebugDirectory() {
   if (Obj.DataDirectories.size() < DEBUG_DIRECTORY)
-    return;
+    return Error::success();
   const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY];
   if (Dir->Size <= 0)
-    return;
+    return Error::success();
   for (const auto &S : Obj.Sections) {
     if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress &&
         Dir->RelativeVirtualAddress <
             S.Header.VirtualAddress + S.Header.SizeOfRawData) {
       if (Dir->RelativeVirtualAddress + Dir->Size >
           S.Header.VirtualAddress + S.Header.SizeOfRawData)
-        reportError(Buf.getName(),
-                    make_error<StringError>(
-                        "Debug directory extends past end of section",
-                        object_error::parse_failed));
+        return make_error<StringError>(
+            "Debug directory extends past end of section",
+            object_error::parse_failed);
 
       size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress;
       uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData + Offset;
@@ -297,21 +296,19 @@ void COFFWriter::patchDebugDirectory() {
         Offset += sizeof(debug_directory) + Debug->SizeOfData;
       }
       // Debug directory found and patched, all done.
-      return;
+      return Error::success();
     }
   }
-  reportError(Buf.getName(),
-              make_error<StringError>("Debug directory not found",
-                                      object_error::parse_failed));
+  return make_error<StringError>("Debug directory not found",
+                                 object_error::parse_failed);
 }
 
-void COFFWriter::write() {
+Error COFFWriter::write() {
   bool IsBigObj = Obj.Sections.size() > MaxNumberOfSections16;
   if (IsBigObj && Obj.IsPE)
-    reportError(Buf.getName(),
-                make_error<StringError>("Too many sections for executable",
-                                        object_error::parse_failed));
-  write(IsBigObj);
+    return make_error<StringError>("Too many sections for executable",
+                                   object_error::parse_failed);
+  return write(IsBigObj);
 }
 
 } // end namespace coff
index 397fda02ee980761333e12d6105c64a6c38579ea..f2e814a0f99eb1eeb7f6753d32e6153af3ed60d8 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "Buffer.h"
 #include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Error.h"
 #include <cstddef>
 #include <utility>
 
@@ -28,7 +29,7 @@ protected:
 
 public:
   virtual ~Writer();
-  virtual void write() = 0;
+  virtual Error write() = 0;
 
   Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
 };
@@ -49,13 +50,13 @@ class COFFWriter : public Writer {
   void writeSections();
   template <class SymbolTy> void writeSymbolStringTables();
 
-  void write(bool IsBigObj);
+  Error write(bool IsBigObj);
 
-  void patchDebugDirectory();
+  Error patchDebugDirectory();
 
 public:
   virtual ~COFFWriter() {}
-  void write() override;
+  Error write() override;
 
   COFFWriter(Object &Obj, Buffer &Buf)
       : Writer(Obj, Buf), StrTabBuilder(StringTableBuilder::WinCOFF) {}