/*
 * 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/HeapBitmap.h"
#include "alloc/HeapSource.h"
#include "alloc/Verify.h"
#include "alloc/Visit.h"

/*
 * Helper routine for verifyRefernce that masks low-tag bits before
 * applying verification checks.  TODO: eliminate the use of low-tag
 * bits and move this code into verifyReference.
 */
static void verifyReferenceUnmask(const void *addr, uintptr_t mask)
{
    const Object *obj;
    uintptr_t tmp;
    bool isValid;

    tmp = (uintptr_t)*(const Object **)addr;
    obj = (const Object *)(tmp & ~mask);
    if (obj == NULL) {
        isValid = true;
    } else {
        isValid = dvmIsValidObject(obj);
    }
    if (!isValid) {
        LOGE("Verify of object %p @ %p failed", obj, addr);
        dvmAbort();
    }
}

/*
 * Assertion that the given reference points to a valid object.
 */
static void verifyReference(const void *addr)
{
    verifyReferenceUnmask(addr, 0);
}

static void visitorCallback(void *addr, void *arg)
{
    verifyReference(addr);
}

/*
 * Verifies an object reference.  Determines the type of the reference
 * and dispatches to a specialized verification routine.
 */
void dvmVerifyObject(const Object *obj)
{
    dvmVisitObject(visitorCallback, (Object *)obj, NULL);
}

/*
 * 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 VM is
 * suspended.
 */
void dvmVerifyBitmap(const HeapBitmap *bitmap)
{
    /* TODO: check that locks are held and the VM is suspended. */
    dvmHeapBitmapWalk(bitmap, verifyBitmapCallback, NULL);
}

/*
 * Applies a verification function to all present values in the hash table.
 */
static void verifyHashTable(HashTable *table,
                            void (*callback)(const void *arg))
{
    int i;

    assert(table != NULL);
    assert(callback != NULL);
    dvmHashTableLock(table);
    for (i = 0; i < table->tableSize; ++i) {
        const HashEntry *entry = &table->pEntries[i];
        if (entry->data != NULL && entry->data != HASH_TOMBSTONE) {
            (*callback)(&entry->data);
        }
    }
    dvmHashTableUnlock(table);
}

/*
 * Applies the verify routine to the given object.
 */
static void verifyStringReference(const void *arg)
{
    assert(arg != NULL);
    verifyReferenceUnmask(arg, 0x1);
}

/*
 * Verifies all entries in the reference table.
 */
static void verifyReferenceTable(const ReferenceTable *table)
{
    Object **entry;

    assert(table != NULL);
    for (entry = table->table; entry < table->nextEntry; ++entry) {
        assert(entry != NULL);
        verifyReference(entry);
    }
}

/*
 * Verifies a large heap reference table.  These objects are list
 * heads.  As such, it is valid for table to be NULL.
 */
static void verifyLargeHeapRefTable(const LargeHeapRefTable *table)
{
    for (; table != NULL; table = table->next) {
        verifyReferenceTable(&table->refs);
    }
}

/*
 * Verifies all stack slots. TODO: verify native methods.
 */
static void verifyThreadStack(const Thread *thread)
{
    const StackSaveArea *saveArea;
    const u4 *framePtr;

    assert(thread != NULL);
    framePtr = (const u4 *)thread->curFrame;
    for (; framePtr != NULL; framePtr = saveArea->prevFrame) {
        Method *method;
        saveArea = SAVEAREA_FROM_FP(framePtr);
        method = (Method *)saveArea->method;
        if (method != NULL && !dvmIsNativeMethod(method)) {
            const RegisterMap* pMap = dvmGetExpandedRegisterMap(method);
            const u1* regVector = NULL;
            int i;

            if (pMap != NULL) {
                /* found map, get registers for this address */
                int addr = saveArea->xtra.currentPc - method->insns;
                regVector = dvmRegisterMapGetLine(pMap, addr);
            }
            if (regVector == NULL) {
                /*
                 * Either there was no register map or there is no
                 * info for the current PC.  Perform a conservative
                 * scan.
                 */
                for (i = 0; i < method->registersSize; ++i) {
                    if (dvmIsValidObject((Object *)framePtr[i])) {
                        verifyReference(&framePtr[i]);
                    }
                }
            } else {
                /*
                 * Precise scan.  v0 is at the lowest address on the
                 * interpreted stack, and is the first bit in the
                 * register vector, so we can walk through the
                 * register map and memory in the same direction.
                 *
                 * A '1' bit indicates a live reference.
                 */
                u2 bits = 1 << 1;
                for (i = 0; i < method->registersSize; ++i) {
                    bits >>= 1;
                    if (bits == 1) {
                        /* set bit 9 so we can tell when we're empty */
                        bits = *regVector++ | 0x0100;
                    }
                    if ((bits & 0x1) != 0) {
                        /*
                         * Register is marked as live, it's a valid root.
                         */
                        verifyReference(&framePtr[i]);
                    }
                }
                dvmReleaseRegisterMapLine(pMap, regVector);
            }
        }
        /*
         * Don't fall into an infinite loop if things get corrupted.
         */
        assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr ||
               saveArea->prevFrame == NULL);
    }
}

/*
 * Verifies all roots associated with a thread.
 */
static void verifyThread(const Thread *thread)
{
    assert(thread != NULL);
    assert(thread->status != THREAD_RUNNING ||
           thread->isSuspended ||
           thread == dvmThreadSelf());
    LOGV("Entering verifyThread(thread=%p)", thread);
    verifyReference(&thread->threadObj);
    verifyReference(&thread->exception);
    verifyReferenceTable(&thread->internalLocalRefTable);
    verifyReferenceTable(&thread->jniLocalRefTable);
    if (thread->jniMonitorRefTable.table) {
        verifyReferenceTable(&thread->jniMonitorRefTable);
    }
    verifyThreadStack(thread);
    LOGV("Exiting verifyThread(thread=%p)", thread);
}

/*
 * Verifies all threads on the thread list.
 */
static void verifyThreads(void)
{
    Thread *thread;

    dvmLockThreadList(dvmThreadSelf());
    thread = gDvm.threadList;
    while (thread) {
        verifyThread(thread);
        thread = thread->next;
    }
    dvmUnlockThreadList();
}

/*
 * Verifies roots.  TODO: verify all roots.
 */
void dvmVerifyRoots(void)
{
    verifyHashTable(gDvm.loadedClasses, verifyReference);
    verifyHashTable(gDvm.dbgRegistry, verifyReference);
    verifyHashTable(gDvm.internedStrings, verifyStringReference);
    verifyReferenceTable(&gDvm.jniGlobalRefTable);
    verifyReferenceTable(&gDvm.jniPinRefTable);
    verifyLargeHeapRefTable(gDvm.gcHeap->referenceOperations);
    verifyLargeHeapRefTable(gDvm.gcHeap->pendingFinalizationRefs);
    verifyThreads();
    /* TODO: verify cached global references. */
}
