summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Shapiro <cshapiro@google.com>2010-08-27 15:21:13 -0700
committerCarl Shapiro <cshapiro@google.com>2010-09-01 18:37:38 -0700
commitc44bca6530787454ee794cf2f83c1c6671a93aa8 (patch)
tree9597da792977d565df98e5e9bdccb038927f657c
parent57ee270b755271166b2349321e5b8b5457731dd7 (diff)
downloadandroid_dalvik-c44bca6530787454ee794cf2f83c1c6671a93aa8.tar.gz
android_dalvik-c44bca6530787454ee794cf2f83c1c6671a93aa8.tar.bz2
android_dalvik-c44bca6530787454ee794cf2f83c1c6671a93aa8.zip
Improve the heap verifier's failure report.
Previously, when a reference verify failed we would print the location of the bad reference and abort. With this change, when a reference fails to verify we try to print out more context. First, we dump the object which contains the bad references and print each reference that failed verification. Following that, we scan the roots and the heap and print all of the objects which reference the bad object.
-rw-r--r--vm/alloc/Verify.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/vm/alloc/Verify.c b/vm/alloc/Verify.c
index c4222adce..48168ddc5 100644
--- a/vm/alloc/Verify.c
+++ b/vm/alloc/Verify.c
@@ -16,49 +16,99 @@
#include "Dalvik.h"
#include "alloc/HeapBitmap.h"
+#include "alloc/HeapSource.h"
#include "alloc/Verify.h"
#include "alloc/Visit.h"
+static void dumpReferencesVisitor(void *pObj, void *arg)
+{
+ Object *obj = *(Object **)pObj;
+ Object *lookingFor = *(Object **)arg;
+ if (lookingFor != NULL && lookingFor == obj) {
+ *(Object **)arg = NULL;
+ }
+}
+
+static void dumpReferencesCallback(void *ptr, void *arg)
+{
+ Object *obj = arg;
+ if (ptr == obj) {
+ LOGD("skipping %p == %p", ptr, obj);
+ return;
+ }
+ dvmVisitObject(dumpReferencesVisitor, ptr, &obj);
+ if (obj == NULL) {
+ LOGD("Found %p in the heap @ %p", arg, ptr);
+ dvmDumpObject(ptr);
+ }
+}
+
+static void dumpReferencesRootVisitor(void *ptr, void *arg)
+{
+ Object *obj = *(Object **)ptr;
+ Object *lookingFor = *(Object **)arg;
+ if (obj == lookingFor) {
+ LOGD("Found %p in a root @ %p", arg, ptr);
+ }
+}
+
+/*
+ * Searches the roots and heap for object references.
+ */
+static void dumpReferences(const Object *obj)
+{
+ HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
+ void *arg = (void *)obj;
+ dvmVisitRoots(dumpReferencesRootVisitor, arg);
+ dvmHeapBitmapWalk(bitmap, dumpReferencesCallback, arg);
+}
+
/*
* Checks that the given reference points to a valid object.
*/
static void verifyReference(void *addr, void *arg)
{
- const Object *obj;
+ Object *obj;
bool isValid;
assert(addr != NULL);
- obj = *(const Object **)addr;
+ obj = *(Object **)addr;
if (obj == NULL) {
isValid = true;
} else {
isValid = dvmIsValidObject(obj);
}
if (!isValid) {
- LOGE("Verify of object %p @ %p failed", obj, addr);
- dvmAbort();
+ Object **parent = arg;
+ if (*parent != NULL) {
+ LOGE("Verify of object %p failed", *parent);
+ dvmDumpObject(*parent);
+ *parent = NULL;
+ }
+ LOGE("Verify of reference %p @ %p failed", obj, addr);
+ dvmDumpObject(obj);
}
}
-static void visitorCallback(void *addr, void *arg)
-{
- verifyReference(addr, arg);
-}
-
/*
* Verifies an object reference.
*/
void dvmVerifyObject(const Object *obj)
{
- dvmVisitObject(visitorCallback, (Object *)obj, NULL);
+ Object *arg = (Object *)obj;
+ dvmVisitObject(verifyReference, (Object *)obj, &arg);
+ if (arg == NULL) {
+ dumpReferences(obj);
+ dvmAbort();
+ }
}
/*
* Helper function to call dvmVerifyObject from a bitmap walker.
*/
-static void verifyBitmapCallback(void *ptrs, void *arg)
+static void verifyBitmapCallback(void *ptr, void *arg)
{
- dvmVerifyObject(ptrs);
+ dvmVerifyObject(ptr);
}
/*
@@ -67,7 +117,6 @@ static void verifyBitmapCallback(void *ptrs, void *arg)
*/
void dvmVerifyBitmap(const HeapBitmap *bitmap)
{
- /* TODO: check that locks are held and the VM is suspended. */
dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
}