static void Dalvik_dalvik_system_VMRuntime_newNonMovableArray(const u4* args,
    JValue* pResult)
{
    ClassObject* elementClass = (ClassObject*) args[1];
    int length = args[2];

    if (elementClass == NULL) {
        dvmThrowNullPointerException("elementClass == null");
        RETURN_VOID();
    }
    if (length < 0) {
        dvmThrowNegativeArraySizeException(length);
        RETURN_VOID();
    }

    // TODO: right now, we don't have a copying collector, so there's no need
    // to do anything special here, but we ought to pass the non-movability
    // through to the allocator.
    ClassObject* arrayClass = dvmFindArrayClassForElement(elementClass);
    ArrayObject* newArray = dvmAllocArrayByClass(arrayClass,
                                                 length,
                                                 ALLOC_NON_MOVING);
    if (newArray == NULL) {
        assert(dvmCheckException(dvmThreadSelf()));
        RETURN_VOID();
    }
    dvmReleaseTrackedAlloc((Object*) newArray, NULL);

    RETURN_PTR(newArray);
}
Пример #2
0
java_lang_Object_p fastiva_Dalvik_dalvik_system_VMRuntime_newNonMovableArray(dalvik_system_VMRuntime_p self, java_lang_Class_p elementClass, jint length) {
#endif

	if (elementClass == NULL) {
        dvmThrowNullPointerException("elementClass == null");
        THROW_V();
    }
    if (length < 0) {
        dvmThrowNegativeArraySizeException(length);
        THROW_V();
    }

    // TODO: right now, we don't have a copying collector, so there's no need
    // to do anything special here, but we ought to pass the non-movability
    // through to the allocator.
    ClassObject* arrayClass = dvmFindArrayClassForElement(elementClass);
    ArrayObject* newArray = dvmAllocArrayByClass(arrayClass,
                                                 length,
                                                 ALLOC_NON_MOVING);
    if (newArray == NULL) {
        assert(dvmCheckException(dvmThreadSelf()));
        THROW_V();
    }
    dvmReleaseTrackedAlloc((Object*) newArray, NULL);

    RETURN_PTR(newArray);
}
Пример #3
0
/*
 * Get an array with all constructors declared by a class.
 */
ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly)
{
    if (!dvmIsClassInitialized(gDvm.classJavaLangReflectConstructor))
        dvmInitClass(gDvm.classJavaLangReflectConstructor);

    /*
     * Ordinarily we init the class the first time we resolve a method.
     * We're bypassing the normal resolution mechanism, so we init it here.
     */
    if (!dvmIsClassInitialized(clazz))
        dvmInitClass(clazz);

    /*
     * Count up the #of relevant methods.
     */
    size_t count = 0;
    for (int i = 0; i < clazz->directMethodCount; ++i) {
        Method* meth = &clazz->directMethods[i];
        if ((!publicOnly || dvmIsPublicMethod(meth)) &&
            dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth))
        {
            count++;
        }
    }

    /*
     * Create an array of Constructor objects.
     */
    ClassObject* arrayClass = gDvm.classJavaLangReflectConstructorArray;
    ArrayObject* ctorArray = dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT);
    if (ctorArray == NULL)
        return NULL;

    /*
     * Fill out the array.
     */
    size_t ctorObjCount = 0;
    for (int i = 0; i < clazz->directMethodCount; ++i) {
        Method* meth = &clazz->directMethods[i];
        if ((!publicOnly || dvmIsPublicMethod(meth)) &&
            dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth))
        {
            Object* ctorObj = createConstructorObject(meth);
            if (ctorObj == NULL) {
              dvmReleaseTrackedAlloc((Object*) ctorArray, NULL);
              return NULL;
            }
            dvmSetObjectArrayElement(ctorArray, ctorObjCount, ctorObj);
            ++ctorObjCount;
            dvmReleaseTrackedAlloc(ctorObj, NULL);
        }
    }

    assert(ctorObjCount == ctorArray->length);

    /* caller must call dvmReleaseTrackedAlloc */
    return ctorArray;
}
Пример #4
0
/*
 * Convert the method signature to an array of classes.
 *
 * The tokenization process may mangle "*pSignature".  On return, it will
 * be pointing at the closing ')'.
 *
 * "defClass" is the method's class, which is needed to make class loaders
 * happy.
 */
