Esempio n. 1
0
/*
 * Try to load all classes in the specified DEX.  If they have some sort
 * of broken dependency, e.g. their superclass lives in a different DEX
 * that wasn't previously loaded into the bootstrap class path, loading
 * will fail.  This is the desired behavior.
 *
 * We have no notion of class loader at this point, so we load all of
 * the classes with the bootstrap class loader.  It turns out this has
 * exactly the behavior we want, and has no ill side effects because we're
 * running in a separate process and anything we load here will be forgotten.
 *
 * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions.
 * This works because we only call here as part of optimization / pre-verify,
 * not during verification as part of loading a class into a running VM.
 *
 * This returns "false" if the world is too screwed up to do anything
 * useful at all.
 */
static bool loadAllClasses(DvmDex* pDvmDex)
{
    u4 count = pDvmDex->pDexFile->pHeader->classDefsSize;
    u4 idx;
    int loaded = 0;

    LOGV("DexOpt: +++ trying to load %d classes\n", count);

    dvmSetBootPathExtraDex(pDvmDex);

    /*
     * We have some circularity issues with Class and Object that are most
     * easily avoided by ensuring that Object is never the first thing we
     * try to find.  Take care of that here.  (We only need to do this when
     * loading classes from the DEX file that contains Object, and only
     * when Object comes first in the list, but it costs very little to
     * do it in all cases.)
     */
    if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) {
        LOGE("ERROR: java.lang.Class does not exist!\n");
        return false;
    }

    for (idx = 0; idx < count; idx++) {
        const DexClassDef* pClassDef;
        const char* classDescriptor;
        ClassObject* newClass;

        pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx);
        classDescriptor =
            dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx);

        LOGV("+++  loading '%s'", classDescriptor);
        //newClass = dvmDefineClass(pDexFile, classDescriptor,
        //        NULL);
        newClass = dvmFindSystemClassNoInit(classDescriptor);
        if (newClass == NULL) {
            LOGV("DexOpt: failed loading '%s'\n", classDescriptor);
            dvmClearOptException(dvmThreadSelf());
        } else if (newClass->pDvmDex != pDvmDex) {
            /*
             * We don't load the new one, and we tag the first one found
             * with the "multiple def" flag so the resolver doesn't try
             * to make it available.
             */
            LOGD("DexOpt: '%s' has an earlier definition; blocking out\n",
                classDescriptor);
            SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS);
        } else {
            loaded++;
        }
    }
    LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded);

    dvmSetBootPathExtraDex(NULL);
    return true;
}
Esempio n. 2
0
static bool initDirectMethodReference(Method** pMethod, const char* className,
        const char* name, const char* descriptor) {
    ClassObject* clazz = dvmFindSystemClassNoInit(className);

    if (clazz == NULL) {
        ALOGE("Could not find essential class %s for direct method lookup", className);
        return false;
    }

    return initDirectMethodReferenceByClass(pMethod, clazz, name, descriptor);
}
Esempio n. 3
0
/*
 * Perform Proxy setup.
 */
bool dvmReflectProxyStartup()
{
    /*
     * Standard methods we must provide in our proxy.
     */
    Method* methE;
    Method* methH;
    Method* methT;
    Method* methF;
    methE = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "equals",
            "(Ljava/lang/Object;)Z");
    methH = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "hashCode",
            "()I");
    methT = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "toString",
            "()Ljava/lang/String;");
    methF = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangObject, "finalize",
            "()V");
    if (methE == NULL || methH == NULL || methT == NULL || methF == NULL) {
        LOGE("Could not find equals/hashCode/toString/finalize in Object\n");
        return false;
    }
    gDvm.voffJavaLangObject_equals = methE->methodIndex;
    gDvm.voffJavaLangObject_hashCode = methH->methodIndex;
    gDvm.voffJavaLangObject_toString = methT->methodIndex;
    gDvm.voffJavaLangObject_finalize = methF->methodIndex;

    /*
     * The prototype signature needs to be cloned from a method in a
     * "real" DEX file.  We declared this otherwise unused method just
     * for this purpose.
     */
    ClassObject* proxyClass;
    Method* meth;
    proxyClass = dvmFindSystemClassNoInit("Ljava/lang/reflect/Proxy;");
    if (proxyClass == NULL) {
        LOGE("No java.lang.reflect.Proxy\n");
        return false;
    }
    meth = dvmFindDirectMethodByDescriptor(proxyClass, "constructorPrototype",
                "(Ljava/lang/reflect/InvocationHandler;)V");
    if (meth == NULL) {
        LOGE("Could not find java.lang.Proxy.constructorPrototype()\n");
        return false;
    }
    gDvm.methJavaLangReflectProxy_constructorPrototype = meth;

    return true;
}
Esempio n. 4
0
static bool initClassReference(ClassObject** pClass, const char* name) {
    ClassObject* result;

    assert(*pClass == NULL);

    if (name[0] == '[') {
        result = dvmFindArrayClass(name, NULL);
    } else {
        result = dvmFindSystemClassNoInit(name);
    }

    if (result == NULL) {
        ALOGE("Could not find essential class %s", name);
        return false;
    }

    *pClass = result;
    return true;
}
Esempio n. 5
0
static bool initVirtualMethodOffset(int* pOffset, const char* className,
        const char* name, const char* descriptor) {
    ClassObject* clazz = dvmFindSystemClassNoInit(className);

    if (clazz == NULL) {
        ALOGE("Could not find essential class %s for virtual method lookup", className);
        return false;
    }

    Method* method = dvmFindVirtualMethodByDescriptor(clazz, name, descriptor);

    if (method == NULL) {
        ALOGE("Could not find essential virtual method %s.%s with descriptor %s",
                clazz->descriptor, name, descriptor);
        return false;
    }

    *pOffset = method->methodIndex;
    return true;
}
Esempio n. 6
0
/*
 * Initialize string globals.
 *
 * This isn't part of the VM init sequence because it's hard to get the
 * timing right -- we need it to happen after java/lang/String has been
 * loaded, but before anybody wants to use a string.  It's easiest to
 * just initialize it on first use.
 *
 * In some unusual circumstances (e.g. trying to throw an exception because
 * String implements java/lang/CharSequence, but CharSequence doesn't exist)
 * we can try to create an exception string internally before anything has
 * really tried to use String.  In that case we basically self-destruct.
 */
