1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1659b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Native method resolution. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Currently the "Dalvik native" methods are only used for internal methods. 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Someday we may want to export the interface as a faster but riskier 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * alternative to JNI. 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <dlfcn.h> 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeSharedLibEntry(void* ptr); 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* lookupSharedLibMethod(const Method* method); 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize the native code loader. 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 361e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmNativeStartup() 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.nativeLibs = dvmHashTableCreate(4, freeSharedLibEntry); 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.nativeLibs == NULL) 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up our tables. 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 481e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmNativeShutdown() 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmHashTableFree(gDvm.nativeLibs); 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.nativeLibs = NULL; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Resolve a native method and invoke it. 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is executed as if it were a native bridge or function. If the 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resolution succeeds, method->insns is replaced, and we don't go through 601e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * here again unless the method is unregistered. 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initializes method's class if necessary. 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An exception is thrown on resolution failure. 6559b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * 6659b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * (This should not be taking "const Method*", because it modifies the 6759b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * structure, but the declaration needs to match the DalvikBridgeFunc 6859b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden * type definition.) 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmResolveNativeMethod(const u4* args, JValue* pResult, 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method, Thread* self) 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* clazz = method->clazz; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this is a static method, it could be called before the class 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has been initialized. 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsStaticMethod(method)) { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(dvmThreadSelf())); 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsClassInitialized(clazz) || 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmIsClassInitializing(clazz)); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* start with our internal-native methods */ 90d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro DalvikNativeFunc infunc = dvmLookupInternalNativeMethod(method); 91d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro if (infunc != NULL) { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* resolution always gets the same answer, so no race here */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 9560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("+++ resolved native %s.%s %s, invoking", 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsSynchronizedMethod(method)) { 100c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("ERROR: internal-native can't be declared 'synchronized'"); 101c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Failing on %s.%s", method->clazz->descriptor, method->name); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // harsh, but this is VM-internal problem 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro DalvikBridgeFunc dfunc = (DalvikBridgeFunc) infunc; 1051e83b4d026199073c057edcb7836d06ae0716390Andy McFadden dvmSetNativeFunc((Method*) method, dfunc, NULL); 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dfunc(args, pResult, method, self); 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* now scan any DLLs we have loaded for JNI signatures */ 111d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro void* func = lookupSharedLibMethod(method); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func != NULL) { 11359b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden /* found it, point it at the JNI bridge and then call it */ 11459b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden dvmUseJNIBridge((Method*) method, func); 1150083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden (*method->nativeFunc)(args, pResult, method, self); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block IF_ALOGW() { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1215cc74502e62d99d40f5c7a841a57fafde5e7ed33Andy McFadden ALOGW("No implementation found for native %s.%s:%s", 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1265cc74502e62d99d40f5c7a841a57fafde5e7ed33Andy McFadden dvmThrowUnsatisfiedLinkError("Native method not found", method); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Native shared library support 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// TODO? if a ClassLoader is unloaded, we need to unload all DLLs that 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// are associated with it. (Or not -- can't determine if native code 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// is still using parts of it.) 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 140d862faa2ceae186da5518607505eb942d634ced9Carl Shapiroenum OnLoadState { 14170318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadPending = 0, /* initial state, must be zero */ 14270318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadFailed, 14370318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadOkay, 144d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 14570318889578ab67943d6df29fedf09b11cfef015Andy McFadden 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We add one of these to the hash table for every library we load. The 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hash is on the "pathName" field. 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 150d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct SharedLib { 15170318889578ab67943d6df29fedf09b11cfef015Andy McFadden char* pathName; /* absolute path to library */ 15270318889578ab67943d6df29fedf09b11cfef015Andy McFadden void* handle; /* from dlopen */ 15370318889578ab67943d6df29fedf09b11cfef015Andy McFadden Object* classLoader; /* ClassLoader we are associated with */ 15470318889578ab67943d6df29fedf09b11cfef015Andy McFadden 15570318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_mutex_t onLoadLock; /* guards remaining items */ 15670318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_t onLoadCond; /* wait for JNI_OnLoad in other thread */ 15770318889578ab67943d6df29fedf09b11cfef015Andy McFadden u4 onLoadThreadId; /* recursive invocation guard */ 15870318889578ab67943d6df29fedf09b11cfef015Andy McFadden OnLoadState onLoadResult; /* result of earlier JNI_OnLoad */ 159d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro}; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.) 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the string. 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpNameStr(const void* ventry, const void* vname) 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) ventry; 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* name = (const char*) vname; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strcmp(pLib->pathName, name); 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.) 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the new entry. 17870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 17970318889578ab67943d6df29fedf09b11cfef015Andy McFadden * We don't compare the class loader here, because you're not allowed to 18070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * have the same shared library associated with more than one CL. 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpSharedLib(const void* ventry, const void* vnewEntry) 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) ventry; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pNewLib = (const SharedLib*) vnewEntry; 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 187062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("--- comparing %p '%s' %p '%s'", 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pLib, pLib->pathName, pNewLib, pNewLib->pathName); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strcmp(pLib->pathName, pNewLib->pathName); 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check to see if an entry with the same pathname already exists. 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 19570318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic SharedLib* findSharedLibEntry(const char* pathName) 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 hash = dvmComputeUtf8Hash(pathName); 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* ent; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ent = dvmHashTableLookup(gDvm.nativeLibs, hash, (void*)pathName, 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashcmpNameStr, false); 202fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro return (SharedLib*)ent; 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the new entry to the table. 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 20870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Returns the table entry, which will not be the same as "pLib" if the 20970318889578ab67943d6df29fedf09b11cfef015Andy McFadden * entry already exists. 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 21170318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic SharedLib* addSharedLibEntry(SharedLib* pLib) 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 hash = dvmComputeUtf8Hash(pLib->pathName); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Do the lookup with the "add" flag set. If we add it, we will get 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our own pointer back. If somebody beat us to the punch, we'll get 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * their pointer back instead. 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 220fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro return (SharedLib*)dvmHashTableLookup(gDvm.nativeLibs, hash, pLib, 221fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro hashcmpSharedLib, true); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up an entry. (This is a dvmHashTableFree callback.) 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeSharedLibEntry(void* ptr) 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SharedLib* pLib = (SharedLib*) ptr; 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calling dlclose() here is somewhat dangerous, because it's possible 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that a thread outside the VM is still accessing the code we loaded. 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (false) 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dlclose(pLib->handle); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pLib->pathName); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pLib); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert library name to system-dependent form, e.g. "jpeg" becomes 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "libjpeg.so". 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Should we have this take buffer+len and avoid the alloc? It gets 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called very rarely.) 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmCreateSystemLibraryName(char* libName) 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char buf[256]; 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len; 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project len = snprintf(buf, sizeof(buf), OS_SHARED_LIB_FORMAT_STR, libName); 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len >= (int) sizeof(buf)) 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strdup(buf); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 26070318889578ab67943d6df29fedf09b11cfef015Andy McFadden/* 26170318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Check the result of an earlier call to JNI_OnLoad on this library. If 26270318889578ab67943d6df29fedf09b11cfef015Andy McFadden * the call has not yet finished in another thread, wait for it. 26370318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 26470318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic bool checkOnLoadResult(SharedLib* pEntry) 26570318889578ab67943d6df29fedf09b11cfef015Andy McFadden{ 26670318889578ab67943d6df29fedf09b11cfef015Andy McFadden Thread* self = dvmThreadSelf(); 26770318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pEntry->onLoadThreadId == self->threadId) { 26870318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 26970318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Check this so we don't end up waiting for ourselves. We need 27070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * to return "true" so the caller can continue. 27170318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 2724308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("threadid=%d: recursive native library load attempt (%s)", 27370318889578ab67943d6df29fedf09b11cfef015Andy McFadden self->threadId, pEntry->pathName); 27470318889578ab67943d6df29fedf09b11cfef015Andy McFadden return true; 27570318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 27670318889578ab67943d6df29fedf09b11cfef015Andy McFadden 27792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ retrieving %s OnLoad status", pEntry->pathName); 27870318889578ab67943d6df29fedf09b11cfef015Andy McFadden bool result; 27970318889578ab67943d6df29fedf09b11cfef015Andy McFadden 28070318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmLockMutex(&pEntry->onLoadLock); 28170318889578ab67943d6df29fedf09b11cfef015Andy McFadden while (pEntry->onLoadResult == kOnLoadPending) { 282062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("threadid=%d: waiting for %s OnLoad status", 28370318889578ab67943d6df29fedf09b11cfef015Andy McFadden self->threadId, pEntry->pathName); 2845617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 28570318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_wait(&pEntry->onLoadCond, &pEntry->onLoadLock); 28670318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmChangeStatus(self, oldStatus); 28770318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 28870318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pEntry->onLoadResult == kOnLoadOkay) { 28992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ earlier OnLoad(%s) okay", pEntry->pathName); 29070318889578ab67943d6df29fedf09b11cfef015Andy McFadden result = true; 29170318889578ab67943d6df29fedf09b11cfef015Andy McFadden } else { 29292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ earlier OnLoad(%s) failed", pEntry->pathName); 29370318889578ab67943d6df29fedf09b11cfef015Andy McFadden result = false; 29470318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 29570318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmUnlockMutex(&pEntry->onLoadLock); 29670318889578ab67943d6df29fedf09b11cfef015Andy McFadden return result; 29770318889578ab67943d6df29fedf09b11cfef015Andy McFadden} 29870318889578ab67943d6df29fedf09b11cfef015Andy McFadden 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef int (*OnLoadFunc)(JavaVM*, void*); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load native code from the specified absolute pathname. Per the spec, 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if we've already loaded a library with the specified pathname, we 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return without doing anything. 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO? for better results we should absolutify the pathname. For fully 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * correct results we should stat to get the inode and compare that. The 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * existing implementation is fine so long as everybody is using 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * System.loadLibrary. 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The library will be associated with the specified class loader. The JNI 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec says we can't load the same library into more than one class loader. 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 314f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes * Returns "true" on success. On failure, sets *detail to a 315f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes * human-readable description of the error or NULL if no detail is 316f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes * available; ownership of the string is transferred to the caller. 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 318f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughesbool dvmLoadNativeCode(const char* pathName, Object* classLoader, 319f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes char** detail) 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 32170318889578ab67943d6df29fedf09b11cfef015Andy McFadden SharedLib* pEntry; 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* handle; 323dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden bool verbose; 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 325dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden /* reduce noise by not chattering about system libraries */ 326b14f405c4492f770c14c9252e81ff4df4401c0efDima Zavin verbose = !!strncmp(pathName, "/system", sizeof("/system")-1); 327b14f405c4492f770c14c9252e81ff4df4401c0efDima Zavin verbose = verbose && !!strncmp(pathName, "/vendor", sizeof("/vendor")-1); 328dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden 329dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) 330062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Trying to load lib %s %p", pathName, classLoader); 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 332f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes *detail = NULL; 333f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if we've already loaded it. If we have, and the class loader 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * matches, return successfully without doing anything. 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pEntry = findSharedLibEntry(pathName); 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pEntry != NULL) { 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pEntry->classLoader != classLoader) { 341e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Shared lib '%s' already opened by CL %p; can't open in %p", 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathName, pEntry->classLoader, classLoader); 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 345dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) { 346062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Shared lib '%s' already loaded in same CL %p", 347dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden pathName, classLoader); 348dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden } 34970318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (!checkOnLoadResult(pEntry)) 35070318889578ab67943d6df29fedf09b11cfef015Andy McFadden return false; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open the shared library. Because we're using a full path, the system 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * doesn't have to search through LD_LIBRARY_PATH. (It may do so to 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resolve this library's dependencies though.) 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 35999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Failures here are expected when java.library.path has several entries 36099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and we have to hunt for the lib. 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 362dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * The current version of the dynamic linker prints detailed information 363dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * about dlopen() failures. Some things to check if the message is 364dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * cryptic: 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - make sure the library exists on the device 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - verify that the right path is being opened (the debug log message 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * above can help with that) 36899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * - check to see if the library is valid (e.g. not zero bytes long) 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - check config/prelink-linux-arm.map to ensure that the library 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is listed and is not being overrun by the previous entry (if 37199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * loading suddenly stops working on a prelinked library, this is 37299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * a good one to check) 37399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * - write a trivial app that calls sleep() then dlopen(), attach 37499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * to it with "strace -p <pid>" while it sleeps, and watch for 37599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * attempts to open nonexistent dependent shared libs 3762aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * 3772aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * This can execute slowly for a large library on a busy system, so we 3782aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * want to switch from RUNNING to VMWAIT while it executes. This allows 3792aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * the GC to ignore us. 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3812aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden Thread* self = dvmThreadSelf(); 3825617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project handle = dlopen(pathName, RTLD_LAZY); 3842aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden dvmChangeStatus(self, oldStatus); 3852aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (handle == NULL) { 387f584b4a56e1d5b98ddd914cf5d40b7616bfa1302Elliott Hughes *detail = strdup(dlerror()); 388bab2237924fa26e16f732965657f8ff93ab27f37Elliott Hughes ALOGE("dlopen(\"%s\") failed: %s", pathName, *detail); 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39270318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* create a new entry */ 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SharedLib* pNewEntry; 39470318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry = (SharedLib*) calloc(1, sizeof(SharedLib)); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->pathName = strdup(pathName); 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->handle = handle; 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->classLoader = classLoader; 39870318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmInitMutex(&pNewEntry->onLoadLock); 39970318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_init(&pNewEntry->onLoadCond, NULL); 40070318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadThreadId = self->threadId; 40170318889578ab67943d6df29fedf09b11cfef015Andy McFadden 40270318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* try to add it to the list */ 40370318889578ab67943d6df29fedf09b11cfef015Andy McFadden SharedLib* pActualEntry = addSharedLibEntry(pNewEntry); 40470318889578ab67943d6df29fedf09b11cfef015Andy McFadden 40570318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pNewEntry != pActualEntry) { 4064308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("WOW: we lost a race to add a shared lib (%s CL=%p)", 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathName, classLoader); 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project freeSharedLibEntry(pNewEntry); 40970318889578ab67943d6df29fedf09b11cfef015Andy McFadden return checkOnLoadResult(pActualEntry); 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 411dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) 412062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Added shared lib %s %p", pathName, classLoader); 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 414d04ecb0b450c0c7a059ee355f6aed7c9f65b671eElliott Hughes bool result = false; 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* vonLoad; 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int version; 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vonLoad = dlsym(handle, "JNI_OnLoad"); 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vonLoad == NULL) { 420d1839748820ad0766d31ee5a20d190ed07315d23Elliott Hughes ALOGD("No JNI_OnLoad found in %s %p, skipping init", pathName, classLoader); 421d1839748820ad0766d31ee5a20d190ed07315d23Elliott Hughes result = true; 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call JNI_OnLoad. We have to override the current class 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader, which will always be "null" since the stuff at the 42670318889578ab67943d6df29fedf09b11cfef015Andy McFadden * top of the stack is around Runtime.loadLibrary(). (See 42770318889578ab67943d6df29fedf09b11cfef015Andy McFadden * the comments in the JNI FindClass function.) 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 429fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro OnLoadFunc func = (OnLoadFunc)vonLoad; 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* prevOverride = self->classLoaderOverride; 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->classLoaderOverride = classLoader; 4332aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden oldStatus = dvmChangeStatus(self, THREAD_NATIVE); 4345719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes if (gDvm.verboseJni) { 4354308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("[Calling JNI_OnLoad for \"%s\"]", pathName); 4365719d5c79558ffdbbb863ddcf61836221aba922dElliott Hughes } 437d5c80e06a771bb34336c1ec5b0d9ce8a47ec4244Elliott Hughes version = (*func)(gDvmJni.jniVm, NULL); 4382aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden dvmChangeStatus(self, oldStatus); 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->classLoaderOverride = prevOverride; 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 441ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes if (version == JNI_ERR) { 442ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes *detail = strdup(StringPrintf("JNI_ERR returned from JNI_OnLoad in \"%s\"", 443ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes pathName).c_str()); 444ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes } else if (dvmIsBadJniVersion(version)) { 445ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes *detail = strdup(StringPrintf("Bad JNI version returned from JNI_OnLoad in \"%s\": %d", 446ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes pathName, version).c_str()); 44770318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 44870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * It's unwise to call dlclose() here, but we can mark it 44970318889578ab67943d6df29fedf09b11cfef015Andy McFadden * as bad and ensure that future load attempts will fail. 45070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 45170318889578ab67943d6df29fedf09b11cfef015Andy McFadden * We don't know how far JNI_OnLoad got, so there could 45270318889578ab67943d6df29fedf09b11cfef015Andy McFadden * be some partially-initialized stuff accessible through 45370318889578ab67943d6df29fedf09b11cfef015Andy McFadden * newly-registered native method calls. We could try to 45470318889578ab67943d6df29fedf09b11cfef015Andy McFadden * unregister them, but that doesn't seem worthwhile. 45570318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 456d04ecb0b450c0c7a059ee355f6aed7c9f65b671eElliott Hughes } else { 457d04ecb0b450c0c7a059ee355f6aed7c9f65b671eElliott Hughes result = true; 458ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes } 459ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes if (gDvm.verboseJni) { 460ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes ALOGI("[Returned %s from JNI_OnLoad for \"%s\"]", 461ff7ff110d17428732a97c37bf31f7f49d194f638Elliott Hughes (result ? "successfully" : "failure"), pathName); 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46570318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (result) 46670318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadResult = kOnLoadOkay; 46770318889578ab67943d6df29fedf09b11cfef015Andy McFadden else 46870318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadResult = kOnLoadFailed; 46970318889578ab67943d6df29fedf09b11cfef015Andy McFadden 47070318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadThreadId = 0; 47170318889578ab67943d6df29fedf09b11cfef015Andy McFadden 47270318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 47370318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Broadcast a wakeup to anybody sleeping on the condition variable. 47470318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 47570318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmLockMutex(&pNewEntry->onLoadLock); 47670318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_broadcast(&pNewEntry->onLoadCond); 47770318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmUnlockMutex(&pNewEntry->onLoadLock); 47870318889578ab67943d6df29fedf09b11cfef015Andy McFadden return result; 47970318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 4841e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * Un-register JNI native methods. 4851e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * 4861e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * There are two relevant fields in struct Method, "nativeFunc" and 4871e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * "insns". The former holds a function pointer to a "bridge" function 4881e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * (or, for internal native, the actual implementation). The latter holds 4891e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * a pointer to the actual JNI method. 4901e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * 4911e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * The obvious approach is to reset both fields to their initial state 4921e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * (nativeFunc points at dvmResolveNativeMethod, insns holds NULL), but 4931e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * that creates some unpleasant race conditions. In particular, if another 4941e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * thread is executing inside the call bridge for the method in question, 4951e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * and we reset insns to NULL, the VM will crash. (See the comments above 4961e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * dvmSetNativeFunc() for additional commentary.) 4971e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * 4981e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * We can't rely on being able to update two 32-bit fields in one atomic 4991e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * operation (e.g. no 64-bit atomic ops on ARMv5TE), so we want to change 5001e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * only one field. It turns out we can simply reset nativeFunc to its 5011e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * initial state, leaving insns alone, because dvmResolveNativeMethod 5021e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * ignores "insns" entirely. 5031e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * 5041e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * When the method is re-registered, both fields will be updated, but 5051e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * dvmSetNativeFunc guarantees that "insns" is updated first. This means 5061e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * we shouldn't be in a situation where we have a "live" call bridge and 5071e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * a stale implementation pointer. 5081e83b4d026199073c057edcb7836d06ae0716390Andy McFadden */ 5091e83b4d026199073c057edcb7836d06ae0716390Andy McFaddenstatic void unregisterJNINativeMethods(Method* methods, size_t count) 5101e83b4d026199073c057edcb7836d06ae0716390Andy McFadden{ 5111e83b4d026199073c057edcb7836d06ae0716390Andy McFadden while (count != 0) { 5121e83b4d026199073c057edcb7836d06ae0716390Andy McFadden count--; 5131e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 5141e83b4d026199073c057edcb7836d06ae0716390Andy McFadden Method* meth = &methods[count]; 5151e83b4d026199073c057edcb7836d06ae0716390Andy McFadden if (!dvmIsNativeMethod(meth)) 5161e83b4d026199073c057edcb7836d06ae0716390Andy McFadden continue; 5171e83b4d026199073c057edcb7836d06ae0716390Andy McFadden if (dvmIsAbstractMethod(meth)) /* avoid abstract method stubs */ 5181e83b4d026199073c057edcb7836d06ae0716390Andy McFadden continue; 5191e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 5201e83b4d026199073c057edcb7836d06ae0716390Andy McFadden /* 5211e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * Strictly speaking this ought to test the function pointer against 5221e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * the various JNI bridge functions to ensure that we only undo 5231e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * methods that were registered through JNI. In practice, any 5241e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * native method with a non-NULL "insns" is a registered JNI method. 5251e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * 5261e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * If we inadvertently unregister an internal-native, it'll get 5271e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * re-resolved on the next call; unregistering an unregistered 5281e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * JNI method is a no-op. So we don't really need to test for 5291e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * anything. 5301e83b4d026199073c057edcb7836d06ae0716390Andy McFadden */ 5311e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 532062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Unregistering JNI method %s.%s:%s", 5331e83b4d026199073c057edcb7836d06ae0716390Andy McFadden meth->clazz->descriptor, meth->name, meth->shorty); 5341e83b4d026199073c057edcb7836d06ae0716390Andy McFadden dvmSetNativeFunc(meth, dvmResolveNativeMethod, NULL); 5351e83b4d026199073c057edcb7836d06ae0716390Andy McFadden } 5361e83b4d026199073c057edcb7836d06ae0716390Andy McFadden} 5371e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 5381e83b4d026199073c057edcb7836d06ae0716390Andy McFadden/* 5391e83b4d026199073c057edcb7836d06ae0716390Andy McFadden * Un-register all JNI native methods from a class. 5401e83b4d026199073c057edcb7836d06ae0716390Andy McFadden */ 5411e83b4d026199073c057edcb7836d06ae0716390Andy McFaddenvoid dvmUnregisterJNINativeMethods(ClassObject* clazz) 5421e83b4d026199073c057edcb7836d06ae0716390Andy McFadden{ 5431e83b4d026199073c057edcb7836d06ae0716390Andy McFadden unregisterJNINativeMethods(clazz->directMethods, clazz->directMethodCount); 5441e83b4d026199073c057edcb7836d06ae0716390Andy McFadden unregisterJNINativeMethods(clazz->virtualMethods, clazz->virtualMethodCount); 5451e83b4d026199073c057edcb7836d06ae0716390Andy McFadden} 5461e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 5471e83b4d026199073c057edcb7836d06ae0716390Andy McFadden 5481e83b4d026199073c057edcb7836d06ae0716390Andy McFadden/* 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Signature-based method lookup 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the pre-mangled form of the class+method string. 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated string, and sets "*pLen" to the length. 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createJniNameString(const char* classDescriptor, 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* methodName, int* pLen) 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* result; 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t descriptorLength = strlen(classDescriptor); 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pLen = 4 + descriptorLength + strlen(methodName); 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 567fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro result = (char*)malloc(*pLen +1); 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result == NULL) 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add one to classDescriptor to skip the "L", and then replace 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the final ";" with a "/" after the sprintf() call. 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(result, "Java/%s%s", classDescriptor + 1, methodName); 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result[5 + (descriptorLength - 2)] = '/'; 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated, mangled copy of "str". 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "str" is a "modified UTF-8" string. We convert it to UTF-16 first to 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * make life simpler. 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* mangleString(const char* str, int len) 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 5894308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block //ALOGI("mangling '%s' %d", str, len); 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(str[len] == '\0'); 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 593d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro size_t charLen = dvmUtf8Len(str); 594d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro u2* utf16 = (u2*) malloc(sizeof(u2) * charLen); 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (utf16 == NULL) 596d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro return NULL; 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmConvertUtf8ToUtf16(utf16, str); 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of the mangled string. 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 603d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro size_t mangleLen = 0; 604d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro for (size_t i = 0; i < charLen; i++) { 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 ch = utf16[i]; 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 607dfdaa8733814dd1a576aec0a0a735848384009dfBrian McKenna if (ch == '$' || ch > 127) { 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen += 6; 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (ch) { 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '_': 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case ';': 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '[': 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen += 2; 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen++; 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 623d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro char* mangle = (char*) malloc(mangleLen +1); 624d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro if (mangle == NULL) { 625d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro free(utf16); 626d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro return NULL; 627d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro } 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 629d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro char* cp = mangle; 630d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro for (size_t i = 0; i < charLen; i++) { 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 ch = utf16[i]; 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 633dfdaa8733814dd1a576aec0a0a735848384009dfBrian McKenna if (ch == '$' || ch > 127) { 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(cp, "_0%04x", ch); 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cp += 6; 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (ch) { 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '_': 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '1'; 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case ';': 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '2'; 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '[': 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '3'; 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '/': 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = (char) ch; 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp = '\0'; 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(utf16); 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mangle; 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the mangled form of the parameter types. 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createMangledSignature(const DexProto* proto) 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexStringCache sigCache; 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* interim; 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* result; 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexStringCacheInit(&sigCache); 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project interim = dexProtoGetParameterDescriptors(proto, &sigCache); 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = mangleString(interim, strlen(interim)); 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexStringCacheRelease(&sigCache); 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashForeach callback.) 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search for a matching method in this shared library. 68770318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 68870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * TODO: we may want to skip libraries for which JNI_OnLoad failed. 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findMethodInLib(void* vlib, void* vmethod) 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) vlib; 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* meth = (const Method*) vmethod; 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* preMangleCM = NULL; 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleCM = NULL; 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleSig = NULL; 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleCMSig = NULL; 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* func = NULL; 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len; 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (meth->clazz->classLoader != pLib->classLoader) { 70292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ not scanning '%s' for '%s' (wrong CL)", 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pLib->pathName, meth->name); 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else 70692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ scanning '%s' for '%s'", pLib->pathName, meth->name); 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * First, we try it without the signature. 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project preMangleCM = 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project createJniNameString(meth->clazz->descriptor, meth->name, &len); 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (preMangleCM == NULL) 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleCM = mangleString(preMangleCM, len); 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleCM == NULL) 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ calling dlsym(%s)", mangleCM); 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = dlsym(pLib->handle, mangleCM); 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func == NULL) { 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleSig = 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project createMangledSignature(&meth->prototype); 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleSig == NULL) 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleCMSig = (char*) malloc(strlen(mangleCM) + strlen(mangleSig) +3); 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleCMSig == NULL) 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(mangleCMSig, "%s__%s", mangleCM, mangleSig); 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 73492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ calling dlsym(%s)", mangleCMSig); 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = dlsym(pLib->handle, mangleCMSig); 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func != NULL) { 73792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Found '%s' with dlsym", mangleCMSig); 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 74092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Found '%s' with dlsym", mangleCM); 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(preMangleCM); 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleCM); 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleSig); 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleCMSig); 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (int) func; 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if the requested method lives in any of the currently-loaded 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shared libraries. We do this by checking each of them for the expected 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method signature. 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* lookupSharedLibMethod(const Method* method) 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.nativeLibs == NULL) { 759c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unexpected init state: nativeLibs not ready"); 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (void*) dvmHashForeach(gDvm.nativeLibs, findMethodInLib, 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (void*) method); 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 765