static ArrayObject* convertSignatureToClassArray(char** pSignature,
    ClassObject* defClass)
{
    char* signature = *pSignature;

    assert(*signature == '(');
    signature++;

    /* count up the number of parameters */
    size_t count = 0;
    char* cp = signature;
    while (*cp != ')') {
        count++;

        if (*cp == '[') {
            while (*++cp == '[')
                ;
        }
        if (*cp == 'L') {
            while (*++cp != ';')
                ;
        }
        cp++;
    }
    LOGVV("REFLECT found %d parameters in '%s'", count, *pSignature);

    /* create an array to hold them */
    ArrayObject* classArray = dvmAllocArrayByClass(gDvm.classJavaLangClassArray,
                     count, ALLOC_DEFAULT);
    if (classArray == NULL)
        return NULL;

    /* fill it in */
    cp = signature;
    for (size_t i = 0; i < count; i++) {
        ClassObject* clazz = convertSignaturePartToClass(&cp, defClass);
        if (clazz == NULL) {
            assert(dvmCheckException(dvmThreadSelf()));
            return NULL;
        }
        LOGVV("REFLECT  %d: '%s'", i, clazz->descriptor);
        dvmSetObjectArrayElement(classArray, i, (Object *)clazz);
    }

    *pSignature = cp;

    /* caller must call dvmReleaseTrackedAlloc */
    return classArray;
}
/*
 * private static String[] getClassNameList(int cookie)
 *
 * Returns a String array that holds the names of all classes in the
 * specified DEX file.
 * 在指定的DEX文件中,返回一个持有所有类名字的String数组
 */
static void Dalvik_dalvik_system_DexFile_getClassNameList(const u4* args,
    JValue* pResult)
{
    int cookie = args[0];
    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
    Thread* self = dvmThreadSelf();

    if (!validateCookie(cookie))
        RETURN_VOID();

    DvmDex* pDvmDex;
    if (pDexOrJar->isDex)
        pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
    else
        pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
    assert(pDvmDex != NULL);
    DexFile* pDexFile = pDvmDex->pDexFile;

    int count = pDexFile->pHeader->classDefsSize;
    ClassObject* arrayClass =
        dvmFindArrayClassForElement(gDvm.classJavaLangString);
    ArrayObject* stringArray =
        dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT);
    if (stringArray == NULL) {
        /* probably OOM */
        ALOGD("Failed allocating array of %d strings", count);
        assert(dvmCheckException(self));
        RETURN_VOID();
    }

    int i;
    for (i = 0; i < count; i++) {
        const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i);
        const char* descriptor =
            dexStringByTypeIdx(pDexFile, pClassDef->classIdx);

        char* className = dvmDescriptorToDot(descriptor);
        StringObject* str = dvmCreateStringFromCstr(className);
        dvmSetObjectArrayElement(stringArray, i, (Object *)str);
        dvmReleaseTrackedAlloc((Object *)str, self);
        free(className);
    }

    dvmReleaseTrackedAlloc((Object*)stringArray, self);
    RETURN_PTR(stringArray);
}
Пример #6
0
/*
 * Convert an array of char* into a String[].
 *
 * Returns NULL on failure, with an exception raised.
 */
static ArrayObject* convertStringArray(char** strings, size_t count)
{
    Thread* self = dvmThreadSelf();

    /*
     * Allocate an array to hold the String objects.
     */
    ClassObject* stringArrayClass =
        dvmFindArrayClass("[Ljava/lang/String;", NULL);
    if (stringArrayClass == NULL) {
        /* shouldn't happen */
        LOGE("Unable to find [Ljava/lang/String;\n");
        dvmAbort();
    }

    ArrayObject* stringArray =
        dvmAllocArrayByClass(stringArrayClass, count, ALLOC_DEFAULT);
    if (stringArray == NULL) {
        /* probably OOM */
        LOGD("Failed allocating array of %d strings\n", count);
        assert(dvmCheckException(self));
        return NULL;
    }

    /*
     * Create the individual String objects and add them to the array.
     */
    size_t i;
    for (i = 0; i < count; i++) {
        Object *str =
            (Object *)dvmCreateStringFromCstr(strings[i]);
        if (str == NULL) {
            /* probably OOM; drop out now */
            assert(dvmCheckException(self));
            dvmReleaseTrackedAlloc((Object*)stringArray, self);
            return NULL;
        }
        dvmSetObjectArrayElement(stringArray, i, str);
        /* stored in tracked array, okay to release */
        dvmReleaseTrackedAlloc(str, self);
    }

    dvmReleaseTrackedAlloc((Object*)stringArray, self);
    return stringArray;
}
Пример #7
0
/*
 * Get all interfaces a class implements. If this is unable to allocate
 * the result array, this raises an OutOfMemoryError and returns NULL.
 */
