Add make_dynamic_error_code().
authorNick Kledzik <kledzik@apple.com>
Tue, 27 May 2014 19:35:41 +0000 (19:35 +0000)
committerNick Kledzik <kledzik@apple.com>
Tue, 27 May 2014 19:35:41 +0000 (19:35 +0000)
This is a short-term fix to allow lld Readers to return error messages
with dynamic content.

The long term fix will be to enhance ErrorOr<> to work with errors other
than error_code.  Or to change the interface to Readers to pass down a
diagnostics object through which all error messages are written.

llvm-svn: 209681

lld/include/lld/Core/Error.h
lld/lib/Core/Error.cpp
lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp

index a91ed30..d59520a 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLD_CORE_ERROR_H
 #define LLD_CORE_ERROR_H
 
+#include "lld/Core/LLVM.h"
 #include "llvm/Support/system_error.h"
 
 namespace lld {
@@ -82,6 +83,16 @@ inline llvm::error_code make_error_code(ReaderError e) {
   return llvm::error_code(static_cast<int>(e), ReaderErrorCategory());
 }
 
+
+/// Creates an error_code object that has associated with it an arbitrary
+/// error messsage.  The value() of the error_code will always be non-zero
+/// but its value is meaningless. The messsage() will be (a copy of) the 
+/// supplied error string.
+/// Note:  Once ErrorOr<> is updated to work with errors other than error_code, 
+/// this can be updated to return some other kind of error.
+llvm::error_code make_dynamic_error_code(StringRef msg);
+llvm::error_code make_dynamic_error_code(const Twine &msg);
+
 } // end namespace lld
 
 namespace llvm {
index 32496b9..d8b6560 100644 (file)
@@ -9,7 +9,12 @@
 
 #include "lld/Core/Error.h"
 
+#include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Mutex.h"
+
+#include <string>
+#include <vector>
 
 using namespace lld;
 
@@ -153,3 +158,52 @@ const llvm::error_category &lld::ReaderErrorCategory() {
   static _ReaderErrorCategory i;
   return i;
 }
+
+
+
+
+namespace lld {
+
+
+/// Temporary class to enable make_dynamic_error_code() until
+/// llvm::ErrorOr<> is updated to work with error encapsulations 
+/// other than error_code.
+class dynamic_error_category : public llvm::_do_message {
+public:
+  const char *name() const override { return "lld.dynamic_error"; }
+
+  std::string message(int ev) const override {
+    assert(ev >= 0);
+    assert(ev < (int)_messages.size());
+    // The value is an index into the string vector.
+    return _messages[ev];
+  }
+  
+  int add(std::string msg) {
+    llvm::sys::SmartScopedLock<true> lock(_mutex);
+    // Value zero is always the successs value.
+    if (_messages.empty())
+      _messages.push_back("Success");
+    _messages.push_back(msg);
+    // Return the index of the string just appended.
+    return _messages.size() - 1;
+  }
+  
+private:
+  std::vector<std::string> _messages;
+  llvm::sys::SmartMutex<true> _mutex;
+};
+
+static dynamic_error_category categorySingleton;
+
+
+llvm::error_code make_dynamic_error_code(StringRef msg) {
+  return llvm::error_code(categorySingleton.add(msg), categorySingleton);
+}
+
+llvm::error_code make_dynamic_error_code(const Twine &msg) {
+  return llvm::error_code(categorySingleton.add(msg.str()), categorySingleton);
+}
+
+}
+
index 769cb39..596a8fe 100644 (file)
@@ -24,6 +24,7 @@
 #include "File.h"
 #include "Atoms.h"
 
+#include "lld/Core/Error.h"
 #include "lld/Core/LLVM.h"
 
 #include "llvm/Support/MachO.h"
@@ -129,7 +130,11 @@ static error_code processSection(MachOFile &file, const Section &section,
     break;
   case llvm::MachO::S_4BYTE_LITERALS:
     if ((section.content.size() % 4) != 0)
-      return llvm::make_error_code(llvm::errc::executable_format_error);
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName 
+                                     + " has type S_4BYTE_LITERALS but its "
+                                     "size (" + Twine(section.content.size()) 
+                                     + ") is not a multiple of 4"); 
     for (size_t i = 0, e = section.content.size(); i != e; i += 4) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 4);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
@@ -139,7 +144,11 @@ static error_code processSection(MachOFile &file, const Section &section,
     break;
   case llvm::MachO::S_8BYTE_LITERALS:
     if ((section.content.size() % 8) != 0)
-      return llvm::make_error_code(llvm::errc::executable_format_error);
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName 
+                                     + " has type S_8YTE_LITERALS but its "
+                                     "size (" + Twine(section.content.size()) 
+                                     + ") is not a multiple of 8"); 
     for (size_t i = 0, e = section.content.size(); i != e; i += 8) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 8);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,
@@ -149,7 +158,11 @@ static error_code processSection(MachOFile &file, const Section &section,
     break;
   case llvm::MachO::S_16BYTE_LITERALS:
     if ((section.content.size() % 16) != 0)
-      return llvm::make_error_code(llvm::errc::executable_format_error);
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName 
+                                     + " has type S_16BYTE_LITERALS but its "
+                                     "size (" + Twine(section.content.size()) 
+                                     + ") is not a multiple of 16"); 
     for (size_t i = 0, e = section.content.size(); i != e; i += 16) {
       ArrayRef<uint8_t> byteContent = section.content.slice(offset, 16);
       file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit,