Add extra logging for bug 77342775.

Test: testrunner.py --host --64 --optimizing
Test: Repeat with disabled filtering to Lorg/apache/http/,
      manually expect failure messages.
Bug: 77342775
Change-Id: I98b1e4fb77dc5c6b57a91c7dda19e1a4b15c29be
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 945442d..8fd95ed 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -24,6 +24,7 @@
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "class_linker-inl.h"
+#include "debug_print.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_instruction-inl.h"
 #include "dex/invoke_type.h"
@@ -152,6 +153,7 @@
 // ClassCastException
 
 void ThrowClassCastException(ObjPtr<mirror::Class> dest_type, ObjPtr<mirror::Class> src_type) {
+  DumpB77342775DebugData(dest_type, src_type);
   ThrowException("Ljava/lang/ClassCastException;", nullptr,
                  StringPrintf("%s cannot be cast to %s",
                               mirror::Class::PrettyDescriptor(src_type).c_str(),
@@ -279,6 +281,7 @@
       << "' does not implement interface '" << mirror::Class::PrettyDescriptor(target_class)
       << "' in call to '"
       << ArtMethod::PrettyMethod(method) << "'";
+  DumpB77342775DebugData(target_class, this_object->GetClass());
   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
                  msg.str().c_str());
@@ -295,6 +298,7 @@
       << "' does not implement interface '"
       << mirror::Class::PrettyDescriptor(interface_method->GetDeclaringClass())
       << "' in call to '" << ArtMethod::PrettyMethod(interface_method) << "'";
+  DumpB77342775DebugData(interface_method->GetDeclaringClass(), this_object->GetClass());
   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
                  msg.str().c_str());
diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc
index 44a1836..c7530be 100644
--- a/runtime/debug_print.cc
+++ b/runtime/debug_print.cc
@@ -110,4 +110,50 @@
   return oss.str();
 }
 
+void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class) {
+  std::string target_descriptor_storage;
+  const char* target_descriptor = target_class->GetDescriptor(&target_descriptor_storage);
+  const char kCheckedPrefix[] = "Lorg/apache/http/";
+  // Avoid spam for other packages. (That spam would break some ART run-tests for example.)
+  if (strncmp(target_descriptor, kCheckedPrefix, sizeof(kCheckedPrefix) - 1) != 0) {
+    return;
+  }
+  auto matcher = [target_descriptor, target_class](ObjPtr<mirror::Class> klass)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (klass->DescriptorEquals(target_descriptor)) {
+      LOG(ERROR) << "    descriptor match in "
+          << DescribeLoaders(klass->GetClassLoader(), target_descriptor)
+          << " match? " << std::boolalpha << (klass == target_class);
+    }
+  };
+
+  std::string source_descriptor_storage;
+  const char* source_descriptor = src_class->GetDescriptor(&source_descriptor_storage);
+
+  if (target_class->IsInterface()) {
+    ObjPtr<mirror::IfTable> iftable = src_class->GetIfTable();
+    CHECK(iftable != nullptr);
+    size_t ifcount = iftable->Count();
+    LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor
+        << " with loader " << DescribeLoaders(src_class->GetClassLoader(), target_descriptor)
+        << " in interface table for " << source_descriptor << " ifcount=" << ifcount;
+    for (size_t i = 0; i != ifcount; ++i) {
+      ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
+      CHECK(iface != nullptr);
+      LOG(ERROR) << "  iface #" << i << ": " << iface->PrettyDescriptor();
+      matcher(iface);
+    }
+  } else {
+    LOG(ERROR) << "Maybe bug 77342775, looking for " << target_descriptor
+        << " with loader " << DescribeLoaders(src_class->GetClassLoader(), target_descriptor)
+        << " in superclass chain for " << source_descriptor;
+    for (ObjPtr<mirror::Class> klass = src_class;
+         klass != nullptr;
+         klass = klass->GetSuperClass()) {
+      LOG(ERROR) << "  - " << klass->PrettyDescriptor();
+      matcher(klass);
+    }
+  }
+}
+
 }  // namespace art
diff --git a/runtime/debug_print.h b/runtime/debug_print.h
index 479c36a..df00f06 100644
--- a/runtime/debug_print.h
+++ b/runtime/debug_print.h
@@ -29,6 +29,9 @@
 std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* class_descriptor)
     REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
 
+void DumpB77342775DebugData(ObjPtr<mirror::Class> target_class, ObjPtr<mirror::Class> src_class)
+    REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR;
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_DEBUG_PRINT_H_
diff --git a/runtime/verifier/register_line-inl.h b/runtime/verifier/register_line-inl.h
index 39d73f5..5160daf 100644
--- a/runtime/verifier/register_line-inl.h
+++ b/runtime/verifier/register_line-inl.h
@@ -20,6 +20,7 @@
 #include "register_line.h"
 
 #include "base/logging.h"  // For VLOG.
+#include "debug_print.h"
 #include "method_verifier.h"
 #include "reg_type_cache-inl.h"
 
@@ -147,6 +148,14 @@
     }
     verifier->Fail(fail_type) << "register v" << vsrc << " has type "
                                << src_type << " but expected " << check_type;
+    if (check_type.IsNonZeroReferenceTypes() &&
+        !check_type.IsUnresolvedTypes() &&
+        check_type.HasClass() &&
+        src_type.IsNonZeroReferenceTypes() &&
+        !src_type.IsUnresolvedTypes() &&
+        src_type.HasClass()) {
+      DumpB77342775DebugData(check_type.GetClass(), src_type.GetClass());
+    }
     return false;
   }
   if (check_type.IsLowHalf()) {