• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Class loading, including bootstrap class loader, linking, and
19  * initialization.
20  */
21 
22 #define LOG_CLASS_LOADING 0
23 
24 #include "Dalvik.h"
25 #include "libdex/DexClass.h"
26 
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <sys/stat.h>
30 
31 #if LOG_CLASS_LOADING
32 #include <unistd.h>
33 #include <pthread.h>
34 #include <cutils/process_name.h>
35 #include <sys/types.h>
36 #endif
37 
38 /*
39 Notes on Linking and Verification
40 
41 The basic way to retrieve a class is to load it, make sure its superclass
42 and interfaces are available, prepare its fields, and return it.  This gets
43 a little more complicated when multiple threads can be trying to retrieve
44 the class simultaneously, requiring that we use the class object's monitor
45 to keep things orderly.
46 
47 The linking (preparing, resolving) of a class can cause us to recursively
48 load superclasses and interfaces.  Barring circular references (e.g. two
49 classes that are superclasses of each other), this will complete without
50 the loader attempting to access the partially-linked class.
51 
52 With verification, the situation is different.  If we try to verify
53 every class as we load it, we quickly run into trouble.  Even the lowly
54 java.lang.Object requires CloneNotSupportedException; follow the list
55 of referenced classes and you can head down quite a trail.  The trail
56 eventually leads back to Object, which is officially not fully-formed yet.
57 
58 The VM spec (specifically, v2 5.4.1) notes that classes pulled in during
59 verification do not need to be prepared or verified.  This means that we
60 are allowed to have loaded but unverified classes.  It further notes that
61 the class must be verified before it is initialized, which allows us to
62 defer verification for all classes until class init.  You can't execute
63 code or access fields in an uninitialized class, so this is safe.
64 
65 It also allows a more peaceful coexistence between verified and
66 unverifiable code.  If class A refers to B, and B has a method that
67 refers to a bogus class C, should we allow class A to be verified?
68 If A only exercises parts of B that don't use class C, then there is
69 nothing wrong with running code in A.  We can fully verify both A and B,
70 and allow execution to continue until B causes initialization of C.  The
71 VerifyError is thrown close to the point of use.
72 
73 This gets a little weird with java.lang.Class, which is the only class
74 that can be instantiated before it is initialized.  We have to force
75 initialization right after the class is created, because by definition we
76 have instances of it on the heap, and somebody might get a class object and
77 start making virtual calls on it.  We can end up going recursive during
78 verification of java.lang.Class, but we avoid that by checking to see if
79 verification is already in progress before we try to initialize it.
80 */
81 
82 /*
83 Notes on class loaders and interaction with optimization / verification
84 
85 In what follows, "pre-verification" and "optimization" are the steps
86 performed by the dexopt command, which attempts to verify and optimize
87 classes as part of unpacking jar files and storing the DEX data in the
88 dalvik-cache directory.  These steps are performed by loading the DEX
89 files directly, without any assistance from ClassLoader instances.
90 
91 When we pre-verify and optimize a class in a DEX file, we make some
92 assumptions about where the class loader will go to look for classes.
93 If we can't guarantee those assumptions, e.g. because a class ("AppClass")
94 references something not defined in the bootstrap jars or the AppClass jar,
95 we can't pre-verify or optimize the class.
96 
97 The VM doesn't define the behavior of user-defined class loaders.
98 For example, suppose application class AppClass, loaded by UserLoader,
99 has a method that creates a java.lang.String.  The first time
100 AppClass.stringyMethod tries to do something with java.lang.String, it
101 asks UserLoader to find it.  UserLoader is expected to defer to its parent
102 loader, but isn't required to.  UserLoader might provide a replacement
103 for String.
104 
105 We can run into trouble if we pre-verify AppClass with the assumption that
106 java.lang.String will come from core.jar, and don't verify this assumption
107 at runtime.  There are two places that an alternate implementation of
108 java.lang.String can come from: the AppClass jar, or from some other jar
109 that UserLoader knows about.  (Someday UserLoader will be able to generate
110 some bytecode and call DefineClass, but not yet.)
111 
112 To handle the first situation, the pre-verifier will explicitly check for
113 conflicts between the class being optimized/verified and the bootstrap
114 classes.  If an app jar contains a class that has the same package and
115 class name as a class in a bootstrap jar, the verification resolver refuses
116 to find either, which will block pre-verification and optimization on
117 classes that reference ambiguity.  The VM will postpone verification of
118 the app class until first load.
119 
120 For the second situation, we need to ensure that all references from a
121 pre-verified class are satisified by the class' jar or earlier bootstrap
122 jars.  In concrete terms: when resolving a reference to NewClass,
123 which was caused by a reference in class AppClass, we check to see if
124 AppClass was pre-verified.  If so, we require that NewClass comes out
125 of either the AppClass jar or one of the jars in the bootstrap path.
126 (We may not control the class loaders, but we do manage the DEX files.
127 We can verify that it's either (loader==null && dexFile==a_boot_dex)
128 or (loader==UserLoader && dexFile==AppClass.dexFile).  Classes from
129 DefineClass can't be pre-verified, so this doesn't apply.)
130 
131 This should ensure that you can't "fake out" the pre-verifier by creating
132 a user-defined class loader that replaces system classes.  It should
133 also ensure that you can write such a loader and have it work in the
134 expected fashion; all you lose is some performance due to "just-in-time
135 verification" and the lack of DEX optimizations.
136 
137 There is a "back door" of sorts in the class resolution check, due to
138 the fact that the "class ref" entries are shared between the bytecode
139 and meta-data references (e.g. annotations and exception handler lists).
140 The class references in annotations have no bearing on class verification,
141 so when a class does an annotation query that causes a class reference
142 index to be resolved, we don't want to fail just because the calling
143 class was pre-verified and the resolved class is in some random DEX file.
144 The successful resolution adds the class to the "resolved classes" table,
145 so when optimized bytecode references it we don't repeat the resolve-time
146 check.  We can avoid this by not updating the "resolved classes" table
147 when the class reference doesn't come out of something that has been
148 checked by the verifier, but that has a nonzero performance impact.
149 Since the ultimate goal of this test is to catch an unusual situation
150 (user-defined class loaders redefining core classes), the added caution
151 may not be worth the performance hit.
152 */
153 
154 /*
155  * Class serial numbers start at this value.  We use a nonzero initial
156  * value so they stand out in binary dumps (e.g. hprof output).
157  */
158 #define INITIAL_CLASS_SERIAL_NUMBER 0x50000000
159 
160 /*
161  * Constant used to size an auxillary class object data structure.
162  * For optimum memory use this should be equal to or slightly larger than
163  * the number of classes loaded when the zygote finishes initializing.
164  */
165 #define ZYGOTE_CLASS_CUTOFF 2304
166 
167 static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap);
168 static void freeCpeArray(ClassPathEntry* cpe);
169 
170 static ClassObject* findClassFromLoaderNoInit(
171     const char* descriptor, Object* loader);
172 static ClassObject* findClassNoInit(const char* descriptor, Object* loader,\
173     DvmDex* pDvmDex);
174 static ClassObject* loadClassFromDex(DvmDex* pDvmDex,
175     const DexClassDef* pClassDef, Object* loader);
176 static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,\
177     Method* meth);
178 static int computeJniArgInfo(const DexProto* proto);
179 static void loadSFieldFromDex(ClassObject* clazz,
180     const DexField* pDexSField, StaticField* sfield);
181 static void loadIFieldFromDex(ClassObject* clazz,
182     const DexField* pDexIField, InstField* field);
183 static void freeMethodInnards(Method* meth);
184 static bool createVtable(ClassObject* clazz);
185 static bool createIftable(ClassObject* clazz);
186 static bool insertMethodStubs(ClassObject* clazz);
187 static bool computeFieldOffsets(ClassObject* clazz);
188 static void throwEarlierClassFailure(ClassObject* clazz);
189 
190 #if LOG_CLASS_LOADING
191 /*
192  * Logs information about a class loading with given timestamp.
193  *
194  * TODO: In the case where we fail in dvmLinkClass() and log the class as closing (type='<'),
195  * it would probably be better to use a new type code to indicate the failure.  This change would
196  * require a matching change in the parser and analysis code in frameworks/base/tools/preload.
197  */
logClassLoadWithTime(char type,ClassObject * clazz,u8 time)198 static void logClassLoadWithTime(char type, ClassObject* clazz, u8 time) {
199     pid_t ppid = getppid();
200     pid_t pid = getpid();
201     unsigned int tid = (unsigned int) pthread_self();
202 
203     LOG(LOG_INFO, "PRELOAD", "%c%d:%d:%d:%s:%d:%s:%lld\n", type, ppid, pid, tid,
204         get_process_name(), (int) clazz->classLoader, clazz->descriptor,
205         time);
206 }
207 
208 /*
209  * Logs information about a class loading.
210  */
logClassLoad(char type,ClassObject * clazz)211 static void logClassLoad(char type, ClassObject* clazz) {
212     logClassLoadWithTime(type, clazz, dvmGetThreadCpuTimeNsec());
213 }
214 #endif
215 
216 /*
217  * Some LinearAlloc unit tests.
218  */
linearAllocTests()219 static void linearAllocTests()
220 {
221     char* fiddle;
222     int try = 1;
223 
224     switch (try) {
225     case 0:
226         fiddle = dvmLinearAlloc(NULL, 3200-28);
227         dvmLinearReadOnly(NULL, fiddle);
228         break;
229     case 1:
230         fiddle = dvmLinearAlloc(NULL, 3200-24);
231         dvmLinearReadOnly(NULL, fiddle);
232         break;
233     case 2:
234         fiddle = dvmLinearAlloc(NULL, 3200-20);
235         dvmLinearReadOnly(NULL, fiddle);
236         break;
237     case 3:
238         fiddle = dvmLinearAlloc(NULL, 3200-16);
239         dvmLinearReadOnly(NULL, fiddle);
240         break;
241     case 4:
242         fiddle = dvmLinearAlloc(NULL, 3200-12);
243         dvmLinearReadOnly(NULL, fiddle);
244         break;
245     }
246     fiddle = dvmLinearAlloc(NULL, 896);
247     dvmLinearReadOnly(NULL, fiddle);
248     fiddle = dvmLinearAlloc(NULL, 20);      // watch addr of this alloc
249     dvmLinearReadOnly(NULL, fiddle);
250 
251     fiddle = dvmLinearAlloc(NULL, 1);
252     fiddle[0] = 'q';
253     dvmLinearReadOnly(NULL, fiddle);
254     fiddle = dvmLinearAlloc(NULL, 4096);
255     fiddle[0] = 'x';
256     fiddle[4095] = 'y';
257     dvmLinearReadOnly(NULL, fiddle);
258     dvmLinearFree(NULL, fiddle);
259     fiddle = dvmLinearAlloc(NULL, 0);
260     dvmLinearReadOnly(NULL, fiddle);
261     fiddle = dvmLinearRealloc(NULL, fiddle, 12);
262     fiddle[11] = 'z';
263     dvmLinearReadOnly(NULL, fiddle);
264     fiddle = dvmLinearRealloc(NULL, fiddle, 5);
265     dvmLinearReadOnly(NULL, fiddle);
266     fiddle = dvmLinearAlloc(NULL, 17001);
267     fiddle[0] = 'x';
268     fiddle[17000] = 'y';
269     dvmLinearReadOnly(NULL, fiddle);
270 
271     char* str = dvmLinearStrdup(NULL, "This is a test!");
272     LOGI("GOT: '%s'\n", str);
273 
274     dvmLinearAllocDump(NULL);
275     dvmLinearFree(NULL, str);
276 }
277 
278 /*
279  * Initialize the bootstrap class loader.
280  *
281  * Call this after the bootclasspath string has been finalized.
282  */
dvmClassStartup(void)283 bool dvmClassStartup(void)
284 {
285     ClassObject* unlinkedClass;
286 
287     /* make this a requirement -- don't currently support dirs in path */
288     if (strcmp(gDvm.bootClassPathStr, ".") == 0) {
289         LOGE("ERROR: must specify non-'.' bootclasspath\n");
290         return false;
291     }
292 
293     gDvm.loadedClasses =
294         dvmHashTableCreate(256, (HashFreeFunc) dvmFreeClassInnards);
295 
296     gDvm.pBootLoaderAlloc = dvmLinearAllocCreate(NULL);
297     if (gDvm.pBootLoaderAlloc == NULL)
298         return false;
299 
300     if (false) {
301         linearAllocTests();
302         exit(0);
303     }
304 
305     /*
306      * Class serial number.  We start with a high value to make it distinct
307      * in binary dumps (e.g. hprof).
308      */
309     gDvm.classSerialNumber = INITIAL_CLASS_SERIAL_NUMBER;
310 
311     /* Set up the table we'll use for tracking initiating loaders for
312      * early classes.
313      * If it's NULL, we just fall back to the InitiatingLoaderList in the
314      * ClassObject, so it's not fatal to fail this allocation.
315      */
316     gDvm.initiatingLoaderList =
317         calloc(ZYGOTE_CLASS_CUTOFF, sizeof(InitiatingLoaderList));
318 
319     /* This placeholder class is used while a ClassObject is
320      * loading/linking so those not in the know can still say
321      * "obj->clazz->...".
322      */
323     unlinkedClass = &gDvm.unlinkedJavaLangClassObject;
324 
325     memset(unlinkedClass, 0, sizeof(*unlinkedClass));
326 
327     /* Set obj->clazz to NULL so anyone who gets too interested
328      * in the fake class will crash.
329      */
330     DVM_OBJECT_INIT(&unlinkedClass->obj, NULL);
331     unlinkedClass->descriptor = "!unlinkedClass";
332     dvmSetClassSerialNumber(unlinkedClass);
333 
334     gDvm.unlinkedJavaLangClass = unlinkedClass;
335 
336     /*
337      * Process the bootstrap class path.  This means opening the specified
338      * DEX or Jar files and possibly running them through the optimizer.
339      */
340     assert(gDvm.bootClassPath == NULL);
341     processClassPath(gDvm.bootClassPathStr, true);
342 
343     if (gDvm.bootClassPath == NULL)
344         return false;
345 
346     return true;
347 }
348 
349 /*
350  * Clean up.
351  */
dvmClassShutdown(void)352 void dvmClassShutdown(void)
353 {
354     int i;
355 
356     /* discard all system-loaded classes */
357     dvmHashTableFree(gDvm.loadedClasses);
358     gDvm.loadedClasses = NULL;
359 
360     /* discard primitive classes created for arrays */
361     for (i = 0; i < PRIM_MAX; i++)
362         dvmFreeClassInnards(gDvm.primitiveClass[i]);
363 
364     /* this closes DEX files, JAR files, etc. */
365     freeCpeArray(gDvm.bootClassPath);
366     gDvm.bootClassPath = NULL;
367 
368     dvmLinearAllocDestroy(NULL);
369 
370     free(gDvm.initiatingLoaderList);
371 }
372 
373 
374 /*
375  * ===========================================================================
376  *      Bootstrap class loader
377  * ===========================================================================
378  */
379 
380 /*
381  * Dump the contents of a ClassPathEntry array.
382  */
dumpClassPath(const ClassPathEntry * cpe)383 static void dumpClassPath(const ClassPathEntry* cpe)
384 {
385     int idx = 0;
386 
387     while (cpe->kind != kCpeLastEntry) {
388         const char* kindStr;
389 
390         switch (cpe->kind) {
391         case kCpeDir:       kindStr = "dir";    break;
392         case kCpeJar:       kindStr = "jar";    break;
393         case kCpeDex:       kindStr = "dex";    break;
394         default:            kindStr = "???";    break;
395         }
396 
397         LOGI("  %2d: type=%s %s %p\n", idx, kindStr, cpe->fileName, cpe->ptr);
398         if (CALC_CACHE_STATS && cpe->kind == kCpeJar) {
399             JarFile* pJarFile = (JarFile*) cpe->ptr;
400             DvmDex* pDvmDex = dvmGetJarFileDex(pJarFile);
401             dvmDumpAtomicCacheStats(pDvmDex->pInterfaceCache);
402         }
403 
404         cpe++;
405         idx++;
406     }
407 }
408 
409 /*
410  * Dump the contents of the bootstrap class path.
411  */
dvmDumpBootClassPath(void)412 void dvmDumpBootClassPath(void)
413 {
414     dumpClassPath(gDvm.bootClassPath);
415 }
416 
417 /*
418  * Returns "true" if the class path contains the specified path.
419  */
dvmClassPathContains(const ClassPathEntry * cpe,const char * path)420 bool dvmClassPathContains(const ClassPathEntry* cpe, const char* path)
421 {
422     while (cpe->kind != kCpeLastEntry) {
423         if (strcmp(cpe->fileName, path) == 0)
424             return true;
425 
426         cpe++;
427     }
428     return false;
429 }
430 
431 /*
432  * Free an array of ClassPathEntry structs.
433  *
434  * We release the contents of each entry, then free the array itself.
435  */
freeCpeArray(ClassPathEntry * cpe)436 static void freeCpeArray(ClassPathEntry* cpe)
437 {
438     ClassPathEntry* cpeStart = cpe;
439 
440     if (cpe == NULL)
441         return;
442 
443     while (cpe->kind != kCpeLastEntry) {
444         switch (cpe->kind) {
445         case kCpeJar:
446             /* free JarFile */
447             dvmJarFileFree((JarFile*) cpe->ptr);
448             break;
449         case kCpeDex:
450             /* free RawDexFile */
451             dvmRawDexFileFree((RawDexFile*) cpe->ptr);
452             break;
453         default:
454             /* e.g. kCpeDir */
455             assert(cpe->ptr == NULL);
456             break;
457         }
458 
459         free(cpe->fileName);
460         cpe++;
461     }
462 
463     free(cpeStart);
464 }
465 
466 /*
467  * Prepare a ClassPathEntry struct, which at this point only has a valid
468  * filename.  We need to figure out what kind of file it is, and for
469  * everything other than directories we need to open it up and see
470  * what's inside.
471  */
prepareCpe(ClassPathEntry * cpe,bool isBootstrap)472 static bool prepareCpe(ClassPathEntry* cpe, bool isBootstrap)
473 {
474     JarFile* pJarFile = NULL;
475     RawDexFile* pRawDexFile = NULL;
476     struct stat sb;
477     int cc;
478 
479     cc = stat(cpe->fileName, &sb);
480     if (cc < 0) {
481         LOGW("Unable to stat classpath element '%s'\n", cpe->fileName);
482         return false;
483     }
484     if (S_ISDIR(sb.st_mode)) {
485         /*
486          * The directory will usually have .class files in subdirectories,
487          * which may be a few levels down.  Doing a recursive scan and
488          * caching the results would help us avoid hitting the filesystem
489          * on misses.  Whether or not this is of measureable benefit
490          * depends on a number of factors, but most likely it is not
491          * worth the effort (especially since most of our stuff will be
492          * in DEX or JAR).
493          */
494         cpe->kind = kCpeDir;
495         assert(cpe->ptr == NULL);
496         return true;
497     }
498 
499     if (dvmJarFileOpen(cpe->fileName, NULL, &pJarFile, isBootstrap) == 0) {
500         cpe->kind = kCpeJar;
501         cpe->ptr = pJarFile;
502         return true;
503     }
504 
505     // TODO: do we still want to support "raw" DEX files in the classpath?
506     if (dvmRawDexFileOpen(cpe->fileName, NULL, &pRawDexFile, isBootstrap) == 0)
507     {
508         cpe->kind = kCpeDex;
509         cpe->ptr = pRawDexFile;
510         return true;
511     }
512 
513     return false;
514 }
515 
516 /*
517  * Convert a colon-separated list of directories, Zip files, and DEX files
518  * into an array of ClassPathEntry structs.
519  *
520  * If we're unable to load a bootstrap class path entry, we fail.  This
521  * is necessary to preserve the dependencies implied by optimized DEX files
522  * (e.g. if the same class appears in multiple places).
523  *
524  * During normal startup we fail if there are no entries, because we won't
525  * get very far without the basic language support classes, but if we're
526  * optimizing a DEX file we allow it.
527  */
processClassPath(const char * pathStr,bool isBootstrap)528 static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
529 {
530     ClassPathEntry* cpe = NULL;
531     char* mangle;
532     char* cp;
533     const char* end;
534     int idx, count;
535 
536     assert(pathStr != NULL);
537 
538     mangle = strdup(pathStr);
539 
540     /*
541      * Run through and essentially strtok() the string.  Get a count of
542      * the #of elements while we're at it.
543      *
544      * If the path was constructed strangely (e.g. ":foo::bar:") this will
545      * over-allocate, which isn't ideal but is mostly harmless.
546      */
547     count = 1;
548     for (cp = mangle; *cp != '\0'; cp++) {
549         if (*cp == ':') {   /* separates two entries */
550             count++;
551             *cp = '\0';
552         }
553     }
554     end = cp;
555 
556     /*
557      * Allocate storage.  We over-alloc by one so we can set an "end" marker.
558      */
559     cpe = (ClassPathEntry*) calloc(count+1, sizeof(ClassPathEntry));
560 
561     /*
562      * Set the global pointer so the DEX file dependency stuff can find it.
563      */
564     gDvm.bootClassPath = cpe;
565 
566     /*
567      * Go through a second time, pulling stuff out.
568      */
569     cp = mangle;
570     idx = 0;
571     while (cp < end) {
572         if (*cp == '\0') {
573             /* leading, trailing, or doubled ':'; ignore it */
574         } else {
575             ClassPathEntry tmp;
576             tmp.kind = kCpeUnknown;
577             tmp.fileName = strdup(cp);
578             tmp.ptr = NULL;
579 
580             /* drop an end marker here so DEX loader can walk unfinished list */
581             cpe[idx].kind = kCpeLastEntry;
582             cpe[idx].fileName = NULL;
583             cpe[idx].ptr = NULL;
584 
585             if (!prepareCpe(&tmp, isBootstrap)) {
586                 LOGD("Failed on '%s' (boot=%d)\n", tmp.fileName, isBootstrap);
587                 /* drop from list and continue on */
588                 free(tmp.fileName);
589 
590                 if (isBootstrap || gDvm.optimizing) {
591                     /* if boot path entry or we're optimizing, this is fatal */
592                     free(cpe);
593                     cpe = NULL;
594                     goto bail;
595                 }
596             } else {
597                 /* copy over, pointers and all */
598                 if (tmp.fileName[0] != '/')
599                     LOGW("Non-absolute bootclasspath entry '%s'\n",
600                         tmp.fileName);
601                 cpe[idx] = tmp;
602                 idx++;
603             }
604         }
605 
606         cp += strlen(cp) +1;
607     }
608     assert(idx <= count);
609     if (idx == 0 && !gDvm.optimizing) {
610         LOGE("ERROR: no valid entries found in bootclasspath '%s'\n", pathStr);
611         free(cpe);
612         cpe = NULL;
613         goto bail;
614     }
615 
616     LOGVV("  (filled %d of %d slots)\n", idx, count);
617 
618     /* put end marker in over-alloc slot */
619     cpe[idx].kind = kCpeLastEntry;
620     cpe[idx].fileName = NULL;
621     cpe[idx].ptr = NULL;
622 
623     //dumpClassPath(cpe);
624 
625 bail:
626     free(mangle);
627     gDvm.bootClassPath = cpe;
628     return cpe;
629 }
630 
631 /*
632  * Search the DEX files we loaded from the bootstrap class path for a DEX
633  * file that has the class with the matching descriptor.
634  *
635  * Returns the matching DEX file and DexClassDef entry if found, otherwise
636  * returns NULL.
637  */
searchBootPathForClass(const char * descriptor,const DexClassDef ** ppClassDef)638 static DvmDex* searchBootPathForClass(const char* descriptor,
639     const DexClassDef** ppClassDef)
640 {
641     const ClassPathEntry* cpe = gDvm.bootClassPath;
642     const DexClassDef* pFoundDef = NULL;
643     DvmDex* pFoundFile = NULL;
644 
645     LOGVV("+++ class '%s' not yet loaded, scanning bootclasspath...\n",
646         descriptor);
647 
648     while (cpe->kind != kCpeLastEntry) {
649         //LOGV("+++  checking '%s' (%d)\n", cpe->fileName, cpe->kind);
650 
651         switch (cpe->kind) {
652         case kCpeDir:
653             LOGW("Directory entries ('%s') not supported in bootclasspath\n",
654                 cpe->fileName);
655             break;
656         case kCpeJar:
657             {
658                 JarFile* pJarFile = (JarFile*) cpe->ptr;
659                 const DexClassDef* pClassDef;
660                 DvmDex* pDvmDex;
661 
662                 pDvmDex = dvmGetJarFileDex(pJarFile);
663                 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
664                 if (pClassDef != NULL) {
665                     /* found */
666                     pFoundDef = pClassDef;
667                     pFoundFile = pDvmDex;
668                     goto found;
669                 }
670             }
671             break;
672         case kCpeDex:
673             {
674                 RawDexFile* pRawDexFile = (RawDexFile*) cpe->ptr;
675                 const DexClassDef* pClassDef;
676                 DvmDex* pDvmDex;
677 
678                 pDvmDex = dvmGetRawDexFileDex(pRawDexFile);
679                 pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
680                 if (pClassDef != NULL) {
681                     /* found */
682                     pFoundDef = pClassDef;
683                     pFoundFile = pDvmDex;
684                     goto found;
685                 }
686             }
687             break;
688         default:
689             LOGE("Unknown kind %d\n", cpe->kind);
690             assert(false);
691             break;
692         }
693 
694         cpe++;
695     }
696 
697     /*
698      * Special handling during verification + optimization.
699      *
700      * The DEX optimizer needs to load classes from the DEX file it's working
701      * on.  Rather than trying to insert it into the bootstrap class path
702      * or synthesizing a class loader to manage it, we just make it available
703      * here.  It logically comes after all existing entries in the bootstrap
704      * class path.
705      */
706     if (gDvm.bootClassPathOptExtra != NULL) {
707         const DexClassDef* pClassDef;
708 
709         pClassDef =
710             dexFindClass(gDvm.bootClassPathOptExtra->pDexFile, descriptor);
711         if (pClassDef != NULL) {
712             /* found */
713             pFoundDef = pClassDef;
714             pFoundFile = gDvm.bootClassPathOptExtra;
715         }
716     }
717 
718 found:
719     *ppClassDef = pFoundDef;
720     return pFoundFile;
721 }
722 
723 /*
724  * Set the "extra" DEX, which becomes a de facto member of the bootstrap
725  * class set.
726  */
dvmSetBootPathExtraDex(DvmDex * pDvmDex)727 void dvmSetBootPathExtraDex(DvmDex* pDvmDex)
728 {
729     gDvm.bootClassPathOptExtra = pDvmDex;
730 }
731 
732 
733 /*
734  * Return the #of entries in the bootstrap class path.
735  *
736  * (Used for ClassLoader.getResources().)
737  */
dvmGetBootPathSize(void)738 int dvmGetBootPathSize(void)
739 {
740     const ClassPathEntry* cpe = gDvm.bootClassPath;
741 
742     while (cpe->kind != kCpeLastEntry)
743         cpe++;
744 
745     return cpe - gDvm.bootClassPath;
746 }
747 
748 /*
749  * Find a resource with the specified name in entry N of the boot class path.
750  *
751  * We return a newly-allocated String of one of these forms:
752  *   file://path/name
753  *   jar:file://path!/name
754  * Where "path" is the bootstrap class path entry and "name" is the string
755  * passed into this method.  "path" needs to be an absolute path (starting
756  * with '/'); if it's not we'd need to "absolutify" it as part of forming
757  * the URL string.
758  */
dvmGetBootPathResource(const char * name,int idx)759 StringObject* dvmGetBootPathResource(const char* name, int idx)
760 {
761     const int kUrlOverhead = 13;        // worst case for Jar URL
762     const ClassPathEntry* cpe = gDvm.bootClassPath;
763     StringObject* urlObj = NULL;
764 
765     LOGV("+++ searching for resource '%s' in %d(%s)\n",
766         name, idx, cpe[idx].fileName);
767 
768     /* we could use direct array index, but I don't entirely trust "idx" */
769     while (idx-- && cpe->kind != kCpeLastEntry)
770         cpe++;
771     if (cpe->kind == kCpeLastEntry) {
772         assert(false);
773         return NULL;
774     }
775 
776     char urlBuf[strlen(name) + strlen(cpe->fileName) + kUrlOverhead +1];
777 
778     switch (cpe->kind) {
779     case kCpeDir:
780         sprintf(urlBuf, "file://%s/%s", cpe->fileName, name);
781         if (access(urlBuf+7, F_OK) != 0)
782             goto bail;
783         break;
784     case kCpeJar:
785         {
786             JarFile* pJarFile = (JarFile*) cpe->ptr;
787             if (dexZipFindEntry(&pJarFile->archive, name) == NULL)
788                 goto bail;
789             sprintf(urlBuf, "jar:file://%s!/%s", cpe->fileName, name);
790         }
791         break;
792     case kCpeDex:
793         LOGV("No resources in DEX files\n");
794         goto bail;
795     default:
796         assert(false);
797         goto bail;
798     }
799 
800     LOGV("+++ using URL='%s'\n", urlBuf);
801     urlObj = dvmCreateStringFromCstr(urlBuf, ALLOC_DEFAULT);
802 
803 bail:
804     return urlObj;
805 }
806 
807 
808 /*
809  * ===========================================================================
810  *      Class list management
811  * ===========================================================================
812  */
813 
814 /* search for these criteria in the Class hash table */
815 typedef struct ClassMatchCriteria {
816     const char* descriptor;
817     Object*     loader;
818 } ClassMatchCriteria;
819 
820 #define kInitLoaderInc  4       /* must be power of 2 */
821 
dvmGetInitiatingLoaderList(ClassObject * clazz)822 static InitiatingLoaderList *dvmGetInitiatingLoaderList(ClassObject* clazz)
823 {
824     assert(clazz->serialNumber > INITIAL_CLASS_SERIAL_NUMBER);
825     int classIndex = clazz->serialNumber-INITIAL_CLASS_SERIAL_NUMBER;
826     if (gDvm.initiatingLoaderList != NULL &&
827         classIndex < ZYGOTE_CLASS_CUTOFF) {
828         return &(gDvm.initiatingLoaderList[classIndex]);
829     } else {
830         return &(clazz->initiatingLoaderList);
831     }
832 }
833 
834 /*
835  * Determine if "loader" appears in clazz' initiating loader list.
836  *
837  * The class hash table lock must be held when calling here, since
838  * it's also used when updating a class' initiating loader list.
839  *
840  * TODO: switch to some sort of lock-free data structure so we don't have
841  * to grab the lock to do a lookup.  Among other things, this would improve
842  * the speed of compareDescriptorClasses().
843  */
dvmLoaderInInitiatingList(const ClassObject * clazz,const Object * loader)844 bool dvmLoaderInInitiatingList(const ClassObject* clazz, const Object* loader)
845 {
846     /*
847      * The bootstrap class loader can't be just an initiating loader for
848      * anything (it's always the defining loader if the class is visible
849      * to it).  We don't put defining loaders in the initiating list.
850      */
851     if (loader == NULL)
852         return false;
853 
854     /*
855      * Scan the list for a match.  The list is expected to be short.
856      */
857     /* Cast to remove the const from clazz, but use const loaderList */
858     ClassObject* nonConstClazz = (ClassObject*) clazz;
859     const InitiatingLoaderList *loaderList =
860         dvmGetInitiatingLoaderList(nonConstClazz);
861     int i;
862     for (i = loaderList->initiatingLoaderCount-1; i >= 0; --i) {
863         if (loaderList->initiatingLoaders[i] == loader) {
864             //LOGI("+++ found initiating match %p in %s\n",
865             //    loader, clazz->descriptor);
866             return true;
867         }
868     }
869     return false;
870 }
871 
872 /*
873  * Add "loader" to clazz's initiating loader set, unless it's the defining
874  * class loader.
875  *
876  * In the common case this will be a short list, so we don't need to do
877  * anything too fancy here.
878  *
879  * This locks gDvm.loadedClasses for synchronization, so don't hold it
880  * when calling here.
881  */
dvmAddInitiatingLoader(ClassObject * clazz,Object * loader)882 void dvmAddInitiatingLoader(ClassObject* clazz, Object* loader)
883 {
884     if (loader != clazz->classLoader) {
885         assert(loader != NULL);
886 
887         LOGVV("Adding %p to '%s' init list\n", loader, clazz->descriptor);
888         dvmHashTableLock(gDvm.loadedClasses);
889 
890         /*
891          * Make sure nobody snuck in.  The penalty for adding twice is
892          * pretty minor, and probably outweighs the O(n^2) hit for
893          * checking before every add, so we may not want to do this.
894          */
895         //if (dvmLoaderInInitiatingList(clazz, loader)) {
896         //    LOGW("WOW: simultaneous add of initiating class loader\n");
897         //    goto bail_unlock;
898         //}
899 
900         /*
901          * The list never shrinks, so we just keep a count of the
902          * number of elements in it, and reallocate the buffer when
903          * we run off the end.
904          *
905          * The pointer is initially NULL, so we *do* want to call realloc
906          * when count==0.
907          */
908         InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
909         if ((loaderList->initiatingLoaderCount & (kInitLoaderInc-1)) == 0) {
910             Object** newList;
911 
912             newList = (Object**) realloc(loaderList->initiatingLoaders,
913                         (loaderList->initiatingLoaderCount + kInitLoaderInc)
914                          * sizeof(Object*));
915             if (newList == NULL) {
916                 /* this is mainly a cache, so it's not the EotW */
917                 assert(false);
918                 goto bail_unlock;
919             }
920             loaderList->initiatingLoaders = newList;
921 
922             //LOGI("Expanded init list to %d (%s)\n",
923             //    loaderList->initiatingLoaderCount+kInitLoaderInc,
924             //    clazz->descriptor);
925         }
926         loaderList->initiatingLoaders[loaderList->initiatingLoaderCount++] =
927             loader;
928 
929 bail_unlock:
930         dvmHashTableUnlock(gDvm.loadedClasses);
931     }
932 }
933 
934 /*
935  * (This is a dvmHashTableLookup callback.)
936  *
937  * Entries in the class hash table are stored as { descriptor, d-loader }
938  * tuples.  If the hashed class descriptor matches the requested descriptor,
939  * and the hashed defining class loader matches the requested class
940  * loader, we're good.  If only the descriptor matches, we check to see if the
941  * loader is in the hashed class' initiating loader list.  If so, we
942  * can return "true" immediately and skip some of the loadClass melodrama.
943  *
944  * The caller must lock the hash table before calling here.
945  *
946  * Returns 0 if a matching entry is found, nonzero otherwise.
947  */
hashcmpClassByCrit(const void * vclazz,const void * vcrit)948 static int hashcmpClassByCrit(const void* vclazz, const void* vcrit)
949 {
950     const ClassObject* clazz = (const ClassObject*) vclazz;
951     const ClassMatchCriteria* pCrit = (const ClassMatchCriteria*) vcrit;
952     bool match;
953 
954     match = (strcmp(clazz->descriptor, pCrit->descriptor) == 0 &&
955              (clazz->classLoader == pCrit->loader ||
956               (pCrit->loader != NULL &&
957                dvmLoaderInInitiatingList(clazz, pCrit->loader)) ));
958     //if (match)
959     //    LOGI("+++ %s %p matches existing %s %p\n",
960     //        pCrit->descriptor, pCrit->loader,
961     //        clazz->descriptor, clazz->classLoader);
962     return !match;
963 }
964 
965 /*
966  * Like hashcmpClassByCrit, but passing in a fully-formed ClassObject
967  * instead of a ClassMatchCriteria.
968  */
hashcmpClassByClass(const void * vclazz,const void * vaddclazz)969 static int hashcmpClassByClass(const void* vclazz, const void* vaddclazz)
970 {
971     const ClassObject* clazz = (const ClassObject*) vclazz;
972     const ClassObject* addClazz = (const ClassObject*) vaddclazz;
973     bool match;
974 
975     match = (strcmp(clazz->descriptor, addClazz->descriptor) == 0 &&
976              (clazz->classLoader == addClazz->classLoader ||
977               (addClazz->classLoader != NULL &&
978                dvmLoaderInInitiatingList(clazz, addClazz->classLoader)) ));
979     return !match;
980 }
981 
982 /*
983  * Search through the hash table to find an entry with a matching descriptor
984  * and an initiating class loader that matches "loader".
985  *
986  * The table entries are hashed on descriptor only, because they're unique
987  * on *defining* class loader, not *initiating* class loader.  This isn't
988  * great, because it guarantees we will have to probe when multiple
989  * class loaders are used.
990  *
991  * Note this does NOT try to load a class; it just finds a class that
992  * has already been loaded.
993  *
994  * If "unprepOkay" is set, this will return classes that have been added
995  * to the hash table but are not yet fully loaded and linked.  Otherwise,
996  * such classes are ignored.  (The only place that should set "unprepOkay"
997  * is findClassNoInit(), which will wait for the prep to finish.)
998  *
999  * Returns NULL if not found.
1000  */
dvmLookupClass(const char * descriptor,Object * loader,bool unprepOkay)1001 ClassObject* dvmLookupClass(const char* descriptor, Object* loader,
1002     bool unprepOkay)
1003 {
1004     ClassMatchCriteria crit;
1005     void* found;
1006     u4 hash;
1007 
1008     crit.descriptor = descriptor;
1009     crit.loader = loader;
1010     hash = dvmComputeUtf8Hash(descriptor);
1011 
1012     LOGVV("threadid=%d: dvmLookupClass searching for '%s' %p\n",
1013         dvmThreadSelf()->threadId, descriptor, loader);
1014 
1015     dvmHashTableLock(gDvm.loadedClasses);
1016     found = dvmHashTableLookup(gDvm.loadedClasses, hash, &crit,
1017                 hashcmpClassByCrit, false);
1018     dvmHashTableUnlock(gDvm.loadedClasses);
1019 
1020     /*
1021      * The class has been added to the hash table but isn't ready for use.
1022      * We're going to act like we didn't see it, so that the caller will
1023      * go through the full "find class" path, which includes locking the
1024      * object and waiting until it's ready.  We could do that lock/wait
1025      * here, but this is an extremely rare case, and it's simpler to have
1026      * the wait-for-class code centralized.
1027      */
1028     if (found != NULL && !unprepOkay && !dvmIsClassLinked(found)) {
1029         LOGV("Ignoring not-yet-ready %s, using slow path\n",
1030             ((ClassObject*)found)->descriptor);
1031         found = NULL;
1032     }
1033 
1034     return (ClassObject*) found;
1035 }
1036 
1037 /*
1038  * Add a new class to the hash table.
1039  *
1040  * The class is considered "new" if it doesn't match on both the class
1041  * descriptor and the defining class loader.
1042  *
1043  * TODO: we should probably have separate hash tables for each
1044  * ClassLoader. This could speed up dvmLookupClass and
1045  * other common operations. It does imply a VM-visible data structure
1046  * for each ClassLoader object with loaded classes, which we don't
1047  * have yet.
1048  */
dvmAddClassToHash(ClassObject * clazz)1049 bool dvmAddClassToHash(ClassObject* clazz)
1050 {
1051     void* found;
1052     u4 hash;
1053 
1054     hash = dvmComputeUtf8Hash(clazz->descriptor);
1055 
1056     dvmHashTableLock(gDvm.loadedClasses);
1057     found = dvmHashTableLookup(gDvm.loadedClasses, hash, clazz,
1058                 hashcmpClassByClass, true);
1059     dvmHashTableUnlock(gDvm.loadedClasses);
1060 
1061     LOGV("+++ dvmAddClassToHash '%s' %p (isnew=%d) --> %p\n",
1062         clazz->descriptor, clazz->classLoader,
1063         (found == (void*) clazz), clazz);
1064 
1065     //dvmCheckClassTablePerf();
1066 
1067     /* can happen if two threads load the same class simultaneously */
1068     return (found == (void*) clazz);
1069 }
1070 
1071 #if 0
1072 /*
1073  * Compute hash value for a class.
1074  */
1075 u4 hashcalcClass(const void* item)
1076 {
1077     return dvmComputeUtf8Hash(((const ClassObject*) item)->descriptor);
1078 }
1079 
1080 /*
1081  * Check the performance of the "loadedClasses" hash table.
1082  */
1083 void dvmCheckClassTablePerf(void)
1084 {
1085     dvmHashTableLock(gDvm.loadedClasses);
1086     dvmHashTableProbeCount(gDvm.loadedClasses, hashcalcClass,
1087         hashcmpClassByClass);
1088     dvmHashTableUnlock(gDvm.loadedClasses);
1089 }
1090 #endif
1091 
1092 /*
1093  * Remove a class object from the hash table.
1094  */
removeClassFromHash(ClassObject * clazz)1095 static void removeClassFromHash(ClassObject* clazz)
1096 {
1097     LOGV("+++ removeClassFromHash '%s'\n", clazz->descriptor);
1098 
1099     u4 hash = dvmComputeUtf8Hash(clazz->descriptor);
1100 
1101     dvmHashTableLock(gDvm.loadedClasses);
1102     if (!dvmHashTableRemove(gDvm.loadedClasses, hash, clazz))
1103         LOGW("Hash table remove failed on class '%s'\n", clazz->descriptor);
1104     dvmHashTableUnlock(gDvm.loadedClasses);
1105 }
1106 
1107 
1108 /*
1109  * ===========================================================================
1110  *      Class creation
1111  * ===========================================================================
1112  */
1113 
1114 /*
1115  * Set clazz->serialNumber to the next available value.
1116  *
1117  * This usually happens *very* early in class creation, so don't expect
1118  * anything else in the class to be ready.
1119  */
dvmSetClassSerialNumber(ClassObject * clazz)1120 void dvmSetClassSerialNumber(ClassObject* clazz)
1121 {
1122     u4 oldValue, newValue;
1123 
1124     assert(clazz->serialNumber == 0);
1125 
1126     do {
1127         oldValue = gDvm.classSerialNumber;
1128         newValue = oldValue + 1;
1129     } while (!ATOMIC_CMP_SWAP(&gDvm.classSerialNumber, oldValue, newValue));
1130 
1131     clazz->serialNumber = (u4) oldValue;
1132 }
1133 
1134 
1135 /*
1136  * Find the named class (by descriptor), using the specified
1137  * initiating ClassLoader.
1138  *
1139  * The class will be loaded and initialized if it has not already been.
1140  * If necessary, the superclass will be loaded.
1141  *
1142  * If the class can't be found, returns NULL with an appropriate exception
1143  * raised.
1144  */
dvmFindClass(const char * descriptor,Object * loader)1145 ClassObject* dvmFindClass(const char* descriptor, Object* loader)
1146 {
1147     ClassObject* clazz;
1148 
1149     clazz = dvmFindClassNoInit(descriptor, loader);
1150     if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1151         /* initialize class */
1152         if (!dvmInitClass(clazz)) {
1153             /* init failed; leave it in the list, marked as bad */
1154             assert(dvmCheckException(dvmThreadSelf()));
1155             assert(clazz->status == CLASS_ERROR);
1156             return NULL;
1157         }
1158     }
1159 
1160     return clazz;
1161 }
1162 
1163 /*
1164  * Find the named class (by descriptor), using the specified
1165  * initiating ClassLoader.
1166  *
1167  * The class will be loaded if it has not already been, as will its
1168  * superclass.  It will not be initialized.
1169  *
1170  * If the class can't be found, returns NULL with an appropriate exception
1171  * raised.
1172  */
dvmFindClassNoInit(const char * descriptor,Object * loader)1173 ClassObject* dvmFindClassNoInit(const char* descriptor,
1174         Object* loader)
1175 {
1176     assert(descriptor != NULL);
1177     //assert(loader != NULL);
1178 
1179     LOGVV("FindClassNoInit '%s' %p\n", descriptor, loader);
1180 
1181     if (*descriptor == '[') {
1182         /*
1183          * Array class.  Find in table, generate if not found.
1184          */
1185         return dvmFindArrayClass(descriptor, loader);
1186     } else {
1187         /*
1188          * Regular class.  Find in table, load if not found.
1189          */
1190         if (loader != NULL) {
1191             return findClassFromLoaderNoInit(descriptor, loader);
1192         } else {
1193             return dvmFindSystemClassNoInit(descriptor);
1194         }
1195     }
1196 }
1197 
1198 /*
1199  * Load the named class (by descriptor) from the specified class
1200  * loader.  This calls out to let the ClassLoader object do its thing.
1201  *
1202  * Returns with NULL and an exception raised on error.
1203  */
findClassFromLoaderNoInit(const char * descriptor,Object * loader)1204 static ClassObject* findClassFromLoaderNoInit(const char* descriptor,
1205     Object* loader)
1206 {
1207     //LOGI("##### findClassFromLoaderNoInit (%s,%p)\n",
1208     //        descriptor, loader);
1209 
1210     Thread* self = dvmThreadSelf();
1211     ClassObject* clazz;
1212 
1213     assert(loader != NULL);
1214 
1215     /*
1216      * Do we already have it?
1217      *
1218      * The class loader code does the "is it already loaded" check as
1219      * well.  However, this call is much faster than calling through
1220      * interpreted code.  Doing this does mean that in the common case
1221      * (365 out of 420 calls booting the sim) we're doing the
1222      * lookup-by-descriptor twice.  It appears this is still a win, so
1223      * I'm keeping it in.
1224      */
1225     clazz = dvmLookupClass(descriptor, loader, false);
1226     if (clazz != NULL) {
1227         LOGVV("Already loaded: %s %p\n", descriptor, loader);
1228         return clazz;
1229     } else {
1230         LOGVV("Not already loaded: %s %p\n", descriptor, loader);
1231     }
1232 
1233     char* dotName = NULL;
1234     StringObject* nameObj = NULL;
1235     Object* excep;
1236     Method* loadClass;
1237 
1238     /* convert "Landroid/debug/Stuff;" to "android.debug.Stuff" */
1239     dotName = dvmDescriptorToDot(descriptor);
1240     if (dotName == NULL) {
1241         dvmThrowException("Ljava/lang/OutOfMemoryError;", NULL);
1242         goto bail;
1243     }
1244     nameObj = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT);
1245     if (nameObj == NULL) {
1246         assert(dvmCheckException(self));
1247         goto bail;
1248     }
1249 
1250     // TODO: cache the vtable offset
1251     loadClass = dvmFindVirtualMethodHierByDescriptor(loader->clazz, "loadClass",
1252                  "(Ljava/lang/String;)Ljava/lang/Class;");
1253     if (loadClass == NULL) {
1254         LOGW("Couldn't find loadClass in ClassLoader\n");
1255         goto bail;
1256     }
1257 
1258 #ifdef WITH_PROFILER
1259     dvmMethodTraceClassPrepBegin();
1260 #endif
1261 
1262     /*
1263      * Invoke loadClass().  This will probably result in a couple of
1264      * exceptions being thrown, because the ClassLoader.loadClass()
1265      * implementation eventually calls VMClassLoader.loadClass to see if
1266      * the bootstrap class loader can find it before doing its own load.
1267      */
1268     LOGVV("--- Invoking loadClass(%s, %p)\n", dotName, loader);
1269     JValue result;
1270     dvmCallMethod(self, loadClass, loader, &result, nameObj);
1271     clazz = (ClassObject*) result.l;
1272 
1273 #ifdef WITH_PROFILER
1274     dvmMethodTraceClassPrepEnd();
1275 #endif
1276 
1277     excep = dvmGetException(self);
1278     if (excep != NULL) {
1279 #if DVM_SHOW_EXCEPTION >= 2
1280         LOGD("NOTE: loadClass '%s' %p threw exception %s\n",
1281             dotName, loader, excep->clazz->descriptor);
1282 #endif
1283         dvmAddTrackedAlloc(excep, self);
1284         dvmClearException(self);
1285         dvmThrowChainedExceptionWithClassMessage(
1286             "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
1287         dvmReleaseTrackedAlloc(excep, self);
1288         clazz = NULL;
1289         goto bail;
1290     } else {
1291         assert(clazz != NULL);
1292     }
1293 
1294     dvmAddInitiatingLoader(clazz, loader);
1295 
1296     LOGVV("--- Successfully loaded %s %p (thisldr=%p clazz=%p)\n",
1297         descriptor, clazz->classLoader, loader, clazz);
1298 
1299 bail:
1300     dvmReleaseTrackedAlloc((Object*)nameObj, NULL);
1301     free(dotName);
1302     return clazz;
1303 }
1304 
1305 /*
1306  * Load the named class (by descriptor) from the specified DEX file.
1307  * Used by class loaders to instantiate a class object from a
1308  * VM-managed DEX.
1309  */
dvmDefineClass(DvmDex * pDvmDex,const char * descriptor,Object * classLoader)1310 ClassObject* dvmDefineClass(DvmDex* pDvmDex, const char* descriptor,
1311     Object* classLoader)
1312 {
1313     assert(pDvmDex != NULL);
1314 
1315     return findClassNoInit(descriptor, classLoader, pDvmDex);
1316 }
1317 
1318 
1319 /*
1320  * Find the named class (by descriptor), scanning through the
1321  * bootclasspath if it hasn't already been loaded.
1322  *
1323  * "descriptor" looks like "Landroid/debug/Stuff;".
1324  *
1325  * Uses NULL as the defining class loader.
1326  */
dvmFindSystemClass(const char * descriptor)1327 ClassObject* dvmFindSystemClass(const char* descriptor)
1328 {
1329     ClassObject* clazz;
1330 
1331     clazz = dvmFindSystemClassNoInit(descriptor);
1332     if (clazz != NULL && clazz->status < CLASS_INITIALIZED) {
1333         /* initialize class */
1334         if (!dvmInitClass(clazz)) {
1335             /* init failed; leave it in the list, marked as bad */
1336             assert(dvmCheckException(dvmThreadSelf()));
1337             assert(clazz->status == CLASS_ERROR);
1338             return NULL;
1339         }
1340     }
1341 
1342     return clazz;
1343 }
1344 
1345 /*
1346  * Find the named class (by descriptor), searching for it in the
1347  * bootclasspath.
1348  *
1349  * On failure, this returns NULL with an exception raised.
1350  */
dvmFindSystemClassNoInit(const char * descriptor)1351 ClassObject* dvmFindSystemClassNoInit(const char* descriptor)
1352 {
1353     return findClassNoInit(descriptor, NULL, NULL);
1354 }
1355 
1356 /*
1357  * Find the named class (by descriptor). If it's not already loaded,
1358  * we load it and link it, but don't execute <clinit>. (The VM has
1359  * specific limitations on which events can cause initialization.)
1360  *
1361  * If "pDexFile" is NULL, we will search the bootclasspath for an entry.
1362  *
1363  * On failure, this returns NULL with an exception raised.
1364  *
1365  * TODO: we need to return an indication of whether we loaded the class or
1366  * used an existing definition.  If somebody deliberately tries to load a
1367  * class twice in the same class loader, they should get a LinkageError,
1368  * but inadvertent simultaneous class references should "just work".
1369  */
findClassNoInit(const char * descriptor,Object * loader,DvmDex * pDvmDex)1370 static ClassObject* findClassNoInit(const char* descriptor, Object* loader,
1371     DvmDex* pDvmDex)
1372 {
1373     Thread* self = dvmThreadSelf();
1374     ClassObject* clazz;
1375 #ifdef WITH_PROFILER
1376     bool profilerNotified = false;
1377 #endif
1378 
1379     if (loader != NULL) {
1380         LOGVV("#### findClassNoInit(%s,%p,%p)\n", descriptor, loader,
1381             pDvmDex->pDexFile);
1382     }
1383 
1384     /*
1385      * We don't expect an exception to be raised at this point.  The
1386      * exception handling code is good about managing this.  This *can*
1387      * happen if a JNI lookup fails and the JNI code doesn't do any
1388      * error checking before doing another class lookup, so we may just
1389      * want to clear this and restore it on exit.  If we don't, some kinds
1390      * of failures can't be detected without rearranging other stuff.
1391      *
1392      * Most often when we hit this situation it means that something is
1393      * broken in the VM or in JNI code, so I'm keeping it in place (and
1394      * making it an informative abort rather than an assert).
1395      */
1396     if (dvmCheckException(self)) {
1397         LOGE("Class lookup %s attemped while exception %s pending\n",
1398             descriptor, dvmGetException(self)->clazz->descriptor);
1399         dvmDumpAllThreads(false);
1400         dvmAbort();
1401     }
1402 
1403     clazz = dvmLookupClass(descriptor, loader, true);
1404     if (clazz == NULL) {
1405         const DexClassDef* pClassDef;
1406 
1407 #ifdef WITH_PROFILER
1408         dvmMethodTraceClassPrepBegin();
1409         profilerNotified = true;
1410 #endif
1411 
1412 #if LOG_CLASS_LOADING
1413         u8 startTime = dvmGetThreadCpuTimeNsec();
1414 #endif
1415 
1416         if (pDvmDex == NULL) {
1417             assert(loader == NULL);     /* shouldn't be here otherwise */
1418             pDvmDex = searchBootPathForClass(descriptor, &pClassDef);
1419         } else {
1420             pClassDef = dexFindClass(pDvmDex->pDexFile, descriptor);
1421         }
1422 
1423         if (pDvmDex == NULL || pClassDef == NULL) {
1424             dvmThrowExceptionWithClassMessage(
1425                 "Ljava/lang/NoClassDefFoundError;", descriptor);
1426             goto bail;
1427         }
1428 
1429         /* found a match, try to load it */
1430         clazz = loadClassFromDex(pDvmDex, pClassDef, loader);
1431         if (dvmCheckException(self)) {
1432             /* class was found but had issues */
1433             dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1434             goto bail;
1435         }
1436 
1437         /*
1438          * Lock the class while we link it so other threads must wait for us
1439          * to finish.  Set the "initThreadId" so we can identify recursive
1440          * invocation.
1441          */
1442         dvmLockObject(self, (Object*) clazz);
1443         clazz->initThreadId = self->threadId;
1444 
1445         /*
1446          * Add to hash table so lookups succeed.
1447          *
1448          * [Are circular references possible when linking a class?]
1449          */
1450         assert(clazz->classLoader == loader);
1451         if (!dvmAddClassToHash(clazz)) {
1452             /*
1453              * Another thread must have loaded the class after we
1454              * started but before we finished.  Discard what we've
1455              * done and leave some hints for the GC.
1456              *
1457              * (Yes, this happens.)
1458              */
1459             //LOGW("WOW: somebody loaded %s simultaneously\n", descriptor);
1460             clazz->initThreadId = 0;
1461             dvmUnlockObject(self, (Object*) clazz);
1462 
1463             /* Let the GC free the class.
1464              */
1465             assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
1466             dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1467 
1468             /* Grab the winning class.
1469              */
1470             clazz = dvmLookupClass(descriptor, loader, true);
1471             assert(clazz != NULL);
1472             goto got_class;
1473         }
1474         dvmReleaseTrackedAlloc((Object*) clazz, NULL);
1475 
1476 #if LOG_CLASS_LOADING
1477         logClassLoadWithTime('>', clazz, startTime);
1478 #endif
1479         /*
1480          * Prepare and resolve.
1481          */
1482         if (!dvmLinkClass(clazz, false)) {
1483             assert(dvmCheckException(self));
1484 
1485             /* Make note of the error and clean up the class.
1486              */
1487             removeClassFromHash(clazz);
1488             clazz->status = CLASS_ERROR;
1489             dvmFreeClassInnards(clazz);
1490 
1491             /* Let any waiters know.
1492              */
1493             clazz->initThreadId = 0;
1494             dvmObjectNotifyAll(self, (Object*) clazz);
1495             dvmUnlockObject(self, (Object*) clazz);
1496 
1497 #if LOG_CLASS_LOADING
1498             LOG(LOG_INFO, "DVMLINK FAILED FOR CLASS ", "%s in %s\n",
1499                 clazz->descriptor, get_process_name());
1500 
1501             /*
1502              * TODO: It would probably be better to use a new type code here (instead of '<') to
1503              * indicate the failure.  This change would require a matching change in the parser
1504              * and analysis code in frameworks/base/tools/preload.
1505              */
1506             logClassLoad('<', clazz);
1507 #endif
1508             clazz = NULL;
1509             if (gDvm.optimizing) {
1510                 /* happens with "external" libs */
1511                 LOGV("Link of class '%s' failed\n", descriptor);
1512             } else {
1513                 LOGW("Link of class '%s' failed\n", descriptor);
1514             }
1515             goto bail;
1516         }
1517         dvmObjectNotifyAll(self, (Object*) clazz);
1518         dvmUnlockObject(self, (Object*) clazz);
1519 
1520         /*
1521          * Add class stats to global counters.
1522          *
1523          * TODO: these should probably be atomic ops.
1524          */
1525         gDvm.numLoadedClasses++;
1526         gDvm.numDeclaredMethods +=
1527             clazz->virtualMethodCount + clazz->directMethodCount;
1528         gDvm.numDeclaredInstFields += clazz->ifieldCount;
1529         gDvm.numDeclaredStaticFields += clazz->sfieldCount;
1530 
1531         /*
1532          * Cache pointers to basic classes.  We want to use these in
1533          * various places, and it's easiest to initialize them on first
1534          * use rather than trying to force them to initialize (startup
1535          * ordering makes it weird).
1536          */
1537         if (gDvm.classJavaLangObject == NULL &&
1538             strcmp(descriptor, "Ljava/lang/Object;") == 0)
1539         {
1540             /* It should be impossible to get here with anything
1541              * but the bootclasspath loader.
1542              */
1543             assert(loader == NULL);
1544             gDvm.classJavaLangObject = clazz;
1545         }
1546 
1547 #if LOG_CLASS_LOADING
1548         logClassLoad('<', clazz);
1549 #endif
1550 
1551     } else {
1552 got_class:
1553         if (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1554             /*
1555              * We can race with other threads for class linking.  We should
1556              * never get here recursively; doing so indicates that two
1557              * classes have circular dependencies.
1558              *
1559              * One exception: we force discovery of java.lang.Class in
1560              * dvmLinkClass(), and Class has Object as its superclass.  So
1561              * if the first thing we ever load is Object, we will init
1562              * Object->Class->Object.  The easiest way to avoid this is to
1563              * ensure that Object is never the first thing we look up, so
1564              * we get Foo->Class->Object instead.
1565              */
1566             dvmLockObject(self, (Object*) clazz);
1567             if (!dvmIsClassLinked(clazz) &&
1568                 clazz->initThreadId == self->threadId)
1569             {
1570                 LOGW("Recursive link on class %s\n", clazz->descriptor);
1571                 dvmUnlockObject(self, (Object*) clazz);
1572                 dvmThrowExceptionWithClassMessage(
1573                     "Ljava/lang/ClassCircularityError;", clazz->descriptor);
1574                 clazz = NULL;
1575                 goto bail;
1576             }
1577             //LOGI("WAITING  for '%s' (owner=%d)\n",
1578             //    clazz->descriptor, clazz->initThreadId);
1579             while (!dvmIsClassLinked(clazz) && clazz->status != CLASS_ERROR) {
1580                 dvmObjectWait(self, (Object*) clazz, 0, 0, false);
1581             }
1582             dvmUnlockObject(self, (Object*) clazz);
1583         }
1584         if (clazz->status == CLASS_ERROR) {
1585             /*
1586              * Somebody else tried to load this and failed.  We need to raise
1587              * an exception and report failure.
1588              */
1589             throwEarlierClassFailure(clazz);
1590             clazz = NULL;
1591             goto bail;
1592         }
1593     }
1594 
1595     /* check some invariants */
1596     assert(dvmIsClassLinked(clazz));
1597     assert(gDvm.classJavaLangClass != NULL);
1598     assert(clazz->obj.clazz == gDvm.classJavaLangClass);
1599     if (clazz != gDvm.classJavaLangObject) {
1600         if (clazz->super == NULL) {
1601             LOGE("Non-Object has no superclass (gDvm.classJavaLangObject=%p)\n",
1602                 gDvm.classJavaLangObject);
1603             dvmAbort();
1604         }
1605     }
1606     if (!dvmIsInterfaceClass(clazz)) {
1607         //LOGI("class=%s vtableCount=%d, virtualMeth=%d\n",
1608         //    clazz->descriptor, clazz->vtableCount,
1609         //    clazz->virtualMethodCount);
1610         assert(clazz->vtableCount >= clazz->virtualMethodCount);
1611     }
1612 
1613     /*
1614      * Normally class objects are initialized before we instantiate them,
1615      * but we can't do that with java.lang.Class (chicken, meet egg).  We
1616      * do it explicitly here.
1617      *
1618      * The verifier could call here to find Class while verifying Class,
1619      * so we need to check for CLASS_VERIFYING as well as !initialized.
1620      */
1621     if (clazz == gDvm.classJavaLangClass && !dvmIsClassInitialized(clazz) &&
1622         !(clazz->status == CLASS_VERIFYING))
1623     {
1624         LOGV("+++ explicitly initializing %s\n", clazz->descriptor);
1625         dvmInitClass(clazz);
1626     }
1627 
1628 bail:
1629 #ifdef WITH_PROFILER
1630     if (profilerNotified)
1631         dvmMethodTraceClassPrepEnd();
1632 #endif
1633     assert(clazz != NULL || dvmCheckException(self));
1634     return clazz;
1635 }
1636 
1637 /*
1638  * Helper for loadClassFromDex, which takes a DexClassDataHeader and
1639  * encoded data pointer in addition to the other arguments.
1640  */
loadClassFromDex0(DvmDex * pDvmDex,const DexClassDef * pClassDef,const DexClassDataHeader * pHeader,const u1 * pEncodedData,Object * classLoader)1641 static ClassObject* loadClassFromDex0(DvmDex* pDvmDex,
1642     const DexClassDef* pClassDef, const DexClassDataHeader* pHeader,
1643     const u1* pEncodedData, Object* classLoader)
1644 {
1645     ClassObject* newClass = NULL;
1646     const DexFile* pDexFile;
1647     const char* descriptor;
1648     int i;
1649 
1650     pDexFile = pDvmDex->pDexFile;
1651     descriptor = dexGetClassDescriptor(pDexFile, pClassDef);
1652 
1653     /*
1654      * Make sure the aren't any "bonus" flags set, since we use them for
1655      * runtime state.
1656      */
1657     if ((pClassDef->accessFlags & ~EXPECTED_FILE_FLAGS) != 0) {
1658         LOGW("Invalid file flags in class %s: %04x\n",
1659             descriptor, pClassDef->accessFlags);
1660         return NULL;
1661     }
1662 
1663     /*
1664      * Allocate storage for the class object on the GC heap, so that other
1665      * objects can have references to it.  We bypass the usual mechanism
1666      * (allocObject), because we don't have all the bits and pieces yet.
1667      *
1668      * Note that we assume that java.lang.Class does not override
1669      * finalize().
1670      */
1671     newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT);
1672     if (newClass == NULL)
1673         return NULL;
1674 
1675     /* Until the class is loaded and linked, use a placeholder
1676      * obj->clazz value as a hint to the GC.  We don't want
1677      * the GC trying to scan the object while it's full of Idx
1678      * values.  Also, the real java.lang.Class may not exist
1679      * yet.
1680      */
1681     DVM_OBJECT_INIT(&newClass->obj, gDvm.unlinkedJavaLangClass);
1682 
1683     dvmSetClassSerialNumber(newClass);
1684     newClass->descriptor = descriptor;
1685     assert(newClass->descriptorAlloc == NULL);
1686     newClass->accessFlags = pClassDef->accessFlags;
1687     newClass->classLoader = classLoader;
1688     newClass->pDvmDex = pDvmDex;
1689     newClass->primitiveType = PRIM_NOT;
1690 
1691     /*
1692      * Stuff the superclass index into the object pointer field.  The linker
1693      * pulls it out and replaces it with a resolved ClassObject pointer.
1694      * I'm doing it this way (rather than having a dedicated superclassIdx
1695      * field) to save a few bytes of overhead per class.
1696      *
1697      * newClass->super is not traversed or freed by dvmFreeClassInnards, so
1698      * this is safe.
1699      */
1700     assert(sizeof(u4) == sizeof(ClassObject*));
1701     newClass->super = (ClassObject*) pClassDef->superclassIdx;
1702 
1703     /*
1704      * Stuff class reference indices into the pointer fields.
1705      *
1706      * The elements of newClass->interfaces are not traversed or freed by
1707      * dvmFreeClassInnards, so this is GC-safe.
1708      */
1709     const DexTypeList* pInterfacesList;
1710     pInterfacesList = dexGetInterfacesList(pDexFile, pClassDef);
1711     if (pInterfacesList != NULL) {
1712         newClass->interfaceCount = pInterfacesList->size;
1713         newClass->interfaces = (ClassObject**) dvmLinearAlloc(classLoader,
1714                 newClass->interfaceCount * sizeof(ClassObject*));
1715 
1716         for (i = 0; i < newClass->interfaceCount; i++) {
1717             const DexTypeItem* pType = dexGetTypeItem(pInterfacesList, i);
1718             newClass->interfaces[i] = (ClassObject*)(u4) pType->typeIdx;
1719         }
1720         dvmLinearReadOnly(classLoader, newClass->interfaces);
1721     }
1722 
1723     /* load field definitions */
1724 
1725     /*
1726      * TODO: consider over-allocating the class object and appending the
1727      * static field info onto the end.  It's fixed-size and known at alloc
1728      * time.  This would save a couple of native heap allocations, but it
1729      * would also make heap compaction more difficult because we pass Field
1730      * pointers around internally.
1731      */
1732 
1733     if (pHeader->staticFieldsSize != 0) {
1734         /* static fields stay on system heap; field data isn't "write once" */
1735         int count = (int) pHeader->staticFieldsSize;
1736         u4 lastIndex = 0;
1737         DexField field;
1738 
1739         newClass->sfieldCount = count;
1740         newClass->sfields =
1741             (StaticField*) calloc(count, sizeof(StaticField));
1742         for (i = 0; i < count; i++) {
1743             dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1744             loadSFieldFromDex(newClass, &field, &newClass->sfields[i]);
1745         }
1746     }
1747 
1748     if (pHeader->instanceFieldsSize != 0) {
1749         int count = (int) pHeader->instanceFieldsSize;
1750         u4 lastIndex = 0;
1751         DexField field;
1752 
1753         newClass->ifieldCount = count;
1754         newClass->ifields = (InstField*) dvmLinearAlloc(classLoader,
1755                 count * sizeof(InstField));
1756         for (i = 0; i < count; i++) {
1757             dexReadClassDataField(&pEncodedData, &field, &lastIndex);
1758             loadIFieldFromDex(newClass, &field, &newClass->ifields[i]);
1759         }
1760         dvmLinearReadOnly(classLoader, newClass->ifields);
1761     }
1762 
1763     /* load method definitions */
1764 
1765     if (pHeader->directMethodsSize != 0) {
1766         int count = (int) pHeader->directMethodsSize;
1767         u4 lastIndex = 0;
1768         DexMethod method;
1769 
1770         newClass->directMethodCount = count;
1771         newClass->directMethods = (Method*) dvmLinearAlloc(classLoader,
1772                 count * sizeof(Method));
1773         for (i = 0; i < count; i++) {
1774             dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1775             loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
1776         }
1777         dvmLinearReadOnly(classLoader, newClass->directMethods);
1778     }
1779 
1780     if (pHeader->virtualMethodsSize != 0) {
1781         int count = (int) pHeader->virtualMethodsSize;
1782         u4 lastIndex = 0;
1783         DexMethod method;
1784 
1785         newClass->virtualMethodCount = count;
1786         newClass->virtualMethods = (Method*) dvmLinearAlloc(classLoader,
1787                 count * sizeof(Method));
1788         for (i = 0; i < count; i++) {
1789             dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
1790             loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
1791         }
1792         dvmLinearReadOnly(classLoader, newClass->virtualMethods);
1793     }
1794 
1795     newClass->sourceFile = dexGetSourceFile(pDexFile, pClassDef);
1796     newClass->status = CLASS_LOADED;
1797 
1798     /* caller must call dvmReleaseTrackedAlloc */
1799     return newClass;
1800 }
1801 
1802 /*
1803  * Try to load the indicated class from the specified DEX file.
1804  *
1805  * This is effectively loadClass()+defineClass() for a DexClassDef.  The
1806  * loading was largely done when we crunched through the DEX.
1807  *
1808  * Returns NULL on failure.  If we locate the class but encounter an error
1809  * while processing it, an appropriate exception is thrown.
1810  */
loadClassFromDex(DvmDex * pDvmDex,const DexClassDef * pClassDef,Object * classLoader)1811 static ClassObject* loadClassFromDex(DvmDex* pDvmDex,
1812     const DexClassDef* pClassDef, Object* classLoader)
1813 {
1814     ClassObject* result;
1815     DexClassDataHeader header;
1816     const u1* pEncodedData;
1817     const DexFile* pDexFile;
1818 
1819     assert((pDvmDex != NULL) && (pClassDef != NULL));
1820     pDexFile = pDvmDex->pDexFile;
1821 
1822     if (gDvm.verboseClass) {
1823         LOGV("CLASS: loading '%s'...\n",
1824             dexGetClassDescriptor(pDexFile, pClassDef));
1825     }
1826 
1827     pEncodedData = dexGetClassData(pDexFile, pClassDef);
1828 
1829     if (pEncodedData != NULL) {
1830         dexReadClassDataHeader(&pEncodedData, &header);
1831     } else {
1832         // Provide an all-zeroes header for the rest of the loading.
1833         memset(&header, 0, sizeof(header));
1834     }
1835 
1836     result = loadClassFromDex0(pDvmDex, pClassDef, &header, pEncodedData,
1837             classLoader);
1838 
1839     if (gDvm.verboseClass && (result != NULL)) {
1840         LOGI("[Loaded %s from DEX %p (cl=%p)]\n",
1841             result->descriptor, pDvmDex, classLoader);
1842     }
1843 
1844     return result;
1845 }
1846 
1847 /*
1848  * Free anything in a ClassObject that was allocated on the system heap.
1849  *
1850  * The ClassObject itself is allocated on the GC heap, so we leave it for
1851  * the garbage collector.
1852  *
1853  * NOTE: this may be called with a partially-constructed object.
1854  * NOTE: there is no particular ordering imposed, so don't go poking at
1855  * superclasses.
1856  */
dvmFreeClassInnards(ClassObject * clazz)1857 void dvmFreeClassInnards(ClassObject* clazz)
1858 {
1859     void *tp;
1860     int i;
1861 
1862     if (clazz == NULL)
1863         return;
1864 
1865     assert(clazz->obj.clazz == gDvm.classJavaLangClass ||
1866            clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
1867 
1868     /* Guarantee that dvmFreeClassInnards can be called on a given
1869      * class multiple times by clearing things out as we free them.
1870      * We don't make any attempt at real atomicity here; higher
1871      * levels need to make sure that no two threads can free the
1872      * same ClassObject at the same time.
1873      *
1874      * TODO: maybe just make it so the GC will never free the
1875      * innards of an already-freed class.
1876      *
1877      * TODO: this #define isn't MT-safe -- the compiler could rearrange it.
1878      */
1879 #define NULL_AND_FREE(p) \
1880     do { \
1881         if ((p) != NULL) { \
1882             tp = (p); \
1883             (p) = NULL; \
1884             free(tp); \
1885         } \
1886     } while (0)
1887 #define NULL_AND_LINEAR_FREE(p) \
1888     do { \
1889         if ((p) != NULL) { \
1890             tp = (p); \
1891             (p) = NULL; \
1892             dvmLinearFree(clazz->classLoader, tp); \
1893         } \
1894     } while (0)
1895 
1896     /* arrays just point at Object's vtable; don't free vtable in this case.
1897      * dvmIsArrayClass() checks clazz->descriptor, so we have to do this check
1898      * before freeing the name.
1899      */
1900     clazz->vtableCount = -1;
1901     if (dvmIsArrayClass(clazz)) {
1902         clazz->vtable = NULL;
1903     } else {
1904         NULL_AND_LINEAR_FREE(clazz->vtable);
1905     }
1906 
1907     clazz->descriptor = NULL;
1908     NULL_AND_FREE(clazz->descriptorAlloc);
1909 
1910     if (clazz->directMethods != NULL) {
1911         Method *directMethods = clazz->directMethods;
1912         int directMethodCount = clazz->directMethodCount;
1913         clazz->directMethods = NULL;
1914         clazz->directMethodCount = -1;
1915         for (i = 0; i < directMethodCount; i++) {
1916             freeMethodInnards(&directMethods[i]);
1917         }
1918         dvmLinearFree(clazz->classLoader, directMethods);
1919     }
1920     if (clazz->virtualMethods != NULL) {
1921         Method *virtualMethods = clazz->virtualMethods;
1922         int virtualMethodCount = clazz->virtualMethodCount;
1923         clazz->virtualMethodCount = -1;
1924         clazz->virtualMethods = NULL;
1925         for (i = 0; i < virtualMethodCount; i++) {
1926             freeMethodInnards(&virtualMethods[i]);
1927         }
1928         dvmLinearFree(clazz->classLoader, virtualMethods);
1929     }
1930 
1931     InitiatingLoaderList *loaderList = dvmGetInitiatingLoaderList(clazz);
1932     loaderList->initiatingLoaderCount = -1;
1933     NULL_AND_FREE(loaderList->initiatingLoaders);
1934 
1935     clazz->interfaceCount = -1;
1936     NULL_AND_LINEAR_FREE(clazz->interfaces);
1937 
1938     clazz->iftableCount = -1;
1939     NULL_AND_LINEAR_FREE(clazz->iftable);
1940 
1941     clazz->ifviPoolCount = -1;
1942     NULL_AND_LINEAR_FREE(clazz->ifviPool);
1943 
1944     clazz->sfieldCount = -1;
1945     NULL_AND_FREE(clazz->sfields);
1946 
1947     clazz->ifieldCount = -1;
1948     NULL_AND_LINEAR_FREE(clazz->ifields);
1949 
1950 #undef NULL_AND_FREE
1951 #undef NULL_AND_LINEAR_FREE
1952 }
1953 
1954 /*
1955  * Free anything in a Method that was allocated on the system heap.
1956  */
freeMethodInnards(Method * meth)1957 static void freeMethodInnards(Method* meth)
1958 {
1959 #if 0
1960     free(meth->exceptions);
1961     free(meth->lines);
1962     free(meth->locals);
1963 #else
1964     // TODO: call dvmFreeRegisterMap() if meth->registerMap was allocated
1965     //       on the system heap
1966     UNUSED_PARAMETER(meth);
1967 #endif
1968 }
1969 
1970 /*
1971  * Clone a Method, making new copies of anything that will be freed up
1972  * by freeMethodInnards().
1973  */
cloneMethod(Method * dst,const Method * src)1974 static void cloneMethod(Method* dst, const Method* src)
1975 {
1976     memcpy(dst, src, sizeof(Method));
1977 #if 0
1978     /* for current usage, these are never set, so no need to implement copy */
1979     assert(dst->exceptions == NULL);
1980     assert(dst->lines == NULL);
1981     assert(dst->locals == NULL);
1982 #endif
1983 }
1984 
1985 /*
1986  * Pull the interesting pieces out of a DexMethod.
1987  *
1988  * The DEX file isn't going anywhere, so we don't need to make copies of
1989  * the code area.
1990  */
loadMethodFromDex(ClassObject * clazz,const DexMethod * pDexMethod,Method * meth)1991 static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod,
1992     Method* meth)
1993 {
1994     DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1995     const DexMethodId* pMethodId;
1996     const DexCode* pDexCode;
1997 
1998     pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
1999 
2000     meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
2001     dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
2002     meth->shorty = dexProtoGetShorty(&meth->prototype);
2003     meth->accessFlags = pDexMethod->accessFlags;
2004     meth->clazz = clazz;
2005     meth->jniArgInfo = 0;
2006 
2007     if (dvmCompareNameDescriptorAndMethod("finalize", "()V", meth) == 0) {
2008         SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2009     }
2010 
2011     pDexCode = dexGetCode(pDexFile, pDexMethod);
2012     if (pDexCode != NULL) {
2013         /* integer constants, copy over for faster access */
2014         meth->registersSize = pDexCode->registersSize;
2015         meth->insSize = pDexCode->insSize;
2016         meth->outsSize = pDexCode->outsSize;
2017 
2018         /* pointer to code area */
2019         meth->insns = pDexCode->insns;
2020     } else {
2021         /*
2022          * We don't have a DexCode block, but we still want to know how
2023          * much space is needed for the arguments (so we don't have to
2024          * compute it later).  We also take this opportunity to compute
2025          * JNI argument info.
2026          *
2027          * We do this for abstract methods as well, because we want to
2028          * be able to substitute our exception-throwing "stub" in.
2029          */
2030         int argsSize = dvmComputeMethodArgsSize(meth);
2031         if (!dvmIsStaticMethod(meth))
2032             argsSize++;
2033         meth->registersSize = meth->insSize = argsSize;
2034         assert(meth->outsSize == 0);
2035         assert(meth->insns == NULL);
2036 
2037         if (dvmIsNativeMethod(meth)) {
2038             meth->nativeFunc = dvmResolveNativeMethod;
2039             meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
2040         }
2041     }
2042 }
2043 
2044 /*
2045  * jniArgInfo (32-bit int) layout:
2046  *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
2047  *
2048  *   S - if set, do things the hard way (scan the signature)
2049  *   R - return-type enumeration
2050  *   H - target-specific hints
2051  *
2052  * This info is used at invocation time by dvmPlatformInvoke.  In most
2053  * cases, the target-specific hints allow dvmPlatformInvoke to avoid
2054  * having to fully parse the signature.
2055  *
2056  * The return-type bits are always set, even if target-specific hint bits
2057  * are unavailable.
2058  */
computeJniArgInfo(const DexProto * proto)2059 static int computeJniArgInfo(const DexProto* proto)
2060 {
2061     const char* sig = dexProtoGetShorty(proto);
2062     int returnType, padFlags, jniArgInfo;
2063     char sigByte;
2064     int stackOffset, padMask;
2065     u4 hints;
2066 
2067     /* The first shorty character is the return type. */
2068     switch (*(sig++)) {
2069     case 'V':
2070         returnType = DALVIK_JNI_RETURN_VOID;
2071         break;
2072     case 'F':
2073         returnType = DALVIK_JNI_RETURN_FLOAT;
2074         break;
2075     case 'D':
2076         returnType = DALVIK_JNI_RETURN_DOUBLE;
2077         break;
2078     case 'J':
2079         returnType = DALVIK_JNI_RETURN_S8;
2080         break;
2081     default:
2082         returnType = DALVIK_JNI_RETURN_S4;
2083         break;
2084     }
2085 
2086     jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;
2087 
2088     hints = dvmPlatformInvokeHints(proto);
2089 
2090     if (hints & DALVIK_JNI_NO_ARG_INFO) {
2091         jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;
2092     } else {
2093         assert((hints & DALVIK_JNI_RETURN_MASK) == 0);
2094         jniArgInfo |= hints;
2095     }
2096 
2097     return jniArgInfo;
2098 }
2099 
2100 /*
2101  * Load information about a static field.
2102  *
2103  * This also "prepares" static fields by initializing them
2104  * to their "standard default values".
2105  */
loadSFieldFromDex(ClassObject * clazz,const DexField * pDexSField,StaticField * sfield)2106 static void loadSFieldFromDex(ClassObject* clazz,
2107     const DexField* pDexSField, StaticField* sfield)
2108 {
2109     DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2110     const DexFieldId* pFieldId;
2111 
2112     pFieldId = dexGetFieldId(pDexFile, pDexSField->fieldIdx);
2113 
2114     sfield->field.clazz = clazz;
2115     sfield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2116     sfield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2117     sfield->field.accessFlags = pDexSField->accessFlags;
2118 
2119     /* Static object field values are set to "standard default values"
2120      * (null or 0) until the class is initialized.  We delay loading
2121      * constant values from the class until that time.
2122      */
2123     //sfield->value.j = 0;
2124     assert(sfield->value.j == 0LL);     // cleared earlier with calloc
2125 
2126 #ifdef PROFILE_FIELD_ACCESS
2127     sfield->field.gets = sfield->field.puts = 0;
2128 #endif
2129 }
2130 
2131 /*
2132  * Load information about an instance field.
2133  */
loadIFieldFromDex(ClassObject * clazz,const DexField * pDexIField,InstField * ifield)2134 static void loadIFieldFromDex(ClassObject* clazz,
2135     const DexField* pDexIField, InstField* ifield)
2136 {
2137     DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2138     const DexFieldId* pFieldId;
2139 
2140     pFieldId = dexGetFieldId(pDexFile, pDexIField->fieldIdx);
2141 
2142     ifield->field.clazz = clazz;
2143     ifield->field.name = dexStringById(pDexFile, pFieldId->nameIdx);
2144     ifield->field.signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
2145     ifield->field.accessFlags = pDexIField->accessFlags;
2146 #ifndef NDEBUG
2147     assert(ifield->byteOffset == 0);    // cleared earlier with calloc
2148     ifield->byteOffset = -1;    // make it obvious if we fail to set later
2149 #endif
2150 
2151 #ifdef PROFILE_FIELD_ACCESS
2152     ifield->field.gets = ifield->field.puts = 0;
2153 #endif
2154 }
2155 
2156 /*
2157  * Cache java.lang.ref.Reference fields and methods.
2158  */
precacheReferenceOffsets(ClassObject * clazz)2159 static bool precacheReferenceOffsets(ClassObject *clazz)
2160 {
2161     Method *meth;
2162     int i;
2163 
2164     /* We trick the GC object scanner by not counting
2165      * java.lang.ref.Reference.referent as an object
2166      * field.  It will get explicitly scanned as part
2167      * of the reference-walking process.
2168      *
2169      * Find the object field named "referent" and put it
2170      * just after the list of object reference fields.
2171      */
2172     dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
2173     for (i = 0; i < clazz->ifieldRefCount; i++) {
2174         InstField *pField = &clazz->ifields[i];
2175         if (strcmp(pField->field.name, "referent") == 0) {
2176             int targetIndex;
2177 
2178             /* Swap this field with the last object field.
2179              */
2180             targetIndex = clazz->ifieldRefCount - 1;
2181             if (i != targetIndex) {
2182                 InstField *swapField = &clazz->ifields[targetIndex];
2183                 InstField tmpField;
2184                 int tmpByteOffset;
2185 
2186                 /* It's not currently strictly necessary
2187                  * for the fields to be in byteOffset order,
2188                  * but it's more predictable that way.
2189                  */
2190                 tmpByteOffset = swapField->byteOffset;
2191                 swapField->byteOffset = pField->byteOffset;
2192                 pField->byteOffset = tmpByteOffset;
2193 
2194                 tmpField = *swapField;
2195                 *swapField = *pField;
2196                 *pField = tmpField;
2197             }
2198 
2199             /* One fewer object field (wink wink).
2200              */
2201             clazz->ifieldRefCount--;
2202             i--;        /* don't trip "didn't find it" test if field was last */
2203             break;
2204         }
2205     }
2206     dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
2207     if (i == clazz->ifieldRefCount) {
2208         LOGE("Unable to reorder 'referent' in %s\n", clazz->descriptor);
2209         return false;
2210     }
2211 
2212     /* Cache pretty much everything about Reference so that
2213      * we don't need to call interpreted code when clearing/enqueueing
2214      * references.  This is fragile, so we'll be paranoid.
2215      */
2216     gDvm.classJavaLangRefReference = clazz;
2217 
2218     gDvm.offJavaLangRefReference_referent =
2219         dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2220                 "referent", "Ljava/lang/Object;");
2221     assert(gDvm.offJavaLangRefReference_referent >= 0);
2222 
2223     gDvm.offJavaLangRefReference_queue =
2224         dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2225                 "queue", "Ljava/lang/ref/ReferenceQueue;");
2226     assert(gDvm.offJavaLangRefReference_queue >= 0);
2227 
2228     gDvm.offJavaLangRefReference_queueNext =
2229         dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2230                 "queueNext", "Ljava/lang/ref/Reference;");
2231     assert(gDvm.offJavaLangRefReference_queueNext >= 0);
2232 
2233     gDvm.offJavaLangRefReference_vmData =
2234         dvmFindFieldOffset(gDvm.classJavaLangRefReference,
2235                 "vmData", "I");
2236     assert(gDvm.offJavaLangRefReference_vmData >= 0);
2237 
2238 #if FANCY_REFERENCE_SUBCLASS
2239     meth = dvmFindVirtualMethodByDescriptor(clazz, "clear", "()V");
2240     assert(meth != NULL);
2241     gDvm.voffJavaLangRefReference_clear = meth->methodIndex;
2242 
2243     meth = dvmFindVirtualMethodByDescriptor(clazz, "enqueue", "()Z");
2244     assert(meth != NULL);
2245     gDvm.voffJavaLangRefReference_enqueue = meth->methodIndex;
2246 #else
2247     /* enqueueInternal() is private and thus a direct method. */
2248     meth = dvmFindDirectMethodByDescriptor(clazz, "enqueueInternal", "()Z");
2249     assert(meth != NULL);
2250     gDvm.methJavaLangRefReference_enqueueInternal = meth;
2251 #endif
2252 
2253     return true;
2254 }
2255 
2256 
2257 /*
2258  * Link (prepare and resolve).  Verification is deferred until later.
2259  *
2260  * This converts symbolic references into pointers.  It's independent of
2261  * the source file format.
2262  *
2263  * If "classesResolved" is false, we assume that superclassIdx and
2264  * interfaces[] are holding class reference indices rather than pointers.
2265  * The class references will be resolved during link.  (This is done when
2266  * loading from DEX to avoid having to create additional storage to pass
2267  * the indices around.)
2268  *
2269  * Returns "false" with an exception pending on failure.
2270  */
dvmLinkClass(ClassObject * clazz,bool classesResolved)2271 bool dvmLinkClass(ClassObject* clazz, bool classesResolved)
2272 {
2273     u4 superclassIdx = 0;
2274     bool okay = false;
2275     bool resolve_okay;
2276     int numInterfacesResolved = 0;
2277     int i;
2278 
2279     if (gDvm.verboseClass)
2280         LOGV("CLASS: linking '%s'...\n", clazz->descriptor);
2281 
2282     /* "Resolve" the class.
2283      *
2284      * At this point, clazz's reference fields contain Dex
2285      * file indices instead of direct object references.
2286      * We need to translate those indices into real references,
2287      * while making sure that the GC doesn't sweep any of
2288      * the referenced objects.
2289      *
2290      * The GC will avoid scanning this object as long as
2291      * clazz->obj.clazz is gDvm.unlinkedJavaLangClass.
2292      * Once clazz is ready, we'll replace clazz->obj.clazz
2293      * with gDvm.classJavaLangClass to let the GC know
2294      * to look at it.
2295      */
2296     assert(clazz->obj.clazz == gDvm.unlinkedJavaLangClass);
2297 
2298     /* It's important that we take care of java.lang.Class
2299      * first.  If we were to do this after looking up the
2300      * superclass (below), Class wouldn't be ready when
2301      * java.lang.Object needed it.
2302      *
2303      * Note that we don't set clazz->obj.clazz yet.
2304      */
2305     if (gDvm.classJavaLangClass == NULL) {
2306         if (clazz->classLoader == NULL &&
2307             strcmp(clazz->descriptor, "Ljava/lang/Class;") == 0)
2308         {
2309             gDvm.classJavaLangClass = clazz;
2310         } else {
2311             gDvm.classJavaLangClass =
2312                 dvmFindSystemClassNoInit("Ljava/lang/Class;");
2313             if (gDvm.classJavaLangClass == NULL) {
2314                 /* should have thrown one */
2315                 assert(dvmCheckException(dvmThreadSelf()));
2316                 goto bail;
2317             }
2318         }
2319     }
2320     assert(gDvm.classJavaLangClass != NULL);
2321 
2322     /*
2323      * Resolve all Dex indices so we can hand the ClassObject
2324      * over to the GC.  If we fail at any point, we need to remove
2325      * any tracked references to avoid leaking memory.
2326      */
2327 
2328     /*
2329      * All classes have a direct superclass, except for java/lang/Object.
2330      */
2331     if (!classesResolved) {
2332         superclassIdx = (u4) clazz->super;          /* unpack temp store */
2333         clazz->super = NULL;
2334     }
2335     if (strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0) {
2336         assert(!classesResolved);
2337         if (superclassIdx != kDexNoIndex) {
2338             /* TODO: is this invariant true for all java/lang/Objects,
2339              * regardless of the class loader?  For now, assume it is.
2340              */
2341             dvmThrowException("Ljava/lang/ClassFormatError;",
2342                 "java.lang.Object has a superclass");
2343             goto bail;
2344         }
2345 
2346         /* Don't finalize objects whose classes use the
2347          * default (empty) Object.finalize().
2348          */
2349         CLEAR_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2350     } else {
2351         if (!classesResolved) {
2352             if (superclassIdx == kDexNoIndex) {
2353                 dvmThrowException("Ljava/lang/LinkageError;",
2354                     "no superclass defined");
2355                 goto bail;
2356             }
2357             clazz->super = dvmResolveClass(clazz, superclassIdx, false);
2358             if (clazz->super == NULL) {
2359                 assert(dvmCheckException(dvmThreadSelf()));
2360                 if (gDvm.optimizing) {
2361                     /* happens with "external" libs */
2362                     LOGV("Unable to resolve superclass of %s (%d)\n",
2363                         clazz->descriptor, superclassIdx);
2364                 } else {
2365                     LOGW("Unable to resolve superclass of %s (%d)\n",
2366                         clazz->descriptor, superclassIdx);
2367                 }
2368                 goto bail;
2369             }
2370         }
2371         /* verify */
2372         if (dvmIsFinalClass(clazz->super)) {
2373             LOGW("Superclass of '%s' is final '%s'\n",
2374                 clazz->descriptor, clazz->super->descriptor);
2375             dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2376                 "superclass is final");
2377             goto bail;
2378         } else if (dvmIsInterfaceClass(clazz->super)) {
2379             LOGW("Superclass of '%s' is interface '%s'\n",
2380                 clazz->descriptor, clazz->super->descriptor);
2381             dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
2382                 "superclass is an interface");
2383             goto bail;
2384         } else if (!dvmCheckClassAccess(clazz, clazz->super)) {
2385             LOGW("Superclass of '%s' (%s) is not accessible\n",
2386                 clazz->descriptor, clazz->super->descriptor);
2387             dvmThrowException("Ljava/lang/IllegalAccessError;",
2388                 "superclass not accessible");
2389             goto bail;
2390         }
2391 
2392         /* Don't let the GC reclaim the superclass.
2393          * TODO: shouldn't be needed; remove when things stabilize
2394          */
2395         dvmAddTrackedAlloc((Object *)clazz->super, NULL);
2396 
2397         /* Inherit finalizability from the superclass.  If this
2398          * class also overrides finalize(), its CLASS_ISFINALIZABLE
2399          * bit will already be set.
2400          */
2401         if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISFINALIZABLE)) {
2402             SET_CLASS_FLAG(clazz, CLASS_ISFINALIZABLE);
2403         }
2404 
2405         /* See if this class descends from java.lang.Reference
2406          * and set the class flags appropriately.
2407          */
2408         if (IS_CLASS_FLAG_SET(clazz->super, CLASS_ISREFERENCE)) {
2409             u4 superRefFlags;
2410 
2411             /* We've already determined the reference type of this
2412              * inheritance chain.  Inherit reference-ness from the superclass.
2413              */
2414             superRefFlags = GET_CLASS_FLAG_GROUP(clazz->super,
2415                     CLASS_ISREFERENCE |
2416                     CLASS_ISWEAKREFERENCE |
2417                     CLASS_ISPHANTOMREFERENCE);
2418             SET_CLASS_FLAG(clazz, superRefFlags);
2419         } else if (clazz->classLoader == NULL &&
2420                 clazz->super->classLoader == NULL &&
2421                 strcmp(clazz->super->descriptor,
2422                        "Ljava/lang/ref/Reference;") == 0)
2423         {
2424             u4 refFlags;
2425 
2426             /* This class extends Reference, which means it should
2427              * be one of the magic Soft/Weak/PhantomReference classes.
2428              */
2429             refFlags = CLASS_ISREFERENCE;
2430             if (strcmp(clazz->descriptor,
2431                        "Ljava/lang/ref/SoftReference;") == 0)
2432             {
2433                 /* Only CLASS_ISREFERENCE is set for soft references.
2434                  */
2435             } else if (strcmp(clazz->descriptor,
2436                        "Ljava/lang/ref/WeakReference;") == 0)
2437             {
2438                 refFlags |= CLASS_ISWEAKREFERENCE;
2439             } else if (strcmp(clazz->descriptor,
2440                        "Ljava/lang/ref/PhantomReference;") == 0)
2441             {
2442                 refFlags |= CLASS_ISPHANTOMREFERENCE;
2443             } else {
2444                 /* No-one else is allowed to inherit directly
2445                  * from Reference.
2446                  */
2447 //xxx is this the right exception?  better than an assertion.
2448                 dvmThrowException("Ljava/lang/LinkageError;",
2449                     "illegal inheritance from Reference");
2450                 goto bail;
2451             }
2452 
2453             /* The class should not have any reference bits set yet.
2454              */
2455             assert(GET_CLASS_FLAG_GROUP(clazz,
2456                     CLASS_ISREFERENCE |
2457                     CLASS_ISWEAKREFERENCE |
2458                     CLASS_ISPHANTOMREFERENCE) == 0);
2459 
2460             SET_CLASS_FLAG(clazz, refFlags);
2461         }
2462     }
2463 
2464     if (!classesResolved && clazz->interfaceCount > 0) {
2465         /*
2466          * Resolve the interfaces implemented directly by this class.  We
2467          * stuffed the class index into the interface pointer slot.
2468          */
2469         dvmLinearReadWrite(clazz->classLoader, clazz->interfaces);
2470         for (i = 0; i < clazz->interfaceCount; i++) {
2471             u4 interfaceIdx;
2472 
2473             interfaceIdx = (u4) clazz->interfaces[i];   /* unpack temp store */
2474             assert(interfaceIdx != kDexNoIndex);
2475 
2476             clazz->interfaces[i] = dvmResolveClass(clazz, interfaceIdx, false);
2477             if (clazz->interfaces[i] == NULL) {
2478                 const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2479 
2480                 assert(dvmCheckException(dvmThreadSelf()));
2481                 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2482 
2483                 const char* classDescriptor;
2484                 classDescriptor = dexStringByTypeIdx(pDexFile, interfaceIdx);
2485                 if (gDvm.optimizing) {
2486                     /* happens with "external" libs */
2487                     LOGV("Failed resolving %s interface %d '%s'\n",
2488                         clazz->descriptor, interfaceIdx, classDescriptor);
2489                 } else {
2490                     LOGI("Failed resolving %s interface %d '%s'\n",
2491                         clazz->descriptor, interfaceIdx, classDescriptor);
2492                 }
2493                 goto bail_during_resolve;
2494             }
2495 
2496             /* are we allowed to implement this interface? */
2497             if (!dvmCheckClassAccess(clazz, clazz->interfaces[i])) {
2498                 dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2499                 LOGW("Interface '%s' is not accessible to '%s'\n",
2500                     clazz->interfaces[i]->descriptor, clazz->descriptor);
2501                 dvmThrowException("Ljava/lang/IllegalAccessError;",
2502                     "interface not accessible");
2503                 goto bail_during_resolve;
2504             }
2505 
2506             /* Don't let the GC reclaim the interface class.
2507              * TODO: shouldn't be needed; remove when things stabilize
2508              */
2509             dvmAddTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2510             numInterfacesResolved++;
2511 
2512             LOGVV("+++  found interface '%s'\n",
2513                 clazz->interfaces[i]->descriptor);
2514         }
2515         dvmLinearReadOnly(clazz->classLoader, clazz->interfaces);
2516     }
2517 
2518     /*
2519      * The ClassObject is now in a GC-able state.  We let the GC
2520      * realize this by punching in the real class type, which is
2521      * always java.lang.Class.
2522      *
2523      * After this line, clazz will be fair game for the GC.
2524      * Every field that the GC will look at must now be valid:
2525      * - clazz->super
2526      * - class->classLoader
2527      * - clazz->sfields
2528      * - clazz->interfaces
2529      */
2530     clazz->obj.clazz = gDvm.classJavaLangClass;
2531 
2532     if (false) {
2533 bail_during_resolve:
2534         resolve_okay = false;
2535     } else {
2536         resolve_okay = true;
2537     }
2538 
2539     /*
2540      * Now that the GC can scan the ClassObject, we can let
2541      * go of the explicit references we were holding onto.
2542      *
2543      * Either that or we failed, in which case we need to
2544      * release the references so we don't leak memory.
2545      */
2546     if (clazz->super != NULL) {
2547         dvmReleaseTrackedAlloc((Object *)clazz->super, NULL);
2548     }
2549     for (i = 0; i < numInterfacesResolved; i++) {
2550         dvmReleaseTrackedAlloc((Object *)clazz->interfaces[i], NULL);
2551     }
2552 
2553     if (!resolve_okay) {
2554         //LOGW("resolve_okay is false\n");
2555         goto bail;
2556     }
2557 
2558     /*
2559      * Populate vtable.
2560      */
2561     if (dvmIsInterfaceClass(clazz)) {
2562         /* no vtable; just set the method indices */
2563         int count = clazz->virtualMethodCount;
2564 
2565         if (count != (u2) count) {
2566             LOGE("Too many methods (%d) in interface '%s'\n", count,
2567                  clazz->descriptor);
2568             goto bail;
2569         }
2570 
2571         dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2572 
2573         for (i = 0; i < count; i++)
2574             clazz->virtualMethods[i].methodIndex = (u2) i;
2575 
2576         dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2577     } else {
2578         if (!createVtable(clazz)) {
2579             LOGW("failed creating vtable\n");
2580             goto bail;
2581         }
2582     }
2583 
2584     /*
2585      * Populate interface method tables.  Can alter the vtable.
2586      */
2587     if (!createIftable(clazz))
2588         goto bail;
2589 
2590     /*
2591      * Insert special-purpose "stub" method implementations.
2592      */
2593     if (!insertMethodStubs(clazz))
2594         goto bail;
2595 
2596     /*
2597      * Compute instance field offsets and, hence, the size of the object.
2598      */
2599     if (!computeFieldOffsets(clazz))
2600         goto bail;
2601 
2602     /*
2603      * Cache fields and methods from java/lang/ref/Reference and
2604      * java/lang/Class.  This has to happen after computeFieldOffsets().
2605      */
2606     if (clazz->classLoader == NULL) {
2607         if (strcmp(clazz->descriptor, "Ljava/lang/ref/Reference;") == 0) {
2608             if (!precacheReferenceOffsets(clazz)) {
2609                 LOGE("failed pre-caching Reference offsets\n");
2610                 dvmThrowException("Ljava/lang/InternalError;", NULL);
2611                 goto bail;
2612             }
2613         } else if (clazz == gDvm.classJavaLangClass) {
2614             gDvm.offJavaLangClass_pd = dvmFindFieldOffset(clazz, "pd",
2615                 "Ljava/security/ProtectionDomain;");
2616             if (gDvm.offJavaLangClass_pd <= 0) {
2617                 LOGE("ERROR: unable to find 'pd' field in Class\n");
2618                 dvmAbort();     /* we're not going to get much farther */
2619                 //goto bail;
2620             }
2621         }
2622     }
2623 
2624     /*
2625      * Done!
2626      */
2627     if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
2628         clazz->status = CLASS_VERIFIED;
2629     else
2630         clazz->status = CLASS_RESOLVED;
2631     okay = true;
2632     if (gDvm.verboseClass)
2633         LOGV("CLASS: linked '%s'\n", clazz->descriptor);
2634 
2635     /*
2636      * We send CLASS_PREPARE events to the debugger from here.  The
2637      * definition of "preparation" is creating the static fields for a
2638      * class and initializing them to the standard default values, but not
2639      * executing any code (that comes later, during "initialization").
2640      *
2641      * We did the static prep in loadSFieldFromDex() while loading the class.
2642      *
2643      * The class has been prepared and resolved but possibly not yet verified
2644      * at this point.
2645      */
2646     if (gDvm.debuggerActive) {
2647         dvmDbgPostClassPrepare(clazz);
2648     }
2649 
2650 bail:
2651     if (!okay) {
2652         clazz->status = CLASS_ERROR;
2653         if (!dvmCheckException(dvmThreadSelf())) {
2654             dvmThrowException("Ljava/lang/VirtualMachineError;", NULL);
2655         }
2656     }
2657     return okay;
2658 }
2659 
2660 /*
2661  * Create the virtual method table.
2662  *
2663  * The top part of the table is a copy of the table from our superclass,
2664  * with our local methods overriding theirs.  The bottom part of the table
2665  * has any new methods we defined.
2666  */
createVtable(ClassObject * clazz)2667 static bool createVtable(ClassObject* clazz)
2668 {
2669     bool result = false;
2670     int maxCount;
2671     int i;
2672 
2673     if (clazz->super != NULL) {
2674         //LOGI("SUPER METHODS %d %s->%s\n", clazz->super->vtableCount,
2675         //    clazz->descriptor, clazz->super->descriptor);
2676     }
2677 
2678     /* the virtual methods we define, plus the superclass vtable size */
2679     maxCount = clazz->virtualMethodCount;
2680     if (clazz->super != NULL) {
2681         maxCount += clazz->super->vtableCount;
2682     } else {
2683         /* TODO: is this invariant true for all java/lang/Objects,
2684          * regardless of the class loader?  For now, assume it is.
2685          */
2686         assert(strcmp(clazz->descriptor, "Ljava/lang/Object;") == 0);
2687     }
2688     //LOGD("+++ max vmethods for '%s' is %d\n", clazz->descriptor, maxCount);
2689 
2690     /*
2691      * Over-allocate the table, then realloc it down if necessary.  So
2692      * long as we don't allocate anything in between we won't cause
2693      * fragmentation, and reducing the size should be unlikely to cause
2694      * a buffer copy.
2695      */
2696     dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
2697     clazz->vtable = (Method**) dvmLinearAlloc(clazz->classLoader,
2698                         sizeof(Method*) * maxCount);
2699     if (clazz->vtable == NULL)
2700         goto bail;
2701 
2702     if (clazz->super != NULL) {
2703         int actualCount;
2704 
2705         memcpy(clazz->vtable, clazz->super->vtable,
2706             sizeof(*(clazz->vtable)) * clazz->super->vtableCount);
2707         actualCount = clazz->super->vtableCount;
2708 
2709         /*
2710          * See if any of our virtual methods override the superclass.
2711          */
2712         for (i = 0; i < clazz->virtualMethodCount; i++) {
2713             Method* localMeth = &clazz->virtualMethods[i];
2714             int si;
2715 
2716             for (si = 0; si < clazz->super->vtableCount; si++) {
2717                 Method* superMeth = clazz->vtable[si];
2718 
2719                 if (dvmCompareMethodNamesAndProtos(localMeth, superMeth) == 0)
2720                 {
2721                     /* verify */
2722                     if (dvmIsFinalMethod(superMeth)) {
2723                         LOGW("Method %s.%s overrides final %s.%s\n",
2724                             localMeth->clazz->descriptor, localMeth->name,
2725                             superMeth->clazz->descriptor, superMeth->name);
2726                         goto bail;
2727                     }
2728                     clazz->vtable[si] = localMeth;
2729                     localMeth->methodIndex = (u2) si;
2730                     //LOGV("+++   override %s.%s (slot %d)\n",
2731                     //    clazz->descriptor, localMeth->name, si);
2732                     break;
2733                 }
2734             }
2735 
2736             if (si == clazz->super->vtableCount) {
2737                 /* not an override, add to end */
2738                 clazz->vtable[actualCount] = localMeth;
2739                 localMeth->methodIndex = (u2) actualCount;
2740                 actualCount++;
2741 
2742                 //LOGV("+++   add method %s.%s\n",
2743                 //    clazz->descriptor, localMeth->name);
2744             }
2745         }
2746 
2747         if (actualCount != (u2) actualCount) {
2748             LOGE("Too many methods (%d) in class '%s'\n", actualCount,
2749                  clazz->descriptor);
2750             goto bail;
2751         }
2752 
2753         assert(actualCount <= maxCount);
2754 
2755         if (actualCount < maxCount) {
2756             assert(clazz->vtable != NULL);
2757             dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2758             clazz->vtable = dvmLinearRealloc(clazz->classLoader, clazz->vtable,
2759                 sizeof(*(clazz->vtable)) * actualCount);
2760             if (clazz->vtable == NULL) {
2761                 LOGE("vtable realloc failed\n");
2762                 goto bail;
2763             } else {
2764                 LOGVV("+++  reduced vtable from %d to %d\n",
2765                     maxCount, actualCount);
2766             }
2767         }
2768 
2769         clazz->vtableCount = actualCount;
2770     } else {
2771         /* java/lang/Object case */
2772         int count = clazz->virtualMethodCount;
2773         if (count != (u2) count) {
2774             LOGE("Too many methods (%d) in base class '%s'\n", count,
2775                  clazz->descriptor);
2776             goto bail;
2777         }
2778 
2779         for (i = 0; i < count; i++) {
2780             clazz->vtable[i] = &clazz->virtualMethods[i];
2781             clazz->virtualMethods[i].methodIndex = (u2) i;
2782         }
2783         clazz->vtableCount = clazz->virtualMethodCount;
2784     }
2785 
2786     result = true;
2787 
2788 bail:
2789     dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
2790     dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
2791     return result;
2792 }
2793 
2794 /*
2795  * Create and populate "iftable".
2796  *
2797  * The set of interfaces we support is the combination of the interfaces
2798  * we implement directly and those implemented by our superclass.  Each
2799  * interface can have one or more "superinterfaces", which we must also
2800  * support.  For speed we flatten the tree out.
2801  *
2802  * We might be able to speed this up when there are lots of interfaces
2803  * by merge-sorting the class pointers and binary-searching when removing
2804  * duplicates.  We could also drop the duplicate removal -- it's only
2805  * there to reduce the memory footprint.
2806  *
2807  * Because of "Miranda methods", this may reallocate clazz->virtualMethods.
2808  *
2809  * Returns "true" on success.
2810  */
createIftable(ClassObject * clazz)2811 static bool createIftable(ClassObject* clazz)
2812 {
2813     bool result = false;
2814     bool zapIftable = false;
2815     bool zapVtable = false;
2816     bool zapIfvipool = false;
2817     int ifCount, superIfCount, idx;
2818     int i;
2819 
2820     if (clazz->super != NULL)
2821         superIfCount = clazz->super->iftableCount;
2822     else
2823         superIfCount = 0;
2824 
2825     ifCount = superIfCount;
2826     ifCount += clazz->interfaceCount;
2827     for (i = 0; i < clazz->interfaceCount; i++)
2828         ifCount += clazz->interfaces[i]->iftableCount;
2829 
2830     LOGVV("INTF: class '%s' direct w/supra=%d super=%d total=%d\n",
2831         clazz->descriptor, ifCount - superIfCount, superIfCount, ifCount);
2832 
2833     if (ifCount == 0) {
2834         assert(clazz->iftableCount == 0);
2835         assert(clazz->iftable == NULL);
2836         result = true;
2837         goto bail;
2838     }
2839 
2840     /*
2841      * Create a table with enough space for all interfaces, and copy the
2842      * superclass' table in.
2843      */
2844     clazz->iftable = (InterfaceEntry*) dvmLinearAlloc(clazz->classLoader,
2845                         sizeof(InterfaceEntry) * ifCount);
2846     zapIftable = true;
2847     memset(clazz->iftable, 0x00, sizeof(InterfaceEntry) * ifCount);
2848     if (superIfCount != 0) {
2849         memcpy(clazz->iftable, clazz->super->iftable,
2850             sizeof(InterfaceEntry) * superIfCount);
2851     }
2852 
2853     /*
2854      * Create a flattened interface hierarchy of our immediate interfaces.
2855      */
2856     idx = superIfCount;
2857 
2858     for (i = 0; i < clazz->interfaceCount; i++) {
2859         ClassObject* interf;
2860         int j;
2861 
2862         interf = clazz->interfaces[i];
2863         assert(interf != NULL);
2864 
2865         /* make sure this is still an interface class */
2866         if (!dvmIsInterfaceClass(interf)) {
2867             LOGW("Class '%s' implements non-interface '%s'\n",
2868                 clazz->descriptor, interf->descriptor);
2869             dvmThrowExceptionWithClassMessage(
2870                 "Ljava/lang/IncompatibleClassChangeError;",
2871                 clazz->descriptor);
2872             goto bail;
2873         }
2874 
2875         /* add entry for this interface */
2876         clazz->iftable[idx++].clazz = interf;
2877 
2878         /* add entries for the interface's superinterfaces */
2879         for (j = 0; j < interf->iftableCount; j++) {
2880             clazz->iftable[idx++].clazz = interf->iftable[j].clazz;
2881         }
2882     }
2883 
2884     assert(idx == ifCount);
2885 
2886     if (false) {
2887         /*
2888          * Remove anything redundant from our recent additions.  Note we have
2889          * to traverse the recent adds when looking for duplicates, because
2890          * it's possible the recent additions are self-redundant.  This
2891          * reduces the memory footprint of classes with lots of inherited
2892          * interfaces.
2893          *
2894          * (I don't know if this will cause problems later on when we're trying
2895          * to find a static field.  It looks like the proper search order is
2896          * (1) current class, (2) interfaces implemented by current class,
2897          * (3) repeat with superclass.  A field implemented by an interface
2898          * and by a superclass might come out wrong if the superclass also
2899          * implements the interface.  The javac compiler will reject the
2900          * situation as ambiguous, so the concern is somewhat artificial.)
2901          *
2902          * UPDATE: this makes ReferenceType.Interfaces difficult to implement,
2903          * because it wants to return just the interfaces declared to be
2904          * implemented directly by the class.  I'm excluding this code for now.
2905          */
2906         for (i = superIfCount; i < ifCount; i++) {
2907             int j;
2908 
2909             for (j = 0; j < ifCount; j++) {
2910                 if (i == j)
2911                     continue;
2912                 if (clazz->iftable[i].clazz == clazz->iftable[j].clazz) {
2913                     LOGVV("INTF: redundant interface %s in %s\n",
2914                         clazz->iftable[i].clazz->descriptor,
2915                         clazz->descriptor);
2916 
2917                     if (i != ifCount-1)
2918                         memmove(&clazz->iftable[i], &clazz->iftable[i+1],
2919                             (ifCount - i -1) * sizeof(InterfaceEntry));
2920                     ifCount--;
2921                     i--;        // adjust for i++ above
2922                     break;
2923                 }
2924             }
2925         }
2926         LOGVV("INTF: class '%s' nodupes=%d\n", clazz->descriptor, ifCount);
2927     } // if (false)
2928 
2929     clazz->iftableCount = ifCount;
2930 
2931     /*
2932      * If we're an interface, we don't need the vtable pointers, so
2933      * we're done.  If this class doesn't implement an interface that our
2934      * superclass doesn't have, then we again have nothing to do.
2935      */
2936     if (dvmIsInterfaceClass(clazz) || superIfCount == ifCount) {
2937         //dvmDumpClass(clazz, kDumpClassFullDetail);
2938         result = true;
2939         goto bail;
2940     }
2941 
2942     /*
2943      * When we're handling invokeinterface, we probably have an object
2944      * whose type is an interface class rather than a concrete class.  We
2945      * need to convert the method reference into a vtable index.  So, for
2946      * every entry in "iftable", we create a list of vtable indices.
2947      *
2948      * Because our vtable encompasses the superclass vtable, we can use
2949      * the vtable indices from our superclass for all of the interfaces
2950      * that weren't directly implemented by us.
2951      *
2952      * Each entry in "iftable" has a pointer to the start of its set of
2953      * vtable offsets.  The iftable entries in the superclass point to
2954      * storage allocated in the superclass, and the iftable entries added
2955      * for this class point to storage allocated in this class.  "iftable"
2956      * is flat for fast access in a class and all of its subclasses, but
2957      * "ifviPool" is only created for the topmost implementor.
2958      */
2959     int poolSize = 0;
2960     for (i = superIfCount; i < ifCount; i++) {
2961         /*
2962          * Note it's valid for an interface to have no methods (e.g.
2963          * java/io/Serializable).
2964          */
2965         LOGVV("INTF: pool: %d from %s\n",
2966             clazz->iftable[i].clazz->virtualMethodCount,
2967             clazz->iftable[i].clazz->descriptor);
2968         poolSize += clazz->iftable[i].clazz->virtualMethodCount;
2969     }
2970 
2971     if (poolSize == 0) {
2972         LOGVV("INTF: didn't find any new interfaces with methods\n");
2973         result = true;
2974         goto bail;
2975     }
2976 
2977     clazz->ifviPoolCount = poolSize;
2978     clazz->ifviPool = (int*) dvmLinearAlloc(clazz->classLoader,
2979                         poolSize * sizeof(int*));
2980     zapIfvipool = true;
2981 
2982     /*
2983      * Fill in the vtable offsets for the interfaces that weren't part of
2984      * our superclass.
2985      */
2986     int poolOffset = 0;
2987     Method** mirandaList = NULL;
2988     int mirandaCount = 0, mirandaAlloc = 0;
2989 
2990     for (i = superIfCount; i < ifCount; i++) {
2991         ClassObject* interface;
2992         int methIdx;
2993 
2994         clazz->iftable[i].methodIndexArray = clazz->ifviPool + poolOffset;
2995         interface = clazz->iftable[i].clazz;
2996         poolOffset += interface->virtualMethodCount;    // end here
2997 
2998         /*
2999          * For each method listed in the interface's method list, find the
3000          * matching method in our class's method list.  We want to favor the
3001          * subclass over the superclass, which just requires walking
3002          * back from the end of the vtable.  (This only matters if the
3003          * superclass defines a private method and this class redefines
3004          * it -- otherwise it would use the same vtable slot.  In Dalvik
3005          * those don't end up in the virtual method table, so it shouldn't
3006          * matter which direction we go.  We walk it backward anyway.)
3007          *
3008          *
3009          * Suppose we have the following arrangement:
3010          *   public interface MyInterface
3011          *     public boolean inInterface();
3012          *   public abstract class MirandaAbstract implements MirandaInterface
3013          *     //public abstract boolean inInterface(); // not declared!
3014          *     public boolean inAbstract() { stuff }    // in vtable
3015          *   public class MirandClass extends MirandaAbstract
3016          *     public boolean inInterface() { stuff }
3017          *     public boolean inAbstract() { stuff }    // in vtable
3018          *
3019          * The javac compiler happily compiles MirandaAbstract even though
3020          * it doesn't declare all methods from its interface.  When we try
3021          * to set up a vtable for MirandaAbstract, we find that we don't
3022          * have an slot for inInterface.  To prevent this, we synthesize
3023          * abstract method declarations in MirandaAbstract.
3024          *
3025          * We have to expand vtable and update some things that point at it,
3026          * so we accumulate the method list and do it all at once below.
3027          */
3028         for (methIdx = 0; methIdx < interface->virtualMethodCount; methIdx++) {
3029             Method* imeth = &interface->virtualMethods[methIdx];
3030             int j;
3031 
3032             IF_LOGVV() {
3033                 char* desc = dexProtoCopyMethodDescriptor(&imeth->prototype);
3034                 LOGVV("INTF:  matching '%s' '%s'\n", imeth->name, desc);
3035                 free(desc);
3036             }
3037 
3038             for (j = clazz->vtableCount-1; j >= 0; j--) {
3039                 if (dvmCompareMethodNamesAndProtos(imeth, clazz->vtable[j])
3040                     == 0)
3041                 {
3042                     LOGVV("INTF:   matched at %d\n", j);
3043                     if (!dvmIsPublicMethod(clazz->vtable[j])) {
3044                         LOGW("Implementation of %s.%s is not public\n",
3045                             clazz->descriptor, clazz->vtable[j]->name);
3046                         dvmThrowException("Ljava/lang/IllegalAccessError;",
3047                             "interface implementation not public");
3048                         goto bail;
3049                     }
3050                     clazz->iftable[i].methodIndexArray[methIdx] = j;
3051                     break;
3052                 }
3053             }
3054             if (j < 0) {
3055                 IF_LOGV() {
3056                     char* desc =
3057                         dexProtoCopyMethodDescriptor(&imeth->prototype);
3058                     LOGV("No match for '%s' '%s' in '%s' (creating miranda)\n",
3059                             imeth->name, desc, clazz->descriptor);
3060                     free(desc);
3061                 }
3062                 //dvmThrowException("Ljava/lang/RuntimeException;", "Miranda!");
3063                 //return false;
3064 
3065                 if (mirandaCount == mirandaAlloc) {
3066                     mirandaAlloc += 8;
3067                     if (mirandaList == NULL) {
3068                         mirandaList = dvmLinearAlloc(clazz->classLoader,
3069                                         mirandaAlloc * sizeof(Method*));
3070                     } else {
3071                         dvmLinearReadOnly(clazz->classLoader, mirandaList);
3072                         mirandaList = dvmLinearRealloc(clazz->classLoader,
3073                                 mirandaList, mirandaAlloc * sizeof(Method*));
3074                     }
3075                     assert(mirandaList != NULL);    // mem failed + we leaked
3076                 }
3077 
3078                 /*
3079                  * These may be redundant (e.g. method with same name and
3080                  * signature declared in two interfaces implemented by the
3081                  * same abstract class).  We can squeeze the duplicates
3082                  * out here.
3083                  */
3084                 int mir;
3085                 for (mir = 0; mir < mirandaCount; mir++) {
3086                     if (dvmCompareMethodNamesAndProtos(
3087                             mirandaList[mir], imeth) == 0)
3088                     {
3089                         IF_LOGVV() {
3090                             char* desc = dexProtoCopyMethodDescriptor(
3091                                     &imeth->prototype);
3092                             LOGVV("MIRANDA dupe: %s and %s %s%s\n",
3093                                 mirandaList[mir]->clazz->descriptor,
3094                                 imeth->clazz->descriptor,
3095                                 imeth->name, desc);
3096                             free(desc);
3097                         }
3098                         break;
3099                     }
3100                 }
3101 
3102                 /* point the iftable at a phantom slot index */
3103                 clazz->iftable[i].methodIndexArray[methIdx] =
3104                     clazz->vtableCount + mir;
3105                 LOGVV("MIRANDA: %s points at slot %d\n",
3106                     imeth->name, clazz->vtableCount + mir);
3107 
3108                 /* if non-duplicate among Mirandas, add to Miranda list */
3109                 if (mir == mirandaCount) {
3110                     //LOGV("MIRANDA: holding '%s' in slot %d\n",
3111                     //    imeth->name, mir);
3112                     mirandaList[mirandaCount++] = imeth;
3113                 }
3114             }
3115         }
3116     }
3117 
3118     if (mirandaCount != 0) {
3119         Method* newVirtualMethods;
3120         Method* meth;
3121         int oldMethodCount, oldVtableCount;
3122 
3123         for (i = 0; i < mirandaCount; i++) {
3124             LOGVV("MIRANDA %d: %s.%s\n", i,
3125                 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
3126         }
3127 
3128         /*
3129          * We found methods in one or more interfaces for which we do not
3130          * have vtable entries.  We have to expand our virtualMethods
3131          * table (which might be empty) to hold some new entries.
3132          */
3133         if (clazz->virtualMethods == NULL) {
3134             newVirtualMethods = (Method*) dvmLinearAlloc(clazz->classLoader,
3135                 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3136         } else {
3137             //dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3138             newVirtualMethods = (Method*) dvmLinearRealloc(clazz->classLoader,
3139                 clazz->virtualMethods,
3140                 sizeof(Method) * (clazz->virtualMethodCount + mirandaCount));
3141         }
3142         if (newVirtualMethods != clazz->virtualMethods) {
3143             /*
3144              * Table was moved in memory.  We have to run through the
3145              * vtable and fix the pointers.  The vtable entries might be
3146              * pointing at superclasses, so we flip it around: run through
3147              * all locally-defined virtual methods, and fix their entries
3148              * in the vtable.  (This would get really messy if sub-classes
3149              * had already been loaded.)
3150              *
3151              * Reminder: clazz->virtualMethods and clazz->virtualMethodCount
3152              * hold the virtual methods declared by this class.  The
3153              * method's methodIndex is the vtable index, and is the same
3154              * for all sub-classes (and all super classes in which it is
3155              * defined).  We're messing with these because the Miranda
3156              * stuff makes it look like the class actually has an abstract
3157              * method declaration in it.
3158              */
3159             LOGVV("MIRANDA fixing vtable pointers\n");
3160             dvmLinearReadWrite(clazz->classLoader, clazz->vtable);
3161             Method* meth = newVirtualMethods;
3162             for (i = 0; i < clazz->virtualMethodCount; i++, meth++)
3163                 clazz->vtable[meth->methodIndex] = meth;
3164             dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3165         }
3166 
3167         oldMethodCount = clazz->virtualMethodCount;
3168         clazz->virtualMethods = newVirtualMethods;
3169         clazz->virtualMethodCount += mirandaCount;
3170 
3171         dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3172 
3173         /*
3174          * We also have to expand the vtable.
3175          */
3176         assert(clazz->vtable != NULL);
3177         clazz->vtable = (Method**) dvmLinearRealloc(clazz->classLoader,
3178                         clazz->vtable,
3179                         sizeof(Method*) * (clazz->vtableCount + mirandaCount));
3180         if (clazz->vtable == NULL) {
3181             assert(false);
3182             goto bail;
3183         }
3184         zapVtable = true;
3185 
3186         oldVtableCount = clazz->vtableCount;
3187         clazz->vtableCount += mirandaCount;
3188 
3189         /*
3190          * Now we need to create the fake methods.  We clone the abstract
3191          * method definition from the interface and then replace a few
3192          * things.
3193          */
3194         meth = clazz->virtualMethods + oldMethodCount;
3195         for (i = 0; i < mirandaCount; i++, meth++) {
3196             dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3197             cloneMethod(meth, mirandaList[i]);
3198             meth->clazz = clazz;
3199             meth->accessFlags |= ACC_MIRANDA;
3200             meth->methodIndex = (u2) (oldVtableCount + i);
3201             dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3202 
3203             /* point the new vtable entry at the new method */
3204             clazz->vtable[oldVtableCount + i] = meth;
3205         }
3206 
3207         dvmLinearReadOnly(clazz->classLoader, mirandaList);
3208         dvmLinearFree(clazz->classLoader, mirandaList);
3209 
3210     }
3211 
3212     /*
3213      * TODO?
3214      * Sort the interfaces by number of declared methods.  All we really
3215      * want is to get the interfaces with zero methods at the end of the
3216      * list, so that when we walk through the list during invoke-interface
3217      * we don't examine interfaces that can't possibly be useful.
3218      *
3219      * The set will usually be small, so a simple insertion sort works.
3220      *
3221      * We have to be careful not to change the order of two interfaces
3222      * that define the same method.  (Not a problem if we only move the
3223      * zero-method interfaces to the end.)
3224      *
3225      * PROBLEM:
3226      * If we do this, we will no longer be able to identify super vs.
3227      * current class interfaces by comparing clazz->super->iftableCount.  This
3228      * breaks anything that only wants to find interfaces declared directly
3229      * by the class (dvmFindStaticFieldHier, ReferenceType.Interfaces,
3230      * dvmDbgOutputAllInterfaces, etc).  Need to provide a workaround.
3231      *
3232      * We can sort just the interfaces implemented directly by this class,
3233      * but that doesn't seem like it would provide much of an advantage.  I'm
3234      * not sure this is worthwhile.
3235      *
3236      * (This has been made largely obsolete by the interface cache mechanism.)
3237      */
3238 
3239     //dvmDumpClass(clazz);
3240 
3241     result = true;
3242 
3243 bail:
3244     if (zapIftable)
3245         dvmLinearReadOnly(clazz->classLoader, clazz->iftable);
3246     if (zapVtable)
3247         dvmLinearReadOnly(clazz->classLoader, clazz->vtable);
3248     if (zapIfvipool)
3249         dvmLinearReadOnly(clazz->classLoader, clazz->ifviPool);
3250     return result;
3251 }
3252 
3253 
3254 /*
3255  * Provide "stub" implementations for methods without them.
3256  *
3257  * Currently we provide an implementation for all abstract methods that
3258  * throws an AbstractMethodError exception.  This allows us to avoid an
3259  * explicit check for abstract methods in every virtual call.
3260  *
3261  * NOTE: for Miranda methods, the method declaration is a clone of what
3262  * was found in the interface class.  That copy may already have had the
3263  * function pointer filled in, so don't be surprised if it's not NULL.
3264  *
3265  * NOTE: this sets the "native" flag, giving us an "abstract native" method,
3266  * which is nonsensical.  Need to make sure that this doesn't escape the
3267  * VM.  We can either mask it out in reflection calls, or copy "native"
3268  * into the high 16 bits of accessFlags and check that internally.
3269  */
insertMethodStubs(ClassObject * clazz)3270 static bool insertMethodStubs(ClassObject* clazz)
3271 {
3272     dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
3273 
3274     Method* meth;
3275     int i;
3276 
3277     meth = clazz->virtualMethods;
3278     for (i = 0; i < clazz->virtualMethodCount; i++, meth++) {
3279         if (dvmIsAbstractMethod(meth)) {
3280             assert(meth->insns == NULL);
3281             assert(meth->nativeFunc == NULL ||
3282                 meth->nativeFunc == (DalvikBridgeFunc)dvmAbstractMethodStub);
3283 
3284             meth->accessFlags |= ACC_NATIVE;
3285             meth->nativeFunc = (DalvikBridgeFunc) dvmAbstractMethodStub;
3286         }
3287     }
3288 
3289     dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
3290     return true;
3291 }
3292 
3293 
3294 /*
3295  * Swap two instance fields.
3296  */
swapField(InstField * pOne,InstField * pTwo)3297 static inline void swapField(InstField* pOne, InstField* pTwo)
3298 {
3299     InstField swap;
3300 
3301     LOGVV("  --- swap '%s' and '%s'\n", pOne->field.name, pTwo->field.name);
3302     swap = *pOne;
3303     *pOne = *pTwo;
3304     *pTwo = swap;
3305 }
3306 
3307 /*
3308  * Assign instance fields to u4 slots.
3309  *
3310  * The top portion of the instance field area is occupied by the superclass
3311  * fields, the bottom by the fields for this class.
3312  *
3313  * "long" and "double" fields occupy two adjacent slots.  On some
3314  * architectures, 64-bit quantities must be 64-bit aligned, so we need to
3315  * arrange fields (or introduce padding) to ensure this.  We assume the
3316  * fields of the topmost superclass (i.e. Object) are 64-bit aligned, so
3317  * we can just ensure that the offset is "even".  To avoid wasting space,
3318  * we want to move non-reference 32-bit fields into gaps rather than
3319  * creating pad words.
3320  *
3321  * In the worst case we will waste 4 bytes, but because objects are
3322  * allocated on >= 64-bit boundaries, those bytes may well be wasted anyway
3323  * (assuming this is the most-derived class).
3324  *
3325  * Pad words are not represented in the field table, so the field table
3326  * itself does not change size.
3327  *
3328  * The number of field slots determines the size of the object, so we
3329  * set that here too.
3330  *
3331  * This function feels a little more complicated than I'd like, but it
3332  * has the property of moving the smallest possible set of fields, which
3333  * should reduce the time required to load a class.
3334  *
3335  * NOTE: reference fields *must* come first, or precacheReferenceOffsets()
3336  * will break.
3337  */
computeFieldOffsets(ClassObject * clazz)3338 static bool computeFieldOffsets(ClassObject* clazz)
3339 {
3340     int fieldOffset;
3341     int i, j;
3342 
3343     dvmLinearReadWrite(clazz->classLoader, clazz->ifields);
3344 
3345     if (clazz->super != NULL)
3346         fieldOffset = clazz->super->objectSize;
3347     else
3348         fieldOffset = offsetof(DataObject, instanceData);
3349 
3350     LOGVV("--- computeFieldOffsets '%s'\n", clazz->descriptor);
3351 
3352     //LOGI("OFFSETS fieldCount=%d\n", clazz->ifieldCount);
3353     //LOGI("dataobj, instance: %d\n", offsetof(DataObject, instanceData));
3354     //LOGI("classobj, access: %d\n", offsetof(ClassObject, accessFlags));
3355     //LOGI("super=%p, fieldOffset=%d\n", clazz->super, fieldOffset);
3356 
3357     /*
3358      * Start by moving all reference fields to the front.
3359      */
3360     clazz->ifieldRefCount = 0;
3361     j = clazz->ifieldCount - 1;
3362     for (i = 0; i < clazz->ifieldCount; i++) {
3363         InstField* pField = &clazz->ifields[i];
3364         char c = pField->field.signature[0];
3365 
3366         if (c != '[' && c != 'L') {
3367             /* This isn't a reference field; see if any reference fields
3368              * follow this one.  If so, we'll move it to this position.
3369              * (quicksort-style partitioning)
3370              */
3371             while (j > i) {
3372                 InstField* refField = &clazz->ifields[j--];
3373                 char rc = refField->field.signature[0];
3374 
3375                 if (rc == '[' || rc == 'L') {
3376                     /* Here's a reference field that follows at least one
3377                      * non-reference field.  Swap it with the current field.
3378                      * (When this returns, "pField" points to the reference
3379                      * field, and "refField" points to the non-ref field.)
3380                      */
3381                     swapField(pField, refField);
3382 
3383                     /* Fix the signature.
3384                      */
3385                     c = rc;
3386 
3387                     clazz->ifieldRefCount++;
3388                     break;
3389                 }
3390             }
3391             /* We may or may not have swapped a field.
3392              */
3393         } else {
3394             /* This is a reference field.
3395              */
3396             clazz->ifieldRefCount++;
3397         }
3398 
3399         /*
3400          * If we've hit the end of the reference fields, break.
3401          */
3402         if (c != '[' && c != 'L')
3403             break;
3404 
3405         pField->byteOffset = fieldOffset;
3406         fieldOffset += sizeof(u4);
3407         LOGVV("  --- offset1 '%s'=%d\n", pField->field.name,pField->byteOffset);
3408     }
3409 
3410     /*
3411      * Now we want to pack all of the double-wide fields together.  If we're
3412      * not aligned, though, we want to shuffle one 32-bit field into place.
3413      * If we can't find one, we'll have to pad it.
3414      */
3415     if (i != clazz->ifieldCount && (fieldOffset & 0x04) != 0) {
3416         LOGVV("  +++ not aligned\n");
3417 
3418         InstField* pField = &clazz->ifields[i];
3419         char c = pField->field.signature[0];
3420 
3421         if (c != 'J' && c != 'D') {
3422             /*
3423              * The field that comes next is 32-bit, so just advance past it.
3424              */
3425             assert(c != '[' && c != 'L');
3426             pField->byteOffset = fieldOffset;
3427             fieldOffset += sizeof(u4);
3428             i++;
3429             LOGVV("  --- offset2 '%s'=%d\n",
3430                 pField->field.name, pField->byteOffset);
3431         } else {
3432             /*
3433              * Next field is 64-bit, so search for a 32-bit field we can
3434              * swap into it.
3435              */
3436             bool found = false;
3437             j = clazz->ifieldCount - 1;
3438             while (j > i) {
3439                 InstField* singleField = &clazz->ifields[j--];
3440                 char rc = singleField->field.signature[0];
3441 
3442                 if (rc != 'J' && rc != 'D') {
3443                     swapField(pField, singleField);
3444                     //c = rc;
3445                     LOGVV("  +++ swapped '%s' for alignment\n",
3446                         pField->field.name);
3447                     pField->byteOffset = fieldOffset;
3448                     fieldOffset += sizeof(u4);
3449                     LOGVV("  --- offset3 '%s'=%d\n",
3450                         pField->field.name, pField->byteOffset);
3451                     found = true;
3452                     i++;
3453                     break;
3454                 }
3455             }
3456             if (!found) {
3457                 LOGV("  +++ inserting pad field in '%s'\n", clazz->descriptor);
3458                 fieldOffset += sizeof(u4);
3459             }
3460         }
3461     }
3462 
3463     /*
3464      * Alignment is good, shuffle any double-wide fields forward, and
3465      * finish assigning field offsets to all fields.
3466      */
3467     assert(i == clazz->ifieldCount || (fieldOffset & 0x04) == 0);
3468     j = clazz->ifieldCount - 1;
3469     for ( ; i < clazz->ifieldCount; i++) {
3470         InstField* pField = &clazz->ifields[i];
3471         char c = pField->field.signature[0];
3472 
3473         if (c != 'D' && c != 'J') {
3474             /* This isn't a double-wide field; see if any double fields
3475              * follow this one.  If so, we'll move it to this position.
3476              * (quicksort-style partitioning)
3477              */
3478             while (j > i) {
3479                 InstField* doubleField = &clazz->ifields[j--];
3480                 char rc = doubleField->field.signature[0];
3481 
3482                 if (rc == 'D' || rc == 'J') {
3483                     /* Here's a double-wide field that follows at least one
3484                      * non-double field.  Swap it with the current field.
3485                      * (When this returns, "pField" points to the reference
3486                      * field, and "doubleField" points to the non-double field.)
3487                      */
3488                     swapField(pField, doubleField);
3489                     c = rc;
3490 
3491                     break;
3492                 }
3493             }
3494             /* We may or may not have swapped a field.
3495              */
3496         } else {
3497             /* This is a double-wide field, leave it be.
3498              */
3499         }
3500 
3501         pField->byteOffset = fieldOffset;
3502         LOGVV("  --- offset4 '%s'=%d\n", pField->field.name,pField->byteOffset);
3503         fieldOffset += sizeof(u4);
3504         if (c == 'J' || c == 'D')
3505             fieldOffset += sizeof(u4);
3506     }
3507 
3508 #ifndef NDEBUG
3509     /* Make sure that all reference fields appear before
3510      * non-reference fields, and all double-wide fields are aligned.
3511      */
3512     j = 0;  // seen non-ref
3513     for (i = 0; i < clazz->ifieldCount; i++) {
3514         InstField *pField = &clazz->ifields[i];
3515         char c = pField->field.signature[0];
3516 
3517         if (c == 'D' || c == 'J') {
3518             assert((pField->byteOffset & 0x07) == 0);
3519         }
3520 
3521         if (c != '[' && c != 'L') {
3522             if (!j) {
3523                 assert(i == clazz->ifieldRefCount);
3524                 j = 1;
3525             }
3526         } else if (j) {
3527             assert(false);
3528         }
3529     }
3530     if (!j) {
3531         assert(clazz->ifieldRefCount == clazz->ifieldCount);
3532     }
3533 #endif
3534 
3535     /*
3536      * We map a C struct directly on top of java/lang/Class objects.  Make
3537      * sure we left enough room for the instance fields.
3538      */
3539     assert(clazz != gDvm.classJavaLangClass || (size_t)fieldOffset <
3540         offsetof(ClassObject, instanceData) + sizeof(clazz->instanceData));
3541 
3542     clazz->objectSize = fieldOffset;
3543 
3544     dvmLinearReadOnly(clazz->classLoader, clazz->ifields);
3545     return true;
3546 }
3547 
3548 /*
3549  * Throw the VM-spec-mandated error when an exception is thrown during
3550  * class initialization.
3551  *
3552  * The safest way to do this is to call the ExceptionInInitializerError
3553  * constructor that takes a Throwable.
3554  *
3555  * [Do we want to wrap it if the original is an Error rather than
3556  * an Exception?]
3557  */
throwClinitError(void)3558 static void throwClinitError(void)
3559 {
3560     Thread* self = dvmThreadSelf();
3561     Object* exception;
3562     Object* eiie;
3563 
3564     exception = dvmGetException(self);
3565     dvmAddTrackedAlloc(exception, self);
3566     dvmClearException(self);
3567 
3568     if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3569         /*
3570          * Always resolves to same thing -- no race condition.
3571          */
3572         gDvm.classJavaLangExceptionInInitializerError =
3573             dvmFindSystemClass(
3574                     "Ljava/lang/ExceptionInInitializerError;");
3575         if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
3576             LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3577             goto fail;
3578         }
3579 
3580         gDvm.methJavaLangExceptionInInitializerError_init =
3581             dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
3582             "<init>", "(Ljava/lang/Throwable;)V");
3583         if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
3584             LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
3585             goto fail;
3586         }
3587     }
3588 
3589     eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
3590                 ALLOC_DEFAULT);
3591     if (eiie == NULL)
3592         goto fail;
3593 
3594     /*
3595      * Construct the new object, and replace the exception with it.
3596      */
3597     JValue unused;
3598     dvmCallMethod(self, gDvm.methJavaLangExceptionInInitializerError_init,
3599         eiie, &unused, exception);
3600     dvmSetException(self, eiie);
3601     dvmReleaseTrackedAlloc(eiie, NULL);
3602     dvmReleaseTrackedAlloc(exception, self);
3603     return;
3604 
3605 fail:       /* restore original exception */
3606     dvmSetException(self, exception);
3607     dvmReleaseTrackedAlloc(exception, self);
3608     return;
3609 }
3610 
3611 /*
3612  * The class failed to initialize on a previous attempt, so we want to throw
3613  * a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
3614  * failed in verification, in which case v2 5.4.1 says we need to re-throw
3615  * the previous error.
3616  */
throwEarlierClassFailure(ClassObject * clazz)3617 static void throwEarlierClassFailure(ClassObject* clazz)
3618 {
3619     LOGI("Rejecting re-init on previously-failed class %s v=%p\n",
3620         clazz->descriptor, clazz->verifyErrorClass);
3621 
3622     if (clazz->verifyErrorClass == NULL) {
3623         dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
3624             clazz->descriptor);
3625     } else {
3626         dvmThrowExceptionByClassWithClassMessage(clazz->verifyErrorClass,
3627             clazz->descriptor);
3628     }
3629 }
3630 
3631 /*
3632  * Initialize any static fields whose values are stored in
3633  * the DEX file.  This must be done during class initialization.
3634  */
initSFields(ClassObject * clazz)3635 static void initSFields(ClassObject* clazz)
3636 {
3637     Thread* self = dvmThreadSelf(); /* for dvmReleaseTrackedAlloc() */
3638     DexFile* pDexFile;
3639     const DexClassDef* pClassDef;
3640     const DexEncodedArray* pValueList;
3641     EncodedArrayIterator iterator;
3642     int i;
3643 
3644     if (clazz->sfieldCount == 0) {
3645         return;
3646     }
3647     if (clazz->pDvmDex == NULL) {
3648         /* generated class; any static fields should already be set up */
3649         LOGV("Not initializing static fields in %s\n", clazz->descriptor);
3650         return;
3651     }
3652     pDexFile = clazz->pDvmDex->pDexFile;
3653 
3654     pClassDef = dexFindClass(pDexFile, clazz->descriptor);
3655     assert(pClassDef != NULL);
3656 
3657     pValueList = dexGetStaticValuesList(pDexFile, pClassDef);
3658     if (pValueList == NULL) {
3659         return;
3660     }
3661 
3662     dvmEncodedArrayIteratorInitialize(&iterator, pValueList, clazz);
3663 
3664     /*
3665      * Iterate over the initial values array, setting the corresponding
3666      * static field for each array element.
3667      */
3668 
3669     for (i = 0; dvmEncodedArrayIteratorHasNext(&iterator); i++) {
3670         AnnotationValue value;
3671         bool parsed = dvmEncodedArrayIteratorGetNext(&iterator, &value);
3672         StaticField* sfield = &clazz->sfields[i];
3673         const char* descriptor = sfield->field.signature;
3674         bool needRelease = false;
3675 
3676         if (! parsed) {
3677             /*
3678              * TODO: Eventually verification should attempt to ensure
3679              * that this can't happen at least due to a data integrity
3680              * problem.
3681              */
3682             LOGE("Static initializer parse failed for %s at index %d",
3683                     clazz->descriptor, i);
3684             dvmAbort();
3685         }
3686 
3687         /* Verify that the value we got was of a valid type. */
3688 
3689         switch (descriptor[0]) {
3690             case 'Z': parsed = (value.type == kDexAnnotationBoolean); break;
3691             case 'B': parsed = (value.type == kDexAnnotationByte);    break;
3692             case 'C': parsed = (value.type == kDexAnnotationChar);    break;
3693             case 'S': parsed = (value.type == kDexAnnotationShort);   break;
3694             case 'I': parsed = (value.type == kDexAnnotationInt);     break;
3695             case 'J': parsed = (value.type == kDexAnnotationLong);    break;
3696             case 'F': parsed = (value.type == kDexAnnotationFloat);   break;
3697             case 'D': parsed = (value.type == kDexAnnotationDouble);  break;
3698             case '[': parsed = (value.type == kDexAnnotationNull);    break;
3699             case 'L': {
3700                 switch (value.type) {
3701                     case kDexAnnotationNull: {
3702                         /* No need for further tests. */
3703                         break;
3704                     }
3705                     case kDexAnnotationString: {
3706                         parsed =
3707                             (strcmp(descriptor, "Ljava/lang/String;") == 0);
3708                         needRelease = true;
3709                         break;
3710                     }
3711                     case kDexAnnotationType: {
3712                         parsed =
3713                             (strcmp(descriptor, "Ljava/lang/Class;") == 0);
3714                         needRelease = true;
3715                         break;
3716                     }
3717                     default: {
3718                         parsed = false;
3719                         break;
3720                     }
3721                 }
3722                 break;
3723             }
3724             default: {
3725                 parsed = false;
3726                 break;
3727             }
3728         }
3729 
3730         if (parsed) {
3731             /*
3732              * All's well, so store the value. Note: This always
3733              * stores the full width of a JValue, even though most of
3734              * the time only the first word is needed.
3735              */
3736             sfield->value = value.value;
3737             if (needRelease) {
3738                 dvmReleaseTrackedAlloc(value.value.l, self);
3739             }
3740         } else {
3741             /*
3742              * Something up above had a problem. TODO: See comment
3743              * above the switch about verfication.
3744              */
3745             LOGE("Bogus static initialization: value type %d in field type "
3746                     "%s for %s at index %d",
3747                 value.type, descriptor, clazz->descriptor, i);
3748             dvmAbort();
3749         }
3750     }
3751 }
3752 
3753 
3754 /*
3755  * Determine whether "descriptor" yields the same class object in the
3756  * context of clazz1 and clazz2.
3757  *
3758  * The caller must hold gDvm.loadedClasses.
3759  *
3760  * Returns "true" if they match.
3761  */
compareDescriptorClasses(const char * descriptor,const ClassObject * clazz1,const ClassObject * clazz2)3762 static bool compareDescriptorClasses(const char* descriptor,
3763     const ClassObject* clazz1, const ClassObject* clazz2)
3764 {
3765     ClassObject* result1;
3766     ClassObject* result2;
3767 
3768     /*
3769      * Do the first lookup by name.
3770      */
3771     result1 = dvmFindClassNoInit(descriptor, clazz1->classLoader);
3772 
3773     /*
3774      * We can skip a second lookup by name if the second class loader is
3775      * in the initiating loader list of the class object we retrieved.
3776      * (This means that somebody already did a lookup of this class through
3777      * the second loader, and it resolved to the same class.)  If it's not
3778      * there, we may simply not have had an opportunity to add it yet, so
3779      * we do the full lookup.
3780      *
3781      * The initiating loader test should catch the majority of cases
3782      * (in particular, the zillions of references to String/Object).
3783      *
3784      * Unfortunately we're still stuck grabbing a mutex to do the lookup.
3785      *
3786      * For this to work, the superclass/interface should be the first
3787      * argument, so that way if it's from the bootstrap loader this test
3788      * will work.  (The bootstrap loader, by definition, never shows up
3789      * as the initiating loader of a class defined by some other loader.)
3790      */
3791     dvmHashTableLock(gDvm.loadedClasses);
3792     bool isInit = dvmLoaderInInitiatingList(result1, clazz2->classLoader);
3793     dvmHashTableUnlock(gDvm.loadedClasses);
3794 
3795     if (isInit) {
3796         //printf("%s(obj=%p) / %s(cl=%p): initiating\n",
3797         //    result1->descriptor, result1,
3798         //    clazz2->descriptor, clazz2->classLoader);
3799         return true;
3800     } else {
3801         //printf("%s(obj=%p) / %s(cl=%p): RAW\n",
3802         //    result1->descriptor, result1,
3803         //    clazz2->descriptor, clazz2->classLoader);
3804         result2 = dvmFindClassNoInit(descriptor, clazz2->classLoader);
3805     }
3806 
3807     if (result1 == NULL || result2 == NULL) {
3808         dvmClearException(dvmThreadSelf());
3809         if (result1 == result2) {
3810             /*
3811              * Neither class loader could find this class.  Apparently it
3812              * doesn't exist.
3813              *
3814              * We can either throw some sort of exception now, or just
3815              * assume that it'll fail later when something actually tries
3816              * to use the class.  For strict handling we should throw now,
3817              * because a "tricky" class loader could start returning
3818              * something later, and a pair of "tricky" loaders could set
3819              * us up for confusion.
3820              *
3821              * I'm not sure if we're allowed to complain about nonexistent
3822              * classes in method signatures during class init, so for now
3823              * this will just return "true" and let nature take its course.
3824              */
3825             return true;
3826         } else {
3827             /* only one was found, so clearly they're not the same */
3828             return false;
3829         }
3830     }
3831 
3832     return result1 == result2;
3833 }
3834 
3835 /*
3836  * For every component in the method descriptor, resolve the class in the
3837  * context of the two classes and compare the results.
3838  *
3839  * For best results, the "superclass" class should be first.
3840  *
3841  * Returns "true" if the classes match, "false" otherwise.
3842  */
checkMethodDescriptorClasses(const Method * meth,const ClassObject * clazz1,const ClassObject * clazz2)3843 static bool checkMethodDescriptorClasses(const Method* meth,
3844     const ClassObject* clazz1, const ClassObject* clazz2)
3845 {
3846     DexParameterIterator iterator;
3847     const char* descriptor;
3848 
3849     /* walk through the list of parameters */
3850     dexParameterIteratorInit(&iterator, &meth->prototype);
3851     while (true) {
3852         descriptor = dexParameterIteratorNextDescriptor(&iterator);
3853 
3854         if (descriptor == NULL)
3855             break;
3856 
3857         if (descriptor[0] == 'L' || descriptor[0] == '[') {
3858             /* non-primitive type */
3859             if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
3860                 return false;
3861         }
3862     }
3863 
3864     /* check the return type */
3865     descriptor = dexProtoGetReturnType(&meth->prototype);
3866     if (descriptor[0] == 'L' || descriptor[0] == '[') {
3867         if (!compareDescriptorClasses(descriptor, clazz1, clazz2))
3868             return false;
3869     }
3870     return true;
3871 }
3872 
3873 /*
3874  * Validate the descriptors in the superclass and interfaces.
3875  *
3876  * What we need to do is ensure that the classes named in the method
3877  * descriptors in our ancestors and ourselves resolve to the same class
3878  * objects.  The only time this matters is when the classes come from
3879  * different class loaders, and the resolver might come up with a
3880  * different answer for the same class name depending on context.
3881  *
3882  * We don't need to check to see if an interface's methods match with
3883  * its superinterface's methods, because you can't instantiate an
3884  * interface and do something inappropriate with it.  If interface I1
3885  * extends I2 and is implemented by C, and I1 and I2 are in separate
3886  * class loaders and have conflicting views of other classes, we will
3887  * catch the conflict when we process C.  Anything that implements I1 is
3888  * doomed to failure, but we don't need to catch that while processing I1.
3889  *
3890  * On failure, throws an exception and returns "false".
3891  */
validateSuperDescriptors(const ClassObject * clazz)3892 static bool validateSuperDescriptors(const ClassObject* clazz)
3893 {
3894     int i;
3895 
3896     if (dvmIsInterfaceClass(clazz))
3897         return true;
3898 
3899     /*
3900      * Start with the superclass-declared methods.
3901      */
3902     if (clazz->super != NULL &&
3903         clazz->classLoader != clazz->super->classLoader)
3904     {
3905         /*
3906          * Walk through every method declared in the superclass, and
3907          * compare resolved descriptor components.  We pull the Method
3908          * structs out of the vtable.  It doesn't matter whether we get
3909          * the struct from the parent or child, since we just need the
3910          * UTF-8 descriptor, which must match.
3911          *
3912          * We need to do this even for the stuff inherited from Object,
3913          * because it's possible that the new class loader has redefined
3914          * a basic class like String.
3915          */
3916         const Method* meth;
3917 
3918         //printf("Checking %s %p vs %s %p\n",
3919         //    clazz->descriptor, clazz->classLoader,
3920         //    clazz->super->descriptor, clazz->super->classLoader);
3921         for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
3922             meth = clazz->vtable[i];
3923             if (!checkMethodDescriptorClasses(meth, clazz->super, clazz)) {
3924                 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
3925                     meth->name, clazz->descriptor, clazz->classLoader,
3926                     clazz->super->descriptor, clazz->super->classLoader);
3927                 dvmThrowException("Ljava/lang/LinkageError;",
3928                     "Classes resolve differently in superclass");
3929                 return false;
3930             }
3931         }
3932     }
3933 
3934     /*
3935      * Check all interfaces we implement.
3936      */
3937     for (i = 0; i < clazz->iftableCount; i++) {
3938         const InterfaceEntry* iftable = &clazz->iftable[i];
3939 
3940         if (clazz->classLoader != iftable->clazz->classLoader) {
3941             const ClassObject* iface = iftable->clazz;
3942             int j;
3943 
3944             for (j = 0; j < iface->virtualMethodCount; j++) {
3945                 const Method* meth;
3946                 int vtableIndex;
3947 
3948                 vtableIndex = iftable->methodIndexArray[j];
3949                 meth = clazz->vtable[vtableIndex];
3950 
3951                 if (!checkMethodDescriptorClasses(meth, iface, clazz)) {
3952                     LOGW("Method mismatch: %s in %s (cl=%p) and "
3953                             "iface %s (cl=%p)\n",
3954                         meth->name, clazz->descriptor, clazz->classLoader,
3955                         iface->descriptor, iface->classLoader);
3956                     dvmThrowException("Ljava/lang/LinkageError;",
3957                         "Classes resolve differently in interface");
3958                     return false;
3959                 }
3960             }
3961         }
3962     }
3963 
3964     return true;
3965 }
3966 
3967 /*
3968  * Returns true if the class is being initialized by us (which means that
3969  * calling dvmInitClass will return immediately after fiddling with locks).
3970  *
3971  * There isn't a race here, because either clazz->initThreadId won't match
3972  * us, or it will and it was set in the same thread.
3973  */
dvmIsClassInitializing(const ClassObject * clazz)3974 bool dvmIsClassInitializing(const ClassObject* clazz)
3975 {
3976     return (clazz->status == CLASS_INITIALIZING &&
3977             clazz->initThreadId == dvmThreadSelf()->threadId);
3978 }
3979 
3980 /*
3981  * If a class has not been initialized, do so by executing the code in
3982  * <clinit>.  The sequence is described in the VM spec v2 2.17.5.
3983  *
3984  * It is possible for multiple threads to arrive here simultaneously, so
3985  * we need to lock the class while we check stuff.  We know that no
3986  * interpreted code has access to the class yet, so we can use the class's
3987  * monitor lock.
3988  *
3989  * We will often be called recursively, e.g. when the <clinit> code resolves
3990  * one of its fields, the field resolution will try to initialize the class.
3991  *
3992  * This can get very interesting if a class has a static field initialized
3993  * to a new instance of itself.  <clinit> will end up calling <init> on
3994  * the members it is initializing, which is fine unless it uses the contents
3995  * of static fields to initialize instance fields.  This will leave the
3996  * static-referenced objects in a partially initialized state.  This is
3997  * reasonably rare and can sometimes be cured with proper field ordering.
3998  *
3999  * On failure, returns "false" with an exception raised.
4000  *
4001  * -----
4002  *
4003  * It is possible to cause a deadlock by having a situation like this:
4004  *   class A { static { sleep(10000); new B(); } }
4005  *   class B { static { sleep(10000); new A(); } }
4006  *   new Thread() { public void run() { new A(); } }.start();
4007  *   new Thread() { public void run() { new B(); } }.start();
4008  * This appears to be expected under the spec.
4009  *
4010  * The interesting question is what to do if somebody calls Thread.interrupt()
4011  * on one of the deadlocked threads.  According to the VM spec, they're both
4012  * sitting in "wait".  Should the interrupt code quietly raise the
4013  * "interrupted" flag, or should the "wait" return immediately with an
4014  * exception raised?
4015  *
4016  * This gets a little murky.  The VM spec says we call "wait", and the
4017  * spec for Thread.interrupt says Object.wait is interruptible.  So it
4018  * seems that, if we get unlucky and interrupt class initialization, we
4019  * are expected to throw (which gets converted to ExceptionInInitializerError
4020  * since InterruptedException is checked).
4021  *
4022  * There are a couple of problems here.  First, all threads are expected to
4023  * present a consistent view of class initialization, so we can't have it
4024  * fail in one thread and succeed in another.  Second, once a class fails
4025  * to initialize, it must *always* fail.  This means that a stray interrupt()
4026  * call could render a class unusable for the lifetime of the VM.
4027  *
4028  * In most cases -- the deadlock example above being a counter-example --
4029  * the interrupting thread can't tell whether the target thread handled
4030  * the initialization itself or had to wait while another thread did the
4031  * work.  Refusing to interrupt class initialization is, in most cases,
4032  * not something that a program can reliably detect.
4033  *
4034  * On the assumption that interrupting class initialization is highly
4035  * undesirable in most circumstances, and that failing to do so does not
4036  * deviate from the spec in a meaningful way, we don't allow class init
4037  * to be interrupted by Thread.interrupt().
4038  */
dvmInitClass(ClassObject * clazz)4039 bool dvmInitClass(ClassObject* clazz)
4040 {
4041 #if LOG_CLASS_LOADING
4042     bool initializedByUs = false;
4043 #endif
4044 
4045     Thread* self = dvmThreadSelf();
4046     const Method* method;
4047 
4048     dvmLockObject(self, (Object*) clazz);
4049     assert(dvmIsClassLinked(clazz) || clazz->status == CLASS_ERROR);
4050 
4051     /*
4052      * If the class hasn't been verified yet, do so now.
4053      */
4054     if (clazz->status < CLASS_VERIFIED) {
4055         /*
4056          * If we're in an "erroneous" state, throw an exception and bail.
4057          */
4058         if (clazz->status == CLASS_ERROR) {
4059             throwEarlierClassFailure(clazz);
4060             goto bail_unlock;
4061         }
4062 
4063         assert(clazz->status == CLASS_RESOLVED);
4064         assert(!IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED));
4065 
4066         if (gDvm.classVerifyMode == VERIFY_MODE_NONE ||
4067             (gDvm.classVerifyMode == VERIFY_MODE_REMOTE &&
4068              clazz->classLoader == NULL))
4069         {
4070             LOGV("+++ not verifying class %s (cl=%p)\n",
4071                 clazz->descriptor, clazz->classLoader);
4072             goto noverify;
4073         }
4074 
4075         if (!gDvm.optimizing)
4076             LOGV("+++ late verify on %s\n", clazz->descriptor);
4077 
4078         /*
4079          * We're not supposed to optimize an unverified class, but during
4080          * development this mode was useful.  We can't verify an optimized
4081          * class because the optimization process discards information.
4082          */
4083         if (IS_CLASS_FLAG_SET(clazz, CLASS_ISOPTIMIZED)) {
4084             LOGW("Class '%s' was optimized without verification; "
4085                  "not verifying now\n",
4086                 clazz->descriptor);
4087             LOGW("  ('rm /data/dalvik-cache/*' and restart to fix this)");
4088             goto verify_failed;
4089         }
4090 
4091         clazz->status = CLASS_VERIFYING;
4092         if (!dvmVerifyClass(clazz, VERIFY_DEFAULT)) {
4093 verify_failed:
4094             dvmThrowExceptionWithClassMessage("Ljava/lang/VerifyError;",
4095                 clazz->descriptor);
4096             clazz->verifyErrorClass = dvmGetException(self)->clazz;
4097             clazz->status = CLASS_ERROR;
4098             goto bail_unlock;
4099         }
4100 
4101         clazz->status = CLASS_VERIFIED;
4102     }
4103 noverify:
4104 
4105     if (clazz->status == CLASS_INITIALIZED)
4106         goto bail_unlock;
4107 
4108     while (clazz->status == CLASS_INITIALIZING) {
4109         /* we caught somebody else in the act; was it us? */
4110         if (clazz->initThreadId == self->threadId) {
4111             //LOGV("HEY: found a recursive <clinit>\n");
4112             goto bail_unlock;
4113         }
4114 
4115         if (dvmCheckException(self)) {
4116             LOGW("GLITCH: exception pending at start of class init\n");
4117             dvmAbort();
4118         }
4119 
4120         /*
4121          * Wait for the other thread to finish initialization.  We pass
4122          * "false" for the "interruptShouldThrow" arg so it doesn't throw
4123          * an exception on interrupt.
4124          */
4125         dvmObjectWait(self, (Object*) clazz, 0, 0, false);
4126 
4127         /*
4128          * When we wake up, repeat the test for init-in-progress.  If there's
4129          * an exception pending (only possible if "interruptShouldThrow"
4130          * was set), bail out.
4131          */
4132         if (dvmCheckException(self)) {
4133             LOGI("Class init of '%s' failing with wait() exception\n",
4134                 clazz->descriptor);
4135             /*
4136              * TODO: this is bogus, because it means the two threads have a
4137              * different idea of the class status.  We need to flag the
4138              * class as bad and ensure that the initializer thread respects
4139              * our notice.  If we get lucky and wake up after the class has
4140              * finished initialization but before being woken, we have to
4141              * swallow the exception, perhaps raising thread->interrupted
4142              * to preserve semantics.
4143              *
4144              * Since we're not currently allowing interrupts, this should
4145              * never happen and we don't need to fix this.
4146              */
4147             assert(false);
4148             throwClinitError();
4149             clazz->status = CLASS_ERROR;
4150             goto bail_unlock;
4151         }
4152         if (clazz->status == CLASS_INITIALIZING) {
4153             LOGI("Waiting again for class init\n");
4154             continue;
4155         }
4156         assert(clazz->status == CLASS_INITIALIZED ||
4157                clazz->status == CLASS_ERROR);
4158         if (clazz->status == CLASS_ERROR) {
4159             /*
4160              * The caller wants an exception, but it was thrown in a
4161              * different thread.  Synthesize one here.
4162              */
4163             dvmThrowException("Ljava/lang/UnsatisfiedLinkError;",
4164                 "(<clinit> failed, see exception in other thread)");
4165         }
4166         goto bail_unlock;
4167     }
4168 
4169     /* see if we failed previously */
4170     if (clazz->status == CLASS_ERROR) {
4171         // might be wise to unlock before throwing; depends on which class
4172         // it is that we have locked
4173         dvmUnlockObject(self, (Object*) clazz);
4174         throwEarlierClassFailure(clazz);
4175         return false;
4176     }
4177 
4178     /*
4179      * We're ready to go, and have exclusive access to the class.
4180      *
4181      * Before we start initialization, we need to do one extra bit of
4182      * validation: make sure that the methods declared here match up
4183      * with our superclass and interfaces.  We know that the UTF-8
4184      * descriptors match, but classes from different class loaders can
4185      * have the same name.
4186      *
4187      * We do this now, rather than at load/link time, for the same reason
4188      * that we defer verification.
4189      *
4190      * It's unfortunate that we need to do this at all, but we risk
4191      * mixing reference types with identical names (see Dalvik test 068).
4192      */
4193     if (!validateSuperDescriptors(clazz)) {
4194         assert(dvmCheckException(self));
4195         clazz->status = CLASS_ERROR;
4196         goto bail_unlock;
4197     }
4198 
4199     /*
4200      * Let's initialize this thing.
4201      *
4202      * We unlock the object so that other threads can politely sleep on
4203      * our mutex with Object.wait(), instead of hanging or spinning trying
4204      * to grab our mutex.
4205      */
4206     assert(clazz->status < CLASS_INITIALIZING);
4207 
4208 #if LOG_CLASS_LOADING
4209     // We started initializing.
4210     logClassLoad('+', clazz);
4211     initializedByUs = true;
4212 #endif
4213 
4214     clazz->status = CLASS_INITIALIZING;
4215     clazz->initThreadId = self->threadId;
4216     dvmUnlockObject(self, (Object*) clazz);
4217 
4218     /* init our superclass */
4219     if (clazz->super != NULL && clazz->super->status != CLASS_INITIALIZED) {
4220         assert(!dvmIsInterfaceClass(clazz));
4221         if (!dvmInitClass(clazz->super)) {
4222             assert(dvmCheckException(self));
4223             clazz->status = CLASS_ERROR;
4224             /* wake up anybody who started waiting while we were unlocked */
4225             dvmLockObject(self, (Object*) clazz);
4226             goto bail_notify;
4227         }
4228     }
4229 
4230     /* Initialize any static fields whose values are
4231      * stored in the Dex file.  This should include all of the
4232      * simple "final static" fields, which are required to
4233      * be initialized first. (vmspec 2 sec 2.17.5 item 8)
4234      * More-complicated final static fields should be set
4235      * at the beginning of <clinit>;  all we can do is trust
4236      * that the compiler did the right thing.
4237      */
4238     initSFields(clazz);
4239 
4240     /* Execute any static initialization code.
4241      */
4242     method = dvmFindDirectMethodByDescriptor(clazz, "<clinit>", "()V");
4243     if (method == NULL) {
4244         LOGVV("No <clinit> found for %s\n", clazz->descriptor);
4245     } else {
4246         LOGVV("Invoking %s.<clinit>\n", clazz->descriptor);
4247         JValue unused;
4248         dvmCallMethod(self, method, NULL, &unused);
4249     }
4250 
4251     if (dvmCheckException(self)) {
4252         /*
4253          * We've had an exception thrown during static initialization.  We
4254          * need to throw an ExceptionInInitializerError, but we want to
4255          * tuck the original exception into the "cause" field.
4256          */
4257         LOGW("Exception %s thrown during %s.<clinit>\n",
4258             (dvmGetException(self)->clazz)->descriptor, clazz->descriptor);
4259         throwClinitError();
4260         //LOGW("+++ replaced\n");
4261 
4262         dvmLockObject(self, (Object*) clazz);
4263         clazz->status = CLASS_ERROR;
4264     } else {
4265         /* success! */
4266         dvmLockObject(self, (Object*) clazz);
4267         clazz->status = CLASS_INITIALIZED;
4268         LOGVV("Initialized class: %s\n", clazz->descriptor);
4269     }
4270 
4271 bail_notify:
4272     /*
4273      * Notify anybody waiting on the object.
4274      */
4275     dvmObjectNotifyAll(self, (Object*) clazz);
4276 
4277 bail_unlock:
4278 
4279 #if LOG_CLASS_LOADING
4280     if (initializedByUs) {
4281         // We finished initializing.
4282         logClassLoad('-', clazz);
4283     }
4284 #endif
4285 
4286     dvmUnlockObject(self, (Object*) clazz);
4287 
4288     return (clazz->status != CLASS_ERROR);
4289 }
4290 
4291 /*
4292  * Replace method->nativeFunc and method->insns with new values.  This is
4293  * performed on resolution of a native method.
4294  */
dvmSetNativeFunc(const Method * method,DalvikBridgeFunc func,const u2 * insns)4295 void dvmSetNativeFunc(const Method* method, DalvikBridgeFunc func,
4296     const u2* insns)
4297 {
4298     ClassObject* clazz = method->clazz;
4299 
4300     /* just open up both; easier that way */
4301     dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4302     dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4303 
4304     ((Method*)method)->nativeFunc = func;
4305     ((Method*)method)->insns = insns;
4306 
4307     dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4308     dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4309 }
4310 
4311 /*
4312  * Add a RegisterMap to a Method.  This is done when we verify the class
4313  * and compute the register maps at class initialization time, which means
4314  * that "pMap" is on the heap and should be freed when the Method is
4315  * discarded.
4316  */
dvmSetRegisterMap(Method * method,const RegisterMap * pMap)4317 void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
4318 {
4319     ClassObject* clazz = method->clazz;
4320 
4321     if (method->registerMap != NULL) {
4322         LOGW("WARNING: registerMap already set for %s.%s\n",
4323             method->clazz->descriptor, method->name);
4324         /* keep going */
4325     }
4326 
4327     /* might be virtual or direct */
4328     dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
4329     dvmLinearReadWrite(clazz->classLoader, clazz->directMethods);
4330 
4331     method->registerMap = pMap;
4332 
4333     dvmLinearReadOnly(clazz->classLoader, clazz->virtualMethods);
4334     dvmLinearReadOnly(clazz->classLoader, clazz->directMethods);
4335 }
4336 
4337 /*
4338  * dvmHashForeach callback.  A nonzero return value causes foreach to
4339  * bail out.
4340  */
findClassCallback(void * vclazz,void * arg)4341 static int findClassCallback(void* vclazz, void* arg)
4342 {
4343     ClassObject* clazz = vclazz;
4344     const char* descriptor = (const char*) arg;
4345 
4346     if (strcmp(clazz->descriptor, descriptor) == 0)
4347         return (int) clazz;
4348     return 0;
4349 }
4350 
4351 /*
4352  * Find a loaded class by descriptor. Returns the first one found.
4353  * Because there can be more than one if class loaders are involved,
4354  * this is not an especially good API. (Currently only used by the
4355  * debugger and "checking" JNI.)
4356  *
4357  * "descriptor" should have the form "Ljava/lang/Class;" or
4358  * "[Ljava/lang/Class;", i.e. a descriptor and not an internal-form
4359  * class name.
4360  */
dvmFindLoadedClass(const char * descriptor)4361 ClassObject* dvmFindLoadedClass(const char* descriptor)
4362 {
4363     int result;
4364 
4365     dvmHashTableLock(gDvm.loadedClasses);
4366     result = dvmHashForeach(gDvm.loadedClasses, findClassCallback,
4367             (void*) descriptor);
4368     dvmHashTableUnlock(gDvm.loadedClasses);
4369 
4370     return (ClassObject*) result;
4371 }
4372 
4373 /*
4374  * Retrieve the system (a/k/a application) class loader.
4375  */
dvmGetSystemClassLoader(void)4376 Object* dvmGetSystemClassLoader(void)
4377 {
4378     ClassObject* clazz;
4379     Method* getSysMeth;
4380     Object* loader;
4381 
4382     clazz = dvmFindSystemClass("Ljava/lang/ClassLoader;");
4383     if (clazz == NULL)
4384         return NULL;
4385 
4386     getSysMeth = dvmFindDirectMethodByDescriptor(clazz, "getSystemClassLoader",
4387         "()Ljava/lang/ClassLoader;");
4388     if (getSysMeth == NULL)
4389         return NULL;
4390 
4391     JValue result;
4392     dvmCallMethod(dvmThreadSelf(), getSysMeth, NULL, &result);
4393     loader = (Object*)result.l;
4394     return loader;
4395 }
4396 
4397 
4398 /*
4399  * This is a dvmHashForeach callback.
4400  */
dumpClass(void * vclazz,void * varg)4401 static int dumpClass(void* vclazz, void* varg)
4402 {
4403     const ClassObject* clazz = (const ClassObject*) vclazz;
4404     const ClassObject* super;
4405     int flags = (int) varg;
4406     char* desc;
4407     int i;
4408 
4409     if (clazz == NULL) {
4410         LOGI("dumpClass: ignoring request to dump null class\n");
4411         return 0;
4412     }
4413 
4414     if ((flags & kDumpClassFullDetail) == 0) {
4415         bool showInit = (flags & kDumpClassInitialized) != 0;
4416         bool showLoader = (flags & kDumpClassClassLoader) != 0;
4417         const char* initStr;
4418 
4419         initStr = dvmIsClassInitialized(clazz) ? "true" : "false";
4420 
4421         if (showInit && showLoader)
4422             LOGI("%s %p %s\n", clazz->descriptor, clazz->classLoader, initStr);
4423         else if (showInit)
4424             LOGI("%s %s\n", clazz->descriptor, initStr);
4425         else if (showLoader)
4426             LOGI("%s %p\n", clazz->descriptor, clazz->classLoader);
4427         else
4428             LOGI("%s\n", clazz->descriptor);
4429 
4430         return 0;
4431     }
4432 
4433     /* clazz->super briefly holds the superclass index during class prep */
4434     if ((u4)clazz->super > 0x10000 && (u4) clazz->super != (u4)-1)
4435         super = clazz->super;
4436     else
4437         super = NULL;
4438 
4439     LOGI("----- %s '%s' cl=%p ser=0x%08x -----\n",
4440         dvmIsInterfaceClass(clazz) ? "interface" : "class",
4441         clazz->descriptor, clazz->classLoader, clazz->serialNumber);
4442     LOGI("  objectSize=%d (%d from super)\n", (int) clazz->objectSize,
4443         super != NULL ? (int) super->objectSize : -1);
4444     LOGI("  access=0x%04x.%04x\n", clazz->accessFlags >> 16,
4445         clazz->accessFlags & JAVA_FLAGS_MASK);
4446     if (super != NULL)
4447         LOGI("  super='%s' (cl=%p)\n", super->descriptor, super->classLoader);
4448     if (dvmIsArrayClass(clazz)) {
4449         LOGI("  dimensions=%d elementClass=%s\n",
4450             clazz->arrayDim, clazz->elementClass->descriptor);
4451     }
4452     if (clazz->iftableCount > 0) {
4453         LOGI("  interfaces (%d):\n", clazz->iftableCount);
4454         for (i = 0; i < clazz->iftableCount; i++) {
4455             InterfaceEntry* ent = &clazz->iftable[i];
4456             int j;
4457 
4458             LOGI("    %2d: %s (cl=%p)\n",
4459                 i, ent->clazz->descriptor, ent->clazz->classLoader);
4460 
4461             /* enable when needed */
4462             if (false && ent->methodIndexArray != NULL) {
4463                 for (j = 0; j < ent->clazz->virtualMethodCount; j++)
4464                     LOGI("      %2d: %d %s %s\n",
4465                         j, ent->methodIndexArray[j],
4466                         ent->clazz->virtualMethods[j].name,
4467                         clazz->vtable[ent->methodIndexArray[j]]->name);
4468             }
4469         }
4470     }
4471     if (!dvmIsInterfaceClass(clazz)) {
4472         LOGI("  vtable (%d entries, %d in super):\n", clazz->vtableCount,
4473             super != NULL ? super->vtableCount : 0);
4474         for (i = 0; i < clazz->vtableCount; i++) {
4475             desc = dexProtoCopyMethodDescriptor(&clazz->vtable[i]->prototype);
4476             LOGI("    %s%2d: %p %20s %s\n",
4477                 (i != clazz->vtable[i]->methodIndex) ? "*** " : "",
4478                 (u4) clazz->vtable[i]->methodIndex, clazz->vtable[i],
4479                 clazz->vtable[i]->name, desc);
4480             free(desc);
4481         }
4482         LOGI("  direct methods (%d entries):\n", clazz->directMethodCount);
4483         for (i = 0; i < clazz->directMethodCount; i++) {
4484             desc = dexProtoCopyMethodDescriptor(
4485                     &clazz->directMethods[i].prototype);
4486             LOGI("    %2d: %20s %s\n", i, clazz->directMethods[i].name,
4487                 desc);
4488             free(desc);
4489         }
4490     } else {
4491         LOGI("  interface methods (%d):\n", clazz->virtualMethodCount);
4492         for (i = 0; i < clazz->virtualMethodCount; i++) {
4493             desc = dexProtoCopyMethodDescriptor(
4494                     &clazz->virtualMethods[i].prototype);
4495             LOGI("    %2d: %2d %20s %s\n", i,
4496                 (u4) clazz->virtualMethods[i].methodIndex,
4497                 clazz->virtualMethods[i].name,
4498                 desc);
4499             free(desc);
4500         }
4501     }
4502     if (clazz->sfieldCount > 0) {
4503         LOGI("  static fields (%d entries):\n", clazz->sfieldCount);
4504         for (i = 0; i < clazz->sfieldCount; i++) {
4505             LOGI("    %2d: %20s %s\n", i, clazz->sfields[i].field.name,
4506                 clazz->sfields[i].field.signature);
4507         }
4508     }
4509     if (clazz->ifieldCount > 0) {
4510         LOGI("  instance fields (%d entries):\n", clazz->ifieldCount);
4511         for (i = 0; i < clazz->ifieldCount; i++) {
4512             LOGI("    %2d: %20s %s\n", i, clazz->ifields[i].field.name,
4513                 clazz->ifields[i].field.signature);
4514         }
4515     }
4516     return 0;
4517 }
4518 
4519 /*
4520  * Dump the contents of a single class.
4521  *
4522  * Pass kDumpClassFullDetail into "flags" to get lots of detail.
4523  */
dvmDumpClass(const ClassObject * clazz,int flags)4524 void dvmDumpClass(const ClassObject* clazz, int flags)
4525 {
4526     dumpClass((void*) clazz, (void*) flags);
4527 }
4528 
4529 /*
4530  * Dump the contents of all classes.
4531  */
dvmDumpAllClasses(int flags)4532 void dvmDumpAllClasses(int flags)
4533 {
4534     dvmHashTableLock(gDvm.loadedClasses);
4535     dvmHashForeach(gDvm.loadedClasses, dumpClass, (void*) flags);
4536     dvmHashTableUnlock(gDvm.loadedClasses);
4537 }
4538 
4539 /*
4540  * Get the number of loaded classes
4541  */
dvmGetNumLoadedClasses()4542 int dvmGetNumLoadedClasses()
4543 {
4544     int count;
4545     dvmHashTableLock(gDvm.loadedClasses);
4546     count = dvmHashTableNumEntries(gDvm.loadedClasses);
4547     dvmHashTableUnlock(gDvm.loadedClasses);
4548     return count;
4549 }
4550 
4551 /*
4552  * Write some statistics to the log file.
4553  */
dvmDumpLoaderStats(const char * msg)4554 void dvmDumpLoaderStats(const char* msg)
4555 {
4556     LOGV("VM stats (%s): cls=%d/%d meth=%d ifld=%d sfld=%d linear=%d\n",
4557         msg, gDvm.numLoadedClasses, dvmHashTableNumEntries(gDvm.loadedClasses),
4558         gDvm.numDeclaredMethods, gDvm.numDeclaredInstFields,
4559         gDvm.numDeclaredStaticFields, gDvm.pBootLoaderAlloc->curOffset);
4560 #ifdef COUNT_PRECISE_METHODS
4561     LOGI("GC precise methods: %d\n",
4562         dvmPointerSetGetCount(gDvm.preciseMethods));
4563 #endif
4564 }
4565 
4566 #ifdef PROFILE_FIELD_ACCESS
4567 /*
4568  * Dump the field access counts for all fields in this method.
4569  */
dumpAccessCounts(void * vclazz,void * varg)4570 static int dumpAccessCounts(void* vclazz, void* varg)
4571 {
4572     const ClassObject* clazz = (const ClassObject*) vclazz;
4573     int i;
4574 
4575     for (i = 0; i < clazz->ifieldCount; i++) {
4576         Field* field = &clazz->ifields[i].field;
4577 
4578         if (field->gets != 0)
4579             printf("GI %d %s.%s\n", field->gets,
4580                 field->clazz->descriptor, field->name);
4581         if (field->puts != 0)
4582             printf("PI %d %s.%s\n", field->puts,
4583                 field->clazz->descriptor, field->name);
4584     }
4585     for (i = 0; i < clazz->sfieldCount; i++) {
4586         Field* field = &clazz->sfields[i].field;
4587 
4588         if (field->gets != 0)
4589             printf("GS %d %s.%s\n", field->gets,
4590                 field->clazz->descriptor, field->name);
4591         if (field->puts != 0)
4592             printf("PS %d %s.%s\n", field->puts,
4593                 field->clazz->descriptor, field->name);
4594     }
4595 
4596     return 0;
4597 }
4598 
4599 /*
4600  * Dump the field access counts for all loaded classes.
4601  */
dvmDumpFieldAccessCounts(void)4602 void dvmDumpFieldAccessCounts(void)
4603 {
4604     dvmHashTableLock(gDvm.loadedClasses);
4605     dvmHashForeach(gDvm.loadedClasses, dumpAccessCounts, NULL);
4606     dvmHashTableUnlock(gDvm.loadedClasses);
4607 }
4608 #endif
4609 
4610 
4611 /*
4612  * Mark all classes associated with the built-in loader.
4613  */
markClassObject(void * clazz,void * arg)4614 static int markClassObject(void *clazz, void *arg)
4615 {
4616     UNUSED_PARAMETER(arg);
4617 
4618     dvmMarkObjectNonNull((Object *)clazz);
4619     return 0;
4620 }
4621 
4622 /*
4623  * The garbage collector calls this to mark the class objects for all
4624  * loaded classes.
4625  */
dvmGcScanRootClassLoader()4626 void dvmGcScanRootClassLoader()
4627 {
4628     /* dvmClassStartup() may not have been called before the first GC.
4629      */
4630     if (gDvm.loadedClasses != NULL) {
4631         dvmHashTableLock(gDvm.loadedClasses);
4632         dvmHashForeach(gDvm.loadedClasses, markClassObject, NULL);
4633         dvmHashTableUnlock(gDvm.loadedClasses);
4634     }
4635 }
4636 
4637 
4638 /*
4639  * ===========================================================================
4640  *      Method Prototypes and Descriptors
4641  * ===========================================================================
4642  */
4643 
4644 /*
4645  * Compare the two method names and prototypes, a la strcmp(). The
4646  * name is considered the "major" order and the prototype the "minor"
4647  * order. The prototypes are compared as if by dvmCompareMethodProtos().
4648  */
dvmCompareMethodNamesAndProtos(const Method * method1,const Method * method2)4649 int dvmCompareMethodNamesAndProtos(const Method* method1,
4650         const Method* method2)
4651 {
4652     int result = strcmp(method1->name, method2->name);
4653 
4654     if (result != 0) {
4655         return result;
4656     }
4657 
4658     return dvmCompareMethodProtos(method1, method2);
4659 }
4660 
4661 /*
4662  * Compare the two method names and prototypes, a la strcmp(), ignoring
4663  * the return value. The name is considered the "major" order and the
4664  * prototype the "minor" order. The prototypes are compared as if by
4665  * dvmCompareMethodArgProtos().
4666  */
dvmCompareMethodNamesAndParameterProtos(const Method * method1,const Method * method2)4667 int dvmCompareMethodNamesAndParameterProtos(const Method* method1,
4668         const Method* method2)
4669 {
4670     int result = strcmp(method1->name, method2->name);
4671 
4672     if (result != 0) {
4673         return result;
4674     }
4675 
4676     return dvmCompareMethodParameterProtos(method1, method2);
4677 }
4678 
4679 /*
4680  * Compare a (name, prototype) pair with the (name, prototype) of
4681  * a method, a la strcmp(). The name is considered the "major" order and
4682  * the prototype the "minor" order. The descriptor and prototype are
4683  * compared as if by dvmCompareDescriptorAndMethodProto().
4684  */
dvmCompareNameProtoAndMethod(const char * name,const DexProto * proto,const Method * method)4685 int dvmCompareNameProtoAndMethod(const char* name,
4686     const DexProto* proto, const Method* method)
4687 {
4688     int result = strcmp(name, method->name);
4689 
4690     if (result != 0) {
4691         return result;
4692     }
4693 
4694     return dexProtoCompare(proto, &method->prototype);
4695 }
4696 
4697 /*
4698  * Compare a (name, method descriptor) pair with the (name, prototype) of
4699  * a method, a la strcmp(). The name is considered the "major" order and
4700  * the prototype the "minor" order. The descriptor and prototype are
4701  * compared as if by dvmCompareDescriptorAndMethodProto().
4702  */
dvmCompareNameDescriptorAndMethod(const char * name,const char * descriptor,const Method * method)4703 int dvmCompareNameDescriptorAndMethod(const char* name,
4704     const char* descriptor, const Method* method)
4705 {
4706     int result = strcmp(name, method->name);
4707 
4708     if (result != 0) {
4709         return result;
4710     }
4711 
4712     return dvmCompareDescriptorAndMethodProto(descriptor, method);
4713 }
4714