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