11e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro/*
21e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * Copyright (C) 2010 The Android Open Source Project
31e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro *
41e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * Licensed under the Apache License, Version 2.0 (the "License");
51e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * you may not use this file except in compliance with the License.
61e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * You may obtain a copy of the License at
71e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro *
81e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro *      http://www.apache.org/licenses/LICENSE-2.0
91e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro *
101e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * Unless required by applicable law or agreed to in writing, software
111e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * distributed under the License is distributed on an "AS IS" BASIS,
121e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * See the License for the specific language governing permissions and
141e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * limitations under the License.
151e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro */
161e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro
171e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro#include "Dalvik.h"
18adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro#include "alloc/HeapBitmap.h"
19c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro#include "alloc/HeapSource.h"
201e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro#include "alloc/Verify.h"
21adc346f4145e409959ec1c657bbd8fecef6d2042Carl Shapiro#include "alloc/Visit.h"
221e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro
2397c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro/*
2497c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * Visitor applied to each reference field when searching for things
2597c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * that point to an object.  Sets the argument to NULL when a match is
2697c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * found.
2797c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro */
28c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapirostatic void dumpReferencesVisitor(void *pObj, void *arg)
29c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro{
30c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    Object *obj = *(Object **)pObj;
31c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    Object *lookingFor = *(Object **)arg;
32c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    if (lookingFor != NULL && lookingFor == obj) {
33c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        *(Object **)arg = NULL;
34c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    }
35c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro}
36c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro
3797c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro/*
3897c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * Visitor applied to each bitmap element to search for things that
3997c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * point to an object.  Logs a message when a match is found.
4097c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro */
410d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapirostatic void dumpReferencesCallback(Object *obj, void *arg)
42c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro{
430d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    if (obj == (Object *)arg) {
44c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        return;
45c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    }
460d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    dvmVisitObject(dumpReferencesVisitor, obj, &arg);
470d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    if (arg == NULL) {
48062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Found %p in the heap @ %p", arg, obj);
490d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro        dvmDumpObject(obj);
50c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    }
51c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro}
52c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro
5397c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro/*
5497c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * Visitor applied to each root to search for things that point to an
5597c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro * object.  Logs a message when a match is found.
5697c3dddbcf9b7426ef2f10e0903eeb4b5a884733Carl Shapiro */
5707018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void dumpReferencesRootVisitor(void *ptr, u4 threadId,
5807018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                                      RootType type, void *arg)
59c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro{
60c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    Object *obj = *(Object **)ptr;
61c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    Object *lookingFor = *(Object **)arg;
62c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    if (obj == lookingFor) {
63062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Found %p in a root @ %p", arg, ptr);
64c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    }
65c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro}
66c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro
67c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro/*
68c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro * Searches the roots and heap for object references.
69c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro */
70c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapirostatic void dumpReferences(const Object *obj)
71c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro{
72c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    HeapBitmap *bitmap = dvmHeapSourceGetLiveBits();
73c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    void *arg = (void *)obj;
74c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    dvmVisitRoots(dumpReferencesRootVisitor, arg);
75c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    dvmHeapBitmapWalk(bitmap, dumpReferencesCallback, arg);
76c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro}
77c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro
78c85ec00dd616da05191f08934f93b711aa6f20ddCarl Shapiro/*
791fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Checks that the given reference points to a valid object.
80c85ec00dd616da05191f08934f93b711aa6f20ddCarl Shapiro */
811fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapirostatic void verifyReference(void *addr, void *arg)
82f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro{
83c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    Object *obj;
84f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    bool isValid;
85f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro
861fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro    assert(addr != NULL);
87c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    obj = *(Object **)addr;
88f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    if (obj == NULL) {
89f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro        isValid = true;
90f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    } else {
91f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro        isValid = dvmIsValidObject(obj);
92f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    }
93f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    if (!isValid) {
94fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        Object **parent = (Object **)arg;
95c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        if (*parent != NULL) {
96c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Verify of object %p failed", *parent);
97c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro            dvmDumpObject(*parent);
98c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro            *parent = NULL;
99c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        }
100c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Verify of reference %p @ %p failed", obj, addr);
101c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        dvmDumpObject(obj);
102f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro    }
103f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro}
1041e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro
1051e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro/*
1061fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Verifies an object reference.
1071e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro */
1081e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapirovoid dvmVerifyObject(const Object *obj)
1091e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro{
1100d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    Object *arg = const_cast<Object*>(obj);
1110d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    dvmVisitObject(verifyReference, arg, &arg);
112c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    if (arg == NULL) {
113c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        dumpReferences(obj);
114c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro        dvmAbort();
115c44bca6530787454ee794cf2f83c1c6671a93aa8Carl Shapiro    }
1161e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro}
1171e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro
1181e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro/*
1191e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro * Helper function to call dvmVerifyObject from a bitmap walker.
1201e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro */
1210d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapirostatic void verifyBitmapCallback(Object *obj, void *arg)
1221e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro{
1230d92a4072c00434e95a03642a4944acf81a81cc3Carl Shapiro    dvmVerifyObject(obj);
1241e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro}
1251e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro
1261e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro/*
127962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * Verifies the object references in a heap bitmap. Assumes the VM is
128962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayes * suspended.
1291e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro */
130962adba4e5db286a36bc8024f5c023bcf6f29312Barry Hayesvoid dvmVerifyBitmap(const HeapBitmap *bitmap)
1311e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro{
1321e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro    dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
1331e714bbd8230ac6fb9e3a8e9e25bca687132c82aCarl Shapiro}
134f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro
135f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro/*
13607018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro * Helper function to call verifyReference from the root verifier.
13707018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro */
13807018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapirostatic void verifyRootReference(void *addr, u4 threadId,
13907018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro                                RootType type, void *arg)
14007018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro{
14107018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    verifyReference(addr, arg);
14207018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro}
14307018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro
14407018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro/*
1451fbfcab90fb4f03fa9053ce2cd567f84904fefefCarl Shapiro * Verifies references in the roots.
146f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro */
1471e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmVerifyRoots()
148f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro{
14907018e2d14b012ae433a0d82025a885ed8debc3bCarl Shapiro    dvmVisitRoots(verifyRootReference, NULL);
150f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro}
151