Native.cpp revision 5617ad30c611f373e16bf10c0feec114faef54ef
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 */ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmNativeStartup(void) 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 */ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmNativeShutdown(void) 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 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * here again. 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 void* func; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this is a static method, it could be called before the class 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has been initialized. 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsStaticMethod(method)) { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) { 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(dvmThreadSelf())); 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmIsClassInitialized(clazz) || 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmIsClassInitializing(clazz)); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* start with our internal-native methods */ 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = dvmLookupInternalNativeMethod(method); 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func != NULL) { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* resolution always gets the same answer, so no race here */ 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGVV() { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ resolved native %s.%s %s, invoking\n", 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsSynchronizedMethod(method)) { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("ERROR: internal-native can't be declared 'synchronized'\n"); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Failing on %s.%s\n", method->clazz->descriptor, method->name); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); // harsh, but this is VM-internal problem 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvikBridgeFunc dfunc = (DalvikBridgeFunc) func; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetNativeFunc(method, dfunc, NULL); 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(method->insns == NULL); 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dfunc(args, pResult, method, self); 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* now scan any DLLs we have loaded for JNI signatures */ 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = lookupSharedLibMethod(method); 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func != NULL) { 11559b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden /* found it, point it at the JNI bridge and then call it */ 11659b6177e2fa9c9f1f16d7eff57e481f5282afbdaAndy McFadden dvmUseJNIBridge((Method*) method, func); 1170083d37b0e1c9e542f671cbca2e9db6819ecccbaAndy McFadden (*method->nativeFunc)(args, pResult, method, self); 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project IF_LOGW() { 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("No implementation found for native %s.%s %s\n", 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project clazz->descriptor, method->name, desc); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(desc); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", method->name); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Native shared library support 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// TODO? if a ClassLoader is unloaded, we need to unload all DLLs that 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// are associated with it. (Or not -- can't determine if native code 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// is still using parts of it.) 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14270318889578ab67943d6df29fedf09b11cfef015Andy McFaddentypedef enum OnLoadState { 14370318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadPending = 0, /* initial state, must be zero */ 14470318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadFailed, 14570318889578ab67943d6df29fedf09b11cfef015Andy McFadden kOnLoadOkay, 14670318889578ab67943d6df29fedf09b11cfef015Andy McFadden} OnLoadState; 14770318889578ab67943d6df29fedf09b11cfef015Andy McFadden 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We add one of these to the hash table for every library we load. The 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hash is on the "pathName" field. 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct SharedLib { 15370318889578ab67943d6df29fedf09b11cfef015Andy McFadden char* pathName; /* absolute path to library */ 15470318889578ab67943d6df29fedf09b11cfef015Andy McFadden void* handle; /* from dlopen */ 15570318889578ab67943d6df29fedf09b11cfef015Andy McFadden Object* classLoader; /* ClassLoader we are associated with */ 15670318889578ab67943d6df29fedf09b11cfef015Andy McFadden 15770318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_mutex_t onLoadLock; /* guards remaining items */ 15870318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_t onLoadCond; /* wait for JNI_OnLoad in other thread */ 15970318889578ab67943d6df29fedf09b11cfef015Andy McFadden u4 onLoadThreadId; /* recursive invocation guard */ 16070318889578ab67943d6df29fedf09b11cfef015Andy McFadden OnLoadState onLoadResult; /* result of earlier JNI_OnLoad */ 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} SharedLib; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.) 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the string. 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpNameStr(const void* ventry, const void* vname) 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) ventry; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* name = (const char*) vname; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strcmp(pLib->pathName, name); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the new entry. 18070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 18170318889578ab67943d6df29fedf09b11cfef015Andy McFadden * We don't compare the class loader here, because you're not allowed to 18270318889578ab67943d6df29fedf09b11cfef015Andy McFadden * have the same shared library associated with more than one CL. 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpSharedLib(const void* ventry, const void* vnewEntry) 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) ventry; 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pNewLib = (const SharedLib*) vnewEntry; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD("--- comparing %p '%s' %p '%s'\n", 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pLib, pLib->pathName, pNewLib, pNewLib->pathName); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strcmp(pLib->pathName, pNewLib->pathName); 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check to see if an entry with the same pathname already exists. 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 19770318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic SharedLib* findSharedLibEntry(const char* pathName) 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 hash = dvmComputeUtf8Hash(pathName); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* ent; 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ent = dvmHashTableLookup(gDvm.nativeLibs, hash, (void*)pathName, 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project hashcmpNameStr, false); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ent; 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the new entry to the table. 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 21070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Returns the table entry, which will not be the same as "pLib" if the 21170318889578ab67943d6df29fedf09b11cfef015Andy McFadden * entry already exists. 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 21370318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic SharedLib* addSharedLibEntry(SharedLib* pLib) 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 hash = dvmComputeUtf8Hash(pLib->pathName); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Do the lookup with the "add" flag set. If we add it, we will get 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our own pointer back. If somebody beat us to the punch, we'll get 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * their pointer back instead. 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 22270318889578ab67943d6df29fedf09b11cfef015Andy McFadden return dvmHashTableLookup(gDvm.nativeLibs, hash, pLib, hashcmpSharedLib, 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project true); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up an entry. (This is a dvmHashTableFree callback.) 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeSharedLibEntry(void* ptr) 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SharedLib* pLib = (SharedLib*) ptr; 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calling dlclose() here is somewhat dangerous, because it's possible 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that a thread outside the VM is still accessing the code we loaded. 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (false) 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dlclose(pLib->handle); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pLib->pathName); 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pLib); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert library name to system-dependent form, e.g. "jpeg" becomes 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "libjpeg.so". 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Should we have this take buffer+len and avoid the alloc? It gets 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called very rarely.) 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmCreateSystemLibraryName(char* libName) 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char buf[256]; 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len; 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project len = snprintf(buf, sizeof(buf), OS_SHARED_LIB_FORMAT_STR, libName); 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len >= (int) sizeof(buf)) 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return strdup(buf); 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a library, given the lib's system-dependent name (e.g. "libjpeg.so"). 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to search through the path defined by the java.library.path 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * property. 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if the library was not found. 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* findLibrary(const char* libSysName) 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* javaLibraryPath = NULL; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* testName = NULL; 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* start; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* cp; 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool done; 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project javaLibraryPath = dvmGetProperty("java.library.path"); 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (javaLibraryPath == NULL) 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ path is '%s'\n", javaLibraryPath); 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = cp = javaLibraryPath; 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (cp != NULL) { 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char pathBuf[256]; 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len; 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cp = strchr(start, ':'); 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cp != NULL) 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp = '\0'; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project len = snprintf(pathBuf, sizeof(pathBuf), "%s/%s", start, libSysName); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (len >= (int) sizeof(pathBuf)) { 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Path overflowed %d bytes: '%s' / '%s'\n", 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project len, start, libSysName); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* keep going, next one might fit */ 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ trying '%s'\n", pathBuf); 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (access(pathBuf, R_OK) == 0) { 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project testName = strdup(pathBuf); 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project start = cp +1; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(javaLibraryPath); 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return testName; 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load a native shared library, given the system-independent piece of 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the library name. 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws an exception on failure. 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLoadNativeLibrary(StringObject* libNameObj, Object* classLoader) 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* libName = NULL; 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* libSysName = NULL; 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* libPath = NULL; 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "classLoader" isn't NULL, call the class loader's "findLibrary" 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method with the lib name. If it returns a non-NULL result, we use 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that as the pathname. 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (classLoader != NULL) { 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* findLibrary; 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* findLibResult; 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project findLibrary = dvmFindVirtualMethodByDescriptor(classLoader->clazz, 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "findLibrary", "(Ljava/lang/String;)Ljava/lang/String;"); 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (findLibrary == NULL) { 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Could not find findLibrary() in %s\n", 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project classLoader->clazz->name); 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "findLibrary"); 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project findLibResult = (Object*)(u4) dvmCallMethod(findLibrary, classLoader, 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project libNameObj); 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException()) { 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("returning early on exception\n"); 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (findLibResult != NULL) { 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* success! */ 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project libPath = dvmCreateCstrFromString(libNameObj); 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Found library through CL: '%s'\n", libPath); 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLoadNativeCode(libPath, classLoader); 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project libName = dvmCreateCstrFromString(libNameObj); 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (libName == NULL) 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project libSysName = dvmCreateSystemLibraryName(libName); 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (libSysName == NULL) 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project libPath = findLibrary(libSysName); 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (libPath != NULL) { 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGD("Found library through path: '%s'\n", libPath); 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLoadNativeCode(libPath, classLoader); 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Unable to locate shared lib matching '%s'\n", libSysName); 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", libName); 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(libName); 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(libSysName); 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(libPath); 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38570318889578ab67943d6df29fedf09b11cfef015Andy McFadden 38670318889578ab67943d6df29fedf09b11cfef015Andy McFadden/* 38770318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Check the result of an earlier call to JNI_OnLoad on this library. If 38870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * the call has not yet finished in another thread, wait for it. 38970318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 39070318889578ab67943d6df29fedf09b11cfef015Andy McFaddenstatic bool checkOnLoadResult(SharedLib* pEntry) 39170318889578ab67943d6df29fedf09b11cfef015Andy McFadden{ 39270318889578ab67943d6df29fedf09b11cfef015Andy McFadden Thread* self = dvmThreadSelf(); 39370318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pEntry->onLoadThreadId == self->threadId) { 39470318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 39570318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Check this so we don't end up waiting for ourselves. We need 39670318889578ab67943d6df29fedf09b11cfef015Andy McFadden * to return "true" so the caller can continue. 39770318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 39870318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGI("threadid=%d: recursive native library load attempt (%s)\n", 39970318889578ab67943d6df29fedf09b11cfef015Andy McFadden self->threadId, pEntry->pathName); 40070318889578ab67943d6df29fedf09b11cfef015Andy McFadden return true; 40170318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 40270318889578ab67943d6df29fedf09b11cfef015Andy McFadden 40370318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGV("+++ retrieving %s OnLoad status\n", pEntry->pathName); 40470318889578ab67943d6df29fedf09b11cfef015Andy McFadden bool result; 40570318889578ab67943d6df29fedf09b11cfef015Andy McFadden 40670318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmLockMutex(&pEntry->onLoadLock); 40770318889578ab67943d6df29fedf09b11cfef015Andy McFadden while (pEntry->onLoadResult == kOnLoadPending) { 40870318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGD("threadid=%d: waiting for %s OnLoad status\n", 40970318889578ab67943d6df29fedf09b11cfef015Andy McFadden self->threadId, pEntry->pathName); 4105617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 41170318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_wait(&pEntry->onLoadCond, &pEntry->onLoadLock); 41270318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmChangeStatus(self, oldStatus); 41370318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 41470318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pEntry->onLoadResult == kOnLoadOkay) { 41570318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGV("+++ earlier OnLoad(%s) okay\n", pEntry->pathName); 41670318889578ab67943d6df29fedf09b11cfef015Andy McFadden result = true; 41770318889578ab67943d6df29fedf09b11cfef015Andy McFadden } else { 41870318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGV("+++ earlier OnLoad(%s) failed\n", pEntry->pathName); 41970318889578ab67943d6df29fedf09b11cfef015Andy McFadden result = false; 42070318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 42170318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmUnlockMutex(&pEntry->onLoadLock); 42270318889578ab67943d6df29fedf09b11cfef015Andy McFadden return result; 42370318889578ab67943d6df29fedf09b11cfef015Andy McFadden} 42470318889578ab67943d6df29fedf09b11cfef015Andy McFadden 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef int (*OnLoadFunc)(JavaVM*, void*); 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load native code from the specified absolute pathname. Per the spec, 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if we've already loaded a library with the specified pathname, we 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return without doing anything. 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO? for better results we should absolutify the pathname. For fully 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * correct results we should stat to get the inode and compare that. The 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * existing implementation is fine so long as everybody is using 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * System.loadLibrary. 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The library will be associated with the specified class loader. The JNI 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec says we can't load the same library into more than one class loader. 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success. 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLoadNativeCode(const char* pathName, Object* classLoader) 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 44470318889578ab67943d6df29fedf09b11cfef015Andy McFadden SharedLib* pEntry; 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* handle; 446dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden bool verbose; 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 448dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden /* reduce noise by not chattering about system libraries */ 449dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden verbose = strncmp(pathName, "/system", sizeof("/system")-1) != 0; 450dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden 451dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) 452dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGD("Trying to load lib %s %p\n", pathName, classLoader); 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if we've already loaded it. If we have, and the class loader 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * matches, return successfully without doing anything. 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pEntry = findSharedLibEntry(pathName); 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pEntry != NULL) { 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pEntry->classLoader != classLoader) { 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Shared lib '%s' already opened by CL %p; can't open in %p\n", 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathName, pEntry->classLoader, classLoader); 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 465dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) { 466dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGD("Shared lib '%s' already loaded in same CL %p\n", 467dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden pathName, classLoader); 468dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden } 46970318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (!checkOnLoadResult(pEntry)) 47070318889578ab67943d6df29fedf09b11cfef015Andy McFadden return false; 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open the shared library. Because we're using a full path, the system 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * doesn't have to search through LD_LIBRARY_PATH. (It may do so to 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resolve this library's dependencies though.) 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 47999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Failures here are expected when java.library.path has several entries 48099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * and we have to hunt for the lib. 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 482dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * The current version of the dynamic linker prints detailed information 483dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * about dlopen() failures. Some things to check if the message is 484dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden * cryptic: 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - make sure the library exists on the device 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - verify that the right path is being opened (the debug log message 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * above can help with that) 48899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * - check to see if the library is valid (e.g. not zero bytes long) 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * - check config/prelink-linux-arm.map to ensure that the library 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is listed and is not being overrun by the previous entry (if 49199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * loading suddenly stops working on a prelinked library, this is 49299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * a good one to check) 49399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * - write a trivial app that calls sleep() then dlopen(), attach 49499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * to it with "strace -p <pid>" while it sleeps, and watch for 49599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * attempts to open nonexistent dependent shared libs 4962aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * 4972aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * This can execute slowly for a large library on a busy system, so we 4982aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * want to switch from RUNNING to VMWAIT while it executes. This allows 4992aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden * the GC to ignore us. 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 5012aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden Thread* self = dvmThreadSelf(); 5025617ad30c611f373e16bf10c0feec114faef54efCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project handle = dlopen(pathName, RTLD_LAZY); 5042aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden dvmChangeStatus(self, oldStatus); 5052aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (handle == NULL) { 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Unable to dlopen(%s): %s\n", pathName, dlerror()); 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51170318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* create a new entry */ 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SharedLib* pNewEntry; 51370318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry = (SharedLib*) calloc(1, sizeof(SharedLib)); 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->pathName = strdup(pathName); 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->handle = handle; 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pNewEntry->classLoader = classLoader; 51770318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmInitMutex(&pNewEntry->onLoadLock); 51870318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_init(&pNewEntry->onLoadCond, NULL); 51970318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadThreadId = self->threadId; 52070318889578ab67943d6df29fedf09b11cfef015Andy McFadden 52170318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* try to add it to the list */ 52270318889578ab67943d6df29fedf09b11cfef015Andy McFadden SharedLib* pActualEntry = addSharedLibEntry(pNewEntry); 52370318889578ab67943d6df29fedf09b11cfef015Andy McFadden 52470318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (pNewEntry != pActualEntry) { 52570318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGI("WOW: we lost a race to add a shared lib (%s CL=%p)\n", 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pathName, classLoader); 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project freeSharedLibEntry(pNewEntry); 52870318889578ab67943d6df29fedf09b11cfef015Andy McFadden return checkOnLoadResult(pActualEntry); 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 530dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden if (verbose) 531dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGD("Added shared lib %s %p\n", pathName, classLoader); 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53370318889578ab67943d6df29fedf09b11cfef015Andy McFadden bool result = true; 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* vonLoad; 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int version; 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vonLoad = dlsym(handle, "JNI_OnLoad"); 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vonLoad == NULL) { 539dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGD("No JNI_OnLoad found in %s %p, skipping init\n", 540dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden pathName, classLoader); 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call JNI_OnLoad. We have to override the current class 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader, which will always be "null" since the stuff at the 54570318889578ab67943d6df29fedf09b11cfef015Andy McFadden * top of the stack is around Runtime.loadLibrary(). (See 54670318889578ab67943d6df29fedf09b11cfef015Andy McFadden * the comments in the JNI FindClass function.) 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OnLoadFunc func = vonLoad; 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* prevOverride = self->classLoaderOverride; 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->classLoaderOverride = classLoader; 5522aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden oldStatus = dvmChangeStatus(self, THREAD_NATIVE); 55370318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGV("+++ calling JNI_OnLoad(%s)\n", pathName); 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project version = (*func)(gDvm.vmList, NULL); 5552aa43610c391868eb6ef80bf3b1f947776defccaAndy McFadden dvmChangeStatus(self, oldStatus); 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->classLoaderOverride = prevOverride; 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project version != JNI_VERSION_1_6) 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("JNI_OnLoad returned bad version (%d) in %s %p\n", 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project version, pathName, classLoader); 56370318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 56470318889578ab67943d6df29fedf09b11cfef015Andy McFadden * It's unwise to call dlclose() here, but we can mark it 56570318889578ab67943d6df29fedf09b11cfef015Andy McFadden * as bad and ensure that future load attempts will fail. 56670318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 56770318889578ab67943d6df29fedf09b11cfef015Andy McFadden * We don't know how far JNI_OnLoad got, so there could 56870318889578ab67943d6df29fedf09b11cfef015Andy McFadden * be some partially-initialized stuff accessible through 56970318889578ab67943d6df29fedf09b11cfef015Andy McFadden * newly-registered native method calls. We could try to 57070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * unregister them, but that doesn't seem worthwhile. 57170318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 57270318889578ab67943d6df29fedf09b11cfef015Andy McFadden result = false; 57370318889578ab67943d6df29fedf09b11cfef015Andy McFadden } else { 57470318889578ab67943d6df29fedf09b11cfef015Andy McFadden LOGV("+++ finished JNI_OnLoad %s\n", pathName); 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 57870318889578ab67943d6df29fedf09b11cfef015Andy McFadden if (result) 57970318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadResult = kOnLoadOkay; 58070318889578ab67943d6df29fedf09b11cfef015Andy McFadden else 58170318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadResult = kOnLoadFailed; 58270318889578ab67943d6df29fedf09b11cfef015Andy McFadden 58370318889578ab67943d6df29fedf09b11cfef015Andy McFadden pNewEntry->onLoadThreadId = 0; 58470318889578ab67943d6df29fedf09b11cfef015Andy McFadden 58570318889578ab67943d6df29fedf09b11cfef015Andy McFadden /* 58670318889578ab67943d6df29fedf09b11cfef015Andy McFadden * Broadcast a wakeup to anybody sleeping on the condition variable. 58770318889578ab67943d6df29fedf09b11cfef015Andy McFadden */ 58870318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmLockMutex(&pNewEntry->onLoadLock); 58970318889578ab67943d6df29fedf09b11cfef015Andy McFadden pthread_cond_broadcast(&pNewEntry->onLoadCond); 59070318889578ab67943d6df29fedf09b11cfef015Andy McFadden dvmUnlockMutex(&pNewEntry->onLoadLock); 59170318889578ab67943d6df29fedf09b11cfef015Andy McFadden return result; 59270318889578ab67943d6df29fedf09b11cfef015Andy McFadden } 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Signature-based method lookup 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * =========================================================================== 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the pre-mangled form of the class+method string. 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated string, and sets "*pLen" to the length. 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createJniNameString(const char* classDescriptor, 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* methodName, int* pLen) 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* result; 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project size_t descriptorLength = strlen(classDescriptor); 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pLen = 4 + descriptorLength + strlen(methodName); 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = malloc(*pLen +1); 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result == NULL) 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add one to classDescriptor to skip the "L", and then replace 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the final ";" with a "/" after the sprintf() call. 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(result, "Java/%s%s", classDescriptor + 1, methodName); 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result[5 + (descriptorLength - 2)] = '/'; 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated, mangled copy of "str". 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "str" is a "modified UTF-8" string. We convert it to UTF-16 first to 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * make life simpler. 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* mangleString(const char* str, int len) 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2* utf16 = NULL; 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangle = NULL; 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int charLen; 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGI("mangling '%s' %d\n", str, len); 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(str[len] == '\0'); 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project charLen = dvmUtf8Len(str); 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project utf16 = (u2*) malloc(sizeof(u2) * charLen); 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (utf16 == NULL) 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmConvertUtf8ToUtf16(utf16, str); 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the length of the mangled string. 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i, mangleLen = 0; 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < charLen; i++) { 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 ch = utf16[i]; 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 660dfdaa8733814dd1a576aec0a0a735848384009dfBrian McKenna if (ch == '$' || ch > 127) { 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen += 6; 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (ch) { 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '_': 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case ';': 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '[': 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen += 2; 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleLen++; 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* cp; 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangle = (char*) malloc(mangleLen +1); 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangle == NULL) 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0, cp = mangle; i < charLen; i++) { 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u2 ch = utf16[i]; 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 685dfdaa8733814dd1a576aec0a0a735848384009dfBrian McKenna if (ch == '$' || ch > 127) { 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(cp, "_0%04x", ch); 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cp += 6; 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (ch) { 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '_': 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '1'; 693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case ';': 695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '2'; 697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '[': 699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '3'; 701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case '/': 703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = '_'; 704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = (char) ch; 707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp = '\0'; 713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(utf16); 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return mangle; 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the mangled form of the parameter types. 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createMangledSignature(const DexProto* proto) 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexStringCache sigCache; 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* interim; 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* result; 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexStringCacheInit(&sigCache); 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project interim = dexProtoGetParameterDescriptors(proto, &sigCache); 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = mangleString(interim, strlen(interim)); 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexStringCacheRelease(&sigCache); 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashForeach callback.) 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search for a matching method in this shared library. 74070318889578ab67943d6df29fedf09b11cfef015Andy McFadden * 74170318889578ab67943d6df29fedf09b11cfef015Andy McFadden * TODO: we may want to skip libraries for which JNI_OnLoad failed. 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findMethodInLib(void* vlib, void* vmethod) 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const SharedLib* pLib = (const SharedLib*) vlib; 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* meth = (const Method*) vmethod; 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* preMangleCM = NULL; 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleCM = NULL; 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleSig = NULL; 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* mangleCMSig = NULL; 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* func = NULL; 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int len; 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (meth->clazz->classLoader != pLib->classLoader) { 755dced79474902ffa57fbd48121eb794aad7d24ddcAndy McFadden LOGV("+++ not scanning '%s' for '%s' (wrong CL)\n", 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pLib->pathName, meth->name); 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ scanning '%s' for '%s'\n", pLib->pathName, meth->name); 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * First, we try it without the signature. 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project preMangleCM = 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project createJniNameString(meth->clazz->descriptor, meth->name, &len); 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (preMangleCM == NULL) 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleCM = mangleString(preMangleCM, len); 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleCM == NULL) 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ calling dlsym(%s)\n", mangleCM); 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = dlsym(pLib->handle, mangleCM); 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func == NULL) { 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleSig = 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project createMangledSignature(&meth->prototype); 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleSig == NULL) 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mangleCMSig = (char*) malloc(strlen(mangleCM) + strlen(mangleSig) +3); 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (mangleCMSig == NULL) 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sprintf(mangleCMSig, "%s__%s", mangleCM, mangleSig); 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ calling dlsym(%s)\n", mangleCMSig); 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project func = dlsym(pLib->handle, mangleCMSig); 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (func != NULL) { 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Found '%s' with dlsym\n", mangleCMSig); 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Found '%s' with dlsym\n", mangleCM); 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(preMangleCM); 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleCM); 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleSig); 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(mangleCMSig); 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (int) func; 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if the requested method lives in any of the currently-loaded 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shared libraries. We do this by checking each of them for the expected 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method signature. 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* lookupSharedLibMethod(const Method* method) 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.nativeLibs == NULL) { 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unexpected init state: nativeLibs not ready\n"); 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return (void*) dvmHashForeach(gDvm.nativeLibs, findMethodInLib, 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (void*) method); 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 818