Fix location of ICCEs and NoSuchMethodErrors.

Also add detail as to why verifier believes an ICCE.

Change-Id: Ie16ea2847fb94e157969c560a780c9345b1e7441
diff --git a/src/class_linker.cc b/src/class_linker.cc
index e693c56..41f14df 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -3524,40 +3524,40 @@
       case kDirect:
       case kStatic:
         if (resolved != NULL) {
-          ThrowIncompatibleClassChangeError(type, kVirtual, resolved);
+          ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
         } else {
           resolved = klass->FindInterfaceMethod(name, signature);
           if (resolved != NULL) {
-            ThrowIncompatibleClassChangeError(type, kInterface, resolved);
+            ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
           } else {
-            ThrowNoSuchMethodError(type, klass, name, signature);
+            ThrowNoSuchMethodError(type, klass, name, signature, referrer);
           }
         }
         break;
       case kInterface:
         if (resolved != NULL) {
-          ThrowIncompatibleClassChangeError(type, kDirect, resolved);
+          ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
         } else {
           resolved = klass->FindVirtualMethod(name, signature);
           if (resolved != NULL) {
-            ThrowIncompatibleClassChangeError(type, kVirtual, resolved);
+            ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
           } else {
-            ThrowNoSuchMethodError(type, klass, name, signature);
+            ThrowNoSuchMethodError(type, klass, name, signature, referrer);
           }
         }
         break;
       case kSuper:
-        ThrowNoSuchMethodError(type, klass, name, signature);
+        ThrowNoSuchMethodError(type, klass, name, signature, referrer);
         break;
       case kVirtual:
         if (resolved != NULL) {
-          ThrowIncompatibleClassChangeError(type, kDirect, resolved);
+          ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
         } else {
           resolved = klass->FindInterfaceMethod(name, signature);
           if (resolved != NULL) {
-            ThrowIncompatibleClassChangeError(type, kInterface, resolved);
+            ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
           } else {
-            ThrowNoSuchMethodError(type, klass, name, signature);
+            ThrowNoSuchMethodError(type, klass, name, signature, referrer);
           }
         }
         break;
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index c5eaffa..c5ce4b3 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -144,11 +144,11 @@
 }
 
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method) {
+                                       Method* method, const Method* referrer) {
   std::ostringstream msg;
   msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
       << expected_type << " but instead was found to be of type " << found_type;
-  ClassHelper kh(method->GetDeclaringClass());
+  ClassHelper kh(referrer->GetDeclaringClass());
   std::string location(kh.GetLocation());
   if (!location.empty()) {
     msg << " (accessed from " << location << ")";
@@ -158,11 +158,12 @@
 }
 
 void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature) {
+                            const StringPiece& signature, const Method* referrer) {
   ClassHelper kh(c);
   std::ostringstream msg;
   msg << "No " << type << " method " << name << signature
       << " in class " << kh.GetDescriptor() << " or its superclasses";
+  kh.ChangeClass(referrer->GetDeclaringClass());
   std::string location(kh.GetLocation());
   if (!location.empty()) {
     msg << " (accessed from " << location << ")";
@@ -575,7 +576,8 @@
     } else {
       // Incompatible class change should have been handled in resolve method.
       if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
-        ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method);
+        ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
+                                          referrer);
         return NULL;  // Failure.
       }
       Class* methods_class = resolved_method->GetDeclaringClass();
@@ -633,7 +635,7 @@
           // Behavior to agree with that of the verifier.
           MethodHelper mh(resolved_method);
           ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
-                                 mh.GetSignature());
+                                 mh.GetSignature(), referrer);
           return NULL;  // Failure.
         }
       }
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 260202b..c6bf0c8 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -58,10 +58,10 @@
                                                                    Object* this_object)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method)
+                                       Method* method, const Method* referrer)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
 void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature)
+                            const StringPiece& signature, const Method* referrer)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
 void ThrowNewIllegalAccessErrorField(Thread* self, Class* referrer, Field* accessed)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 0cdff83..9c0e380 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -2596,8 +2596,8 @@
       (method_type == METHOD_STATIC && !res_method->IsStatic()) ||
       ((method_type == METHOD_VIRTUAL || method_type == METHOD_INTERFACE) && res_method->IsDirect())
       ) {
-    Fail(VERIFY_ERROR_CLASS_CHANGE) << "invoke type does not match method type of "
-                                    << PrettyMethod(res_method);
+    Fail(VERIFY_ERROR_CLASS_CHANGE) << "invoke type (" << method_type << ") does not match method "
+                                       " type of " << PrettyMethod(res_method);
     return NULL;
   }
   return res_method;
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index 3c15c10..273552d 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -71,6 +71,7 @@
   METHOD_VIRTUAL,     // virtual, super
   METHOD_INTERFACE    // interface
 };
+std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
 
 /*
  * An enumeration of problems that can turn up during verification.