/* * Issue a method call with a variable number of arguments. We process * the contents of "args" by scanning the method signature. * * Pass in NULL for "obj" on calls to static methods. * * We don't need to take the class as an argument because, in Dalvik, * we don't need to worry about static synchronized methods. */ void dvmCallMethodV(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, va_list args) { const char* desc = &(method->shorty[1]); // [0] is the return type. int verifyCount = 0; ClassObject* clazz; u4* ins; #ifdef WITH_TAINT_TRACKING int slot_cnt = 0; bool nativeTarget = dvmIsNativeMethod(method); #endif clazz = callPrep(self, method, obj, false); if (clazz == NULL) return; /* "ins" for new frame start at frame pointer plus locals */ #ifdef WITH_TAINT_TRACKING if (nativeTarget) { /* native target, no taint tag interleaving */ ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); } else { /* interpreted target, taint tags are interleaved */ ins = ((u4*)self->curFrame) + ((method->registersSize - method->insSize) << 1); } #else ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); #endif //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { #ifdef WITH_EXTRA_OBJECT_VALIDATION assert(obj != NULL && dvmIsValidObject(obj)); #endif *ins++ = (u4) obj; #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; } JNIEnv* env = self->jniEnv; while (*desc != '\0') { switch (*(desc++)) { case 'D': case 'J': { u8 val = va_arg(args, u8); memcpy(ins, &val, 8); // EABI prevents direct store #ifdef WITH_TAINT_TRACKING if (nativeTarget) { ins += 2; } else { /* adjust for taint tag interleaving */ ins[2] = ins[1]; ins[1] = TAINT_CLEAR; ins[3] = TAINT_CLEAR; ins += 4; } slot_cnt += 2; #else ins += 2; #endif verifyCount += 2; break; } case 'F': { /* floats were normalized to doubles; convert back */ float f = (float) va_arg(args, double); *ins++ = dvmFloatToU4(f); #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; break; } case 'L': { /* 'shorty' descr uses L for all refs, incl array */ void* argObj = va_arg(args, void*); assert(obj == NULL || dvmIsValidObject(obj)); if (fromJni) *ins++ = (u4) dvmDecodeIndirectRef(env, argObj); else *ins++ = (u4) argObj; #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; break; } default: { /* Z B C S I -- all passed as 32-bit integers */ *ins++ = va_arg(args, u4); #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; break; } } } #ifdef WITH_TAINT_TRACKING /* native hack spacer */ *ins++ = TAINT_CLEAR; /* if nativeTarget, this is return taint */ { int i; if (nativeTarget) { for (i = 0; i < slot_cnt; i++) { *ins++ = TAINT_CLEAR; } } } #endif #ifndef NDEBUG if (verifyCount != method->insSize) { LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, method->insSize, clazz->descriptor, method->name); assert(false); goto bail; } #endif //dvmDumpThreadStack(dvmThreadSelf()); if (dvmIsNativeMethod(method)) { TRACE_METHOD_ENTER(self, method); /* * Because we leave no space for local variables, "curFrame" points * directly at the method arguments. */ (*method->nativeFunc)(self->curFrame, pResult, method, self); TRACE_METHOD_EXIT(self, method); } else { #ifdef WITH_TAINT_TRACKING u4 rtaint; /* not used */ dvmInterpret(self, method, pResult, &rtaint); #else dvmInterpret(self, method, pResult); #endif } #ifndef NDEBUG bail: #endif dvmPopFrame(self); }
/* * Issue a method call with a variable number of arguments. We process * the contents of "args" by scanning the method signature. * * Pass in NULL for "obj" on calls to static methods. * * We don't need to take the class as an argument because, in Dalvik, * we don't need to worry about static synchronized methods. */ void dvmCallMethodV(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, va_list args) { //salma //__android_log_print(ANDROID_LOG_DEBUG, "DVM DEBUG", "dvmCallMethodV method name = %s, clazz name: %s", method->name, method->clazz->descriptor); //end salma const char* desc = &(method->shorty[1]); // [0] is the return type. int verifyCount = 0; ClassObject* clazz; u4* ins; clazz = callPrep(self, method, obj, false); if (clazz == NULL) return; /* "ins" for new frame start at frame pointer plus locals */ ins = ((u4*)self->interpSave.curFrame) + (method->registersSize - method->insSize); //ALOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { #ifdef WITH_EXTRA_OBJECT_VALIDATION assert(obj != NULL && dvmIsHeapAddress(obj)); #endif *ins++ = (u4) obj; verifyCount++; } while (*desc != '\0') { switch (*(desc++)) { case 'D': case 'J': { u8 val = va_arg(args, u8); memcpy(ins, &val, 8); // EABI prevents direct store ins += 2; verifyCount += 2; break; } case 'F': { /* floats were normalized to doubles; convert back */ float f = (float) va_arg(args, double); *ins++ = dvmFloatToU4(f); verifyCount++; break; } case 'L': { /* 'shorty' descr uses L for all refs, incl array */ void* arg = va_arg(args, void*); assert(obj == NULL || dvmIsHeapAddress(obj)); jobject argObj = reinterpret_cast<jobject>(arg); if (fromJni) *ins++ = (u4) dvmDecodeIndirectRef(self, argObj); else *ins++ = (u4) argObj; verifyCount++; break; } default: { /* Z B C S I -- all passed as 32-bit integers */ *ins++ = va_arg(args, u4); verifyCount++; break; } } } #ifndef NDEBUG if (verifyCount != method->insSize) { ALOGE("Got vfycount=%d insSize=%d for %s.%s", verifyCount, method->insSize, clazz->descriptor, method->name); assert(false); goto bail; } #endif //dvmDumpThreadStack(dvmThreadSelf()); if (dvmIsNativeMethod(method)) { TRACE_METHOD_ENTER(self, method); /* * Because we leave no space for local variables, "curFrame" points * directly at the method arguments. */ (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult, method, self); TRACE_METHOD_EXIT(self, method); } else { dvmInterpret(self, method, pResult); } #ifndef NDEBUG bail: #endif dvmPopFrame(self); }
/* * Issue a method call with a variable number of arguments. We process * the contents of "args" by scanning the method signature. * * Pass in NULL for "obj" on calls to static methods. * * We don't need to take the class as an argument because, in Dalvik, * we don't need to worry about static synchronized methods. */ void dvmCallMethodV(Thread* self, const Method* method, Object* obj, JValue* pResult, va_list args) { const char* desc = &(method->shorty[1]); // [0] is the return type. int verifyCount = 0; ClassObject* clazz; u4* ins; clazz = callPrep(self, method, obj, false); if (clazz == NULL) return; /* "ins" for new frame start at frame pointer plus locals */ ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize); //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { #ifdef WITH_EXTRA_OBJECT_VALIDATION assert(obj != NULL && dvmIsValidObject(obj)); #endif *ins++ = (u4) obj; verifyCount++; } while (*desc != '\0') { switch (*(desc++)) { case 'D': case 'J': { u8 val = va_arg(args, u8); memcpy(ins, &val, 8); // EABI prevents direct store ins += 2; verifyCount += 2; break; } case 'F': { /* floats were normalized to doubles; convert back */ float f = (float) va_arg(args, double); *ins++ = dvmFloatToU4(f); verifyCount++; break; } #ifdef WITH_EXTRA_OBJECT_VALIDATION case 'L': { /* 'shorty' descr uses L for all refs, incl array */ Object* argObj = (Object*) va_arg(args, u4); assert(obj == NULL || dvmIsValidObject(obj)); *ins++ = (u4) argObj; verifyCount++; break; } #endif default: { *ins++ = va_arg(args, u4); verifyCount++; break; } } } #ifndef NDEBUG if (verifyCount != method->insSize) { LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount, method->insSize, clazz->descriptor, method->name); assert(false); goto bail; } #endif //dvmDumpThreadStack(dvmThreadSelf()); if (dvmIsNativeMethod(method)) { /* * Because we leave no space for local variables, "curFrame" points * directly at the method arguments. */ (*method->nativeFunc)(self->curFrame, pResult, method, self); } else { dvmInterpret(self, method, pResult); } bail: dvmPopFrame(self); }