blob: 212b6ea531b32e0a28ba0dff489358832435d391 [file] [log] [blame]
Carl Shapiro1e714bb2010-03-16 03:26:49 -07001/*
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/HeapSource.h"
19#include "alloc/Verify.h"
Barry Hayes962adba2010-03-17 12:12:39 -070020#include "alloc/HeapBitmap.h"
Carl Shapiro1e714bb2010-03-16 03:26:49 -070021
Carl Shapiroc85ec002010-04-05 19:36:37 -070022/*
Carl Shapirof5718252010-05-11 20:55:13 -070023 * Helper routine for verifyRefernce that masks low-tag bits before
24 * applying verification checks. TODO: eliminate the use of low-tag
25 * bits and move this code into verfiyReference.
Carl Shapiroc85ec002010-04-05 19:36:37 -070026 */
Carl Shapirof5718252010-05-11 20:55:13 -070027static void verifyReferenceUnmask(const void *addr, uintptr_t mask)
28{
29 const Object *obj;
30 uintptr_t tmp;
31 bool isValid;
32
33 tmp = (uintptr_t)*(const Object **)addr;
34 obj = (const Object *)(tmp & ~mask);
35 if (obj == NULL) {
36 isValid = true;
37 } else {
38 isValid = dvmIsValidObject(obj);
39 }
40 if (!isValid) {
41 LOGE("Verify of object %p @ %p failed", obj, addr);
42 dvmAbort();
43 }
44}
Carl Shapiro1e714bb2010-03-16 03:26:49 -070045
46/*
Carl Shapirof5718252010-05-11 20:55:13 -070047 * Assertion that the given reference points to a valid object.
Carl Shapiro1e714bb2010-03-16 03:26:49 -070048 */
Carl Shapirof5718252010-05-11 20:55:13 -070049static void verifyReference(const void *addr)
Carl Shapiro1e714bb2010-03-16 03:26:49 -070050{
Carl Shapirof5718252010-05-11 20:55:13 -070051 verifyReferenceUnmask(addr, 0);
Carl Shapiro1e714bb2010-03-16 03:26:49 -070052}
53
54/*
Carl Shapirod28668c2010-04-15 16:10:00 -070055 * Verifies instance fields.
56 */
57static void verifyInstanceFields(const Object *obj)
58{
59 ClassObject *clazz;
60 int i;
61
62 assert(obj != NULL);
63 assert(obj->clazz != NULL);
Carl Shapiro68733662010-05-10 19:55:50 -070064 LOGV("Entering verifyInstanceFields(obj=%p)", obj);
Carl Shapirod28668c2010-04-15 16:10:00 -070065 /* TODO(cshapiro): check reference offsets bitmap for agreement. */
66 for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
67 InstField *field = clazz->ifields;
68 for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
69 void *addr = BYTE_OFFSET((Object *)obj, field->byteOffset);
Carl Shapirof5718252010-05-11 20:55:13 -070070 verifyReference(&((JValue *)addr)->l);
Carl Shapirod28668c2010-04-15 16:10:00 -070071 }
72 }
Carl Shapiro68733662010-05-10 19:55:50 -070073 LOGV("Exiting verifyInstanceFields(obj=%p)", obj);
Carl Shapirod28668c2010-04-15 16:10:00 -070074}
75
76/*
77 * Verifies the header, static field references, and interface
Carl Shapiro1e714bb2010-03-16 03:26:49 -070078 * pointers of a class object.
79 */
80static void verifyClassObject(const ClassObject *obj)
81{
82 int i;
Carl Shapiro1e714bb2010-03-16 03:26:49 -070083
84 LOGV("Entering verifyClassObject(obj=%p)", obj);
85 if (obj == gDvm.unlinkedJavaLangClass) {
86 assert(obj->obj.clazz == NULL);
87 goto exit;
88 }
Carl Shapirof5718252010-05-11 20:55:13 -070089 verifyReference(&obj->obj.clazz);
Carl Shapiro1e714bb2010-03-16 03:26:49 -070090 assert(!strcmp(obj->obj.clazz->descriptor, "Ljava/lang/Class;"));
91 if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) {
Carl Shapirof5718252010-05-11 20:55:13 -070092 verifyReference(&obj->elementClass);
Carl Shapiro1e714bb2010-03-16 03:26:49 -070093 }
Carl Shapirof5718252010-05-11 20:55:13 -070094 verifyReference(&obj->super);
95 verifyReference(&obj->classLoader);
Carl Shapiro1e714bb2010-03-16 03:26:49 -070096 /* Verify static field references. */
97 for (i = 0; i < obj->sfieldCount; ++i) {
Carl Shapirod28668c2010-04-15 16:10:00 -070098 char ch = obj->sfields[i].field.signature[0];
Carl Shapiro1e714bb2010-03-16 03:26:49 -070099 if (ch == '[' || ch == 'L') {
Carl Shapirof5718252010-05-11 20:55:13 -0700100 verifyReference(&obj->sfields[i].value.l);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700101 }
102 }
Carl Shapirod28668c2010-04-15 16:10:00 -0700103 /* Verify the instance fields. */
104 verifyInstanceFields((const Object *)obj);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700105 /* Verify interface references. */
106 for (i = 0; i < obj->interfaceCount; ++i) {
Carl Shapirof5718252010-05-11 20:55:13 -0700107 verifyReference(&obj->interfaces[i]);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700108 }
109exit:
110 LOGV("Exiting verifyClassObject(obj=%p)", obj);
111}
112
113/*
114 * Verifies the header of all array objects. If the array object is
115 * specialized to a reference type, verifies the array data as well.
116 */
117static void verifyArrayObject(const ArrayObject *array)
118{
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700119 size_t i;
120
Carl Shapiro68733662010-05-10 19:55:50 -0700121 LOGV("Entering verifyArrayObject(array=%p)", array);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700122 /* Verify the class object reference. */
123 assert(array->obj.clazz != NULL);
Carl Shapirof5718252010-05-11 20:55:13 -0700124 verifyReference(&array->obj.clazz);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700125 if (IS_CLASS_FLAG_SET(array->obj.clazz, CLASS_ISOBJECTARRAY)) {
126 /* Verify the array contents. */
Carl Shapirod28668c2010-04-15 16:10:00 -0700127 Object **contents = (Object **)array->contents;
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700128 for (i = 0; i < array->length; ++i) {
Carl Shapirof5718252010-05-11 20:55:13 -0700129 verifyReference(&contents[i]);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700130 }
131 }
Carl Shapiro68733662010-05-10 19:55:50 -0700132 LOGV("Exiting verifyArrayObject(array=%p)", array);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700133}
134
135/*
136 * Verifies the header and field references of a data object.
137 */
138static void verifyDataObject(const DataObject *obj)
139{
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700140 LOGV("Entering verifyDataObject(obj=%p)", obj);
141 /* Verify the class object. */
142 assert(obj->obj.clazz != NULL);
Carl Shapirof5718252010-05-11 20:55:13 -0700143 verifyReference(&obj->obj.clazz);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700144 /* Verify the instance fields. */
Carl Shapirod28668c2010-04-15 16:10:00 -0700145 verifyInstanceFields((const Object *)obj);
Barry Hayes49576ae2010-03-19 10:10:59 -0700146 if (IS_CLASS_FLAG_SET(obj->obj.clazz, CLASS_ISREFERENCE)) {
Carl Shapiroc85ec002010-04-05 19:36:37 -0700147 /* Verify the hidden Reference.referent field. */
Carl Shapirod28668c2010-04-15 16:10:00 -0700148 size_t offset = gDvm.offJavaLangRefReference_referent;
149 void *addr = BYTE_OFFSET((Object *)obj, offset);
Carl Shapirof5718252010-05-11 20:55:13 -0700150 verifyReference(&((JValue *)addr)->l);
Barry Hayes49576ae2010-03-19 10:10:59 -0700151 }
Carl Shapiro68733662010-05-10 19:55:50 -0700152 LOGV("Exiting verifyDataObject(obj=%p)", obj);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700153}
154
155/*
156 * Verifies an object reference. Determines the type of the reference
157 * and dispatches to a specialized verification routine.
158 */
159void dvmVerifyObject(const Object *obj)
160{
161 ClassObject *clazz;
162
163 LOGV("Entering dvmVerifyObject(obj=%p)", obj);
164 assert(obj != NULL);
Carl Shapirod28668c2010-04-15 16:10:00 -0700165 /* Check that the object is aligned. */
166 assert(((uintptr_t)obj & 7) == 0);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700167 clazz = obj->clazz;
Carl Shapirod28668c2010-04-15 16:10:00 -0700168 /* Check that the class object is aligned. */
169 assert(((uintptr_t)clazz & 7) == 0);
170 /* Dispatch a type-specific verification routine. */
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700171 if (clazz == gDvm.classJavaLangClass ||
172 obj == (Object *)gDvm.unlinkedJavaLangClass) {
173 verifyClassObject((ClassObject *)obj);
174 } else {
175 assert(clazz != NULL);
176 if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) {
177 verifyArrayObject((ArrayObject *)obj);
178 } else {
179 verifyDataObject((DataObject *)obj);
180 }
181 }
182 LOGV("Exiting dvmVerifyObject(obj=%p)", obj);
183}
184
185/*
186 * Helper function to call dvmVerifyObject from a bitmap walker.
187 */
188static bool verifyBitmapCallback(size_t numPtrs, void **ptrs,
189 const void *finger, void *arg)
190{
191 size_t i;
192
193 for (i = 0; i < numPtrs; i++) {
194 dvmVerifyObject(*ptrs++);
195 }
196 return true;
197}
198
199/*
Barry Hayes962adba2010-03-17 12:12:39 -0700200 * Verifies the object references in a heap bitmap. Assumes the VM is
201 * suspended.
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700202 */
203void dvmVerifyBitmap(const HeapBitmap *bitmap)
204{
Barry Hayes962adba2010-03-17 12:12:39 -0700205 /* TODO: check that locks are held and the VM is suspended. */
206 dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
Carl Shapiro1e714bb2010-03-16 03:26:49 -0700207}
Carl Shapirof5718252010-05-11 20:55:13 -0700208
209/*
210 * Applies a verification function to all present values in the hash table.
211 */
212static void verifyHashTable(HashTable *table,
213 void (*callback)(const void *arg))
214{
215 int i;
216
217 assert(table != NULL);
218 assert(callback != NULL);
219 dvmHashTableLock(table);
220 for (i = 0; i < table->tableSize; ++i) {
221 const HashEntry *entry = &table->pEntries[i];
222 if (entry->data != NULL && entry->data != HASH_TOMBSTONE) {
223 (*callback)(&entry->data);
224 }
225 }
226 dvmHashTableUnlock(table);
227}
228
229/*
230 * Applies the verify routine to the given object.
231 */
232static void verifyStringReference(const void *arg)
233{
234 assert(arg != NULL);
235 verifyReferenceUnmask(arg, 0x1);
236}
237
238/*
239 * Verifies all entries in the reference table.
240 */
241static void verifyReferenceTable(const ReferenceTable *table)
242{
243 Object **entry;
244
245 assert(table != NULL);
246 for (entry = table->table; entry < table->nextEntry; ++entry) {
247 assert(entry != NULL);
248 verifyReference(entry);
249 }
250}
251
252/*
Carl Shapiroc92fd7c2010-05-20 15:43:30 -0700253 * Applies the verify routine to a heap worker reference operation.
254 */
255static void verifyReferenceOperation(const void *arg)
256{
257 assert(arg != NULL);
258 verifyReferenceUnmask(arg, 0x3);
259}
260
261/*
262 * Verifies a large heap reference table. These objects are list
263 * heads. As such, it is valid for table to be NULL.
264 */
265static void verifyLargeHeapRefTable(LargeHeapRefTable *table,
266 void (*callback)(const void *arg))
267{
268 Object **ref;
269
270 assert(callback != NULL);
271 for (; table != NULL; table = table->next) {
272 for (ref = table->refs.table; ref < table->refs.nextEntry; ++ref) {
273 assert(ref != NULL);
274 (*callback)(ref);
275 }
276 }
277}
278
279/*
280 * Verifies all stack slots. TODO: verify native methods.
281 */
282static void verifyThreadStack(const Thread *thread)
283{
284 const StackSaveArea *saveArea;
285 const u4 *framePtr;
286
287 assert(thread != NULL);
288 framePtr = (const u4 *)thread->curFrame;
289 for (; framePtr != NULL; framePtr = saveArea->prevFrame) {
290 Method *method;
291 saveArea = SAVEAREA_FROM_FP(framePtr);
292 method = (Method *)saveArea->method;
293 if (method != NULL && !dvmIsNativeMethod(method)) {
294 const RegisterMap* pMap = dvmGetExpandedRegisterMap(method);
295 const u1* regVector = NULL;
296 int i;
297
298 if (pMap != NULL) {
299 /* found map, get registers for this address */
300 int addr = saveArea->xtra.currentPc - method->insns;
301 regVector = dvmRegisterMapGetLine(pMap, addr);
302 }
303 if (regVector == NULL) {
304 /*
305 * Either there was no register map or there is no
306 * info for the current PC. Perform a conservative
307 * scan.
308 */
309 for (i = 0; i < method->registersSize; ++i) {
310 if (dvmIsValidObject((Object *)framePtr[i])) {
311 verifyReference(&framePtr[i]);
312 }
313 }
314 } else {
315 /*
316 * Precise scan. v0 is at the lowest address on the
317 * interpreted stack, and is the first bit in the
318 * register vector, so we can walk through the
319 * register map and memory in the same direction.
320 *
321 * A '1' bit indicates a live reference.
322 */
323 u2 bits = 1 << 1;
324 for (i = 0; i < method->registersSize; ++i) {
325 bits >>= 1;
326 if (bits == 1) {
327 /* set bit 9 so we can tell when we're empty */
328 bits = *regVector++ | 0x0100;
329 }
330 if ((bits & 0x1) != 0) {
331 /*
332 * Register is marked as live, it's a valid root.
333 */
334 verifyReference(&framePtr[i]);
335 }
336 }
337 dvmReleaseRegisterMapLine(pMap, regVector);
338 }
339 }
340 /*
341 * Don't fall into an infinite loop if things get corrupted.
342 */
343 assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr ||
344 saveArea->prevFrame == NULL);
345 }
346}
347
348/*
349 * Verifies all roots associated with a thread.
350 */
351static void verifyThread(const Thread *thread)
352{
353 assert(thread != NULL);
354 assert(thread->status != THREAD_RUNNING ||
355 thread->isSuspended ||
356 thread == dvmThreadSelf());
357 LOGV("Entering verifyThread(thread=%p)", thread);
358 verifyReference(&thread->threadObj);
359 verifyReference(&thread->exception);
360 verifyReferenceTable(&thread->internalLocalRefTable);
361 verifyReferenceTable(&thread->jniLocalRefTable);
362 if (thread->jniMonitorRefTable.table) {
363 verifyReferenceTable(&thread->jniMonitorRefTable);
364 }
365 verifyThreadStack(thread);
366 LOGV("Exiting verifyThread(thread=%p)", thread);
367}
368
369/*
370 * Verifies all threads on the thread list.
371 */
372static void verifyThreads(void)
373{
374 Thread *thread;
375
376 dvmLockThreadList(dvmThreadSelf());
377 thread = gDvm.threadList;
378 while (thread) {
379 verifyThread(thread);
380 thread = thread->next;
381 }
382 dvmUnlockThreadList();
383}
384
385/*
Carl Shapirof5718252010-05-11 20:55:13 -0700386 * Verifies roots. TODO: verify all roots.
387 */
388void dvmVerifyRoots(void)
389{
390 verifyHashTable(gDvm.loadedClasses, verifyReference);
391 verifyHashTable(gDvm.dbgRegistry, verifyReference);
392 verifyHashTable(gDvm.internedStrings, verifyStringReference);
393 verifyReferenceTable(&gDvm.jniGlobalRefTable);
394 verifyReferenceTable(&gDvm.jniPinRefTable);
395 verifyReferenceTable(&gDvm.gcHeap->nonCollectableRefs);
Carl Shapiroc92fd7c2010-05-20 15:43:30 -0700396 verifyLargeHeapRefTable(gDvm.gcHeap->referenceOperations,
397 verifyReferenceOperation);
398 verifyLargeHeapRefTable(gDvm.gcHeap->pendingFinalizationRefs,
399 verifyReference);
400 verifyThreads();
Carl Shapirof5718252010-05-11 20:55:13 -0700401 /* TODO: verify cached global references. */
Carl Shapirof5718252010-05-11 20:55:13 -0700402}