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 * Convert the output from "dx" into a locally-optimized DEX file.
19 *
20 * TODO: the format of the optimized header is currently "whatever we
21 * happen to write", since the VM that writes it is by definition the same
22 * as the VM that reads it.  Still, it should be better documented and
23 * more rigorously structured.
24 */
25#include "Dalvik.h"
26#include "libdex/InstrUtils.h"
27#include "libdex/OptInvocation.h"
28#include "analysis/RegisterMap.h"
29
30#include <zlib.h>
31
32#include <stdlib.h>
33#include <unistd.h>
34#include <sys/mman.h>
35#include <sys/stat.h>
36#include <sys/file.h>
37#include <sys/wait.h>
38#include <fcntl.h>
39#include <errno.h>
40
41/*
42 * Virtual/direct calls to "method" are replaced with an execute-inline
43 * instruction with index "idx".
44 */
45typedef struct InlineSub {
46    Method* method;
47    int     inlineIdx;
48} InlineSub;
49
50
51/* fwd */
52static int writeDependencies(int fd, u4 modWhen, u4 crc);
53static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\
54    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder);
55static void logFailedWrite(size_t expected, ssize_t actual, const char* msg,
56    int err);
57static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum);
58
59static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,\
60    u4* pHeaderFlags, DexClassLookup** ppClassLookup);
61static void updateChecksum(u1* addr, int len, DexHeader* pHeader);
62static bool loadAllClasses(DvmDex* pDvmDex);
63static void optimizeLoadedClasses(DexFile* pDexFile);
64static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs);
65static bool optimizeMethod(Method* method, const InlineSub* inlineSubs);
66static void rewriteInstField(Method* method, u2* insns, OpCode newOpc);
67static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc);
68static bool rewriteEmptyDirectInvoke(Method* method, u2* insns);
69static bool rewriteExecuteInline(Method* method, u2* insns,
70    MethodType methodType, const InlineSub* inlineSubs);
71static bool rewriteExecuteInlineRange(Method* method, u2* insns,
72    MethodType methodType, const InlineSub* inlineSubs);
73
74
75/*
76 * Return the fd of an open file in the DEX file cache area.  If the cache
77 * file doesn't exist or is out of date, this will remove the old entry,
78 * create a new one (writing only the file header), and return with the
79 * "new file" flag set.
80 *
81 * It's possible to execute from an unoptimized DEX file directly,
82 * assuming the byte ordering and structure alignment is correct, but
83 * disadvantageous because some significant optimizations are not possible.
84 * It's not generally possible to do the same from an uncompressed Jar
85 * file entry, because we have to guarantee 32-bit alignment in the
86 * memory-mapped file.
87 *
88 * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen"
89 * and "crc32" come from the Zip directory entry.  For a stand-alone DEX
90 * file, it's the modification date of the file and the Adler32 from the
91 * DEX header (which immediately follows the magic).  If these don't
92 * match what's stored in the opt header, we reject the file immediately.
93 *
94 * On success, the file descriptor will be positioned just past the "opt"
95 * file header, and will be locked with flock.  "*pCachedName" will point
96 * to newly-allocated storage.
97 */
98int dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName,
99    u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing)
100{
101    int fd, cc;
102    struct stat fdStat, fileStat;
103    bool readOnly = false;
104
105    *pNewFile = false;
106
107retry:
108    /*
109     * Try to open the cache file.  If we've been asked to,
110     * create it if it doesn't exist.
111     */
112    fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
113    if (fd < 0) {
114        fd = open(cacheFileName, O_RDONLY, 0);
115        if (fd < 0) {
116            if (createIfMissing) {
117                LOGE("Can't open dex cache '%s': %s\n",
118                    cacheFileName, strerror(errno));
119            }
120            return fd;
121        }
122        readOnly = true;
123    }
124
125    /*
126     * Grab an exclusive lock on the cache file.  If somebody else is
127     * working on it, we'll block here until they complete.  Because
128     * we're waiting on an external resource, we go into VMWAIT mode.
129     */
130    int oldStatus;
131    LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n",
132        cacheFileName, fd, isBootstrap);
133    oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
134    cc = flock(fd, LOCK_EX | LOCK_NB);
135    if (cc != 0) {
136        LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName);
137        cc = flock(fd, LOCK_EX);
138    }
139    dvmChangeStatus(NULL, oldStatus);
140    if (cc != 0) {
141        LOGE("Can't lock dex cache '%s': %d\n", cacheFileName, cc);
142        close(fd);
143        return -1;
144    }
145    LOGV("DexOpt:  locked cache file\n");
146
147    /*
148     * Check to see if the fd we opened and locked matches the file in
149     * the filesystem.  If they don't, then somebody else unlinked ours
150     * and created a new file, and we need to use that one instead.  (If
151     * we caught them between the unlink and the create, we'll get an
152     * ENOENT from the file stat.)
153     */
154    cc = fstat(fd, &fdStat);
155    if (cc != 0) {
156        LOGE("Can't stat open file '%s'\n", cacheFileName);
157        LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
158        goto close_fail;
159    }
160    cc = stat(cacheFileName, &fileStat);
161    if (cc != 0 ||
162        fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino)
163    {
164        LOGD("DexOpt: our open cache file is stale; sleeping and retrying\n");
165        LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
166        flock(fd, LOCK_UN);
167        close(fd);
168        usleep(250 * 1000);     /* if something is hosed, don't peg machine */
169        goto retry;
170    }
171
172    /*
173     * We have the correct file open and locked.  If the file size is zero,
174     * then it was just created by us, and we want to fill in some fields
175     * in the "opt" header and set "*pNewFile".  Otherwise, we want to
176     * verify that the fields in the header match our expectations, and
177     * reset the file if they don't.
178     */
179    if (fdStat.st_size == 0) {
180        if (readOnly) {
181            LOGW("DexOpt: file has zero length and isn't writable\n");
182            goto close_fail;
183        }
184        cc = dexOptCreateEmptyHeader(fd);
185        if (cc != 0)
186            goto close_fail;
187        *pNewFile = true;
188        LOGV("DexOpt: successfully initialized new cache file\n");
189    } else {
190        bool expectVerify, expectOpt;
191
192        if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
193            expectVerify = false;
194        else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
195            expectVerify = !isBootstrap;
196        else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
197            expectVerify = true;
198
199        if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
200            expectOpt = false;
201        else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
202            expectOpt = expectVerify;
203        else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
204            expectOpt = true;
205
206        LOGV("checking deps, expecting vfy=%d opt=%d\n",
207            expectVerify, expectOpt);
208
209        if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc,
210                expectVerify, expectOpt))
211        {
212            if (readOnly) {
213                /*
214                 * We could unlink and rewrite the file if we own it or
215                 * the "sticky" bit isn't set on the directory.  However,
216                 * we're not able to truncate it, which spoils things.  So,
217                 * give up now.
218                 */
219                if (createIfMissing) {
220                    LOGW("Cached DEX '%s' (%s) is stale and not writable\n",
221                        fileName, cacheFileName);
222                }
223                goto close_fail;
224            }
225
226            /*
227             * If we truncate the existing file before unlinking it, any
228             * process that has it mapped will fail when it tries to touch
229             * the pages.
230             *
231             * This is very important.  The zygote process will have the
232             * boot DEX files (core, framework, etc.) mapped early.  If
233             * (say) core.dex gets updated, and somebody launches an app
234             * that uses App.dex, then App.dex gets reoptimized because it's
235             * dependent upon the boot classes.  However, dexopt will be
236             * using the *new* core.dex to do the optimizations, while the
237             * app will actually be running against the *old* core.dex
238             * because it starts from zygote.
239             *
240             * Even without zygote, it's still possible for a class loader
241             * to pull in an APK that was optimized against an older set
242             * of DEX files.  We must ensure that everything fails when a
243             * boot DEX gets updated, and for general "why aren't my
244             * changes doing anything" purposes its best if we just make
245             * everything crash when a DEX they're using gets updated.
246             */
247            LOGD("Stale deps in cache file; removing and retrying\n");
248            if (ftruncate(fd, 0) != 0) {
249                LOGW("Warning: unable to truncate cache file '%s': %s\n",
250                    cacheFileName, strerror(errno));
251                /* keep going */
252            }
253            if (unlink(cacheFileName) != 0) {
254                LOGW("Warning: unable to remove cache file '%s': %d %s\n",
255                    cacheFileName, errno, strerror(errno));
256                /* keep going; permission failure should probably be fatal */
257            }
258            LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
259            flock(fd, LOCK_UN);
260            close(fd);
261            goto retry;
262        } else {
263            LOGV("DexOpt: good deps in cache file\n");
264        }
265    }
266
267    assert(fd >= 0);
268    return fd;
269
270close_fail:
271    flock(fd, LOCK_UN);
272    close(fd);
273    return -1;
274}
275
276/*
277 * Unlock the file descriptor.
278 *
279 * Returns "true" on success.
280 */
281bool dvmUnlockCachedDexFile(int fd)
282{
283    LOGVV("DexOpt: unlocking cache file fd=%d\n", fd);
284    return (flock(fd, LOCK_UN) == 0);
285}
286
287
288/*
289 * Given a descriptor for a file with DEX data in it, produce an
290 * optimized version.
291 *
292 * The file pointed to by "fd" is expected to be a locked shared resource
293 * (or private); we make no efforts to enforce multi-process correctness
294 * here.
295 *
296 * "fileName" is only used for debug output.  "modWhen" and "crc" are stored
297 * in the dependency set.
298 *
299 * The "isBootstrap" flag determines how the optimizer and verifier handle
300 * package-scope access checks.  When optimizing, we only load the bootstrap
301 * class DEX files and the target DEX, so the flag determines whether the
302 * target DEX classes are given a (synthetic) non-NULL classLoader pointer.
303 * This only really matters if the target DEX contains classes that claim to
304 * be in the same package as bootstrap classes.
305 *
306 * The optimizer will need to load every class in the target DEX file.
307 * This is generally undesirable, so we start a subprocess to do the
308 * work and wait for it to complete.
309 *
310 * Returns "true" on success.  All data will have been written to "fd".
311 */
312bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength,
313    const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
314{
315    const char* lastPart = strrchr(fileName, '/');
316    if (lastPart != NULL)
317        lastPart++;
318    else
319        lastPart = fileName;
320
321    /*
322     * For basic optimizations (byte-swapping and structure aligning) we
323     * don't need to fork().  It looks like fork+exec is causing problems
324     * with gdb on our bewildered Linux distro, so in some situations we
325     * want to avoid this.
326     *
327     * For optimization and/or verification, we need to load all the classes.
328     *
329     * We don't check gDvm.generateRegisterMaps, since that is dependent
330     * upon the verifier state.
331     */
332    if (gDvm.classVerifyMode == VERIFY_MODE_NONE &&
333        (gDvm.dexOptMode == OPTIMIZE_MODE_NONE ||
334         gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED))
335    {
336        LOGD("DexOpt: --- BEGIN (quick) '%s' ---\n", lastPart);
337        return dvmContinueOptimization(fd, dexOffset, dexLength,
338                fileName, modWhen, crc, isBootstrap);
339    }
340
341
342    LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap);
343
344    pid_t pid;
345
346    /*
347     * This could happen if something in our bootclasspath, which we thought
348     * was all optimized, got rejected.
349     */
350    if (gDvm.optimizing) {
351        LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName);
352        return false;
353    }
354
355    pid = fork();
356    if (pid == 0) {
357        static const int kUseValgrind = 0;
358        static const char* kDexOptBin = "/bin/dexopt";
359        static const char* kValgrinder = "/usr/bin/valgrind";
360        static const int kFixedArgCount = 10;
361        static const int kValgrindArgCount = 5;
362        static const int kMaxIntLen = 12;   // '-'+10dig+'\0' -OR- 0x+8dig
363        int bcpSize = dvmGetBootPathSize();
364        int argc = kFixedArgCount + bcpSize
365            + (kValgrindArgCount * kUseValgrind);
366        char* argv[argc+1];             // last entry is NULL
367        char values[argc][kMaxIntLen];
368        char* execFile;
369        char* androidRoot;
370        int flags;
371
372        /* change process groups, so we don't clash with ProcessManager */
373        setpgid(0, 0);
374
375        /* full path to optimizer */
376        androidRoot = getenv("ANDROID_ROOT");
377        if (androidRoot == NULL) {
378            LOGW("ANDROID_ROOT not set, defaulting to /system\n");
379            androidRoot = "/system";
380        }
381        execFile = malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1);
382        strcpy(execFile, androidRoot);
383        strcat(execFile, kDexOptBin);
384
385        /*
386         * Create arg vector.
387         */
388        int curArg = 0;
389
390        if (kUseValgrind) {
391            /* probably shouldn't ship the hard-coded path */
392            argv[curArg++] = (char*)kValgrinder;
393            argv[curArg++] = "--tool=memcheck";
394            argv[curArg++] = "--leak-check=yes";        // check for leaks too
395            argv[curArg++] = "--leak-resolution=med";   // increase from 2 to 4
396            argv[curArg++] = "--num-callers=16";        // default is 12
397            assert(curArg == kValgrindArgCount);
398        }
399        argv[curArg++] = execFile;
400
401        argv[curArg++] = "--dex";
402
403        sprintf(values[2], "%d", DALVIK_VM_BUILD);
404        argv[curArg++] = values[2];
405
406        sprintf(values[3], "%d", fd);
407        argv[curArg++] = values[3];
408
409        sprintf(values[4], "%d", (int) dexOffset);
410        argv[curArg++] = values[4];
411
412        sprintf(values[5], "%d", (int) dexLength);
413        argv[curArg++] = values[5];
414
415        argv[curArg++] = (char*)fileName;
416
417        sprintf(values[7], "%d", (int) modWhen);
418        argv[curArg++] = values[7];
419
420        sprintf(values[8], "%d", (int) crc);
421        argv[curArg++] = values[8];
422
423        flags = 0;
424        if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) {
425            flags |= DEXOPT_OPT_ENABLED;
426            if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)
427                flags |= DEXOPT_OPT_ALL;
428        }
429        if (gDvm.classVerifyMode != VERIFY_MODE_NONE) {
430            flags |= DEXOPT_VERIFY_ENABLED;
431            if (gDvm.classVerifyMode == VERIFY_MODE_ALL)
432                flags |= DEXOPT_VERIFY_ALL;
433        }
434        if (isBootstrap)
435            flags |= DEXOPT_IS_BOOTSTRAP;
436        if (gDvm.generateRegisterMaps)
437            flags |= DEXOPT_GEN_REGISTER_MAP;
438        sprintf(values[9], "%d", flags);
439        argv[curArg++] = values[9];
440
441        assert(((!kUseValgrind && curArg == kFixedArgCount) ||
442               ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount))));
443
444        ClassPathEntry* cpe;
445        for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
446            argv[curArg++] = cpe->fileName;
447        }
448        assert(curArg == argc);
449
450        argv[curArg] = NULL;
451
452        if (kUseValgrind)
453            execv(kValgrinder, argv);
454        else
455            execv(execFile, argv);
456
457        LOGE("execv '%s'%s failed: %s\n", execFile,
458            kUseValgrind ? " [valgrind]" : "", strerror(errno));
459        exit(1);
460    } else {
461        LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid);
462        int status;
463        pid_t gotPid;
464        int oldStatus;
465
466        /*
467         * Wait for the optimization process to finish.  We go into VMWAIT
468         * mode here so GC suspension won't have to wait for us.
469         */
470        oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
471        while (true) {
472            gotPid = waitpid(pid, &status, 0);
473            if (gotPid == -1 && errno == EINTR) {
474                LOGD("waitpid interrupted, retrying\n");
475            } else {
476                break;
477            }
478        }
479        dvmChangeStatus(NULL, oldStatus);
480        if (gotPid != pid) {
481            LOGE("waitpid failed: wanted %d, got %d: %s\n",
482                (int) pid, (int) gotPid, strerror(errno));
483            return false;
484        }
485
486        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
487            LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart);
488            return true;
489        } else {
490            LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n",
491                lastPart, status);
492            return false;
493        }
494    }
495}
496
497/*
498 * Do the actual optimization.  This is called directly for "minimal"
499 * optimization, or from a newly-created process for "full" optimization.
500 *
501 * For best use of disk/memory, we want to extract once and perform
502 * optimizations in place.  If the file has to expand or contract
503 * to match local structure padding/alignment expectations, we want
504 * to do the rewrite as part of the extract, rather than extracting
505 * into a temp file and slurping it back out.  (The structure alignment
506 * is currently correct for all platforms, and this isn't expected to
507 * change, so we should be okay with having it already extracted.)
508 *
509 * Returns "true" on success.
510 */
511bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
512    const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
513{
514    DexClassLookup* pClassLookup = NULL;
515    IndexMapSet* pIndexMapSet = NULL;
516    RegisterMapBuilder* pRegMapBuilder = NULL;
517    bool doVerify, doOpt;
518    u4 headerFlags = 0;
519
520    if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
521        doVerify = false;
522    else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
523        doVerify = !isBootstrap;
524    else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
525        doVerify = true;
526
527    if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
528        doOpt = false;
529    else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
530        doOpt = doVerify;
531    else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
532        doOpt = true;
533
534    LOGV("Continuing optimization (%s, isb=%d, vfy=%d, opt=%d)\n",
535        fileName, isBootstrap, doVerify, doOpt);
536
537    assert(dexOffset >= 0);
538
539    /* quick test so we don't blow up on empty file */
540    if (dexLength < (int) sizeof(DexHeader)) {
541        LOGE("too small to be DEX\n");
542        return false;
543    }
544    if (dexOffset < (int) sizeof(DexOptHeader)) {
545        LOGE("not enough room for opt header\n");
546        return false;
547    }
548
549    bool result = false;
550
551    /*
552     * Drop this into a global so we don't have to pass it around.  We could
553     * also add a field to DexFile, but since it only pertains to DEX
554     * creation that probably doesn't make sense.
555     */
556    gDvm.optimizingBootstrapClass = isBootstrap;
557
558    {
559        /*
560         * Map the entire file (so we don't have to worry about page
561         * alignment).  The expectation is that the output file contains
562         * our DEX data plus room for a small header.
563         */
564        bool success;
565        void* mapAddr;
566        mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE,
567                    MAP_SHARED, fd, 0);
568        if (mapAddr == MAP_FAILED) {
569            LOGE("unable to mmap DEX cache: %s\n", strerror(errno));
570            goto bail;
571        }
572
573        /*
574         * Rewrite the file.  Byte reordering, structure realigning,
575         * class verification, and bytecode optimization are all performed
576         * here.
577         *
578         * In theory the file could change size and bits could shift around.
579         * In practice this would be annoying to deal with, so the file
580         * layout is designed so that it can always be rewritten in place.
581         *
582         * This sets "headerFlags" and creates the class lookup table as
583         * part of doing the processing.
584         */
585        success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
586                    doVerify, doOpt, &headerFlags, &pClassLookup);
587
588        if (success) {
589            DvmDex* pDvmDex = NULL;
590            u1* dexAddr = ((u1*) mapAddr) + dexOffset;
591
592            if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) {
593                LOGE("Unable to create DexFile\n");
594                success = false;
595            } else {
596                /*
597                 * If configured to do so, scan the instructions, looking
598                 * for ways to reduce the size of the resolved-constant table.
599                 * This is done post-optimization, across the instructions
600                 * in all methods in all classes (even the ones that failed
601                 * to load).
602                 */
603                pIndexMapSet = dvmRewriteConstants(pDvmDex);
604
605                /*
606                 * If configured to do so, generate a full set of register
607                 * maps for all verified classes.
608                 */
609                if (gDvm.generateRegisterMaps) {
610                    pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex);
611                    if (pRegMapBuilder == NULL) {
612                        LOGE("Failed generating register maps\n");
613                        success = false;
614                    }
615                }
616
617                DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader;
618                updateChecksum(dexAddr, dexLength, pHeader);
619
620                dvmDexFileFree(pDvmDex);
621            }
622        }
623
624        /* unmap the read-write version, forcing writes to disk */
625        if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) {
626            LOGW("msync failed: %s\n", strerror(errno));
627            // weird, but keep going
628        }
629#if 1
630        /*
631         * This causes clean shutdown to fail, because we have loaded classes
632         * that point into it.  For the optimizer this isn't a problem,
633         * because it's more efficient for the process to simply exit.
634         * Exclude this code when doing clean shutdown for valgrind.
635         */
636        if (munmap(mapAddr, dexOffset + dexLength) != 0) {
637            LOGE("munmap failed: %s\n", strerror(errno));
638            goto bail;
639        }
640#endif
641
642        if (!success)
643            goto bail;
644    }
645
646    /* get start offset, and adjust deps start for 64-bit alignment */
647    off_t depsOffset, auxOffset, endOffset, adjOffset;
648    int depsLength, auxLength;
649    u4 optChecksum;
650
651    depsOffset = lseek(fd, 0, SEEK_END);
652    if (depsOffset < 0) {
653        LOGE("lseek to EOF failed: %s\n", strerror(errno));
654        goto bail;
655    }
656    adjOffset = (depsOffset + 7) & ~(0x07);
657    if (adjOffset != depsOffset) {
658        LOGV("Adjusting deps start from %d to %d\n",
659            (int) depsOffset, (int) adjOffset);
660        depsOffset = adjOffset;
661        lseek(fd, depsOffset, SEEK_SET);
662    }
663
664    /*
665     * Append the dependency list.
666     */
667    if (writeDependencies(fd, modWhen, crc) != 0) {
668        LOGW("Failed writing dependencies\n");
669        goto bail;
670    }
671
672    /* compute deps length, then adjust aux start for 64-bit alignment */
673    auxOffset = lseek(fd, 0, SEEK_END);
674    depsLength = auxOffset - depsOffset;
675
676    adjOffset = (auxOffset + 7) & ~(0x07);
677    if (adjOffset != auxOffset) {
678        LOGV("Adjusting aux start from %d to %d\n",
679            (int) auxOffset, (int) adjOffset);
680        auxOffset = adjOffset;
681        lseek(fd, auxOffset, SEEK_SET);
682    }
683
684    /*
685     * Append any auxillary pre-computed data structures.
686     */
687    if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
688        LOGW("Failed writing aux data\n");
689        goto bail;
690    }
691
692    endOffset = lseek(fd, 0, SEEK_END);
693    auxLength = endOffset - auxOffset;
694
695    /* compute checksum from start of deps to end of aux area */
696    if (!computeFileChecksum(fd, depsOffset,
697            (auxOffset+auxLength) - depsOffset, &optChecksum))
698    {
699        goto bail;
700    }
701
702    /*
703     * Output the "opt" header with all values filled in and a correct
704     * magic number.
705     */
706    DexOptHeader optHdr;
707    memset(&optHdr, 0xff, sizeof(optHdr));
708    memcpy(optHdr.magic, DEX_OPT_MAGIC, 4);
709    memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4);
710    optHdr.dexOffset = (u4) dexOffset;
711    optHdr.dexLength = (u4) dexLength;
712    optHdr.depsOffset = (u4) depsOffset;
713    optHdr.depsLength = (u4) depsLength;
714    optHdr.auxOffset = (u4) auxOffset;
715    optHdr.auxLength = (u4) auxLength;
716
717    optHdr.flags = headerFlags;
718    optHdr.checksum = optChecksum;
719
720    ssize_t actual;
721    lseek(fd, 0, SEEK_SET);
722    actual = write(fd, &optHdr, sizeof(optHdr));
723    if (actual != sizeof(optHdr)) {
724        logFailedWrite(sizeof(optHdr), actual, "opt header", errno);
725        goto bail;
726    }
727
728    LOGV("Successfully wrote DEX header\n");
729    result = true;
730
731    //dvmRegisterMapDumpStats();
732
733bail:
734    dvmFreeIndexMapSet(pIndexMapSet);
735    dvmFreeRegisterMapBuilder(pRegMapBuilder);
736    free(pClassLookup);
737    return result;
738}
739
740
741/*
742 * Get the cache file name from a ClassPathEntry.
743 */
744static const char* getCacheFileName(const ClassPathEntry* cpe)
745{
746    switch (cpe->kind) {
747    case kCpeJar:
748        return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr);
749    case kCpeDex:
750        return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr);
751    default:
752        LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind);
753        dvmAbort();
754        return NULL;
755    }
756}
757
758/*
759 * Get the SHA-1 signature.
760 */
761static const u1* getSignature(const ClassPathEntry* cpe)
762{
763    DvmDex* pDvmDex;
764
765    switch (cpe->kind) {
766    case kCpeJar:
767        pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr);
768        break;
769    case kCpeDex:
770        pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr);
771        break;
772    default:
773        LOGE("unexpected cpe kind %d\n", cpe->kind);
774        dvmAbort();
775        pDvmDex = NULL;         // make gcc happy
776    }
777
778    assert(pDvmDex != NULL);
779    return pDvmDex->pDexFile->pHeader->signature;
780}
781
782
783/*
784 * Dependency layout:
785 *  4b  Source file modification time, in seconds since 1970 UTC
786 *  4b  CRC-32 from Zip entry, or Adler32 from source DEX header
787 *  4b  Dalvik VM build number
788 *  4b  Number of dependency entries that follow
789 *  Dependency entries:
790 *    4b  Name length (including terminating null)
791 *    var Full path of cache entry (null terminated)
792 *    20b SHA-1 signature from source DEX file
793 *
794 * If this changes, update DEX_OPT_MAGIC_VERS.
795 */
796static const size_t kMinDepSize = 4 * 4;
797static const size_t kMaxDepSize = 4 * 4 + 1024;     // sanity check
798
799/*
800 * Read the "opt" header, verify it, then read the dependencies section
801 * and verify that data as well.
802 *
803 * If "sourceAvail" is "true", this will verify that "modWhen" and "crc"
804 * match up with what is stored in the header.  If they don't, we reject
805 * the file so that it can be recreated from the updated original.  If
806 * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments.
807 *
808 * On successful return, the file will be seeked immediately past the
809 * "opt" header.
810 */
811bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen,
812    u4 crc, bool expectVerify, bool expectOpt)
813{
814    DexOptHeader optHdr;
815    u1* depData = NULL;
816    const u1* magic;
817    off_t posn;
818    int result = false;
819    ssize_t actual;
820
821    /*
822     * Start at the start.  The "opt" header, when present, will always be
823     * the first thing in the file.
824     */
825    if (lseek(fd, 0, SEEK_SET) != 0) {
826        LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno));
827        goto bail;
828    }
829
830    /*
831     * Read and do trivial verification on the opt header.  The header is
832     * always in host byte order.
833     */
834    if (read(fd, &optHdr, sizeof(optHdr)) != sizeof(optHdr)) {
835        LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno));
836        goto bail;
837    }
838
839    magic = optHdr.magic;
840    if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) {
841        /* not a DEX file, or previous attempt was interrupted */
842        LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
843            magic[0], magic[1], magic[2], magic[3]);
844        goto bail;
845    }
846    if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
847        LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n",
848            magic[4], magic[5], magic[6], magic[7]);
849        goto bail;
850    }
851    if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) {
852        LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength);
853        goto bail;
854    }
855
856    /*
857     * Do the header flags match up with what we want?
858     *
859     * This is useful because it allows us to automatically regenerate
860     * a file when settings change (e.g. verification is now mandatory),
861     * but can cause difficulties if the bootstrap classes we depend upon
862     * were handled differently than the current options specify.  We get
863     * upset because they're not verified or optimized, but we're not able
864     * to regenerate them because the installer won't let us.
865     *
866     * (This is also of limited value when !sourceAvail.)
867     *
868     * So, for now, we essentially ignore "expectVerify" and "expectOpt"
869     * by limiting the match mask.
870     *
871     * The only thing we really can't handle is incorrect byte-ordering.
872     */
873    const u4 matchMask = DEX_OPT_FLAG_BIG;
874    u4 expectedFlags = 0;
875#if __BYTE_ORDER != __LITTLE_ENDIAN
876    expectedFlags |= DEX_OPT_FLAG_BIG;
877#endif
878    if (expectVerify)
879        expectedFlags |= DEX_FLAG_VERIFIED;
880    if (expectOpt)
881        expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
882    if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
883        LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
884            expectedFlags, optHdr.flags, matchMask);
885        goto bail;
886    }
887
888    posn = lseek(fd, optHdr.depsOffset, SEEK_SET);
889    if (posn < 0) {
890        LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno));
891        goto bail;
892    }
893
894    /*
895     * Read all of the dependency stuff into memory.
896     */
897    depData = (u1*) malloc(optHdr.depsLength);
898    if (depData == NULL) {
899        LOGW("DexOpt: unable to allocate %d bytes for deps\n",
900            optHdr.depsLength);
901        goto bail;
902    }
903    actual = read(fd, depData, optHdr.depsLength);
904    if (actual != (ssize_t) optHdr.depsLength) {
905        LOGW("DexOpt: failed reading deps: %d of %d (err=%s)\n",
906            (int) actual, optHdr.depsLength, strerror(errno));
907        goto bail;
908    }
909
910    /*
911     * Verify simple items.
912     */
913    const u1* ptr;
914    u4 val;
915
916    ptr = depData;
917    val = read4LE(&ptr);
918    if (sourceAvail && val != modWhen) {
919        LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n",
920            val, modWhen);
921        goto bail;
922    }
923    val = read4LE(&ptr);
924    if (sourceAvail && val != crc) {
925        LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc);
926        goto bail;
927    }
928    val = read4LE(&ptr);
929    if (val != DALVIK_VM_BUILD) {
930        LOGD("DexOpt: VM build version mismatch (%d vs %d)\n",
931            val, DALVIK_VM_BUILD);
932        goto bail;
933    }
934
935    /*
936     * Verify dependencies on other cached DEX files.  It must match
937     * exactly with what is currently defined in the bootclasspath.
938     */
939    ClassPathEntry* cpe;
940    u4 numDeps;
941
942    numDeps = read4LE(&ptr);
943    LOGV("+++ DexOpt: numDeps = %d\n", numDeps);
944    for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
945        const char* cacheFileName = getCacheFileName(cpe);
946        const u1* signature = getSignature(cpe);
947        size_t len = strlen(cacheFileName) +1;
948        u4 storedStrLen;
949
950        if (numDeps == 0) {
951            /* more entries in bootclasspath than in deps list */
952            LOGI("DexOpt: not all deps represented\n");
953            goto bail;
954        }
955
956        storedStrLen = read4LE(&ptr);
957        if (len != storedStrLen ||
958            strcmp(cacheFileName, (const char*) ptr) != 0)
959        {
960            LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n",
961                cacheFileName, ptr);
962            goto bail;
963        }
964
965        ptr += storedStrLen;
966
967        if (memcmp(signature, ptr, kSHA1DigestLen) != 0) {
968            LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName);
969            goto bail;
970        }
971        ptr += kSHA1DigestLen;
972
973        LOGV("DexOpt: dep match on '%s'\n", cacheFileName);
974
975        numDeps--;
976    }
977
978    if (numDeps != 0) {
979        /* more entries in deps list than in classpath */
980        LOGI("DexOpt: Some deps went away\n");
981        goto bail;
982    }
983
984    // consumed all data and no more?
985    if (ptr != depData + optHdr.depsLength) {
986        LOGW("DexOpt: Spurious dep data? %d vs %d\n",
987            (int) (ptr - depData), optHdr.depsLength);
988        assert(false);
989    }
990
991    result = true;
992
993bail:
994    free(depData);
995    return result;
996}
997
998/*
999 * Write the dependency info to "fd" at the current file position.
1000 */
1001static int writeDependencies(int fd, u4 modWhen, u4 crc)
1002{
1003    u1* buf = NULL;
1004    ssize_t actual;
1005    int result = -1;
1006    ssize_t bufLen;
1007    ClassPathEntry* cpe;
1008    int i, numDeps;
1009
1010    /*
1011     * Count up the number of completed entries in the bootclasspath.
1012     */
1013    numDeps = 0;
1014    bufLen = 0;
1015    for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1016        const char* cacheFileName = getCacheFileName(cpe);
1017        LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName);
1018
1019        numDeps++;
1020        bufLen += strlen(cacheFileName) +1;
1021    }
1022
1023    bufLen += 4*4 + numDeps * (4+kSHA1DigestLen);
1024
1025    buf = malloc(bufLen);
1026
1027    set4LE(buf+0, modWhen);
1028    set4LE(buf+4, crc);
1029    set4LE(buf+8, DALVIK_VM_BUILD);
1030    set4LE(buf+12, numDeps);
1031
1032    // TODO: do we want to add dvmGetInlineOpsTableLength() here?  Won't
1033    // help us if somebody replaces an existing entry, but it'd catch
1034    // additions/removals.
1035
1036    u1* ptr = buf + 4*4;
1037    for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1038        const char* cacheFileName = getCacheFileName(cpe);
1039        const u1* signature = getSignature(cpe);
1040        int len = strlen(cacheFileName) +1;
1041
1042        if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) {
1043            LOGE("DexOpt: overran buffer\n");
1044            dvmAbort();
1045        }
1046
1047        set4LE(ptr, len);
1048        ptr += 4;
1049        memcpy(ptr, cacheFileName, len);
1050        ptr += len;
1051        memcpy(ptr, signature, kSHA1DigestLen);
1052        ptr += kSHA1DigestLen;
1053    }
1054
1055    assert(ptr == buf + bufLen);
1056
1057    actual = write(fd, buf, bufLen);
1058    if (actual != bufLen) {
1059        result = (errno != 0) ? errno : -1;
1060        logFailedWrite(bufLen, actual, "dep info", errno);
1061    } else {
1062        result = 0;
1063    }
1064
1065    free(buf);
1066    return result;
1067}
1068
1069
1070/*
1071 * Write a block of data in "chunk" format.
1072 *
1073 * The chunk header fields are always in "native" byte order.  If "size"
1074 * is not a multiple of 8 bytes, the data area is padded out.
1075 */
1076static bool writeChunk(int fd, u4 type, const void* data, size_t size)
1077{
1078    ssize_t actual;
1079    union {             /* save a syscall by grouping these together */
1080        char raw[8];
1081        struct {
1082            u4 type;
1083            u4 size;
1084        } ts;
1085    } header;
1086
1087    assert(sizeof(header) == 8);
1088
1089    LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size);
1090
1091    header.ts.type = type;
1092    header.ts.size = (u4) size;
1093    actual = write(fd, &header, sizeof(header));
1094    if (actual != sizeof(header)) {
1095        logFailedWrite(size, actual, "aux chunk header write", errno);
1096        return false;
1097    }
1098
1099    if (size > 0) {
1100        actual = write(fd, data, size);
1101        if (actual != (ssize_t) size) {
1102            logFailedWrite(size, actual, "aux chunk write", errno);
1103            return false;
1104        }
1105    }
1106
1107    /* if necessary, pad to 64-bit alignment */
1108    if ((size & 7) != 0) {
1109        int padSize = 8 - (size & 7);
1110        LOGV("size was %d, inserting %d pad bytes\n", size, padSize);
1111        lseek(fd, padSize, SEEK_CUR);
1112    }
1113
1114    assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0);
1115
1116    return true;
1117}
1118
1119/*
1120 * Write aux data.
1121 *
1122 * We have different pieces, some of which may be optional.  To make the
1123 * most effective use of space, we use a "chunk" format, with a 4-byte
1124 * type and a 4-byte length.  We guarantee 64-bit alignment for the data,
1125 * so it can be used directly when the file is mapped for reading.
1126 */
1127static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,
1128    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder)
1129{
1130    /* pre-computed class lookup hash table */
1131    if (!writeChunk(fd, (u4) kDexChunkClassLookup,
1132            pClassLookup, pClassLookup->size))
1133    {
1134        return false;
1135    }
1136
1137    /* remapped constants (optional) */
1138    if (pIndexMapSet != NULL) {
1139        if (!writeChunk(fd, pIndexMapSet->chunkType,
1140                pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen))
1141        {
1142            return false;
1143        }
1144    }
1145
1146    /* register maps (optional) */
1147    if (pRegMapBuilder != NULL) {
1148        if (!writeChunk(fd, (u4) kDexChunkRegisterMaps,
1149                pRegMapBuilder->data, pRegMapBuilder->size))
1150        {
1151            return false;
1152        }
1153    }
1154
1155    /* write the end marker */
1156    if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) {
1157        return false;
1158    }
1159
1160    return true;
1161}
1162
1163/*
1164 * Log a failed write.
1165 */
1166static void logFailedWrite(size_t expected, ssize_t actual, const char* msg,
1167    int err)
1168{
1169    LOGE("Write failed: %s (%d of %d): %s\n",
1170        msg, (int)actual, (int)expected, strerror(err));
1171}
1172
1173/*
1174 * Compute a checksum on a piece of an open file.
1175 *
1176 * File will be positioned at end of checksummed area.
1177 *
1178 * Returns "true" on success.
1179 */
1180static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum)
1181{
1182    unsigned char readBuf[8192];
1183    ssize_t actual;
1184    uLong adler;
1185
1186    if (lseek(fd, start, SEEK_SET) != start) {
1187        LOGE("Unable to seek to start of checksum area (%ld): %s\n",
1188            (long) start, strerror(errno));
1189        return false;
1190    }
1191
1192    adler = adler32(0L, Z_NULL, 0);
1193
1194    while (length != 0) {
1195        size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf);
1196        actual = read(fd, readBuf, wanted);
1197        if (actual <= 0) {
1198            LOGE("Read failed (%d) while computing checksum (len=%zu): %s\n",
1199                (int) actual, length, strerror(errno));
1200            return false;
1201        }
1202
1203        adler = adler32(adler, readBuf, actual);
1204
1205        length -= actual;
1206    }
1207
1208    *pSum = adler;
1209    return true;
1210}
1211
1212
1213/*
1214 * ===========================================================================
1215 *      Optimizations
1216 * ===========================================================================
1217 */
1218
1219/*
1220 * Perform in-place rewrites on a memory-mapped DEX file.
1221 *
1222 * This happens in a short-lived child process, so we can go nutty with
1223 * loading classes and allocating memory.
1224 */
1225static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,
1226    u4* pHeaderFlags, DexClassLookup** ppClassLookup)
1227{
1228    u8 prepWhen, loadWhen, verifyWhen, optWhen;
1229    DvmDex* pDvmDex = NULL;
1230    bool result = false;
1231
1232    *pHeaderFlags = 0;
1233
1234    LOGV("+++ swapping bytes\n");
1235    if (dexFixByteOrdering(addr, len) != 0)
1236        goto bail;
1237#if __BYTE_ORDER != __LITTLE_ENDIAN
1238    *pHeaderFlags |= DEX_OPT_FLAG_BIG;
1239#endif
1240
1241    /*
1242     * Now that the DEX file can be read directly, create a DexFile for it.
1243     */
1244    if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) {
1245        LOGE("Unable to create DexFile\n");
1246        goto bail;
1247    }
1248
1249    /*
1250     * Create the class lookup table.
1251     */
1252    //startWhen = dvmGetRelativeTimeUsec();
1253    *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
1254    if (*ppClassLookup == NULL)
1255        goto bail;
1256
1257    /*
1258     * Bail out early if they don't want The Works.  The current implementation
1259     * doesn't fork a new process if this flag isn't set, so we really don't
1260     * want to continue on with the crazy class loading.
1261     */
1262    if (!doVerify && !doOpt) {
1263        result = true;
1264        goto bail;
1265    }
1266
1267    /* this is needed for the next part */
1268    pDvmDex->pDexFile->pClassLookup = *ppClassLookup;
1269
1270    prepWhen = dvmGetRelativeTimeUsec();
1271
1272    /*
1273     * Load all classes found in this DEX file.  If they fail to load for
1274     * some reason, they won't get verified (which is as it should be).
1275     */
1276    if (!loadAllClasses(pDvmDex))
1277        goto bail;
1278    loadWhen = dvmGetRelativeTimeUsec();
1279
1280    /*
1281     * Verify all classes in the DEX file.  Export the "is verified" flag
1282     * to the DEX file we're creating.
1283     */
1284    if (doVerify) {
1285        dvmVerifyAllClasses(pDvmDex->pDexFile);
1286        *pHeaderFlags |= DEX_FLAG_VERIFIED;
1287    }
1288    verifyWhen = dvmGetRelativeTimeUsec();
1289
1290    /*
1291     * Optimize the classes we successfully loaded.  If the opt mode is
1292     * OPTIMIZE_MODE_VERIFIED, each class must have been successfully
1293     * verified or we'll skip it.
1294     */
1295#ifndef PROFILE_FIELD_ACCESS
1296    if (doOpt) {
1297        optimizeLoadedClasses(pDvmDex->pDexFile);
1298        *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
1299    }
1300#endif
1301    optWhen = dvmGetRelativeTimeUsec();
1302
1303    LOGD("DexOpt: load %dms, verify %dms, opt %dms\n",
1304        (int) (loadWhen - prepWhen) / 1000,
1305        (int) (verifyWhen - loadWhen) / 1000,
1306        (int) (optWhen - verifyWhen) / 1000);
1307
1308    result = true;
1309
1310bail:
1311    /* free up storage */
1312    dvmDexFileFree(pDvmDex);
1313
1314    return result;
1315}
1316
1317/*
1318 * Update the Adler-32 checksum stored in the DEX file.  This covers the
1319 * swapped and optimized DEX data, but does not include the opt header
1320 * or auxillary data.
1321 */
1322static void updateChecksum(u1* addr, int len, DexHeader* pHeader)
1323{
1324    /*
1325     * Rewrite the checksum.  We leave the SHA-1 signature alone.
1326     */
1327    uLong adler = adler32(0L, Z_NULL, 0);
1328    const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
1329
1330    adler = adler32(adler, addr + nonSum, len - nonSum);
1331    pHeader->checksum = adler;
1332}
1333
1334/*
1335 * Try to load all classes in the specified DEX.  If they have some sort
1336 * of broken dependency, e.g. their superclass lives in a different DEX
1337 * that wasn't previously loaded into the bootstrap class path, loading
1338 * will fail.  This is the desired behavior.
1339 *
1340 * We have no notion of class loader at this point, so we load all of
1341 * the classes with the bootstrap class loader.  It turns out this has
1342 * exactly the behavior we want, and has no ill side effects because we're
1343 * running in a separate process and anything we load here will be forgotten.
1344 *
1345 * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions.
1346 * This works because we only call here as part of optimization / pre-verify,
1347 * not during verification as part of loading a class into a running VM.
1348 *
1349 * This returns "false" if the world is too screwed up to do anything
1350 * useful at all.
1351 */
1352static bool loadAllClasses(DvmDex* pDvmDex)
1353{
1354    u4 count = pDvmDex->pDexFile->pHeader->classDefsSize;
1355    u4 idx;
1356    int loaded = 0;
1357
1358    LOGV("DexOpt: +++ trying to load %d classes\n", count);
1359
1360    dvmSetBootPathExtraDex(pDvmDex);
1361
1362    /*
1363     * We have some circularity issues with Class and Object that are most
1364     * easily avoided by ensuring that Object is never the first thing we
1365     * try to find.  Take care of that here.  (We only need to do this when
1366     * loading classes from the DEX file that contains Object, and only
1367     * when Object comes first in the list, but it costs very little to
1368     * do it in all cases.)
1369     */
1370    if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) {
1371        LOGE("ERROR: java.lang.Class does not exist!\n");
1372        return false;
1373    }
1374
1375    for (idx = 0; idx < count; idx++) {
1376        const DexClassDef* pClassDef;
1377        const char* classDescriptor;
1378        ClassObject* newClass;
1379
1380        pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx);
1381        classDescriptor =
1382            dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx);
1383
1384        LOGV("+++  loading '%s'", classDescriptor);
1385        //newClass = dvmDefineClass(pDexFile, classDescriptor,
1386        //        NULL);
1387        newClass = dvmFindSystemClassNoInit(classDescriptor);
1388        if (newClass == NULL) {
1389            LOGV("DexOpt: failed loading '%s'\n", classDescriptor);
1390            dvmClearOptException(dvmThreadSelf());
1391        } else if (newClass->pDvmDex != pDvmDex) {
1392            /*
1393             * We don't load the new one, and we tag the first one found
1394             * with the "multiple def" flag so the resolver doesn't try
1395             * to make it available.
1396             */
1397            LOGD("DexOpt: '%s' has an earlier definition; blocking out\n",
1398                classDescriptor);
1399            SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS);
1400        } else {
1401            loaded++;
1402        }
1403    }
1404    LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded);
1405
1406    dvmSetBootPathExtraDex(NULL);
1407    return true;
1408}
1409
1410
1411/*
1412 * Create a table of inline substitutions.
1413 *
1414 * TODO: this is currently just a linear array.  We will want to put this
1415 * into a hash table as the list size increases.
1416 */
1417static InlineSub* createInlineSubsTable(void)
1418{
1419    const InlineOperation* ops = dvmGetInlineOpsTable();
1420    const int count = dvmGetInlineOpsTableLength();
1421    InlineSub* table;
1422    Method* method;
1423    ClassObject* clazz;
1424    int i, tableIndex;
1425
1426    /*
1427     * Allocate for optimism: one slot per entry, plus an end-of-list marker.
1428     */
1429    table = malloc(sizeof(InlineSub) * (count+1));
1430
1431    tableIndex = 0;
1432    for (i = 0; i < count; i++) {
1433        clazz = dvmFindClassNoInit(ops[i].classDescriptor, NULL);
1434        if (clazz == NULL) {
1435            LOGV("DexOpt: can't inline for class '%s': not found\n",
1436                ops[i].classDescriptor);
1437            dvmClearOptException(dvmThreadSelf());
1438        } else {
1439            /*
1440             * Method could be virtual or direct.  Try both.  Don't use
1441             * the "hier" versions.
1442             */
1443            method = dvmFindDirectMethodByDescriptor(clazz, ops[i].methodName,
1444                        ops[i].methodSignature);
1445            if (method == NULL)
1446                method = dvmFindVirtualMethodByDescriptor(clazz, ops[i].methodName,
1447                        ops[i].methodSignature);
1448            if (method == NULL) {
1449                LOGW("DexOpt: can't inline %s.%s %s: method not found\n",
1450                    ops[i].classDescriptor, ops[i].methodName,
1451                    ops[i].methodSignature);
1452            } else {
1453                if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) {
1454                    LOGW("DexOpt: WARNING: inline op on non-final class/method "
1455                         "%s.%s\n",
1456                        clazz->descriptor, method->name);
1457                    /* fail? */
1458                }
1459                if (dvmIsSynchronizedMethod(method) ||
1460                    dvmIsDeclaredSynchronizedMethod(method))
1461                {
1462                    LOGW("DexOpt: WARNING: inline op on synchronized method "
1463                         "%s.%s\n",
1464                        clazz->descriptor, method->name);
1465                    /* fail? */
1466                }
1467
1468                table[tableIndex].method = method;
1469                table[tableIndex].inlineIdx = i;
1470                tableIndex++;
1471
1472                LOGV("DexOpt: will inline %d: %s.%s %s\n", i,
1473                    ops[i].classDescriptor, ops[i].methodName,
1474                    ops[i].methodSignature);
1475            }
1476        }
1477    }
1478
1479    /* mark end of table */
1480    table[tableIndex].method = NULL;
1481    LOGV("DexOpt: inline table has %d entries\n", tableIndex);
1482
1483    return table;
1484}
1485
1486/*
1487 * Run through all classes that were successfully loaded from this DEX
1488 * file and optimize their code sections.
1489 */
1490static void optimizeLoadedClasses(DexFile* pDexFile)
1491{
1492    u4 count = pDexFile->pHeader->classDefsSize;
1493    u4 idx;
1494    InlineSub* inlineSubs = NULL;
1495
1496    LOGV("DexOpt: +++ optimizing up to %d classes\n", count);
1497    assert(gDvm.dexOptMode != OPTIMIZE_MODE_NONE);
1498
1499    inlineSubs = createInlineSubsTable();
1500
1501    for (idx = 0; idx < count; idx++) {
1502        const DexClassDef* pClassDef;
1503        const char* classDescriptor;
1504        ClassObject* clazz;
1505
1506        pClassDef = dexGetClassDef(pDexFile, idx);
1507        classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
1508
1509        /* all classes are loaded into the bootstrap class loader */
1510        clazz = dvmLookupClass(classDescriptor, NULL, false);
1511        if (clazz != NULL) {
1512            if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) == 0 &&
1513                gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
1514            {
1515                LOGV("DexOpt: not optimizing '%s': not verified\n",
1516                    classDescriptor);
1517            } else if (clazz->pDvmDex->pDexFile != pDexFile) {
1518                /* shouldn't be here -- verifier should have caught */
1519                LOGD("DexOpt: not optimizing '%s': multiple definitions\n",
1520                    classDescriptor);
1521            } else {
1522                optimizeClass(clazz, inlineSubs);
1523
1524                /* set the flag whether or not we actually did anything */
1525                ((DexClassDef*)pClassDef)->accessFlags |=
1526                    CLASS_ISOPTIMIZED;
1527            }
1528        } else {
1529            LOGV("DexOpt: not optimizing unavailable class '%s'\n",
1530                classDescriptor);
1531        }
1532    }
1533
1534    free(inlineSubs);
1535}
1536
1537/*
1538 * Optimize the specified class.
1539 */
1540static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs)
1541{
1542    int i;
1543
1544    for (i = 0; i < clazz->directMethodCount; i++) {
1545        if (!optimizeMethod(&clazz->directMethods[i], inlineSubs))
1546            goto fail;
1547    }
1548    for (i = 0; i < clazz->virtualMethodCount; i++) {
1549        if (!optimizeMethod(&clazz->virtualMethods[i], inlineSubs))
1550            goto fail;
1551    }
1552
1553    return;
1554
1555fail:
1556    LOGV("DexOpt: ceasing optimization attempts on %s\n", clazz->descriptor);
1557}
1558
1559/*
1560 * Optimize instructions in a method.
1561 *
1562 * Returns "true" if all went well, "false" if we bailed out early when
1563 * something failed.
1564 */
1565static bool optimizeMethod(Method* method, const InlineSub* inlineSubs)
1566{
1567    u4 insnsSize;
1568    u2* insns;
1569    u2 inst;
1570
1571    if (dvmIsNativeMethod(method) || dvmIsAbstractMethod(method))
1572        return true;
1573
1574    insns = (u2*) method->insns;
1575    assert(insns != NULL);
1576    insnsSize = dvmGetMethodInsnsSize(method);
1577
1578    while (insnsSize > 0) {
1579        int width;
1580
1581        inst = *insns & 0xff;
1582
1583        switch (inst) {
1584        case OP_IGET:
1585        case OP_IGET_BOOLEAN:
1586        case OP_IGET_BYTE:
1587        case OP_IGET_CHAR:
1588        case OP_IGET_SHORT:
1589            rewriteInstField(method, insns, OP_IGET_QUICK);
1590            break;
1591        case OP_IGET_WIDE:
1592            rewriteInstField(method, insns, OP_IGET_WIDE_QUICK);
1593            break;
1594        case OP_IGET_OBJECT:
1595            rewriteInstField(method, insns, OP_IGET_OBJECT_QUICK);
1596            break;
1597        case OP_IPUT:
1598        case OP_IPUT_BOOLEAN:
1599        case OP_IPUT_BYTE:
1600        case OP_IPUT_CHAR:
1601        case OP_IPUT_SHORT:
1602            rewriteInstField(method, insns, OP_IPUT_QUICK);
1603            break;
1604        case OP_IPUT_WIDE:
1605            rewriteInstField(method, insns, OP_IPUT_WIDE_QUICK);
1606            break;
1607        case OP_IPUT_OBJECT:
1608            rewriteInstField(method, insns, OP_IPUT_OBJECT_QUICK);
1609            break;
1610
1611        case OP_INVOKE_VIRTUAL:
1612            if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL,inlineSubs))
1613            {
1614                if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_VIRTUAL_QUICK))
1615                    return false;
1616            }
1617            break;
1618        case OP_INVOKE_VIRTUAL_RANGE:
1619            if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL,
1620                    inlineSubs))
1621            {
1622                if (!rewriteVirtualInvoke(method, insns,
1623                        OP_INVOKE_VIRTUAL_QUICK_RANGE))
1624                {
1625                    return false;
1626                }
1627            }
1628            break;
1629        case OP_INVOKE_SUPER:
1630            if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK))
1631                return false;
1632            break;
1633        case OP_INVOKE_SUPER_RANGE:
1634            if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK_RANGE))
1635                return false;
1636            break;
1637
1638        case OP_INVOKE_DIRECT:
1639            if (!rewriteExecuteInline(method, insns, METHOD_DIRECT, inlineSubs))
1640            {
1641                if (!rewriteEmptyDirectInvoke(method, insns))
1642                    return false;
1643            }
1644            break;
1645        case OP_INVOKE_DIRECT_RANGE:
1646            rewriteExecuteInlineRange(method, insns, METHOD_DIRECT, inlineSubs);
1647            break;
1648
1649        case OP_INVOKE_STATIC:
1650            rewriteExecuteInline(method, insns, METHOD_STATIC, inlineSubs);
1651            break;
1652        case OP_INVOKE_STATIC_RANGE:
1653            rewriteExecuteInlineRange(method, insns, METHOD_STATIC, inlineSubs);
1654            break;
1655
1656        default:
1657            // ignore this instruction
1658            ;
1659        }
1660
1661        if (*insns == kPackedSwitchSignature) {
1662            width = 4 + insns[1] * 2;
1663        } else if (*insns == kSparseSwitchSignature) {
1664            width = 2 + insns[1] * 4;
1665        } else if (*insns == kArrayDataSignature) {
1666            u2 elemWidth = insns[1];
1667            u4 len = insns[2] | (((u4)insns[3]) << 16);
1668            width = 4 + (elemWidth * len + 1) / 2;
1669        } else {
1670            width = dexGetInstrWidth(gDvm.instrWidth, inst);
1671        }
1672        assert(width > 0);
1673
1674        insns += width;
1675        insnsSize -= width;
1676    }
1677
1678    assert(insnsSize == 0);
1679    return true;
1680}
1681
1682
1683/*
1684 * If "referrer" and "resClass" don't come from the same DEX file, and
1685 * the DEX we're working on is not destined for the bootstrap class path,
1686 * tweak the class loader so package-access checks work correctly.
1687 *
1688 * Only do this if we're doing pre-verification or optimization.
1689 */
1690static void tweakLoader(ClassObject* referrer, ClassObject* resClass)
1691{
1692    if (!gDvm.optimizing)
1693        return;
1694    assert(referrer->classLoader == NULL);
1695    assert(resClass->classLoader == NULL);
1696
1697    if (!gDvm.optimizingBootstrapClass) {
1698        /* class loader for an array class comes from element type */
1699        if (dvmIsArrayClass(resClass))
1700            resClass = resClass->elementClass;
1701        if (referrer->pDvmDex != resClass->pDvmDex)
1702            resClass->classLoader = (Object*) 0xdead3333;
1703    }
1704}
1705
1706/*
1707 * Undo the effects of tweakLoader.
1708 */
1709static void untweakLoader(ClassObject* referrer, ClassObject* resClass)
1710{
1711    if (!gDvm.optimizing || gDvm.optimizingBootstrapClass)
1712        return;
1713
1714    if (dvmIsArrayClass(resClass))
1715        resClass = resClass->elementClass;
1716    resClass->classLoader = NULL;
1717}
1718
1719
1720/*
1721 * Alternate version of dvmResolveClass for use with verification and
1722 * optimization.  Performs access checks on every resolve, and refuses
1723 * to acknowledge the existence of classes defined in more than one DEX
1724 * file.
1725 *
1726 * Exceptions caused by failures are cleared before returning.
1727 *
1728 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1729 */
1730ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
1731    VerifyError* pFailure)
1732{
1733    DvmDex* pDvmDex = referrer->pDvmDex;
1734    ClassObject* resClass;
1735
1736    /*
1737     * Check the table first.  If not there, do the lookup by name.
1738     */
1739    resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
1740    if (resClass == NULL) {
1741        const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx);
1742        if (className[0] != '\0' && className[1] == '\0') {
1743            /* primitive type */
1744            resClass = dvmFindPrimitiveClass(className[0]);
1745        } else {
1746            resClass = dvmFindClassNoInit(className, referrer->classLoader);
1747        }
1748        if (resClass == NULL) {
1749            /* not found, exception should be raised */
1750            LOGV("DexOpt: class %d (%s) not found\n",
1751                classIdx,
1752                dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
1753            if (pFailure != NULL) {
1754                /* dig through the wrappers to find the original failure */
1755                Object* excep = dvmGetException(dvmThreadSelf());
1756                while (true) {
1757                    Object* cause = dvmGetExceptionCause(excep);
1758                    if (cause == NULL)
1759                        break;
1760                    excep = cause;
1761                }
1762                if (strcmp(excep->clazz->descriptor,
1763                    "Ljava/lang/IncompatibleClassChangeError;") == 0)
1764                {
1765                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1766                } else {
1767                    *pFailure = VERIFY_ERROR_NO_CLASS;
1768                }
1769            }
1770            dvmClearOptException(dvmThreadSelf());
1771            return NULL;
1772        }
1773
1774        /*
1775         * Add it to the resolved table so we're faster on the next lookup.
1776         */
1777        dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
1778    }
1779
1780    /* multiple definitions? */
1781    if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) {
1782        LOGI("DexOpt: not resolving ambiguous class '%s'\n",
1783            resClass->descriptor);
1784        if (pFailure != NULL)
1785            *pFailure = VERIFY_ERROR_NO_CLASS;
1786        return NULL;
1787    }
1788
1789    /* access allowed? */
1790    tweakLoader(referrer, resClass);
1791    bool allowed = dvmCheckClassAccess(referrer, resClass);
1792    untweakLoader(referrer, resClass);
1793    if (!allowed) {
1794        LOGW("DexOpt: resolve class illegal access: %s -> %s\n",
1795            referrer->descriptor, resClass->descriptor);
1796        if (pFailure != NULL)
1797            *pFailure = VERIFY_ERROR_ACCESS_CLASS;
1798        return NULL;
1799    }
1800
1801    return resClass;
1802}
1803
1804/*
1805 * Alternate version of dvmResolveInstField().
1806 *
1807 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1808 */
1809InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
1810    VerifyError* pFailure)
1811{
1812    DvmDex* pDvmDex = referrer->pDvmDex;
1813    InstField* resField;
1814
1815    resField = (InstField*) dvmDexGetResolvedField(pDvmDex, ifieldIdx);
1816    if (resField == NULL) {
1817        const DexFieldId* pFieldId;
1818        ClassObject* resClass;
1819
1820        pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx);
1821
1822        /*
1823         * Find the field's class.
1824         */
1825        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
1826        if (resClass == NULL) {
1827            //dvmClearOptException(dvmThreadSelf());
1828            assert(!dvmCheckException(dvmThreadSelf()));
1829            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
1830            return NULL;
1831        }
1832
1833        resField = (InstField*)dvmFindFieldHier(resClass,
1834            dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
1835            dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
1836        if (resField == NULL) {
1837            LOGD("DexOpt: couldn't find field %s.%s\n",
1838                resClass->descriptor,
1839                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1840            if (pFailure != NULL)
1841                *pFailure = VERIFY_ERROR_NO_FIELD;
1842            return NULL;
1843        }
1844        if (dvmIsStaticField(&resField->field)) {
1845            LOGD("DexOpt: wanted instance, got static for field %s.%s\n",
1846                resClass->descriptor,
1847                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1848            if (pFailure != NULL)
1849                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1850            return NULL;
1851        }
1852
1853        /*
1854         * Add it to the resolved table so we're faster on the next lookup.
1855         */
1856        dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*) resField);
1857    }
1858
1859    /* access allowed? */
1860    tweakLoader(referrer, resField->field.clazz);
1861    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
1862    untweakLoader(referrer, resField->field.clazz);
1863    if (!allowed) {
1864        LOGI("DexOpt: access denied from %s to field %s.%s\n",
1865            referrer->descriptor, resField->field.clazz->descriptor,
1866            resField->field.name);
1867        if (pFailure != NULL)
1868            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
1869        return NULL;
1870    }
1871
1872    return resField;
1873}
1874
1875/*
1876 * Alternate version of dvmResolveStaticField().
1877 *
1878 * Does not force initialization of the resolved field's class.
1879 *
1880 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1881 */
1882StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
1883    VerifyError* pFailure)
1884{
1885    DvmDex* pDvmDex = referrer->pDvmDex;
1886    StaticField* resField;
1887
1888    resField = (StaticField*)dvmDexGetResolvedField(pDvmDex, sfieldIdx);
1889    if (resField == NULL) {
1890        const DexFieldId* pFieldId;
1891        ClassObject* resClass;
1892
1893        pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx);
1894
1895        /*
1896         * Find the field's class.
1897         */
1898        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
1899        if (resClass == NULL) {
1900            //dvmClearOptException(dvmThreadSelf());
1901            assert(!dvmCheckException(dvmThreadSelf()));
1902            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
1903            return NULL;
1904        }
1905
1906        resField = (StaticField*)dvmFindFieldHier(resClass,
1907                    dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
1908                    dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
1909        if (resField == NULL) {
1910            LOGD("DexOpt: couldn't find static field\n");
1911            if (pFailure != NULL)
1912                *pFailure = VERIFY_ERROR_NO_FIELD;
1913            return NULL;
1914        }
1915        if (!dvmIsStaticField(&resField->field)) {
1916            LOGD("DexOpt: wanted static, got instance for field %s.%s\n",
1917                resClass->descriptor,
1918                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
1919            if (pFailure != NULL)
1920                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
1921            return NULL;
1922        }
1923
1924        /*
1925         * Add it to the resolved table so we're faster on the next lookup.
1926         *
1927         * We can only do this if we're in "dexopt", because the presence
1928         * of a valid value in the resolution table implies that the class
1929         * containing the static field has been initialized.
1930         */
1931        if (gDvm.optimizing)
1932            dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField);
1933    }
1934
1935    /* access allowed? */
1936    tweakLoader(referrer, resField->field.clazz);
1937    bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField);
1938    untweakLoader(referrer, resField->field.clazz);
1939    if (!allowed) {
1940        LOGI("DexOpt: access denied from %s to field %s.%s\n",
1941            referrer->descriptor, resField->field.clazz->descriptor,
1942            resField->field.name);
1943        if (pFailure != NULL)
1944            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
1945        return NULL;
1946    }
1947
1948    return resField;
1949}
1950
1951
1952/*
1953 * Rewrite an iget/iput instruction.  These all have the form:
1954 *   op vA, vB, field@CCCC
1955 *
1956 * Where vA holds the value, vB holds the object reference, and CCCC is
1957 * the field reference constant pool offset.  We want to replace CCCC
1958 * with the byte offset from the start of the object.
1959 *
1960 * "clazz" is the referring class.  We need this because we verify
1961 * access rights here.
1962 */
1963static void rewriteInstField(Method* method, u2* insns, OpCode newOpc)
1964{
1965    ClassObject* clazz = method->clazz;
1966    u2 fieldIdx = insns[1];
1967    InstField* field;
1968    int byteOffset;
1969
1970    field = dvmOptResolveInstField(clazz, fieldIdx, NULL);
1971    if (field == NULL) {
1972        LOGI("DexOpt: unable to optimize field ref 0x%04x at 0x%02x in %s.%s\n",
1973            fieldIdx, (int) (insns - method->insns), clazz->descriptor,
1974            method->name);
1975        return;
1976    }
1977
1978    if (field->byteOffset >= 65536) {
1979        LOGI("DexOpt: field offset exceeds 64K (%d)\n", field->byteOffset);
1980        return;
1981    }
1982
1983    insns[0] = (insns[0] & 0xff00) | (u2) newOpc;
1984    insns[1] = (u2) field->byteOffset;
1985    LOGVV("DexOpt: rewrote access to %s.%s --> %d\n",
1986        field->field.clazz->descriptor, field->field.name,
1987        field->byteOffset);
1988}
1989
1990/*
1991 * Alternate version of dvmResolveMethod().
1992 *
1993 * Doesn't throw exceptions, and checks access on every lookup.
1994 *
1995 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
1996 */
1997Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
1998    MethodType methodType, VerifyError* pFailure)
1999{
2000    DvmDex* pDvmDex = referrer->pDvmDex;
2001    Method* resMethod;
2002
2003    assert(methodType == METHOD_DIRECT ||
2004           methodType == METHOD_VIRTUAL ||
2005           methodType == METHOD_STATIC);
2006
2007    LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
2008        referrer->descriptor);
2009
2010    resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
2011    if (resMethod == NULL) {
2012        const DexMethodId* pMethodId;
2013        ClassObject* resClass;
2014
2015        pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
2016
2017        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
2018        if (resClass == NULL) {
2019            /*
2020             * Can't find the class that the method is a part of, or don't
2021             * have permission to access the class.
2022             */
2023            LOGV("DexOpt: can't find called method's class (?.%s)\n",
2024                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
2025            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
2026            return NULL;
2027        }
2028        if (dvmIsInterfaceClass(resClass)) {
2029            /* method is part of an interface; this is wrong method for that */
2030            LOGW("DexOpt: method is in an interface\n");
2031            if (pFailure != NULL)
2032                *pFailure = VERIFY_ERROR_GENERIC;
2033            return NULL;
2034        }
2035
2036        /*
2037         * We need to chase up the class hierarchy to find methods defined
2038         * in super-classes.  (We only want to check the current class
2039         * if we're looking for a constructor.)
2040         */
2041        DexProto proto;
2042        dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
2043
2044        if (methodType == METHOD_DIRECT) {
2045            resMethod = dvmFindDirectMethod(resClass,
2046                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
2047        } else {
2048            /* METHOD_STATIC or METHOD_VIRTUAL */
2049            resMethod = dvmFindMethodHier(resClass,
2050                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
2051        }
2052
2053        if (resMethod == NULL) {
2054            LOGV("DexOpt: couldn't find method '%s'\n",
2055                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
2056            if (pFailure != NULL)
2057                *pFailure = VERIFY_ERROR_NO_METHOD;
2058            return NULL;
2059        }
2060        if (methodType == METHOD_STATIC) {
2061            if (!dvmIsStaticMethod(resMethod)) {
2062                LOGD("DexOpt: wanted static, got instance for method %s.%s\n",
2063                    resClass->descriptor, resMethod->name);
2064                if (pFailure != NULL)
2065                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
2066                return NULL;
2067            }
2068        } else if (methodType == METHOD_VIRTUAL) {
2069            if (dvmIsStaticMethod(resMethod)) {
2070                LOGD("DexOpt: wanted instance, got static for method %s.%s\n",
2071                    resClass->descriptor, resMethod->name);
2072                if (pFailure != NULL)
2073                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
2074                return NULL;
2075            }
2076        }
2077
2078        /* see if this is a pure-abstract method */
2079        if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
2080            LOGW("DexOpt: pure-abstract method '%s' in %s\n",
2081                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
2082                resClass->descriptor);
2083            if (pFailure != NULL)
2084                *pFailure = VERIFY_ERROR_GENERIC;
2085            return NULL;
2086        }
2087
2088        /*
2089         * Add it to the resolved table so we're faster on the next lookup.
2090         *
2091         * We can only do this for static methods if we're not in "dexopt",
2092         * because the presence of a valid value in the resolution table
2093         * implies that the class containing the static field has been
2094         * initialized.
2095         */
2096        if (methodType != METHOD_STATIC || gDvm.optimizing)
2097            dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
2098    }
2099
2100    LOGVV("--- found method %d (%s.%s)\n",
2101        methodIdx, resMethod->clazz->descriptor, resMethod->name);
2102
2103    /* access allowed? */
2104    tweakLoader(referrer, resMethod->clazz);
2105    bool allowed = dvmCheckMethodAccess(referrer, resMethod);
2106    untweakLoader(referrer, resMethod->clazz);
2107    if (!allowed) {
2108        IF_LOGI() {
2109            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
2110            LOGI("DexOpt: illegal method access (call %s.%s %s from %s)\n",
2111                resMethod->clazz->descriptor, resMethod->name, desc,
2112                referrer->descriptor);
2113            free(desc);
2114        }
2115        if (pFailure != NULL)
2116            *pFailure = VERIFY_ERROR_ACCESS_METHOD;
2117        return NULL;
2118    }
2119
2120    return resMethod;
2121}
2122
2123/*
2124 * Rewrite invoke-virtual, invoke-virtual/range, invoke-super, and
2125 * invoke-super/range.  These all have the form:
2126 *   op vAA, meth@BBBB, reg stuff @CCCC
2127 *
2128 * We want to replace the method constant pool index BBBB with the
2129 * vtable index.
2130 */
2131static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc)
2132{
2133    ClassObject* clazz = method->clazz;
2134    Method* baseMethod;
2135    u2 methodIdx = insns[1];
2136
2137    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL);
2138    if (baseMethod == NULL) {
2139        LOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s\n",
2140            methodIdx,
2141            (int) (insns - method->insns), clazz->descriptor,
2142            method->name);
2143        return false;
2144    }
2145
2146    assert((insns[0] & 0xff) == OP_INVOKE_VIRTUAL ||
2147           (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE ||
2148           (insns[0] & 0xff) == OP_INVOKE_SUPER ||
2149           (insns[0] & 0xff) == OP_INVOKE_SUPER_RANGE);
2150
2151    /*
2152     * Note: Method->methodIndex is a u2 and is range checked during the
2153     * initial load.
2154     */
2155    insns[0] = (insns[0] & 0xff00) | (u2) newOpc;
2156    insns[1] = baseMethod->methodIndex;
2157
2158    //LOGI("DexOpt: rewrote call to %s.%s --> %s.%s\n",
2159    //    method->clazz->descriptor, method->name,
2160    //    baseMethod->clazz->descriptor, baseMethod->name);
2161
2162    return true;
2163}
2164
2165/*
2166 * Rewrite invoke-direct, which has the form:
2167 *   op vAA, meth@BBBB, reg stuff @CCCC
2168 *
2169 * There isn't a lot we can do to make this faster, but in some situations
2170 * we can make it go away entirely.
2171 *
2172 * This must only be used when the invoked method does nothing and has
2173 * no return value (the latter being very important for verification).
2174 */
2175static bool rewriteEmptyDirectInvoke(Method* method, u2* insns)
2176{
2177    ClassObject* clazz = method->clazz;
2178    Method* calledMethod;
2179    u2 methodIdx = insns[1];
2180
2181    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
2182    if (calledMethod == NULL) {
2183        LOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s\n",
2184            methodIdx,
2185            (int) (insns - method->insns), clazz->descriptor,
2186            method->name);
2187        return false;
2188    }
2189
2190    /* TODO: verify that java.lang.Object() is actually empty! */
2191    if (calledMethod->clazz == gDvm.classJavaLangObject &&
2192        dvmCompareNameDescriptorAndMethod("<init>", "()V", calledMethod) == 0)
2193    {
2194        /*
2195         * Replace with "empty" instruction.  DO NOT disturb anything
2196         * else about it, as we want it to function the same as
2197         * OP_INVOKE_DIRECT when debugging is enabled.
2198         */
2199        assert((insns[0] & 0xff) == OP_INVOKE_DIRECT);
2200        insns[0] = (insns[0] & 0xff00) | (u2) OP_INVOKE_DIRECT_EMPTY;
2201
2202        //LOGI("DexOpt: marked-empty call to %s.%s --> %s.%s\n",
2203        //    method->clazz->descriptor, method->name,
2204        //    calledMethod->clazz->descriptor, calledMethod->name);
2205    }
2206
2207    return true;
2208}
2209
2210/*
2211 * Resolve an interface method reference.
2212 *
2213 * No method access check here -- interface methods are always public.
2214 *
2215 * Returns NULL if the method was not found.  Does not throw an exception.
2216 */
2217Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx)
2218{
2219    DvmDex* pDvmDex = referrer->pDvmDex;
2220    Method* resMethod;
2221    int i;
2222
2223    LOGVV("--- resolving interface method %d (referrer=%s)\n",
2224        methodIdx, referrer->descriptor);
2225
2226    resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx);
2227    if (resMethod == NULL) {
2228        const DexMethodId* pMethodId;
2229        ClassObject* resClass;
2230
2231        pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
2232
2233        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL);
2234        if (resClass == NULL) {
2235            /* can't find the class that the method is a part of */
2236            dvmClearOptException(dvmThreadSelf());
2237            return NULL;
2238        }
2239        if (!dvmIsInterfaceClass(resClass)) {
2240            /* whoops */
2241            LOGI("Interface method not part of interface class\n");
2242            return NULL;
2243        }
2244
2245        const char* methodName =
2246            dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
2247        DexProto proto;
2248        dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId);
2249
2250        LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n",
2251            methodName, methodSig, resClass->descriptor);
2252        resMethod = dvmFindVirtualMethod(resClass, methodName, &proto);
2253        if (resMethod == NULL) {
2254            /* scan superinterfaces and superclass interfaces */
2255            LOGVV("+++ did not resolve immediately\n");
2256            for (i = 0; i < resClass->iftableCount; i++) {
2257                resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz,
2258                                methodName, &proto);
2259                if (resMethod != NULL)
2260                    break;
2261            }
2262
2263            if (resMethod == NULL) {
2264                LOGVV("+++ unable to resolve method %s\n", methodName);
2265                return NULL;
2266            }
2267        } else {
2268            LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name,
2269                resMethod->clazz->descriptor, (u4) resMethod->methodIndex);
2270        }
2271
2272        /* we're expecting this to be abstract */
2273        if (!dvmIsAbstractMethod(resMethod)) {
2274            char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
2275            LOGW("Found non-abstract interface method %s.%s %s\n",
2276                resMethod->clazz->descriptor, resMethod->name, desc);
2277            free(desc);
2278            return NULL;
2279        }
2280
2281        /*
2282         * Add it to the resolved table so we're faster on the next lookup.
2283         */
2284        dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod);
2285    }
2286
2287    LOGVV("--- found interface method %d (%s.%s)\n",
2288        methodIdx, resMethod->clazz->descriptor, resMethod->name);
2289
2290    /* interface methods are always public; no need to check access */
2291
2292    return resMethod;
2293}
2294
2295/*
2296 * See if the method being called can be rewritten as an inline operation.
2297 * Works for invoke-virtual, invoke-direct, and invoke-static.
2298 *
2299 * Returns "true" if we replace it.
2300 */
2301static bool rewriteExecuteInline(Method* method, u2* insns,
2302    MethodType methodType, const InlineSub* inlineSubs)
2303{
2304    ClassObject* clazz = method->clazz;
2305    Method* calledMethod;
2306    u2 methodIdx = insns[1];
2307
2308    //return false;
2309
2310    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
2311    if (calledMethod == NULL) {
2312        LOGV("+++ DexOpt inline: can't find %d\n", methodIdx);
2313        return false;
2314    }
2315
2316    while (inlineSubs->method != NULL) {
2317        /*
2318        if (extra) {
2319            LOGI("comparing %p vs %p %s.%s %s\n",
2320                inlineSubs->method, calledMethod,
2321                inlineSubs->method->clazz->descriptor,
2322                inlineSubs->method->name,
2323                inlineSubs->method->signature);
2324        }
2325        */
2326        if (inlineSubs->method == calledMethod) {
2327            assert((insns[0] & 0xff) == OP_INVOKE_DIRECT ||
2328                   (insns[0] & 0xff) == OP_INVOKE_STATIC ||
2329                   (insns[0] & 0xff) == OP_INVOKE_VIRTUAL);
2330            insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE;
2331            insns[1] = (u2) inlineSubs->inlineIdx;
2332
2333            //LOGI("DexOpt: execute-inline %s.%s --> %s.%s\n",
2334            //    method->clazz->descriptor, method->name,
2335            //    calledMethod->clazz->descriptor, calledMethod->name);
2336            return true;
2337        }
2338
2339        inlineSubs++;
2340    }
2341
2342    return false;
2343}
2344
2345/*
2346 * See if the method being called can be rewritten as an inline operation.
2347 * Works for invoke-virtual/range, invoke-direct/range, and invoke-static/range.
2348 *
2349 * Returns "true" if we replace it.
2350 */
2351static bool rewriteExecuteInlineRange(Method* method, u2* insns,
2352    MethodType methodType, const InlineSub* inlineSubs)
2353{
2354    ClassObject* clazz = method->clazz;
2355    Method* calledMethod;
2356    u2 methodIdx = insns[1];
2357
2358    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
2359    if (calledMethod == NULL) {
2360        LOGV("+++ DexOpt inline/range: can't find %d\n", methodIdx);
2361        return false;
2362    }
2363
2364    while (inlineSubs->method != NULL) {
2365        if (inlineSubs->method == calledMethod) {
2366            assert((insns[0] & 0xff) == OP_INVOKE_DIRECT_RANGE ||
2367                   (insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE ||
2368                   (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE);
2369            insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE_RANGE;
2370            insns[1] = (u2) inlineSubs->inlineIdx;
2371
2372            //LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s\n",
2373            //    method->clazz->descriptor, method->name,
2374            //    calledMethod->clazz->descriptor, calledMethod->name);
2375            return true;
2376        }
2377
2378        inlineSubs++;
2379    }
2380
2381    return false;
2382}
2383
2384