Пример #1
0
/*
 * Common code for dvmCallMethodV/A and dvmInvokeMethod.
 *
 * Pushes a call frame on, advancing self->interpSave.curFrame.
 */
static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
    bool checkAccess)
{
    ClassObject* clazz;


#ifndef NDEBUG
    if (self->status != THREAD_RUNNING) {
        ALOGW("threadid=%d: status=%d on call to %s.%s -",
            self->threadId, self->status,
            method->clazz->descriptor, method->name);
    }
#endif

    assert(self != NULL);
    assert(method != NULL);

    if (obj != NULL)
        clazz = obj->clazz;
    else
        clazz = method->clazz;

    //salma
	// __android_log_print(ANDROID_LOG_DEBUG, "DVM DEBUG","call prep: methodclazz=%s, methodname=%s", clazz->descriptor, method->name);
    //endsalma

    IF_LOGVV() {
        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
        LOGVV("thread=%d native code calling %s.%s %s", self->threadId,
            clazz->descriptor, method->name, desc);
        free(desc);
    }

    if (checkAccess) {
        /* needed for java.lang.reflect.Method.invoke */
        if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->interpSave.curFrame),
                method))
        {
            /* note this throws IAException, not IAError */
            dvmThrowIllegalAccessException("access to method denied");
            return NULL;
        }
    }

    /*
     * Push a call frame on.  If there isn't enough room for ins, locals,
     * outs, and the saved state, it will throw an exception.
     *
     * This updates self->interpSave.curFrame.
     */
    if (dvmIsNativeMethod(method)) {
        /* native code calling native code the hard way */
        if (!dvmPushJNIFrame(self, method)) {
            assert(dvmCheckException(self));
            return NULL;
        }
    } else {
        /* native code calling interpreted code */
        if (!dvmPushInterpFrame(self, method)) {
            assert(dvmCheckException(self));
            return NULL;
        }
    }

    return clazz;
}
/*
 * Get the address of a field from an object.  This can be used with "get"
 * or "set".
 *
 * "declaringClass" is the class in which the field was declared.  For an
 * instance field, "obj" is the object that holds the field data; for a
 * static field its value is ignored.
 *
 * "If the underlying field is static, the class that declared the
 * field is initialized if it has not already been initialized."
 *
 * On failure, throws an exception and returns NULL.
 *
 * The documentation lists exceptional conditions and the exceptions that
 * should be thrown, but doesn't say which exception previals when two or
 * more exceptional conditions exist at the same time.  For example,
 * attempting to set a protected field from an unrelated class causes an
 * IllegalAccessException, while passing in a data type that doesn't match
 * the field causes an IllegalArgumentException.  If code does both at the
 * same time, we have to choose one or othe other.
 *
 * The expected order is:
 *  (1) Check for illegal access. Throw IllegalAccessException.
 *  (2) Make sure the object actually has the field.  Throw
 *      IllegalArgumentException.
 *  (3) Make sure the field matches the expected type, e.g. if we issued
 *      a "getInteger" call make sure the field is an integer or can be
 *      converted to an int with a widening conversion.  Throw
 *      IllegalArgumentException.
 *  (4) Make sure "obj" is not null.  Throw NullPointerException.
 *
 * TODO: we're currently handling #3 after #4, because we don't check the
 * widening conversion until we're actually extracting the value from the
 * object (which won't work well if it's a null reference).
 */
static JValue* getFieldDataAddr(Object* obj, ClassObject* declaringClass,
                                int slot, bool isSetOperation, bool noAccessCheck)
{
    Field* field;
    JValue* result;

    field = dvmSlotToField(declaringClass, slot);
    assert(field != NULL);

    /* verify access */
    if (!noAccessCheck) {
        if (isSetOperation && dvmIsFinalField(field)) {
            dvmThrowException("Ljava/lang/IllegalAccessException;",
                              "field is marked 'final'");
            return NULL;
        }

        ClassObject* callerClass =
            dvmGetCaller2Class(dvmThreadSelf()->curFrame);

        /*
         * We need to check two things:
         *  (1) Would an instance of the calling class have access to the field?
         *  (2) If the field is "protected", is the object an instance of the
         *      calling class, or is the field's declaring class in the same
         *      package as the calling class?
         *
         * #1 is basic access control.  #2 ensures that, just because
         * you're a subclass of Foo, you can't mess with protected fields
         * in arbitrary Foo objects from other packages.
         */
        if (!dvmCheckFieldAccess(callerClass, field)) {
            dvmThrowException("Ljava/lang/IllegalAccessException;",
                              "access to field not allowed");
            return NULL;
        }
        if (dvmIsProtectedField(field)) {
            bool isInstance, samePackage;

            if (obj != NULL)
                isInstance = dvmInstanceof(obj->clazz, callerClass);
            else
                isInstance = false;
            samePackage = dvmInSamePackage(declaringClass, callerClass);

            if (!isInstance && !samePackage) {
                dvmThrowException("Ljava/lang/IllegalAccessException;",
                                  "access to protected field not allowed");
                return NULL;
            }
        }
    }

    if (dvmIsStaticField(field)) {
        /* init class if necessary, then return ptr to storage in "field" */
        if (!dvmIsClassInitialized(declaringClass)) {
            if (!dvmInitClass(declaringClass)) {
                assert(dvmCheckException(dvmThreadSelf()));
                return NULL;
            }
        }

        result = dvmStaticFieldPtr((StaticField*) field);
    } else {
        /*
         * Verify object is of correct type (i.e. it actually has the
         * expected field in it), then grab a pointer to obj storage.
         * The call to dvmVerifyObjectInClass throws an NPE if "obj" is NULL.
         */
        if (!dvmVerifyObjectInClass(obj, declaringClass)) {
            assert(dvmCheckException(dvmThreadSelf()));
            if (obj != NULL) {
                LOGD("Wrong type of object for field lookup: %s %s\n",
                     obj->clazz->descriptor, declaringClass->descriptor);
            }
            return NULL;
        }
        result = dvmFieldPtr(obj, ((InstField*) field)->byteOffset);
    }

    return result;
}