static bool stringStartup()
{
    if (gDvm.javaLangStringReady < 0) {
        LOGE("ERROR: reentrant string initialization\n");
        assert(false);
        return false;
    }
    assert(gDvm.javaLangStringReady == 0);

    gDvm.javaLangStringReady = -1;

    if (gDvm.classJavaLangString == NULL)
        gDvm.classJavaLangString =
            dvmFindSystemClassNoInit("Ljava/lang/String;");

    gDvm.offJavaLangString_value =
        dvmFindFieldOffset(gDvm.classJavaLangString, "value", "[C");
    gDvm.offJavaLangString_count =
        dvmFindFieldOffset(gDvm.classJavaLangString, "count", "I");
    gDvm.offJavaLangString_offset =
        dvmFindFieldOffset(gDvm.classJavaLangString, "offset", "I");
    gDvm.offJavaLangString_hashCode =
        dvmFindFieldOffset(gDvm.classJavaLangString, "hashCode", "I");

    if (gDvm.offJavaLangString_value < 0 ||
            gDvm.offJavaLangString_count < 0 ||
            gDvm.offJavaLangString_offset < 0 ||
            gDvm.offJavaLangString_hashCode < 0)
    {
        LOGE("VM-required field missing from java/lang/String\n");
        return false;
    }

    gDvm.javaLangStringReady = 1;

    return true;
}
Esempio n. 7
0
static bool initFieldOffsets() {
    struct FieldInfo {
        int* offset;
        const char* name;
        const char* type;
    };

    static struct FieldInfo infoDdmcChunk[] = {
        { &gDvm.offDalvikDdmcChunk_type,   "type",   "I" },
        { &gDvm.offDalvikDdmcChunk_data,   "data",   "[B" },
        { &gDvm.offDalvikDdmcChunk_offset, "offset", "I" },
        { &gDvm.offDalvikDdmcChunk_length, "length", "I" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoFileDescriptor[] = {
        { &gDvm.offJavaIoFileDescriptor_descriptor, "descriptor", "I" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoString[] = {
        { &gDvm.offJavaLangString_value,    "value",    "[C" },
        { &gDvm.offJavaLangString_count,    "count",    "I" },
        { &gDvm.offJavaLangString_offset,   "offset",   "I" },
        { &gDvm.offJavaLangString_hashCode, "hashCode", "I" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoThread[] = {
        { &gDvm.offJavaLangThread_vmThread,           "vmThread",           "Ljava/lang/VMThread;" },
        { &gDvm.offJavaLangThread_group,              "group",              "Ljava/lang/ThreadGroup;" },
        { &gDvm.offJavaLangThread_daemon,             "daemon",             "Z" },
        { &gDvm.offJavaLangThread_name,               "name",               "Ljava/lang/String;" },
        { &gDvm.offJavaLangThread_priority,           "priority",           "I" },
        { &gDvm.offJavaLangThread_uncaughtHandler,    "uncaughtHandler",    "Ljava/lang/Thread$UncaughtExceptionHandler;" },
        { &gDvm.offJavaLangThread_contextClassLoader, "contextClassLoader", "Ljava/lang/ClassLoader;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoThreadGroup[] = {
        { &gDvm.offJavaLangThreadGroup_name,   "name",   "Ljava/lang/String;" },
        { &gDvm.offJavaLangThreadGroup_parent, "parent", "Ljava/lang/ThreadGroup;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoThrowable[] = {
        { &gDvm.offJavaLangThrowable_stackState, "stackState", "Ljava/lang/Object;" },
        { &gDvm.offJavaLangThrowable_cause,      "cause",      "Ljava/lang/Throwable;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoVMThread[] = {
        { &gDvm.offJavaLangVMThread_thread, "thread", "Ljava/lang/Thread;" },
        { &gDvm.offJavaLangVMThread_vmData, "vmData", "I" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoFinalizerReference[] = {
        { &gDvm.offJavaLangRefFinalizerReference_zombie, "zombie", "Ljava/lang/Object;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoConstructor[] = {
        { &gDvm.offJavaLangReflectConstructor_slot,      "slot",           "I" },
        { &gDvm.offJavaLangReflectConstructor_declClass, "declaringClass", "Ljava/lang/Class;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoField[] = {
        { &gDvm.offJavaLangReflectField_slot,      "slot",           "I" },
        { &gDvm.offJavaLangReflectField_declClass, "declaringClass", "Ljava/lang/Class;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoMethod[] = {
        { &gDvm.offJavaLangReflectMethod_slot,      "slot",           "I" },
        { &gDvm.offJavaLangReflectMethod_declClass, "declaringClass", "Ljava/lang/Class;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoProxy[] = {
        { &gDvm.offJavaLangReflectProxy_h, "h", "Ljava/lang/reflect/InvocationHandler;" },
        { NULL, NULL, NULL }
    };

    static struct FieldInfo infoBuffer[] = {
        { &gDvm.offJavaNioBuffer_capacity,               "capacity",               "I" },
        { &gDvm.offJavaNioBuffer_effectiveDirectAddress, "effectiveDirectAddress", "J" },
        { NULL, NULL, NULL }
    };

    static struct { const char* name; const struct FieldInfo* fields; } classes[] = {
        { "Lorg/apache/harmony/dalvik/ddmc/Chunk;", infoDdmcChunk },
        { "Ljava/io/FileDescriptor;",               infoFileDescriptor },
        { "Ljava/lang/String;",                     infoString },
        { "Ljava/lang/Thread;",                     infoThread },
        { "Ljava/lang/ThreadGroup;",                infoThreadGroup },
        { "Ljava/lang/Throwable;",                  infoThrowable },
        { "Ljava/lang/VMThread;",                   infoVMThread },
        { "Ljava/lang/ref/FinalizerReference;", infoFinalizerReference },
        { "Ljava/lang/reflect/Constructor;",        infoConstructor },
        { "Ljava/lang/reflect/Field;",              infoField },
        { "Ljava/lang/reflect/Method;",             infoMethod },
        { "Ljava/lang/reflect/Proxy;",              infoProxy },
        { "Ljava/nio/Buffer;",                      infoBuffer },
        { NULL, NULL }
    };

    int i;
    for (i = 0; classes[i].name != NULL; i++) {
        const char* className = classes[i].name;
        ClassObject* clazz = dvmFindSystemClassNoInit(className);
        const struct FieldInfo* fields = classes[i].fields;

        if (clazz == NULL) {
            ALOGE("Could not find essential class %s for field lookup", className);
            return false;
        }

        int j;
        for (j = 0; fields[j].offset != NULL; j++) {
            if (!initFieldOffset(clazz, fields[j].offset, fields[j].name, fields[j].type)) {
                return false;
            }
        }
    }

    return true;
}
Esempio n. 8
0
/*
 * Cache pointers to some of the exception classes we use locally.
 *
 * Note this is NOT called during dexopt optimization.  Some of the fields
 * are initialized by the verifier (dvmVerifyCodeFlow).
 */
bool dvmExceptionStartup(void)
{
    gDvm.classJavaLangThrowable =
        dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
    gDvm.classJavaLangRuntimeException =
        dvmFindSystemClassNoInit("Ljava/lang/RuntimeException;");
    gDvm.classJavaLangStackOverflowError =
        dvmFindSystemClassNoInit("Ljava/lang/StackOverflowError;");
    gDvm.classJavaLangError =
        dvmFindSystemClassNoInit("Ljava/lang/Error;");
    gDvm.classJavaLangStackTraceElement =
        dvmFindSystemClassNoInit("Ljava/lang/StackTraceElement;");
    gDvm.classJavaLangStackTraceElementArray =
        dvmFindArrayClass("[Ljava/lang/StackTraceElement;", NULL);
    if (gDvm.classJavaLangThrowable == NULL ||
        gDvm.classJavaLangStackTraceElement == NULL ||
        gDvm.classJavaLangStackTraceElementArray == NULL)
    {
        LOGE("Could not find one or more essential exception classes\n");
        return false;
    }

    /*
     * Find the constructor.  Note that, unlike other saved method lookups,
     * we're using a Method* instead of a vtable offset.  This is because
     * constructors don't have vtable offsets.  (Also, since we're creating
     * the object in question, it's impossible for anyone to sub-class it.)
     */
    Method* meth;
    meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
        "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
    if (meth == NULL) {
        LOGE("Unable to find constructor for StackTraceElement\n");
        return false;
    }
    gDvm.methJavaLangStackTraceElement_init = meth;

    /* grab an offset for the stackData field */
    gDvm.offJavaLangThrowable_stackState =
        dvmFindFieldOffset(gDvm.classJavaLangThrowable,
            "stackState", "Ljava/lang/Object;");
    if (gDvm.offJavaLangThrowable_stackState < 0) {
        LOGE("Unable to find Throwable.stackState\n");
        return false;
    }

    /* and one for the message field, in case we want to show it */
    gDvm.offJavaLangThrowable_message =
        dvmFindFieldOffset(gDvm.classJavaLangThrowable,
            "detailMessage", "Ljava/lang/String;");
    if (gDvm.offJavaLangThrowable_message < 0) {
        LOGE("Unable to find Throwable.detailMessage\n");
        return false;
    }

    /* and one for the cause field, just 'cause */
    gDvm.offJavaLangThrowable_cause =
        dvmFindFieldOffset(gDvm.classJavaLangThrowable,
            "cause", "Ljava/lang/Throwable;");
    if (gDvm.offJavaLangThrowable_cause < 0) {
        LOGE("Unable to find Throwable.cause\n");
        return false;
    }

    return true;
}
Esempio n. 9
0
/*
 * Initialize string globals.
 *
 * This isn't part of the VM init sequence because it's hard to get the
 * timing right -- we need it to happen after java/lang/String has been
 * loaded, but before anybody wants to use a string.  It's easiest to
 * just initialize it on first use.
 *
 * In some unusual circumstances (e.g. trying to throw an exception because
 * String implements java/lang/CharSequence, but CharSequence doesn't exist)
 * we can try to create an exception string internally before anything has
 * really tried to use String.  In that case we basically self-destruct.
 */
static bool stringStartup()
{
    if (gDvm.javaLangStringReady < 0) {
        LOGE("ERROR: reentrant string initialization\n");
        assert(false);
        return false;
    }
    assert(gDvm.javaLangStringReady == 0);

    gDvm.javaLangStringReady = -1;

    if (gDvm.classJavaLangString == NULL)
        gDvm.classJavaLangString =
            dvmFindSystemClassNoInit("Ljava/lang/String;");

    gDvm.offJavaLangString_value =
        dvmFindFieldOffset(gDvm.classJavaLangString, "value", "[C");
    gDvm.offJavaLangString_count =
        dvmFindFieldOffset(gDvm.classJavaLangString, "count", "I");
    gDvm.offJavaLangString_offset =
        dvmFindFieldOffset(gDvm.classJavaLangString, "offset", "I");
    gDvm.offJavaLangString_hashCode =
        dvmFindFieldOffset(gDvm.classJavaLangString, "hashCode", "I");

    if (gDvm.offJavaLangString_value < 0 ||
        gDvm.offJavaLangString_count < 0 ||
        gDvm.offJavaLangString_offset < 0 ||
        gDvm.offJavaLangString_hashCode < 0)
    {
        LOGE("VM-required field missing from java/lang/String\n");
        return false;
    }

    bool badValue = false;
    if (gDvm.offJavaLangString_value != STRING_FIELDOFF_VALUE) {
        LOGE("InlineNative: String.value offset = %d, expected %d\n",
            gDvm.offJavaLangString_value, STRING_FIELDOFF_VALUE);
        badValue = true;
    }
    if (gDvm.offJavaLangString_count != STRING_FIELDOFF_COUNT) {
        LOGE("InlineNative: String.count offset = %d, expected %d\n",
            gDvm.offJavaLangString_count, STRING_FIELDOFF_COUNT);
        badValue = true;
    }
    if (gDvm.offJavaLangString_offset != STRING_FIELDOFF_OFFSET) {
        LOGE("InlineNative: String.offset offset = %d, expected %d\n",
            gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
        badValue = true;
    }
    if (gDvm.offJavaLangString_hashCode != STRING_FIELDOFF_HASHCODE) {
        LOGE("InlineNative: String.hashCode offset = %d, expected %d\n",
            gDvm.offJavaLangString_hashCode, STRING_FIELDOFF_HASHCODE);
        badValue = true;
    }
    if (badValue)
        return false;

    gDvm.javaLangStringReady = 1;

    return true;
}