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
23 /*
24 * Visitor applied to each reference field when searching for things
25 * that point to an object. Sets the argument to NULL when a match is
26 * found.
27 */
dumpReferencesVisitor(void * pObj,void * arg)28 static void dumpReferencesVisitor(void *pObj, void *arg)
29 {
30 Object *obj = *(Object **)pObj;
31 Object *lookingFor = *(Object **)arg;
32 if (lookingFor != NULL && lookingFor == obj) {
33 *(Object **)arg = NULL;
34 }
35 }
36
37 /*
38 * Visitor applied to each bitmap element to search for things that
39 * point to an object. Logs a message when a match is found.
40 */
dumpReferencesCallback(Object * obj,void * arg)41 static void dumpReferencesCallback(Object *obj, void *arg)
42 {
43 if (obj == (Object *)arg) {
44 return;
45 }
46 dvmVisitObject(dumpReferencesVisitor, obj, &arg);
47 if (arg == NULL) {
48 ALOGD("Found %p in the heap @ %p", arg, obj);
49 dvmDumpObject(obj);
50 }
51 }
52
53 /*
54 * Visitor applied to each root to search for things that point to an
55 * object. Logs a message when a match is found.
56 */
dumpReferencesRootVisitor(void * ptr,u4 threadId,RootType type,void * arg)57 static void dumpReferencesRootVisitor(void *ptr, u4 threadId,
58 RootType type, void *arg)
59 {
60 Object *obj = *(Object **)ptr;
61 Object *lookingFor = *(Object **)arg;
62 if (obj == lookingFor) {
63 ALOGD("Found %p in a root @ %p", arg, ptr);
64 }
65 }
66
67 /*
68 * Searches the roots and heap for object references.
69 */
dumpReferences(const Object * obj)70 static void dumpReferences(const Object *obj)
71 {
72 HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
73 void *arg = (void *)obj;
74 dvmVisitRoots(dumpReferencesRootVisitor, arg);
75 dvmHeapBitmapWalk(bitmap, dumpReferencesCallback, arg);
76 }
77
78 /*
79 * Checks that the given reference points to a valid object.
80 */
verifyReference(void * addr,void * arg)81 static void verifyReference(void *addr, void *arg)
82 {
83 Object *obj;
84 bool isValid;
85
86 assert(addr != NULL);
87 obj = *(Object **)addr;
88 if (obj == NULL) {
89 isValid = true;
90 } else {
91 isValid = dvmIsValidObject(obj);
92 }
93 if (!isValid) {
94 Object **parent = (Object **)arg;
95 if (*parent != NULL) {
96 ALOGE("Verify of object %p failed", *parent);
97 dvmDumpObject(*parent);
98 *parent = NULL;
99 }
100 ALOGE("Verify of reference %p @ %p failed", obj, addr);
101 dvmDumpObject(obj);
102 }
103 }
104
105 /*
106 * Verifies an object reference.
107 */
dvmVerifyObject(const Object * obj)108 void dvmVerifyObject(const Object *obj)
109 {
110 Object *arg = const_cast<Object*>(obj);
111 dvmVisitObject(verifyReference, arg, &arg);
112 if (arg == NULL) {
113 dumpReferences(obj);
114 dvmAbort();
115 }
116 }
117
118 /*
119 * Helper function to call dvmVerifyObject from a bitmap walker.
120 */
verifyBitmapCallback(Object * obj,void * arg)121 static void verifyBitmapCallback(Object *obj, void *arg)
122 {
123 dvmVerifyObject(obj);
124 }
125
126 /*
127 * Verifies the object references in a heap bitmap. Assumes the VM is
128 * suspended.
129 */
dvmVerifyBitmap(const HeapBitmap * bitmap)130 void dvmVerifyBitmap(const HeapBitmap *bitmap)
131 {
132 dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
133 }
134
135 /*
136 * Helper function to call verifyReference from the root verifier.
137 */
verifyRootReference(void * addr,u4 threadId,RootType type,void * arg)138 static void verifyRootReference(void *addr, u4 threadId,
139 RootType type, void *arg)
140 {
141 verifyReference(addr, arg);
142 }
143
144 /*
145 * Verifies references in the roots.
146 */
dvmVerifyRoots()147 void dvmVerifyRoots()
148 {
149 dvmVisitRoots(verifyRootReference, NULL);
150 }
151