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/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dalvik.system.DexFile
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "native/InternalNativePriv.h"
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein/*
24eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein * Return true if the given name ends with ".dex".
25eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein */
26eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornsteinstatic bool hasDexExtension(const char* name) {
27eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein    size_t len = strlen(name);
28eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein
29eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein    return (len >= 5)
30eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein        && (name[len - 5] != '/')
31eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein        && (strcmp(&name[len - 4], ".dex") == 0);
32eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein}
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Internal struct for managing DexFile.
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
37d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct DexOrJar {
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char*       fileName;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        isDex;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool        okayToFree;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RawDexFile* pRawDexFile;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile*    pJarFile;
43c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    u1*         pDexMemory; // malloc()ed memory, if any
44d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableFree callback.)
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmFreeDexOrJar(void* vptr)
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) vptr;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("Freeing DexOrJar '%s'", pDexOrJar->fileName);
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->isDex)
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmRawDexFileFree(pDexOrJar->pRawDexFile);
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmJarFileFree(pDexOrJar->pJarFile);
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pDexOrJar->fileName);
60c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    free(pDexOrJar->pDexMemory);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(pDexOrJar);
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This is a dvmHashTableLookup compare func.)
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Args are DexOrJar*.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int hashcmpDexOrJar(const void* tableVal, const void* newVal)
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return (int) newVal - (int) tableVal;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that the "cookie" is a DEX file we opened.
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Expects that the hash table will be *unlocked* here.
78dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden *
79dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden * If the cookie is invalid, we throw an exception and return "false".
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool validateCookie(int cookie)
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("+++ dex verifying cookie %p", pDexOrJar);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar == NULL)
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
909d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden    u4 hash = cookie;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableLock(gDvm.userDexFiles);
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* result = dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                hashcmpDexOrJar, false);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmHashTableUnlock(gDvm.userDexFiles);
95dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden    if (result == NULL) {
96d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowRuntimeException("invalid DexFile cookie");
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
98dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden    }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
104c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein/*
105c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * Add given DexOrJar to the hash table of user-loaded dex files.
106c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein */
107c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornsteinstatic void addToDexFileTable(DexOrJar* pDexOrJar) {
108c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    /*
109c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * Later on, we will receive this pointer as an argument and need
110c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * to find it in the hash table without knowing if it's valid or
111c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * not, which means we can't compute a hash value from anything
112c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * inside DexOrJar. We don't share DexOrJar structs when the same
113c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * file is opened multiple times, so we can just use the low 32
114c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * bits of the pointer as the hash.
115c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     */
116c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    u4 hash = (u4) pDexOrJar;
117c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    void* result;
118c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
119c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    dvmHashTableLock(gDvm.userDexFiles);
120c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    result = dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,
121c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein            hashcmpDexOrJar, true);
122c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    dvmHashTableUnlock(gDvm.userDexFiles);
123c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
124c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (result != pDexOrJar) {
125c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Pointer has already been added?");
126c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        dvmAbort();
127c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
128c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
129c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->okayToFree = true;
130c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein}
131c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1337c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom * private static int openDexFileNative(String sourceName, String outputName,
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     int flags) throws IOException
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open a DEX file, returning a pointer to our internal data structure.
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "sourceName" should point to the "source" jar or DEX file.
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "outputName" is NULL, the DEX code will automatically find the
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "optimized" version in the cache directory, creating it if necessary.
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If it's non-NULL, the specified file will be used instead.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: at present we will happily open the same file more than once.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To optimize this away we could search for existing entries in the hash
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * table and refCount them.  Requires atomic ops or adding "synchronized"
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the non-native code that calls here.
1489d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden *
1499d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden * TODO: should be using "long" for a pointer.
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1517c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstromstatic void Dalvik_dalvik_system_DexFile_openDexFileNative(const u4* args,
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* sourceNameObj = (StringObject*) args[0];
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* outputNameObj = (StringObject*) args[1];
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = NULL;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile* pJarFile;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RawDexFile* pRawDexFile;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* sourceName;
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* outputName;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (sourceNameObj == NULL) {
163a8b4a0eec5e3ab181b3d26223c84c556bead06c8Elliott Hughes        dvmThrowNullPointerException("sourceName == null");
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sourceName = dvmCreateCstrFromString(sourceNameObj);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (outputNameObj != NULL)
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputName = dvmCreateCstrFromString(outputNameObj);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputName = NULL;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to deal with the possibility that somebody might try to
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * open one of our bootstrap class DEX files.  The set of dependencies
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will be different, and hence the results of optimization might be
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * different, which means we'd actually need to have two versions of
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the optimized DEX: one that only knows about part of the boot class
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * path, and one that knows about everything in it.  The latter might
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * optimize field/method accesses based on a class that appeared later
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the class path.
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can't let the user-defined class loader open it and start using
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the classes, since the optimized form of the code skips some of
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the method and field resolution that we would ordinarily do, and
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we'd have the wrong semantics.
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to reject attempts to manually open a DEX file from the boot
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class path.  The easiest way to do this is by filename, which works
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * out because variations in name (e.g. "/system/framework/./ext.jar")
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * result in us hitting a different dalvik-cache entry.  It's also fine
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if the caller specifies their own output file.
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmClassPathContains(gDvm.bootClassPath, sourceName)) {
195e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("Refusing to reopen boot DEX '%s'", sourceName);
196d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowIOException(
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "Re-opening BOOTCLASSPATH DEX files is not allowed");
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(sourceName);
199e3f9c573d0edb186f4583fea1dbcdf9c12c0c36cKenny Root        free(outputName);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
204eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * Try to open it directly as a DEX if the name ends with ".dex".
205eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * If that fails (or isn't tried in the first place), try it as a
206eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * Zip with a "classes.dex" inside.
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
208eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein    if (hasDexExtension(sourceName)
209eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein            && dvmRawDexFileOpen(sourceName, outputName, &pRawDexFile, false) == 0) {
21092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Opening DEX file '%s' (DEX)", sourceName);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->isDex = true;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->pRawDexFile = pRawDexFile;
2159edce86c96d4df3ed5e439bd9581c1a997c67ebfDan Bornstein        pDexOrJar->pDexMemory = NULL;
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false) == 0) {
21792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Opening DEX file '%s' (Jar)", sourceName);
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->isDex = false;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->pJarFile = pJarFile;
2229edce86c96d4df3ed5e439bd9581c1a997c67ebfDan Bornstein        pDexOrJar->pDexMemory = NULL;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
22492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Unable to open DEX file '%s'", sourceName);
225d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowIOException("unable to open DEX file");
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar != NULL) {
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->fileName = sourceName;
230c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        addToDexFileTable(pDexOrJar);
231c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    } else {
232c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        free(sourceName);
233c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2350dcf6bb34a8c8ef1a54f875c6052901d4aa1d5e8You Kim    free(outputName);
236c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    RETURN_PTR(pDexOrJar);
237c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein}
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein/*
240c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * private static int openDexFile(byte[] fileContents) throws IOException
241c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein *
242c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * Open a DEX file represented in a byte[], returning a pointer to our
243c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * internal data structure.
244c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein *
245c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * The system will only perform "essential" optimizations on the given file.
246c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein *
247c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * TODO: should be using "long" for a pointer.
248c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein */
249c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornsteinstatic void Dalvik_dalvik_system_DexFile_openDexFile_bytearray(const u4* args,
250c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    JValue* pResult)
251c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein{
252c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    ArrayObject* fileContentsObj = (ArrayObject*) args[0];
253c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    u4 length;
254c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    u1* pBytes;
255c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    RawDexFile* pRawDexFile;
256c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    DexOrJar* pDexOrJar = NULL;
257c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
258c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (fileContentsObj == NULL) {
259a8b4a0eec5e3ab181b3d26223c84c556bead06c8Elliott Hughes        dvmThrowNullPointerException("fileContents == null");
260c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
261c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
262c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
26357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden    /* TODO: Avoid making a copy of the array. (note array *is* modified) */
264c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    length = fileContentsObj->length;
265c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pBytes = (u1*) malloc(length);
266c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
267c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (pBytes == NULL) {
268d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowRuntimeException("unable to allocate DEX memory");
269c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
270c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
271c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
272c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    memcpy(pBytes, fileContentsObj->contents, length);
273c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
274c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (dvmRawDexFileOpenArray(pBytes, length, &pRawDexFile) != 0) {
27592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("Unable to open in-memory DEX file");
276c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        free(pBytes);
277d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowRuntimeException("unable to open in-memory DEX file");
278c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
279c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
280c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
28192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("Opening in-memory DEX");
282c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
283c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->isDex = true;
284c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->pRawDexFile = pRawDexFile;
285c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->pDexMemory = pBytes;
286c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->fileName = strdup("<memory>"); // Needs to be free()able.
287c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    addToDexFileTable(pDexOrJar);
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(pDexOrJar);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static void closeDexFile(int cookie)
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release resources associated with a user-loaded DEX file.
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_closeDexFile(const u4* args,
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[0];
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar == NULL)
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
306dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("Closing DEX file %p (%s)", pDexOrJar, pDexOrJar->fileName);
3099d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can't just free arbitrary DEX files because they have bits and
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pieces of loaded classes.  The only exception to this rule is if
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they were never used to load classes.
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we can't free them here, dvmInternalNativeShutdown() will free
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * them when the VM shuts down.
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->okayToFree) {
3199d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden        u4 hash = (u4) pDexOrJar;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.userDexFiles);
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmHashTableRemove(gDvm.userDexFiles, hash, pDexOrJar)) {
322e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("WARNING: could not remove '%s' from DEX hash table",
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDexOrJar->fileName);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.userDexFiles);
32692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("+++ freeing DexFile '%s' resources", pDexOrJar->fileName);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFreeDexOrJar(pDexOrJar);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
32992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block        ALOGV("+++ NOT freeing DexFile '%s' resources", pDexOrJar->fileName);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_VOID();
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3367c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom * private static Class defineClassNative(String name, ClassLoader loader,
337f60f48e917d715fff9ec1ce24a75b7fb0d000a58Elliott Hughes *      int cookie)
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load a class from a DEX file.  This is roughly equivalent to defineClass()
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a regular VM -- it's invoked by the class loader to cause the
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creation of a specific class.  The difference is that the search for and
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reading of the bytes is done within the VM.
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3440ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden * The class name is a "binary name", e.g. "java.lang.String".
3450ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden *
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a null pointer with no exception if the class was not found.
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws an exception on other failures.
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
3497c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstromstatic void Dalvik_dalvik_system_DexFile_defineClassNative(const u4* args,
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = (StringObject*) args[0];
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader = (Object*) args[1];
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[2];
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = NULL;
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* descriptor;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmCreateCstrFromString(nameObj);
3620ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden    descriptor = dvmDotToDescriptor(name);
36392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("--- Explicit class load '%s' l=%p c=0x%08x",
36457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden        descriptor, loader, cookie);
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
368dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->isDex)
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* once we load something, we can't unmap the storage */
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexOrJar->okayToFree = false;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmDefineClass(pDvmDex, descriptor, loader);
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we threw a "class not found" exception, stifle it, since the
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * contract in the higher method says we simply return null if
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the class is not found.
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* excep = dvmGetException(self);
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(excep->clazz->descriptor,
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   "Ljava/lang/ClassNotFoundException;") == 0 ||
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(excep->clazz->descriptor,
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   "Ljava/lang/NoClassDefFoundError;") == 0)
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmClearException(self);
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = NULL;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(descriptor);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(clazz);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static String[] getClassNameList(int cookie)
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a String array that holds the names of all classes in the
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specified DEX file.
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_getClassNameList(const u4* args,
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[0];
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
412364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    Thread* self = dvmThreadSelf();
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
415dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
417a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    DvmDex* pDvmDex;
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->isDex)
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pDvmDex != NULL);
423a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    DexFile* pDexFile = pDvmDex->pDexFile;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = pDexFile->pHeader->classDefsSize;
426a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ClassObject* arrayClass =
427a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro        dvmFindArrayClassForElement(gDvm.classJavaLangString);
428a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ArrayObject* stringArray =
429a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro        dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT);
430364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    if (stringArray == NULL) {
431364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        /* probably OOM */
432062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Failed allocating array of %d strings", count);
433364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        assert(dvmCheckException(self));
434364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        RETURN_VOID();
435364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i);
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* descriptor =
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* className = dvmDescriptorToDot(descriptor);
444364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        StringObject* str = dvmCreateStringFromCstr(className);
445364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmSetObjectArrayElement(stringArray, i, (Object *)str);
446364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmReleaseTrackedAlloc((Object *)str, self);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(className);
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    dvmReleaseTrackedAlloc((Object*)stringArray, self);
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(stringArray);
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
455a8b4a0eec5e3ab181b3d26223c84c556bead06c8Elliott Hughes * public static boolean isDexOptNeeded(String fileName)
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         throws FileNotFoundException, IOException
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the VM believes that the apk/jar file is out of date
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and should be passed through "dexopt" again.
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param fileName the absolute path to the apk/jar file to examine.
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return true if dexopt should be called on the file, false otherwise.
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.io.FileNotFoundException if fileName is not readable,
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         not a file, or not present.
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.io.IOException if fileName is not a valid apk/jar file or
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         if problems occur while parsing it.
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.lang.NullPointerException if fileName is null.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws dalvik.system.StaleDexCacheError if the optimized dex file
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         is stale but exists on a read-only partition.
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_isDexOptNeeded(const u4* args,
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = (StringObject*) args[0];
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexCacheStatus status;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmCreateCstrFromString(nameObj);
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (name == NULL) {
481a8b4a0eec5e3ab181b3d26223c84c556bead06c8Elliott Hughes        dvmThrowNullPointerException("fileName == null");
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (access(name, R_OK) != 0) {
485d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowFileNotFoundException(name);
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(name);
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    status = dvmDexCacheStatus(name);
49092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block    ALOGV("dvmDexCacheStatus(%s) returned %d", name, status);
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (status) {
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default: //FALLTHROUGH
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_BAD_ARCHIVE:
496d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowIOException(name);
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = -1;
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_OK:
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = false;
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_STALE:
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_STALE_ODEX:
50674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein        dvmThrowStaleDexCacheError(name);
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = -1;
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result >= 0) {
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_BOOLEAN(result);
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconst DalvikNativeMethod dvm_dalvik_system_DexFile[] = {
5207c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom    { "openDexFileNative",  "(Ljava/lang/String;Ljava/lang/String;I)I",
5217c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom        Dalvik_dalvik_system_DexFile_openDexFileNative },
522c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    { "openDexFile",        "([B)I",
523c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        Dalvik_dalvik_system_DexFile_openDexFile_bytearray },
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "closeDexFile",       "(I)V",
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_closeDexFile },
5267c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom    { "defineClassNative",  "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;",
5277c295c62290eb8703daa5574e106d5bf74c7a0d9Brian Carlstrom        Dalvik_dalvik_system_DexFile_defineClassNative },
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "getClassNameList",   "(I)[Ljava/lang/String;",
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_getClassNameList },
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "isDexOptNeeded",     "(Ljava/lang/String;)Z",
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_isDexOptNeeded },
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { NULL, NULL, NULL },
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
534