1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Dalvik.h"
18 #include "alloc/HeapBitmap.h"
19 #include "alloc/HeapSource.h"
20 #include "alloc/Verify.h"
21 #include "alloc/Visit.h"
22
dumpReferencesVisitor(void * pObj,void * arg)23 static void dumpReferencesVisitor(void *pObj, void *arg)
24 {
25 Object *obj = *(Object **)pObj;
26 Object *lookingFor = *(Object **)arg;
27 if (lookingFor != NULL && lookingFor == obj) {
28 *(Object **)arg = NULL;
29 }
30 }
31
dumpReferencesCallback(void * ptr,void * arg)32 static void dumpReferencesCallback(void *ptr, void *arg)
33 {
34 Object *obj = arg;
35 if (ptr == obj) {
36 LOGD("skipping %p == %p", ptr, obj);
37 return;
38 }
39 dvmVisitObject(dumpReferencesVisitor, ptr, &obj);
40 if (obj == NULL) {
41 LOGD("Found %p in the heap @ %p", arg, ptr);
42 dvmDumpObject(ptr);
43 }
44 }
45
dumpReferencesRootVisitor(void * ptr,void * arg)46 static void dumpReferencesRootVisitor(void *ptr, void *arg)
47 {
48 Object *obj = *(Object **)ptr;
49 Object *lookingFor = *(Object **)arg;
50 if (obj == lookingFor) {
51 LOGD("Found %p in a root @ %p", arg, ptr);
52 }
53 }
54
55 /*
56 * Searches the roots and heap for object references.
57 */
dumpReferences(const Object * obj)58 static void dumpReferences(const Object *obj)
59 {
60 HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
61 void *arg = (void *)obj;
62 dvmVisitRoots(dumpReferencesRootVisitor, arg);
63 dvmHeapBitmapWalk(bitmap, dumpReferencesCallback, arg);
64 }
65
66 /*
67 * Checks that the given reference points to a valid object.
68 */
verifyReference(void * addr,void * arg)69 static void verifyReference(void *addr, void *arg)
70 {
71 Object *obj;
72 bool isValid;
73
74 assert(addr != NULL);
75 obj = *(Object **)addr;
76 if (obj == NULL) {
77 isValid = true;
78 } else {
79 isValid = dvmIsValidObject(obj);
80 }
81 if (!isValid) {
82 Object **parent = arg;
83 if (*parent != NULL) {
84 LOGE("Verify of object %p failed", *parent);
85 dvmDumpObject(*parent);
86 *parent = NULL;
87 }
88 LOGE("Verify of reference %p @ %p failed", obj, addr);
89 dvmDumpObject(obj);
90 }
91 }
92
93 /*
94 * Verifies an object reference.
95 */
dvmVerifyObject(const Object * obj)96 void dvmVerifyObject(const Object *obj)
97 {
98 Object *arg = (Object *)obj;
99 dvmVisitObject(verifyReference, (Object *)obj, &arg);
100 if (arg == NULL) {
101 dumpReferences(obj);
102 dvmAbort();
103 }
104 }
105
106 /*
107 * Helper function to call dvmVerifyObject from a bitmap walker.
108 */
verifyBitmapCallback(void * ptr,void * arg)109 static void verifyBitmapCallback(void *ptr, void *arg)
110 {
111 dvmVerifyObject(ptr);
112 }
113
114 /*
115 * Verifies the object references in a heap bitmap. Assumes the VM is
116 * suspended.
117 */
dvmVerifyBitmap(const HeapBitmap * bitmap)118 void dvmVerifyBitmap(const HeapBitmap *bitmap)
119 {
120 dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
121 }
122
123 /*
124 * Verifies references in the roots.
125 */
dvmVerifyRoots(void)126 void dvmVerifyRoots(void)
127 {
128 dvmVisitRoots(verifyReference, NULL);
129 }
130