ArrayObject* dvmGetInterfaces(ClassObject* clazz)
{
    if (!dvmIsClassInitialized(gDvm.classJavaLangReflectMethod))
        dvmInitClass(gDvm.classJavaLangReflectMethod);

    /*
     * Create an array of Class objects.
     */
    size_t count = clazz->interfaceCount;
    ArrayObject* interfaceArray =
        dvmAllocArrayByClass(gDvm.classJavaLangClassArray, count, ALLOC_DEFAULT);
    if (interfaceArray == NULL)
        return NULL;

    /*
     * Fill out the array.
     */
    memcpy(interfaceArray->contents, clazz->interfaces,
           count * sizeof(Object *));
    dvmWriteBarrierArray(interfaceArray, 0, count);

    /* caller must call dvmReleaseTrackedAlloc */
    return interfaceArray;
}
Пример #8
0
GOTO_TARGET(filledNewArray, bool methodCallRange)
    {
        ClassObject* arrayClass;
        ArrayObject* newArray;
        u4* contents;
        char typeCh;
        int i;
        u4 arg5;

        EXPORT_PC();

        ref = FETCH(1);             /* class ref */
        vdst = FETCH(2);            /* first 4 regs -or- range base */

        if (methodCallRange) {
            vsrc1 = INST_AA(inst);  /* #of elements */
            arg5 = -1;              /* silence compiler warning */
            ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
                vsrc1, ref, vdst, vdst+vsrc1-1);
        } else {
            arg5 = INST_A(inst);
            vsrc1 = INST_B(inst);   /* #of elements */
            ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
                vsrc1, ref, vdst, arg5);
        }

        /*
         * Resolve the array class.
         */
        arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
        if (arrayClass == NULL) {
            arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
            if (arrayClass == NULL)
                GOTO_exceptionThrown();
        }
        /*
        if (!dvmIsArrayClass(arrayClass)) {
            dvmThrowException("Ljava/lang/RuntimeError;",
                "filled-new-array needs array class");
            GOTO_exceptionThrown();
        }
        */
        /* verifier guarantees this is an array class */
        assert(dvmIsArrayClass(arrayClass));
        assert(dvmIsClassInitialized(arrayClass));

        /*
         * Create an array of the specified type.
         */
        LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
        typeCh = arrayClass->descriptor[1];
        if (typeCh == 'D' || typeCh == 'J') {
            /* category 2 primitives not allowed */
            dvmThrowException("Ljava/lang/RuntimeError;",
                "bad filled array req");
            GOTO_exceptionThrown();
        } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
            /* TODO: requires multiple "fill in" loops with different widths */
            LOGE("non-int primitives not implemented\n");
            dvmThrowException("Ljava/lang/InternalError;",
                "filled-new-array not implemented for anything but 'int'");
            GOTO_exceptionThrown();
        }

        newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
        if (newArray == NULL)
            GOTO_exceptionThrown();

        /*
         * Fill in the elements.  It's legal for vsrc1 to be zero.
         */
        contents = (u4*) newArray->contents;
        if (methodCallRange) {
            for (i = 0; i < vsrc1; i++)
                contents[i] = GET_REGISTER(vdst+i);
        } else {
            assert(vsrc1 <= 5);
            if (vsrc1 == 5) {
                contents[4] = GET_REGISTER(arg5);
                vsrc1--;
            }
            for (i = 0; i < vsrc1; i++) {
                contents[i] = GET_REGISTER(vdst & 0x0f);
                vdst >>= 4;
            }
        }

        retval.l = newArray;
    }
