Show ArtMethods in imgdiag

Since ArtMethods were moved out of mirror:: classes imgdiag does not
show information about them.  Diff ArtMethods to facilitate finding
dirty memory there.

Bug: 38173645
Test: imgdiag --boot-image=/system/framework/boot.art --image-diff-pid=`pid system_server`
Change-Id: Icd86a9ef14d5177a297026c22c81c080f5c85fc1
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 2d67761..dab3f23 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -671,6 +671,24 @@
   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
   ALWAYS_INLINE void UpdateEntrypoints(const Visitor& visitor, PointerSize pointer_size);
 
+  // Visit the individual members of an ArtMethod.  Used by imgdiag.
+  // As imgdiag does not support mixing instruction sets or pointer sizes (e.g., using imgdiag32
+  // to inspect 64-bit images, etc.), we can go beneath the accessors directly to the class members.
+  template <typename VisitorFunc>
+  void VisitMembers(VisitorFunc& visitor) {
+    DCHECK(IsImagePointerSize(kRuntimePointerSize));
+    visitor(this, &declaring_class_, "declaring_class_");
+    visitor(this, &access_flags_, "access_flags_");
+    visitor(this, &dex_code_item_offset_, "dex_code_item_offset_");
+    visitor(this, &dex_method_index_, "dex_method_index_");
+    visitor(this, &method_index_, "method_index_");
+    visitor(this, &hotness_count_, "hotness_count_");
+    visitor(this, &ptr_sized_fields_.data_, "ptr_sized_fields_.data_");
+    visitor(this,
+            &ptr_sized_fields_.entry_point_from_quick_compiled_code_,
+            "ptr_sized_fields_.entry_point_from_quick_compiled_code_");
+  }
+
  protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4161754..835d940 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -8368,6 +8368,10 @@
       (quick_generic_jni_trampoline_ == entry_point);
 }
 
+bool ClassLinker::IsJniDlsymLookupStub(const void* entry_point) const {
+  return entry_point == GetJniDlsymLookupStub();
+}
+
 const void* ClassLinker::GetRuntimeQuickGenericJniStub() const {
   return GetQuickGenericJniStub();
 }
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 9727adf..2f92da3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -500,6 +500,9 @@
   // Is the given entry point quick code to run the generic JNI stub?
   bool IsQuickGenericJniStub(const void* entry_point) const;
 
+  // Is the given entry point the JNI dlsym lookup stub?
+  bool IsJniDlsymLookupStub(const void* entry_point) const;
+
   const void* GetQuickToInterpreterBridgeTrampoline() const {
     return quick_to_interpreter_bridge_trampoline_;
   }
diff --git a/runtime/image.cc b/runtime/image.cc
index c8581c1..0236f47 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -144,6 +144,19 @@
   return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End();
 }
 
+void ImageHeader::VisitObjects(ObjectVisitor* visitor,
+                               uint8_t* base,
+                               PointerSize pointer_size) const {
+  DCHECK_EQ(pointer_size, GetPointerSize());
+  const ImageSection& objects = GetObjectsSection();
+  static const size_t kStartPos = RoundUp(sizeof(ImageHeader), kObjectAlignment);
+  for (size_t pos = kStartPos; pos < objects.Size(); ) {
+    mirror::Object* object = reinterpret_cast<mirror::Object*>(base + objects.Offset() + pos);
+    visitor->Visit(object);
+    pos += RoundUp(object->SizeOf(), kObjectAlignment);
+  }
+}
+
 void ImageHeader::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const {
   const ImageSection& fields = GetFieldsSection();
   for (size_t pos = 0; pos < fields.Size(); ) {
diff --git a/runtime/image.h b/runtime/image.h
index 2b24087..da04333 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -29,6 +29,13 @@
 class ArtField;
 class ArtMethod;
 
+class ObjectVisitor {
+ public:
+  virtual ~ObjectVisitor() {}
+
+  virtual void Visit(mirror::Object* object) = 0;
+};
+
 class ArtMethodVisitor {
  public:
   virtual ~ArtMethodVisitor() {}
@@ -328,6 +335,13 @@
     return RoundUp(tables_size, kPageSize);
   }
 
+  // Visit mirror::Objects in the section starting at base.
+  // TODO: Delete base parameter if it is always equal to GetImageBegin.
+  void VisitObjects(ObjectVisitor* visitor,
+                    uint8_t* base,
+                    PointerSize pointer_size) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   // Visit ArtMethods in the section starting at base. Includes runtime methods.
   // TODO: Delete base parameter if it is always equal to GetImageBegin.
   void VisitPackedArtMethods(ArtMethodVisitor* visitor,