Add verification for image ArtMethod declaring classes
Try and see if any ArtMethods in the image have declaring classes
that are not marked in the heap live bitmap. Trying to mark these
would cause a SIGSEGV since the bitmap is read only.
TODO: Disable for performance.
(cherry-picked from commit 03c1dd9858962071bf3f0c988abc39e0e6ed7a1e)
Bug: 27493510
Change-Id: I231b07b84d98dcd7ee1557c18956c86264058ee1
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 32ad422..ba935f7 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -50,7 +50,7 @@
#include "experimental_flags.h"
#include "gc_root-inl.h"
#include "gc/accounting/card_table-inl.h"
-#include "gc/accounting/heap_bitmap.h"
+#include "gc/accounting/heap_bitmap-inl.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
#include "handle_scope-inl.h"
@@ -96,6 +96,7 @@
namespace art {
static constexpr bool kSanityCheckObjects = kIsDebugBuild;
+static constexpr bool kVerifyArtMethodDeclaringClasses = true;
static void ThrowNoClassDefFoundError(const char* fmt, ...)
__attribute__((__format__(__printf__, 1, 2)))
@@ -1197,6 +1198,23 @@
ClassTable* const table_;
};
+class VerifyDeclaringClassVisitor : public ArtMethodVisitor {
+ public:
+ VerifyDeclaringClassVisitor() SHARED_REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_)
+ : live_bitmap_(Runtime::Current()->GetHeap()->GetLiveBitmap()) {}
+
+ virtual void Visit(ArtMethod* method)
+ SHARED_REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+ mirror::Class* klass = method->GetDeclaringClassUnchecked();
+ if (klass != nullptr) {
+ CHECK(live_bitmap_->Test(klass)) << "Image method has unmarked declaring class";
+ }
+ }
+
+ private:
+ gc::accounting::HeapBitmap* const live_bitmap_;
+};
+
bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
@@ -1416,15 +1434,24 @@
}
}
}
- if (*out_forward_dex_cache_array) {
- ScopedTrace timing("Fixup ArtMethod dex cache arrays");
- FixupArtMethodArrayVisitor visitor(header);
- header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
- &visitor,
- space->Begin(),
- sizeof(void*));
- Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
- }
+ }
+ if (*out_forward_dex_cache_array) {
+ ScopedTrace timing("Fixup ArtMethod dex cache arrays");
+ FixupArtMethodArrayVisitor visitor(header);
+ header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
+ &visitor,
+ space->Begin(),
+ sizeof(void*));
+ Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
+ }
+ if (kVerifyArtMethodDeclaringClasses) {
+ ScopedTrace timing("Verify declaring classes");
+ ReaderMutexLock rmu(self, *Locks::heap_bitmap_lock_);
+ VerifyDeclaringClassVisitor visitor;
+ header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods(
+ &visitor,
+ space->Begin(),
+ sizeof(void*));
}
return true;
}