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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 147 void dvmVerifyRoots() 148 { 149 dvmVisitRoots(verifyRootReference, NULL); 150 } 151