Native.cpp revision 59b6177e2fa9c9f1f16d7eff57e481f5282afbda
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);
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallJNIMethod(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
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We add one of these to the hash table for every library we load.  The
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * hash is on the "pathName" field.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct SharedLib {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char*       pathName;       /* absolute path to library */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void*       handle;         /* from dlopen */
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object*     classLoader;    /* ClassLoader we are associated with */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} SharedLib;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.)
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the string.
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpNameStr(const void* ventry, const void* vname)
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const SharedLib* pLib = (const SharedLib*) ventry;
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* name = (const char*) vname;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return strcmp(pLib->pathName, name);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup callback.)
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find an entry that matches the new entry.
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpSharedLib(const void* ventry, const void* vnewEntry)
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const SharedLib* pLib = (const SharedLib*) ventry;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const SharedLib* pNewLib = (const SharedLib*) vnewEntry;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("--- comparing %p '%s' %p '%s'\n",
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pLib, pLib->pathName, pNewLib, pNewLib->pathName);
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return strcmp(pLib->pathName, pNewLib->pathName);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check to see if an entry with the same pathname already exists.
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const SharedLib* findSharedLibEntry(const char* pathName)
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash = dvmComputeUtf8Hash(pathName);
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* ent;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ent = dvmHashTableLookup(gDvm.nativeLibs, hash, (void*)pathName,
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpNameStr, false);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return ent;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Add the new entry to the table.
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success, "false" if the entry already exists.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool addSharedLibEntry(SharedLib* pLib)
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 hash = dvmComputeUtf8Hash(pLib->pathName);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* ent;
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Do the lookup with the "add" flag set.  If we add it, we will get
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * our own pointer back.  If somebody beat us to the punch, we'll get
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * their pointer back instead.
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ent = dvmHashTableLookup(gDvm.nativeLibs, hash, pLib, hashcmpSharedLib,
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                true);
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (ent == pLib);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up an entry.  (This is a dvmHashTableFree callback.)
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void freeSharedLibEntry(void* ptr)
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SharedLib* pLib = (SharedLib*) ptr;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Calling dlclose() here is somewhat dangerous, because it's possible
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that a thread outside the VM is still accessing the code we loaded.
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (false)
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dlclose(pLib->handle);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pLib->pathName);
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pLib);
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Convert library name to system-dependent form, e.g. "jpeg" becomes
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "libjpeg.so".
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Should we have this take buffer+len and avoid the alloc?  It gets
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called very rarely.)
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar* dvmCreateSystemLibraryName(char* libName)
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char buf[256];
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    len = snprintf(buf, sizeof(buf), OS_SHARED_LIB_FORMAT_STR, libName);
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (len >= (int) sizeof(buf))
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return strdup(buf);
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a library, given the lib's system-dependent name (e.g. "libjpeg.so").
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to search through the path defined by the java.library.path
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * property.
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns NULL if the library was not found.
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* findLibrary(const char* libSysName)
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* javaLibraryPath = NULL;
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* testName = NULL;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* start;
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool done;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    javaLibraryPath = dvmGetProperty("java.library.path");
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (javaLibraryPath == NULL)
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ path is '%s'\n", javaLibraryPath);
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    start = cp = javaLibraryPath;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (cp != NULL) {
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char pathBuf[256];
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int len;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp = strchr(start, ':');
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cp != NULL)
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len = snprintf(pathBuf, sizeof(pathBuf), "%s/%s", start, libSysName);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (len >= (int) sizeof(pathBuf)) {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Path overflowed %d bytes: '%s' / '%s'\n",
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                len, start, libSysName);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* keep going, next one might fit */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGVV("+++  trying '%s'\n", pathBuf);
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (access(pathBuf, R_OK) == 0) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                testName = strdup(pathBuf);
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        start = cp +1;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(javaLibraryPath);
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return testName;
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load a native shared library, given the system-independent piece of
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the library name.
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws an exception on failure.
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLoadNativeLibrary(StringObject* libNameObj, Object* classLoader)
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* libName = NULL;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* libSysName = NULL;
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* libPath = NULL;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If "classLoader" isn't NULL, call the class loader's "findLibrary"
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * method with the lib name.  If it returns a non-NULL result, we use
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * that as the pathname.
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (classLoader != NULL) {
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* findLibrary;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* findLibResult;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        findLibrary = dvmFindVirtualMethodByDescriptor(classLoader->clazz,
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "findLibrary", "(Ljava/lang/String;)Ljava/lang/String;");
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (findLibrary == NULL) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Could not find findLibrary() in %s\n",
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                classLoader->clazz->name);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "findLibrary");
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        findLibResult = (Object*)(u4) dvmCallMethod(findLibrary, classLoader,
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                            libNameObj);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException()) {
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("returning early on exception\n");
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (findLibResult != NULL) {
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* success! */
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            libPath = dvmCreateCstrFromString(libNameObj);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("Found library through CL: '%s'\n", libPath);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmLoadNativeCode(libPath, classLoader);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    libName = dvmCreateCstrFromString(libNameObj);
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (libName == NULL)
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    libSysName = dvmCreateSystemLibraryName(libName);
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (libSysName == NULL)
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    libPath = findLibrary(libSysName);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (libPath != NULL) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("Found library through path: '%s'\n", libPath);
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmLoadNativeCode(libPath, classLoader);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Unable to locate shared lib matching '%s'\n", libSysName);
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", libName);
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(libName);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(libSysName);
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(libPath);
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef int (*OnLoadFunc)(JavaVM*, void*);
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load native code from the specified absolute pathname.  Per the spec,
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if we've already loaded a library with the specified pathname, we
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return without doing anything.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO? for better results we should absolutify the pathname.  For fully
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * correct results we should stat to get the inode and compare that.  The
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * existing implementation is fine so long as everybody is using
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * System.loadLibrary.
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The library will be associated with the specified class loader.  The JNI
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * spec says we can't load the same library into more than one class loader.
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" on success.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmLoadNativeCode(const char* pathName, Object* classLoader)
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const SharedLib* pEntry;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* handle;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGD("Trying to load lib %s %p\n", pathName, classLoader);
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we've already loaded it.  If we have, and the class loader
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * matches, return successfully without doing anything.
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pEntry = findSharedLibEntry(pathName);
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pEntry != NULL) {
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pEntry->classLoader != classLoader) {
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Shared lib '%s' already opened by CL %p; can't open in %p\n",
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pathName, pEntry->classLoader, classLoader);
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("Shared lib '%s' already loaded in same CL %p\n",
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pathName, classLoader);
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Open the shared library.  Because we're using a full path, the system
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * doesn't have to search through LD_LIBRARY_PATH.  (It may do so to
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * resolve this library's dependencies though.)
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
41799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Failures here are expected when java.library.path has several entries
41899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * and we have to hunt for the lib.
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The current android-arm dynamic linker implementation tends to
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return "Cannot find library" from dlerror() regardless of the actual
42299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * problem.  A more useful diagnostic may be sent to stdout/stderr if
42399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * linker diagnostics are enabled, but that's not usually visible in
42499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Android apps.  Some things to try:
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *   - make sure the library exists on the device
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *   - verify that the right path is being opened (the debug log message
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     above can help with that)
42899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   - check to see if the library is valid (e.g. not zero bytes long)
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *   - check config/prelink-linux-arm.map to ensure that the library
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     is listed and is not being overrun by the previous entry (if
43199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     loading suddenly stops working on a prelinked library, this is
43299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     a good one to check)
43399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   - write a trivial app that calls sleep() then dlopen(), attach
43499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     to it with "strace -p <pid>" while it sleeps, and watch for
43599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     attempts to open nonexistent dependent shared libs
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    handle = dlopen(pathName, RTLD_LAZY);
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (handle == NULL) {
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("Unable to dlopen(%s): %s\n", pathName, dlerror());
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    SharedLib* pNewEntry;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pNewEntry = (SharedLib*) malloc(sizeof(SharedLib));
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pNewEntry->pathName = strdup(pathName);
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pNewEntry->handle = handle;
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pNewEntry->classLoader = classLoader;
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!addSharedLibEntry(pNewEntry)) {
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("WOW: we lost a race to add a shared lib (%s %p)\n",
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pathName, classLoader);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* free up our entry, and just return happy that one exists */
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        freeSharedLibEntry(pNewEntry);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("Added shared lib %s %p\n", pathName, classLoader);
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        void* vonLoad;
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int version;
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        vonLoad = dlsym(handle, "JNI_OnLoad");
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (vonLoad == NULL) {
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGD("No JNI_OnLoad found in %s %p\n", pathName, classLoader);
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Call JNI_OnLoad.  We have to override the current class
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * loader, which will always be "null" since the stuff at the
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * top of the stack is around Runtime.loadLibrary().
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            OnLoadFunc func = vonLoad;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Thread* self = dvmThreadSelf();
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object* prevOverride = self->classLoaderOverride;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->classLoaderOverride = classLoader;
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmChangeStatus(NULL, THREAD_NATIVE);
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            version = (*func)(gDvm.vmList, NULL);
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmChangeStatus(NULL, THREAD_RUNNING);
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->classLoaderOverride = prevOverride;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 &&
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                version != JNI_VERSION_1_6)
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            {
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("JNI_OnLoad returned bad version (%d) in %s %p\n",
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    version, pathName, classLoader);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // TODO: dlclose, remove hash table entry
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      Signature-based method lookup
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ===========================================================================
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the pre-mangled form of the class+method string.
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated string, and sets "*pLen" to the length.
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createJniNameString(const char* classDescriptor,
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* methodName, int* pLen)
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* result;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t descriptorLength = strlen(classDescriptor);
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *pLen = 4 + descriptorLength + strlen(methodName);
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = malloc(*pLen +1);
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result == NULL)
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return NULL;
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Add one to classDescriptor to skip the "L", and then replace
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the final ";" with a "/" after the sprintf() call.
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sprintf(result, "Java/%s%s", classDescriptor + 1, methodName);
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result[5 + (descriptorLength - 2)] = '/';
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a newly-allocated, mangled copy of "str".
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "str" is a "modified UTF-8" string.  We convert it to UTF-16 first to
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * make life simpler.
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* mangleString(const char* str, int len)
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u2* utf16 = NULL;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangle = NULL;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int charLen;
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGI("mangling '%s' %d\n", str, len);
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(str[len] == '\0');
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    charLen = dvmUtf8Len(str);
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    utf16 = (u2*) malloc(sizeof(u2) * charLen);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (utf16 == NULL)
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmConvertUtf8ToUtf16(utf16, str);
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute the length of the mangled string.
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i, mangleLen = 0;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < charLen; i++) {
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 ch = utf16[i];
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ch > 127) {
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mangleLen += 6;
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (ch) {
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '_':
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ';':
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '[':
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mangleLen += 2;
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                mangleLen++;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp;
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mangle = (char*) malloc(mangleLen +1);
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mangle == NULL)
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0, cp = mangle; i < charLen; i++) {
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        u2 ch = utf16[i];
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ch > 127) {
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sprintf(cp, "_0%04x", ch);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += 6;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (ch) {
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '_':
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '_';
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '1';
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ';':
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '_';
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '2';
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '[':
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '_';
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '3';
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case '/':
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = '_';
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = (char) ch;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *cp = '\0';
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(utf16);
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return mangle;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create the mangled form of the parameter types.
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic char* createMangledSignature(const DexProto* proto)
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexStringCache sigCache;
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* interim;
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* result;
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexStringCacheInit(&sigCache);
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    interim = dexProtoGetParameterDescriptors(proto, &sigCache);
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = mangleString(interim, strlen(interim));
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexStringCacheRelease(&sigCache);
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashForeach callback.)
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search for a matching method in this shared library.
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findMethodInLib(void* vlib, void* vmethod)
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const SharedLib* pLib = (const SharedLib*) vlib;
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const Method* meth = (const Method*) vmethod;
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* preMangleCM = NULL;
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangleCM = NULL;
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangleSig = NULL;
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* mangleCMSig = NULL;
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* func = NULL;
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len;
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (meth->clazz->classLoader != pLib->classLoader) {
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("+++ not scanning '%s' for '%s' (wrong CL)\n",
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pLib->pathName, meth->name);
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return 0;
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ scanning '%s' for '%s'\n", pLib->pathName, meth->name);
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * First, we try it without the signature.
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    preMangleCM =
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        createJniNameString(meth->clazz->descriptor, meth->name, &len);
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (preMangleCM == NULL)
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mangleCM = mangleString(preMangleCM, len);
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (mangleCM == NULL)
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("+++ calling dlsym(%s)\n", mangleCM);
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    func = dlsym(pLib->handle, mangleCM);
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (func == NULL) {
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mangleSig =
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            createMangledSignature(&meth->prototype);
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mangleSig == NULL)
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mangleCMSig = (char*) malloc(strlen(mangleCM) + strlen(mangleSig) +3);
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (mangleCMSig == NULL)
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sprintf(mangleCMSig, "%s__%s", mangleCM, mangleSig);
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ calling dlsym(%s)\n", mangleCMSig);
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        func = dlsym(pLib->handle, mangleCMSig);
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (func != NULL) {
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("Found '%s' with dlsym\n", mangleCMSig);
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Found '%s' with dlsym\n", mangleCM);
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(preMangleCM);
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangleCM);
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangleSig);
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(mangleCMSig);
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (int) func;
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See if the requested method lives in any of the currently-loaded
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * shared libraries.  We do this by checking each of them for the expected
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method signature.
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* lookupSharedLibMethod(const Method* method)
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.nativeLibs == NULL) {
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unexpected init state: nativeLibs not ready\n");
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (void*) dvmHashForeach(gDvm.nativeLibs, findMethodInLib,
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (void*) method);
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
714