dalvik_system_DexFile.cpp revision e3f9c573d0edb186f4583fea1dbcdf9c12c0c36c
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 */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct 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
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DexOrJar;
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
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("Freeing DexOrJar '%s'\n", 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
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("+++ dex verifying cookie %p\n", 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) {
96dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        dvmThrowException("Ljava/lang/RuntimeException;",
97dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden            "invalid DexFile cookie");
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
99dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden    }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
105c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein/*
106c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein * Add given DexOrJar to the hash table of user-loaded dex files.
107c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein */
108c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornsteinstatic void addToDexFileTable(DexOrJar* pDexOrJar) {
109c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    /*
110c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * Later on, we will receive this pointer as an argument and need
111c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * to find it in the hash table without knowing if it's valid or
112c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * not, which means we can't compute a hash value from anything
113c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * inside DexOrJar. We don't share DexOrJar structs when the same
114c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * file is opened multiple times, so we can just use the low 32
115c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     * bits of the pointer as the hash.
116c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein     */
117c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    u4 hash = (u4) pDexOrJar;
118c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    void* result;
119c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
120c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    dvmHashTableLock(gDvm.userDexFiles);
121c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    result = dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,
122c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein            hashcmpDexOrJar, true);
123c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    dvmHashTableUnlock(gDvm.userDexFiles);
124c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
125c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (result != pDexOrJar) {
126c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        LOGE("Pointer has already been added?\n");
127c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        dvmAbort();
128c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
129c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
130c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->okayToFree = true;
131c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein}
132c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static int openDexFile(String sourceName, String outputName,
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     int flags) throws IOException
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open a DEX file, returning a pointer to our internal data structure.
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "sourceName" should point to the "source" jar or DEX file.
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "outputName" is NULL, the DEX code will automatically find the
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "optimized" version in the cache directory, creating it if necessary.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If it's non-NULL, the specified file will be used instead.
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: at present we will happily open the same file more than once.
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * To optimize this away we could search for existing entries in the hash
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * table and refCount them.  Requires atomic ops or adding "synchronized"
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to the non-native code that calls here.
1499d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden *
1509d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden * TODO: should be using "long" for a pointer.
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_openDexFile(const u4* args,
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* sourceNameObj = (StringObject*) args[0];
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* outputNameObj = (StringObject*) args[1];
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = NULL;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile* pJarFile;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RawDexFile* pRawDexFile;
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* sourceName;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* outputName;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (sourceNameObj == NULL) {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sourceName = dvmCreateCstrFromString(sourceNameObj);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (outputNameObj != NULL)
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputName = dvmCreateCstrFromString(outputNameObj);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outputName = NULL;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to deal with the possibility that somebody might try to
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * open one of our bootstrap class DEX files.  The set of dependencies
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * will be different, and hence the results of optimization might be
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * different, which means we'd actually need to have two versions of
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the optimized DEX: one that only knows about part of the boot class
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * path, and one that knows about everything in it.  The latter might
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * optimize field/method accesses based on a class that appeared later
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the class path.
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can't let the user-defined class loader open it and start using
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the classes, since the optimized form of the code skips some of
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the method and field resolution that we would ordinarily do, and
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we'd have the wrong semantics.
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have to reject attempts to manually open a DEX file from the boot
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * class path.  The easiest way to do this is by filename, which works
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * out because variations in name (e.g. "/system/framework/./ext.jar")
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * result in us hitting a different dalvik-cache entry.  It's also fine
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if the caller specifies their own output file.
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmClassPathContains(gDvm.bootClassPath, sourceName)) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Refusing to reopen boot DEX '%s'\n", sourceName);
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/io/IOException;",
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "Re-opening BOOTCLASSPATH DEX files is not allowed");
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(sourceName);
200e3f9c573d0edb186f4583fea1dbcdf9c12c0c36cKenny Root        free(outputName);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
205eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * Try to open it directly as a DEX if the name ends with ".dex".
206eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * If that fails (or isn't tried in the first place), try it as a
207eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein     * Zip with a "classes.dex" inside.
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
209eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein    if (hasDexExtension(sourceName)
210eab7355f9280dabcfe62fa2f21ca4e5511a59a24Dan Bornstein            && dvmRawDexFileOpen(sourceName, outputName, &pRawDexFile, false) == 0) {
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Opening DEX file '%s' (DEX)\n", sourceName);
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->isDex = true;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->pRawDexFile = pRawDexFile;
2169edce86c96d4df3ed5e439bd9581c1a997c67ebfDan Bornstein        pDexOrJar->pDexMemory = NULL;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false) == 0) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Opening DEX file '%s' (Jar)\n", sourceName);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->isDex = false;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->pJarFile = pJarFile;
2239edce86c96d4df3ed5e439bd9581c1a997c67ebfDan Bornstein        pDexOrJar->pDexMemory = NULL;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Unable to open DEX file '%s'\n", sourceName);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/io/IOException;", "unable to open DEX file");
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar != NULL) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDexOrJar->fileName = sourceName;
231c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        addToDexFileTable(pDexOrJar);
232c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    } else {
233c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        free(sourceName);
234c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
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) {
259c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
260c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
261c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
262c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
263c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    /* TODO: Avoid making a copy of the array. */
264c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    length = fileContentsObj->length;
265c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pBytes = (u1*) malloc(length);
266c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
267c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (pBytes == NULL) {
268c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        dvmThrowException("Ljava/lang/RuntimeException;",
269c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein                "unable to allocate DEX memory");
270c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
271c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
272c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
273c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    memcpy(pBytes, fileContentsObj->contents, length);
274c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
275c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    if (dvmRawDexFileOpenArray(pBytes, length, &pRawDexFile) != 0) {
276c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        LOGV("Unable to open in-memory DEX file\n");
277c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        free(pBytes);
278c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        dvmThrowException("Ljava/io/RuntimeException;",
279c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein                "unable to open in-memory DEX file");
280c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        RETURN_VOID();
281c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    }
282c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein
283c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    LOGV("Opening in-memory DEX\n");
284c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
285c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->isDex = true;
286c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->pRawDexFile = pRawDexFile;
287c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->pDexMemory = pBytes;
288c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    pDexOrJar->fileName = strdup("<memory>"); // Needs to be free()able.
289c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    addToDexFileTable(pDexOrJar);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(pDexOrJar);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static void closeDexFile(int cookie)
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Release resources associated with a user-loaded DEX file.
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_closeDexFile(const u4* args,
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[0];
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar == NULL)
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
308dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3109d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden    LOGV("Closing DEX file %p (%s)\n", pDexOrJar, pDexOrJar->fileName);
3119d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We can't just free arbitrary DEX files because they have bits and
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * pieces of loaded classes.  The only exception to this rule is if
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * they were never used to load classes.
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If we can't free them here, dvmInternalNativeShutdown() will free
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * them when the VM shuts down.
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->okayToFree) {
3219d674e9a03ffa05bec6d83c260d349e18bf7c21fAndy McFadden        u4 hash = (u4) pDexOrJar;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableLock(gDvm.userDexFiles);
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmHashTableRemove(gDvm.userDexFiles, hash, pDexOrJar)) {
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: could not remove '%s' from DEX hash table\n",
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pDexOrJar->fileName);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmHashTableUnlock(gDvm.userDexFiles);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ freeing DexFile '%s' resources\n", pDexOrJar->fileName);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFreeDexOrJar(pDexOrJar);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("+++ NOT freeing DexFile '%s' resources\n", pDexOrJar->fileName);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_VOID();
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static Class defineClass(String name, ClassLoader loader,
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      int cookie, ProtectionDomain pd)
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Load a class from a DEX file.  This is roughly equivalent to defineClass()
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in a regular VM -- it's invoked by the class loader to cause the
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * creation of a specific class.  The difference is that the search for and
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reading of the bytes is done within the VM.
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
3460ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden * The class name is a "binary name", e.g. "java.lang.String".
3470ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden *
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a null pointer with no exception if the class was not found.
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throws an exception on other failures.
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_defineClass(const u4* args,
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = (StringObject*) args[0];
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* loader = (Object*) args[1];
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[2];
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* pd = (Object*) args[3];
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* clazz = NULL;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name;
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* descriptor;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmCreateCstrFromString(nameObj);
3650ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden    descriptor = dvmDotToDescriptor(name);
3660ab3ad36caebfd490612275d5bc3c3b0d5e46f3dAndy McFadden    LOGV("--- Explicit class load '%s' 0x%08x\n", descriptor, cookie);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
370dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->isDex)
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* once we load something, we can't unmap the storage */
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexOrJar->okayToFree = false;
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    clazz = dvmDefineClass(pDvmDex, descriptor, loader);
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmCheckException(self)) {
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we threw a "class not found" exception, stifle it, since the
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * contract in the higher method says we simply return null if
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the class is not found.
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* excep = dvmGetException(self);
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(excep->clazz->descriptor,
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   "Ljava/lang/ClassNotFoundException;") == 0 ||
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strcmp(excep->clazz->descriptor,
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   "Ljava/lang/NoClassDefFoundError;") == 0)
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmClearException(self);
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clazz = NULL;
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Set the ProtectionDomain -- do we need this to happen before we
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * link the class and make it available? If so, we need to pass it
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * through dvmDefineClass (and figure out some other
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stuff, like where it comes from for bootstrap classes).
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (clazz != NULL) {
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGI("SETTING pd '%s' to %p\n", clazz->descriptor, pd);
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmSetFieldObject((Object*) clazz, gDvm.offJavaLangClass_pd, pd);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(descriptor);
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(clazz);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * private static String[] getClassNameList(int cookie)
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a String array that holds the names of all classes in the
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * specified DEX file.
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_getClassNameList(const u4* args,
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cookie = args[0];
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOrJar* pDexOrJar = (DexOrJar*) cookie;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex;
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexFile* pDexFile;
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* stringArray;
428364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    Thread* self = dvmThreadSelf();
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!validateCookie(cookie))
431dbedb4e578f9376483fb531978a772693400cdf9Andy McFadden        RETURN_VOID();
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pDexOrJar->isDex)
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(pDvmDex != NULL);
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pDexFile = pDvmDex->pDexFile;
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int count = pDexFile->pHeader->classDefsSize;
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stringArray = dvmAllocObjectArray(gDvm.classJavaLangString, count,
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ALLOC_DEFAULT);
443364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    if (stringArray == NULL) {
444364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        /* probably OOM */
445364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        LOGD("Failed allocating array of %d strings\n", count);
446364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        assert(dvmCheckException(self));
447364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        RETURN_VOID();
448364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    }
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < count; i++) {
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* descriptor =
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* className = dvmDescriptorToDot(descriptor);
457364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        StringObject* str = dvmCreateStringFromCstr(className);
458364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmSetObjectArrayElement(stringArray, i, (Object *)str);
459364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmReleaseTrackedAlloc((Object *)str, self);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(className);
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
463364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes    dvmReleaseTrackedAlloc((Object*)stringArray, self);
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    RETURN_PTR(stringArray);
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public static boolean isDexOptNeeded(String apkName)
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         throws FileNotFoundException, IOException
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns true if the VM believes that the apk/jar file is out of date
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and should be passed through "dexopt" again.
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param fileName the absolute path to the apk/jar file to examine.
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return true if dexopt should be called on the file, false otherwise.
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.io.FileNotFoundException if fileName is not readable,
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         not a file, or not present.
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.io.IOException if fileName is not a valid apk/jar file or
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         if problems occur while parsing it.
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws java.lang.NullPointerException if fileName is null.
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws dalvik.system.StaleDexCacheError if the optimized dex file
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *         is stale but exists on a read-only partition.
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void Dalvik_dalvik_system_DexFile_isDexOptNeeded(const u4* args,
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue* pResult)
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* nameObj = (StringObject*) args[0];
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* name;
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexCacheStatus status;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result;
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    name = dvmCreateCstrFromString(nameObj);
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (name == NULL) {
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (access(name, R_OK) != 0) {
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/io/FileNotFoundException;", name);
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(name);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    status = dvmDexCacheStatus(name);
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("dvmDexCacheStatus(%s) returned %d\n", name, status);
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (status) {
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default: //FALLTHROUGH
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_BAD_ARCHIVE:
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ljava/io/IOException;", name);
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = -1;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_OK:
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = false;
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_STALE:
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = true;
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case DEX_CACHE_STALE_ODEX:
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowException("Ldalvik/system/StaleDexCacheError;", name);
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        result = -1;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(name);
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (result >= 0) {
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_BOOLEAN(result);
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RETURN_VOID();
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconst DalvikNativeMethod dvm_dalvik_system_DexFile[] = {
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "openDexFile",        "(Ljava/lang/String;Ljava/lang/String;I)I",
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_openDexFile },
535c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein    { "openDexFile",        "([B)I",
536c5ba2b6a98636c841f6cb17094503c3c8199e852Dan Bornstein        Dalvik_dalvik_system_DexFile_openDexFile_bytearray },
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "closeDexFile",       "(I)V",
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_closeDexFile },
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "defineClass",        "(Ljava/lang/String;Ljava/lang/ClassLoader;ILjava/security/ProtectionDomain;)Ljava/lang/Class;",
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_defineClass },
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "getClassNameList",   "(I)[Ljava/lang/String;",
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_getClassNameList },
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { "isDexOptNeeded",     "(Ljava/lang/String;)Z",
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Dalvik_dalvik_system_DexFile_isDexOptNeeded },
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    { NULL, NULL, NULL },
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project};
547