Пример #9
0
/*
 * Get an array with all methods declared by a class.
 *
 * This includes both static and virtual methods, and can include private
 * members if "publicOnly" is false.  It does not include Miranda methods,
 * since those weren't declared in the class, or constructors.
 */
ArrayObject* dvmGetDeclaredMethods(ClassObject* clazz, bool publicOnly)
{
    if (!dvmIsClassInitialized(gDvm.classJavaLangReflectMethod))
        dvmInitClass(gDvm.classJavaLangReflectMethod);

    /*
     * Count up the #of relevant methods.
     *
     * Ignore virtual Miranda methods and direct class/object constructors.
     */
    size_t count = 0;
    Method* meth = clazz->virtualMethods;
    for (int i = 0; i < clazz->virtualMethodCount; i++, meth++) {
        if ((!publicOnly || dvmIsPublicMethod(meth)) &&
            !dvmIsMirandaMethod(meth))
        {
            count++;
        }
    }
    meth = clazz->directMethods;
    for (int i = 0; i < clazz->directMethodCount; i++, meth++) {
        if ((!publicOnly || dvmIsPublicMethod(meth)) && meth->name[0] != '<') {
            count++;
        }
    }

    /*
     * Create an array of Method objects.
     */
    ArrayObject* methodArray =
        dvmAllocArrayByClass(gDvm.classJavaLangReflectMethodArray, count, ALLOC_DEFAULT);
    if (methodArray == NULL)
        return NULL;

    /*
     * Fill out the array.
     */
    meth = clazz->virtualMethods;
    size_t methObjCount = 0;
    for (int i = 0; i < clazz->virtualMethodCount; i++, meth++) {
        if ((!publicOnly || dvmIsPublicMethod(meth)) &&
            !dvmIsMirandaMethod(meth))
        {
            Object* methObj = dvmCreateReflectMethodObject(meth);
            if (methObj == NULL)
                goto fail;
            dvmSetObjectArrayElement(methodArray, methObjCount, methObj);
            ++methObjCount;
            dvmReleaseTrackedAlloc(methObj, NULL);
        }
    }
    meth = clazz->directMethods;
    for (int i = 0; i < clazz->directMethodCount; i++, meth++) {
        if ((!publicOnly || dvmIsPublicMethod(meth)) &&
            meth->name[0] != '<')
        {
            Object* methObj = dvmCreateReflectMethodObject(meth);
            if (methObj == NULL)
                goto fail;
            dvmSetObjectArrayElement(methodArray, methObjCount, methObj);
            ++methObjCount;
            dvmReleaseTrackedAlloc(methObj, NULL);
        }
    }

    assert(methObjCount == methodArray->length);

    /* caller must call dvmReleaseTrackedAlloc */
    return methodArray;

fail:
    dvmReleaseTrackedAlloc((Object*) methodArray, NULL);
    return NULL;
}
Пример #10
0
/*
 *
 * Get an array with all fields declared by a class.
 *
 * This includes both static and instance fields.
 */
