summaryrefslogtreecommitdiffstats
path: root/vm/alloc/Verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/alloc/Verify.c')
-rw-r--r--vm/alloc/Verify.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/vm/alloc/Verify.c b/vm/alloc/Verify.c
new file mode 100644
index 000000000..0d942ce61
--- /dev/null
+++ b/vm/alloc/Verify.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dalvik.h"
+#include "alloc/HeapSource.h"
+#include "alloc/Verify.h"
+
+/* comment everything, of course! */
+#define VERIFY_REFERENCE(x) do { \
+ if (!verifyReference((x), &(x))) { \
+ LOGE("Verify of %p at %p failed", (x), &(x)); \
+ dvmAbort(); \
+ } \
+ } while (0)
+
+/*
+ * Verifies that a reference points to an object header.
+ */
+static bool verifyReference(const void *obj, const void *addr)
+{
+ if (obj == NULL) {
+ return true;
+ }
+ return dvmIsValidObject(obj);
+}
+
+/*
+ * Verifies the header, static fields references, and interface
+ * pointers of a class object.
+ */
+static void verifyClassObject(const ClassObject *obj)
+{
+ int i;
+ char ch;
+
+ LOGV("Entering verifyClassObject(obj=%p)", obj);
+ if (obj == gDvm.unlinkedJavaLangClass) {
+ assert(obj->obj.clazz == NULL);
+ goto exit;
+ }
+ VERIFY_REFERENCE(obj->obj.clazz);
+ assert(!strcmp(obj->obj.clazz->descriptor, "Ljava/lang/Class;"));
+ if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) {
+ VERIFY_REFERENCE(obj->elementClass);
+ }
+ VERIFY_REFERENCE(obj->super);
+ VERIFY_REFERENCE(obj->classLoader);
+ /* Verify static field references. */
+ for (i = 0; i < obj->sfieldCount; ++i) {
+ ch = obj->sfields[i].field.signature[0];
+ if (ch == '[' || ch == 'L') {
+ VERIFY_REFERENCE(obj->sfields[i].value.l);
+ }
+ }
+ /* Verify interface references. */
+ for (i = 0; i < obj->interfaceCount; ++i) {
+ VERIFY_REFERENCE(obj->interfaces[i]);
+ }
+exit:
+ LOGV("Exiting verifyClassObject(obj=%p)", obj);
+}
+
+/*
+ * Verifies the header of all array objects. If the array object is
+ * specialized to a reference type, verifies the array data as well.
+ */
+static void verifyArrayObject(const ArrayObject *array)
+{
+ ClassObject *clazz;
+ Object **contents;
+ size_t i;
+
+ LOGV("Entering verifyArrayObject(obj=%p)", obj);
+ /* Verify the class object reference. */
+ assert(array->obj.clazz != NULL);
+ VERIFY_REFERENCE(array->obj.clazz);
+ if (IS_CLASS_FLAG_SET(array->obj.clazz, CLASS_ISOBJECTARRAY)) {
+ /* Verify the array contents. */
+ contents = (Object **) array->contents;
+ for (i = 0; i < array->length; ++i) {
+ VERIFY_REFERENCE(contents[i]);
+ }
+ }
+ LOGV("Exiting verifyArrayObject(obj=%p)", obj);
+}
+
+/*
+ * Verifies the header and field references of a data object.
+ */
+static void verifyDataObject(const DataObject *obj)
+{
+ ClassObject *clazz;
+ InstField *field;
+ void *addr;
+ size_t offset;
+ int i, count;
+
+ LOGV("Entering verifyDataObject(obj=%p)", obj);
+ /* Verify the class object. */
+ assert(obj->obj.clazz != NULL);
+ VERIFY_REFERENCE(obj->obj.clazz);
+ /* Verify the instance fields. */
+ for (clazz = obj->obj.clazz; clazz != NULL; clazz = clazz->super) {
+ field = clazz->ifields;
+ count = clazz->ifieldRefCount;
+ for (i = 0; i < count; ++i, ++field) {
+ addr = BYTE_OFFSET((Object *)obj, field->byteOffset);
+ VERIFY_REFERENCE(((JValue *)addr)->l);
+ }
+ }
+ LOGV("Exiting verifyDataObject(obj=%p) %zx", obj, length);
+}
+
+/*
+ * Verifies an object reference. Determines the type of the reference
+ * and dispatches to a specialized verification routine.
+ */
+void dvmVerifyObject(const Object *obj)
+{
+ ClassObject *clazz;
+
+ LOGV("Entering dvmVerifyObject(obj=%p)", obj);
+ assert(obj != NULL);
+ clazz = obj->clazz;
+ if (clazz == gDvm.classJavaLangClass ||
+ obj == (Object *)gDvm.unlinkedJavaLangClass) {
+ verifyClassObject((ClassObject *)obj);
+ } else {
+ assert(clazz != NULL);
+ if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
+ verifyArrayObject((ArrayObject *)obj);
+ } else {
+ verifyDataObject((DataObject *)obj);
+ }
+ }
+ LOGV("Exiting dvmVerifyObject(obj=%p)", obj);
+}
+
+/*
+ * Helper function to call dvmVerifyObject from a bitmap walker.
+ */
+static bool verifyBitmapCallback(size_t numPtrs, void **ptrs,
+ const void *finger, void *arg)
+{
+ size_t i;
+
+ for (i = 0; i < numPtrs; i++) {
+ dvmVerifyObject(*ptrs++);
+ }
+ return true;
+}
+
+/*
+ * Verifies the object references in a heap bitmap. Assumes the heap
+ * is locked.
+ */
+void dvmVerifyBitmapUnlocked(const HeapBitmap *bitmap)
+{
+ /* TODO: check that locks are held and the VM is suspended. */
+ dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
+}
+
+/*
+ * Verifies the object references in a heap bitmap. Suspends the VM
+ * for the duration of verification.
+ */
+void dvmVerifyBitmap(const HeapBitmap *bitmap)
+{
+ /* Suspend the VM. */
+ dvmSuspendAllThreads(SUSPEND_FOR_VERIFY);
+ dvmLockMutex(&gDvm.heapWorkerLock);
+ dvmAssertHeapWorkerThreadRunning();
+ dvmLockMutex(&gDvm.heapWorkerListLock);
+
+ dvmVerifyBitmapUnlocked(bitmap);
+
+ /* Resume the VM. */
+ dvmUnlockMutex(&gDvm.heapWorkerListLock);
+ dvmUnlockMutex(&gDvm.heapWorkerLock);
+ dvmResumeAllThreads(SUSPEND_FOR_VERIFY);
+}