Better error reporting when loading dex files

Collect all partial error messages and return them as cause
exceptions for the top-level exception returned.

Change-Id: I9661b8aed2a571dc88bf0f06d447108eeaed1409
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 15a5779..6af16f4 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -104,6 +104,7 @@
 
   uint32_t dex_location_checksum;
   uint32_t* dex_location_checksum_pointer = &dex_location_checksum;
+  std::vector<std::string> error_msgs;
   std::string error_msg;
   if (!DexFile::GetChecksum(sourceName.c_str(), dex_location_checksum_pointer, &error_msg)) {
     dex_location_checksum_pointer = NULL;
@@ -113,9 +114,8 @@
   const DexFile* dex_file;
   if (outputName.c_str() == nullptr) {
     // FindOrCreateOatFileForDexLocation can tolerate a missing dex_location_checksum
-    error_msg.clear();
     dex_file = linker->FindDexFileInOatFileFromDexLocation(sourceName.c_str(),
-                                                           dex_location_checksum_pointer, &error_msg);
+                                                           dex_location_checksum_pointer, &error_msgs);
   } else {
     // FindOrCreateOatFileForDexLocation requires the dex_location_checksum
     if (dex_location_checksum_pointer == NULL) {
@@ -125,12 +125,19 @@
       return 0;
     }
     dex_file = linker->FindOrCreateOatFileForDexLocation(sourceName.c_str(), dex_location_checksum,
-                                                         outputName.c_str(), &error_msg);
+                                                         outputName.c_str(), &error_msgs);
   }
   if (dex_file == nullptr) {
     ScopedObjectAccess soa(env);
-    CHECK(!error_msg.empty());
-    ThrowIOException("%s", error_msg.c_str());
+    CHECK(!error_msgs.empty());
+    // The most important message is at the end. So set up nesting by going forward, which will
+    // wrap the existing exception as a cause for the following one.
+    auto it = error_msgs.begin();
+    auto itEnd = error_msgs.end();
+    for ( ; it != itEnd; ++it) {
+      ThrowWrappedIOException("%s", it->c_str());
+    }
+
     return 0;
   }
   return static_cast<jlong>(reinterpret_cast<uintptr_t>(dex_file));