bool dvmPerformInlineOp7Dbg(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult, int opIndex, u4 arg4, u4 arg5, u4 arg6) { Method* method = dvmResolveInlineNative(opIndex); if (method == NULL) { return ((InlineOp7Func)(*gDvmInlineOpsTable[opIndex].func))(arg0, arg1, arg2, arg3, pResult, arg4, arg5, arg6); } Thread* self = dvmThreadSelf(); TRACE_METHOD_ENTER(self, method); bool result = ((InlineOp7Func)(*gDvmInlineOpsTable[opIndex].func))(arg0, arg1, arg2, arg3, pResult, arg4, arg5, arg6); TRACE_METHOD_EXIT(self, method); return result; }
HRESULT CNfcRadioManager::FinalRelease() { TRACE_METHOD_ENTRY(LEVEL_VERBOSE); if (NULL != m_nfcDevQuery) { DevCloseObjectQuery(m_nfcDevQuery); m_nfcDevQuery = NULL; } if (m_nfcRadioCollection) { m_nfcRadioCollection->Release(); m_nfcRadioCollection = NULL; } DeleteCriticalSection(&m_csAddRemoveLock); TRACE_METHOD_EXIT(LEVEL_VERBOSE); return S_OK; }
HRESULT CNfcRadioInstanceCollection::FinalRelease() { TRACE_METHOD_ENTRY(LEVEL_VERBOSE); EnterCriticalSection(&m_csListLock); // Free all references for objects in the list and clear up node memory while (m_listHead != NULL) { PNFC_RADIO_NODE tempHead = m_listHead; m_listHead = m_listHead->next; tempHead->nfcRadioInstance->Release(); delete tempHead; m_listLength--; } LeaveCriticalSection(&m_csListLock); DeleteCriticalSection(&m_csListLock); TRACE_METHOD_EXIT(LEVEL_VERBOSE); return S_OK; }
/* * Invoke a method, using the specified arguments and return type, through * one of the reflection interfaces. Could be a virtual or direct method * (including constructors). Used for reflection. * * Deals with boxing/unboxing primitives and performs widening conversions. * * "invokeObj" will be null for a static method. * * If the invocation returns with an exception raised, we have to wrap it. */ Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck) { //salma // __android_log_print(ANDROID_LOG_DEBUG, "DVM DEBUG", "dvmInvokeMethod method name = %s\n,clazz name: %s", method->name, method->clazz->descriptor); //end salma ClassObject* clazz; Object* retObj = NULL; Thread* self = dvmThreadSelf(); s4* ins; int verifyCount, argListLength; JValue retval; bool needPop = false; /* verify arg count */ if (argList != NULL) argListLength = argList->length; else argListLength = 0; if (argListLength != (int) params->length) { dvmThrowExceptionFmt(gDvm.exIllegalArgumentException, "wrong number of arguments; expected %d, got %d", params->length, argListLength); return NULL; } clazz = callPrep(self, method, obj, !noAccessCheck); if (clazz == NULL) return NULL; needPop = true; /* "ins" for new frame start at frame pointer plus locals */ ins = ((s4*)self->interpSave.curFrame) + (method->registersSize - method->insSize); verifyCount = 0; //ALOGD(" FP is %p, INs live at >= %p", self->interpSave.curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { assert(obj != NULL); *ins++ = (s4) obj; verifyCount++; } /* * Copy the args onto the stack. Primitive types are converted when * necessary, and object types are verified. */ DataObject** args = (DataObject**)(void*)argList->contents; ClassObject** types = (ClassObject**)(void*)params->contents; for (int i = 0; i < argListLength; i++) { int width = dvmConvertArgument(*args++, *types++, ins); if (width < 0) { dvmPopFrame(self); // throw wants to pull PC out of stack needPop = false; throwArgumentTypeMismatch(i, *(types-1), *(args-1)); goto bail; } ins += width; verifyCount += width; } #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 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, &retval, method, self); TRACE_METHOD_EXIT(self, method); } else { dvmInterpret(self, method, &retval); } /* * Pop the frame immediately. The "wrap" calls below can cause * allocations, and we don't want the GC to walk the now-dead frame. */ dvmPopFrame(self); needPop = false; /* * If an exception is raised, wrap and replace. This is necessary * because the invoked method could have thrown a checked exception * that the caller wasn't prepared for. * * We might be able to do this up in the interpreted code, but that will * leave us with a shortened stack trace in the top-level exception. */ if (dvmCheckException(self)) { dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); } else { /* * If this isn't a void method or constructor, convert the return type * to an appropriate object. * * We don't do this when an exception is raised because the value * in "retval" is undefined. */ if (returnType != NULL) { retObj = (Object*)dvmBoxPrimitive(retval, returnType); dvmReleaseTrackedAlloc(retObj, NULL); } } bail: if (needPop) { dvmPopFrame(self); } return retObj; }
/* * Issue a method call with arguments provided in an array. We process * the contents of "args" by scanning the method signature. * * The values were likely placed into an uninitialized jvalue array using * the field specifiers, which means that sub-32-bit fields (e.g. short, * boolean) may not have 32 or 64 bits of valid data. This is different * from the varargs invocation where the C compiler does a widening * conversion when calling a function. As a result, we have to be a * little more precise when pulling stuff out. * * "args" may be NULL if the method has no arguments. */ void dvmCallMethodA(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, const jvalue* args) { //salma // __android_log_print(ANDROID_LOG_DEBUG, "DVM DEBUG", "dvmCallMethodA 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); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { assert(obj != NULL); *ins++ = (u4) obj; /* obj is a "real" ref */ verifyCount++; } while (*desc != '\0') { switch (*desc++) { case 'D': /* 64-bit quantity; have to use */ case 'J': /* memcpy() in case of mis-alignment */ memcpy(ins, &args->j, 8); ins += 2; verifyCount++; /* this needs an extra push */ break; case 'L': /* includes array refs */ if (fromJni) *ins++ = (u4) dvmDecodeIndirectRef(self, args->l); else *ins++ = (u4) args->l; break; case 'F': case 'I': *ins++ = args->i; /* full 32 bits */ break; case 'S': *ins++ = args->s; /* 16 bits, sign-extended */ break; case 'C': *ins++ = args->c; /* 16 bits, unsigned */ break; case 'B': *ins++ = args->b; /* 8 bits, sign-extended */ break; case 'Z': *ins++ = args->z; /* 8 bits, zero or non-zero */ break; default: ALOGE("Invalid char %c in short signature of %s.%s", *(desc-1), clazz->descriptor, method->name); assert(false); goto bail; } verifyCount++; args++; } #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 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); } bail: 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); }
/* * Invoke a method, using the specified arguments and return type, through * one of the reflection interfaces. Could be a virtual or direct method * (including constructors). Used for reflection. * * Deals with boxing/unboxing primitives and performs widening conversions. * * "invokeObj" will be null for a static method. * * If the invocation returns with an exception raised, we have to wrap it. */ Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck) { ClassObject* clazz; Object* retObj = NULL; Thread* self = dvmThreadSelf(); s4* ins; int verifyCount, argListLength; JValue retval; /* verify arg count */ if (argList != NULL) argListLength = argList->length; else argListLength = 0; if (argListLength != (int) params->length) { LOGI("invoke: expected %d args, received %d args\n", params->length, argListLength); dvmThrowException("Ljava/lang/IllegalArgumentException;", "wrong number of arguments"); return NULL; } clazz = callPrep(self, method, obj, !noAccessCheck); if (clazz == NULL) return NULL; /* "ins" for new frame start at frame pointer plus locals */ ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); verifyCount = 0; //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { assert(obj != NULL); *ins++ = (s4) obj; verifyCount++; } /* * Copy the args onto the stack. Primitive types are converted when * necessary, and object types are verified. */ DataObject** args; ClassObject** types; int i; args = (DataObject**) argList->contents; types = (ClassObject**) params->contents; for (i = 0; i < argListLength; i++) { int width; width = dvmConvertArgument(*args++, *types++, ins); if (width < 0) { if (*(args-1) != NULL) { LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n", i, (*(args-1))->obj.clazz->descriptor, (*(types-1))->descriptor); } dvmPopFrame(self); // throw wants to pull PC out of stack dvmThrowException("Ljava/lang/IllegalArgumentException;", "argument type mismatch"); goto bail_popped; } ins += width; verifyCount += width; } 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; } //dvmDumpThreadStack(dvmThreadSelf()); if (dvmIsNativeMethod(method)) { #ifdef WITH_PROFILER TRACE_METHOD_ENTER(self, method); #endif /* * Because we leave no space for local variables, "curFrame" points * directly at the method arguments. */ (*method->nativeFunc)(self->curFrame, &retval, method, self); #ifdef WITH_PROFILER TRACE_METHOD_EXIT(self, method); #endif } else { dvmInterpret(self, method, &retval); } /* * If an exception is raised, wrap and replace. This is necessary * because the invoked method could have thrown a checked exception * that the caller wasn't prepared for. * * We might be able to do this up in the interpreted code, but that will * leave us with a shortened stack trace in the top-level exception. */ if (dvmCheckException(self)) { dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); } else { /* * If this isn't a void method or constructor, convert the return type * to an appropriate object. * * We don't do this when an exception is raised because the value * in "retval" is undefined. */ if (returnType != NULL) { retObj = (Object*)dvmWrapPrimitive(retval, returnType); dvmReleaseTrackedAlloc(retObj, NULL); } } bail: dvmPopFrame(self); bail_popped: return retObj; }
/* * Invoke a method, using the specified arguments and return type, through * one of the reflection interfaces. Could be a virtual or direct method * (including constructors). Used for reflection. * * Deals with boxing/unboxing primitives and performs widening conversions. * * "invokeObj" will be null for a static method. * * If the invocation returns with an exception raised, we have to wrap it. */ Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck) { ClassObject* clazz; Object* retObj = NULL; Thread* self = dvmThreadSelf(); s4* ins; int verifyCount, argListLength; JValue retval; bool needPop = false; #ifdef WITH_TAINT_TRACKING u4 rtaint = TAINT_CLEAR; int slot_cnt = 0; bool nativeTarget = dvmIsNativeMethod(method); /* For simplicity, argument tags for native targets * are unioned. This may cause false positives, but * it is the easiest way to handle this for now. */ u4 nativeTag = TAINT_CLEAR; #endif /* verify arg count */ if (argList != NULL) argListLength = argList->length; else argListLength = 0; if (argListLength != (int) params->length) { LOGI("invoke: expected %d args, received %d args\n", params->length, argListLength); dvmThrowException("Ljava/lang/IllegalArgumentException;", "wrong number of arguments"); return NULL; } clazz = callPrep(self, method, obj, !noAccessCheck); if (clazz == NULL) return NULL; needPop = true; /* "ins" for new frame start at frame pointer plus locals */ #ifdef WITH_TAINT_TRACKING if (nativeTarget) { /* native target, no taint tag interleaving */ ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); } else { /* interpreted target, taint tags are interleaved */ ins = ((s4*)self->curFrame) + ((method->registersSize - method->insSize) << 1); } #else ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize); #endif verifyCount = 0; //LOGD(" FP is %p, INs live at >= %p\n", self->curFrame, ins); /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { assert(obj != NULL); *ins++ = (s4) obj; #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; } /* * Copy the args onto the stack. Primitive types are converted when * necessary, and object types are verified. */ DataObject** args; ClassObject** types; int i; args = (DataObject**) argList->contents; types = (ClassObject**) params->contents; for (i = 0; i < argListLength; i++) { int width; #ifdef WITH_TAINT_TRACKING int tag = dvmGetPrimitiveTaint(*args, *types); #endif width = dvmConvertArgument(*args++, *types++, ins); if (width < 0) { if (*(args-1) != NULL) { LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n", i, (*(args-1))->obj.clazz->descriptor, (*(types-1))->descriptor); } dvmPopFrame(self); // throw wants to pull PC out of stack needPop = false; dvmThrowException("Ljava/lang/IllegalArgumentException;", "argument type mismatch"); goto bail; } #ifdef WITH_TAINT_TRACKING /* dvmConvertArgument() returns -1, 1, or 2 */ if (nativeTarget) { nativeTag |= tag; /* TODO: is there a better way to do this?*/ ins += width; } else { if (width == 2) { ins[2] = ins[1]; ins[1] = tag; ins[3] = tag; ins += 4; } else if (width == 1) { ins[1] = tag; ins += 2; } else { /* error condition duplicated from above */ dvmPopFrame(self); dvmThrowException("Ljava/lang/IllegalArgumentException;", "argument type mismatch"); goto bail_popped; } } slot_cnt += width; #else ins += width; #endif verifyCount += width; } #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++ = nativeTag; /* TODO: better way? */ } } } #endif 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; } //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, &retval, method, self); TRACE_METHOD_EXIT(self, method); #ifdef WITH_TAINT_TRACKING rtaint = ((u4*)self->curFrame)[slot_cnt]; #endif } else { #ifdef WITH_TAINT_TRACKING dvmInterpret(self, method, &retval, &rtaint); #else dvmInterpret(self, method, &retval); #endif } /* * Pop the frame immediately. The "wrap" calls below can cause * allocations, and we don't want the GC to walk the now-dead frame. */ dvmPopFrame(self); needPop = false; /* * If an exception is raised, wrap and replace. This is necessary * because the invoked method could have thrown a checked exception * that the caller wasn't prepared for. * * We might be able to do this up in the interpreted code, but that will * leave us with a shortened stack trace in the top-level exception. */ if (dvmCheckException(self)) { dvmWrapException("Ljava/lang/reflect/InvocationTargetException;"); } else { /* * If this isn't a void method or constructor, convert the return type * to an appropriate object. * * We don't do this when an exception is raised because the value * in "retval" is undefined. */ if (returnType != NULL) { retObj = (Object*)dvmWrapPrimitive(retval, returnType); #ifdef WITH_TAINT_TRACKING dvmSetPrimitiveTaint((DataObject *)retObj, returnType, rtaint); #endif dvmReleaseTrackedAlloc(retObj, NULL); } } bail: if (needPop) { dvmPopFrame(self); } bail_popped: return retObj; }
/* * Issue a method call with arguments provided in an array. We process * the contents of "args" by scanning the method signature. * * The values were likely placed into an uninitialized jvalue array using * the field specifiers, which means that sub-32-bit fields (e.g. short, * boolean) may not have 32 or 64 bits of valid data. This is different * from the varargs invocation where the C compiler does a widening * conversion when calling a function. As a result, we have to be a * little more precise when pulling stuff out. * * "args" may be NULL if the method has no arguments. */ void dvmCallMethodA(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, const jvalue* 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 /* put "this" pointer into in0 if appropriate */ if (!dvmIsStaticMethod(method)) { assert(obj != NULL); *ins++ = (u4) obj; /* obj is a "real" ref */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif verifyCount++; } JNIEnv* env = self->jniEnv; while (*desc != '\0') { switch (*desc++) { case 'D': /* 64-bit quantity; have to use */ case 'J': /* memcpy() in case of mis-alignment */ memcpy(ins, &args->j, 8); #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++; /* this needs an extra push */ break; case 'L': /* includes array refs */ if (fromJni) *ins++ = (u4) dvmDecodeIndirectRef(env, args->l); else *ins++ = (u4) args->l; #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; case 'F': case 'I': *ins++ = args->i; /* full 32 bits */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; case 'S': *ins++ = args->s; /* 16 bits, sign-extended */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; case 'C': *ins++ = args->c; /* 16 bits, unsigned */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; case 'B': *ins++ = args->b; /* 8 bits, sign-extended */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; case 'Z': *ins++ = args->z; /* 8 bits, zero or non-zero */ #ifdef WITH_TAINT_TRACKING if (!nativeTarget) { *ins++ = TAINT_CLEAR; } slot_cnt++; #endif break; default: LOGE("Invalid char %c in short signature of %s.%s\n", *(desc-1), clazz->descriptor, method->name); assert(false); goto bail; } verifyCount++; args++; } #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 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 } bail: 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) { 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); }