ArrayObject* dvmGetDeclaredFields(ClassObject* clazz, bool publicOnly)
{
    if (!dvmIsClassInitialized(gDvm.classJavaLangReflectField))
        dvmInitClass(gDvm.classJavaLangReflectField);

    /* count #of fields */
    size_t count;
    if (!publicOnly)
        count = clazz->sfieldCount + clazz->ifieldCount;
    else {
        count = 0;
        for (int i = 0; i < clazz->sfieldCount; i++) {
            if ((clazz->sfields[i].accessFlags & ACC_PUBLIC) != 0)
                count++;
        }
        for (int i = 0; i < clazz->ifieldCount; i++) {
            if ((clazz->ifields[i].accessFlags & ACC_PUBLIC) != 0)
                count++;
        }
    }

    /* create the Field[] array */
    ArrayObject* fieldArray =
        dvmAllocArrayByClass(gDvm.classJavaLangReflectFieldArray, count, ALLOC_DEFAULT);
    if (fieldArray == NULL)
        return NULL;

    /* populate */
    size_t fieldCount = 0;
    for (int i = 0; i < clazz->sfieldCount; i++) {
        if (!publicOnly ||
            (clazz->sfields[i].accessFlags & ACC_PUBLIC) != 0)
        {
            Object* field = createFieldObject(&clazz->sfields[i], clazz);
            if (field == NULL) {
                goto fail;
            }
            dvmSetObjectArrayElement(fieldArray, fieldCount, field);
            dvmReleaseTrackedAlloc(field, NULL);
            ++fieldCount;
        }
    }
    for (int i = 0; i < clazz->ifieldCount; i++) {
        if (!publicOnly ||
            (clazz->ifields[i].accessFlags & ACC_PUBLIC) != 0)
        {
            Object* field = createFieldObject(&clazz->ifields[i], clazz);
            if (field == NULL) {
                goto fail;
            }
            dvmSetObjectArrayElement(fieldArray, fieldCount, field);
            dvmReleaseTrackedAlloc(field, NULL);
            ++fieldCount;
        }
    }

    assert(fieldCount == fieldArray->length);

    /* caller must call dvmReleaseTrackedAlloc */
    return fieldArray;

fail:
    dvmReleaseTrackedAlloc((Object*) fieldArray, NULL);
    return NULL;
}
Пример #11
0
static void xposedCallHandler(const u4* args, JValue* pResult,
		const Method* method, ::Thread* self) {
	if (!xposedIsHooked(method)) {
		dvmThrowNoSuchMethodError(
				"could not find Xposed original method - how did you even get here?");
		return;
	}

	XposedHookInfo* hookInfo = (XposedHookInfo*) method->insns;
	Method* original = (Method*) hookInfo;
	Object* originalReflected = hookInfo->reflectedMethod;
	Object* additionalInfo = hookInfo->additionalInfo;

	// convert/box arguments
	const char* desc = &method->shorty[1]; // [0] is the return type.
	Object* thisObject = NULL;
	size_t srcIndex = 0;
	size_t dstIndex = 0;

	// for non-static methods determine the "this" pointer
	if (!dvmIsStaticMethod(original)) {
		thisObject = (Object*) args[0];
		srcIndex++;
	}

	ArrayObject* argsArray = dvmAllocArrayByClass(objectArrayClass,
			strlen(method->shorty) - 1, ALLOC_DEFAULT);
	if (argsArray == NULL) {
		return;
	}

	while (*desc != '\0') {
		char descChar = *(desc++);
		JValue value;
		Object* obj;

		switch (descChar) {
		case 'Z':
		case 'C':
		case 'F':
		case 'B':
		case 'S':
		case 'I':
			value.i = args[srcIndex++];
			obj = (Object*) dvmBoxPrimitive(value,
					dvmFindPrimitiveClass(descChar));
			dvmReleaseTrackedAlloc(obj, self);
			break;
		case 'D':
		case 'J':
			value.j = dvmGetArgLong(args, srcIndex);
			srcIndex += 2;
			obj = (Object*) dvmBoxPrimitive(value,
					dvmFindPrimitiveClass(descChar));
			dvmReleaseTrackedAlloc(obj, self);
			break;
		case '[':
		case 'L':
			obj = (Object*) args[srcIndex++];
			break;
		default:
			ALOGE("Unknown method signature description character: %c\n",
					descChar);
			obj = NULL;
			srcIndex++;
		}
		xposedSetObjectArrayElement(argsArray, dstIndex++, obj);
	}

	// call the Java handler function
	JValue result;
	dvmCallMethod(self, xposedHandleHookedMethod, NULL, &result,
			originalReflected, (int) original, additionalInfo, thisObject,
			argsArray);

	dvmReleaseTrackedAlloc(argsArray, self);

	// exceptions are thrown to the caller
	if (dvmCheckException(self)) {
		return;
	}

	// return result with proper type
	ClassObject* returnType = dvmGetBoxedReturnType(method);
	if (returnType->primitiveType == PRIM_VOID) {
		// ignored
	} else if (result.l == NULL) {
		if (dvmIsPrimitiveClass(returnType)) {
			dvmThrowNullPointerException("null result when primitive expected");
		}
		pResult->l = NULL;
	} else {
		if (!dvmUnboxPrimitive(result.l, returnType, pResult)) {
			dvmThrowClassCastException(result.l->clazz, returnType);
		}
	}
}