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