OSDN Git Service

Dalvik houdini hook rebase on KK
authorllin4 <ling.lin@intel.com>
Tue, 12 Nov 2013 08:38:39 +0000 (16:38 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Thu, 13 Feb 2014 19:58:37 +0000 (03:58 +0800)
Including positive hash code patch port from OTC https://otc-android.intel.com/gerrit/#/c/13089/:
Make x86 version of Dalvik to always return positive hash code
when Houdini is enabled in the platform, to match
the ARM app's assumption on its native platform.
MiTalk fails without this fix.

Category: feature differentiation
Domain: AOSP.Houdini-Integration

Change-Id: I3d5df892360cfccb1acd7a4f13315795384375eb
Signed-off-by: llin4 <ling.lin@intel.com>
vm/Jni.cpp
vm/Native.cpp
vm/ReconfigureDvm.mk
vm/Sync.cpp
vm/oo/Object.h

index 0e77fab..01770d7 100644 (file)
@@ -703,6 +703,14 @@ static void throwNoSuchMethodError(ClassObject* c, const char* name, const char*
     dvmThrowNoSuchMethodError(msg.c_str());
 }
 
+#ifdef WITH_HOUDINI
+namespace houdini {
+bool hookCheckMethod(void *fnPtr);
+void dvmHookPlatformInvoke(void* pEnv, void* clazz, int argInfo, int argc,
+    const int* argv, const char* shorty, void* func, void* pReturn);
+}
+#endif
+
 /*
  * Register a method that uses JNI calling conventions.
  */
@@ -762,6 +770,10 @@ static bool dvmRegisterJNIMethod(ClassObject* clazz, const char* methodName,
         ALOGV("Note: %s.%s:%s was already registered", clazz->descriptor, methodName, signature);
     }
 
+#ifdef WITH_HOUDINI
+    method->needHoudini = houdini::hookCheckMethod(fnPtr);
+#endif
+
     method->fastJni = fastJni;
     dvmUseJNIBridge(method, fnPtr);
 
@@ -1153,6 +1165,13 @@ void dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method, Thr
 
     JNIEnv* env = self->jniEnv;
     COMPUTE_STACK_SUM(self);
+#ifdef WITH_HOUDINI
+    if (dvmNeedHoudiniMethod(method))
+        houdini::dvmHookPlatformInvoke(env, (ClassObject*)staticMethodClass,
+            method->jniArgInfo, method->insSize, (const int*)modArgs, method->shorty,
+            (void*)method->insns, pResult);
+    else
+#endif
     dvmPlatformInvoke(env,
             (ClassObject*) staticMethodClass,
             method->jniArgInfo, method->insSize, modArgs, method->shorty,
index a12c4e0..b39beef 100644 (file)
 static void freeSharedLibEntry(void* ptr);
 static void* lookupSharedLibMethod(const Method* method);
 
+#ifdef WITH_HOUDINI
+/*
+ * Pointer to hold Houdini Hook structure defined in libhoudini_hook.a
+ */
+void *gHoudiniHook = NULL;
+
+namespace houdini {
+void* hookDlopen(const char* filename, int flag, bool* useHoudini);
+void* hookDlsym(bool useHoudini, void* handle, const char* symbol);
+int hookJniOnload(bool useHoudini, void* func, void* jniVm, void* arg);
+}
+/*
+ * Get the shorty string for a method.
+ */
+const char* dvmGetMethodShorty(void* method)
+{
+    const Method* meth = (const Method*)method;
+    return meth->shorty;
+}
+#endif
 
 /*
  * Initialize the native code loader.
@@ -156,6 +176,9 @@ struct SharedLib {
     pthread_cond_t  onLoadCond;     /* wait for JNI_OnLoad in other thread */
     u4              onLoadThreadId; /* recursive invocation guard */
     OnLoadState     onLoadResult;   /* result of earlier JNI_OnLoad */
+#ifdef WITH_HOUDINI
+    bool        useHoudini;
+#endif
 };
 
 /*
@@ -380,7 +403,12 @@ bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
      */
     Thread* self = dvmThreadSelf();
     ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
+#ifdef WITH_HOUDINI
+    bool useHoudini = false;
+    handle = houdini::hookDlopen(pathName, RTLD_LAZY, &useHoudini);
+#else
     handle = dlopen(pathName, RTLD_LAZY);
+#endif
     dvmChangeStatus(self, oldStatus);
 
     if (handle == NULL) {
@@ -394,6 +422,9 @@ bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
     pNewEntry = (SharedLib*) calloc(1, sizeof(SharedLib));
     pNewEntry->pathName = strdup(pathName);
     pNewEntry->handle = handle;
+#ifdef WITH_HOUDINI
+    pNewEntry->useHoudini = useHoudini;
+#endif
     pNewEntry->classLoader = classLoader;
     dvmInitMutex(&pNewEntry->onLoadLock);
     pthread_cond_init(&pNewEntry->onLoadCond, NULL);
@@ -415,7 +446,11 @@ bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
         void* vonLoad;
         int version;
 
+#ifdef WITH_HOUDINI
+        vonLoad = houdini::hookDlsym(useHoudini, handle, "JNI_OnLoad");
+#else
         vonLoad = dlsym(handle, "JNI_OnLoad");
+#endif
         if (vonLoad == NULL) {
             ALOGD("No JNI_OnLoad found in %s %p, skipping init", pathName, classLoader);
             result = true;
@@ -434,7 +469,11 @@ bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
             if (gDvm.verboseJni) {
                 ALOGI("[Calling JNI_OnLoad for \"%s\"]", pathName);
             }
+#ifdef WITH_HOUDINI
+            version = houdini::hookJniOnload(useHoudini, (void*)func, (void*)gDvmJni.jniVm, NULL);
+#else
             version = (*func)(gDvmJni.jniVm, NULL);
+#endif
             dvmChangeStatus(self, oldStatus);
             self->classLoaderOverride = prevOverride;
 
@@ -705,6 +744,10 @@ static int findMethodInLib(void* vlib, void* vmethod)
     } else
         ALOGV("+++ scanning '%s' for '%s'", pLib->pathName, meth->name);
 
+#ifdef WITH_HOUDINI
+    dvmSetHoudiniMethod((Method*)vmethod, pLib->useHoudini);
+#endif
+
     /*
      * First, we try it without the signature.
      */
@@ -718,7 +761,11 @@ static int findMethodInLib(void* vlib, void* vmethod)
         goto bail;
 
     ALOGV("+++ calling dlsym(%s)", mangleCM);
+#ifdef WITH_HOUDINI
+    func = houdini::hookDlsym(pLib->useHoudini, pLib->handle, mangleCM);
+#else
     func = dlsym(pLib->handle, mangleCM);
+#endif
     if (func == NULL) {
         mangleSig =
             createMangledSignature(&meth->prototype);
@@ -732,7 +779,11 @@ static int findMethodInLib(void* vlib, void* vmethod)
         sprintf(mangleCMSig, "%s__%s", mangleCM, mangleSig);
 
         ALOGV("+++ calling dlsym(%s)", mangleCMSig);
+#ifdef WITH_HOUDINI
+        func = houdini::hookDlsym(pLib->useHoudini, pLib->handle, mangleCMSig);
+#else
         func = dlsym(pLib->handle, mangleCMSig);
+#endif
         if (func != NULL) {
             ALOGV("Found '%s' with dlsym", mangleCMSig);
         }
index 6e161c9..d96c628 100644 (file)
@@ -30,8 +30,15 @@ LOCAL_SHARED_LIBRARIES += \
        libselinux \
        libz
 
+ifeq ($(INTEL_HOUDINI),true)
+    LOCAL_CFLAGS += -DWITH_HOUDINI
+endif
 LOCAL_STATIC_LIBRARIES += libdex
 
+ifeq ($(INTEL_HOUDINI),true)
+    LOCAL_STATIC_LIBRARIES += libhoudini_hook
+endif
+
 LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
 LOCAL_SHARED_LIBRARIES += libstlport
 
index f42004c..2b4c025 100644 (file)
@@ -1218,7 +1218,12 @@ void dvmThreadInterrupt(Thread* thread)
 #ifndef WITH_COPYING_GC
 u4 dvmIdentityHashCode(Object *obj)
 {
-    return (u4)obj;
+    /*
+     * The following assumes that objects are allocated at even boundaries, so
+     * the shift preserves uniqueness of hashCode() while guaranteeing a
+     * non-negative result (for the convenience of some applications,like MiTalk).
+     */
+    return (u4)(((u4)obj)>>1);
 }
 #else
 /*
index 92438ba..034f74f 100644 (file)
@@ -578,6 +578,9 @@ struct Method {
 
     /* set if method was called during method profiling */
     bool            inProfile;
+#ifdef WITH_HOUDINI
+    bool            needHoudini;
+#endif
 };
 
 u4 dvmGetMethodIdx(const Method* method);
@@ -691,6 +694,14 @@ INLINE bool dvmIsFinalMethod(const Method* method) {
 INLINE bool dvmIsNativeMethod(const Method* method) {
     return (method->accessFlags & ACC_NATIVE) != 0;
 }
+#ifdef WITH_HOUDINI
+INLINE void dvmSetHoudiniMethod(Method* method, bool needHoudini) {
+    method->needHoudini = needHoudini;
+}
+INLINE bool dvmNeedHoudiniMethod(const Method* method) {
+    return (method->needHoudini);
+}
+#endif
 INLINE bool dvmIsAbstractMethod(const Method* method) {
     return (method->accessFlags & ACC_ABSTRACT) != 0;
 }