Home | History | Annotate | Download | only in vm
      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  * Dalvik initialization, shutdown, and command-line argument processing.
     19  */
     20 #include "Dalvik.h"
     21 #include "test/Test.h"
     22 #include "mterp/Mterp.h"
     23 #include "Hash.h"
     24 
     25 #include <stdlib.h>
     26 #include <stdio.h>
     27 #include <signal.h>
     28 #include <limits.h>
     29 #include <ctype.h>
     30 #include <sys/wait.h>
     31 #include <unistd.h>
     32 
     33 #define kMinHeapStartSize   (1*1024*1024)
     34 #define kMinHeapSize        (2*1024*1024)
     35 #define kMaxHeapSize        (1*1024*1024*1024)
     36 
     37 /*
     38  * Register VM-agnostic native methods for system classes.
     39  */
     40 extern int jniRegisterSystemMethods(JNIEnv* env);
     41 
     42 /* fwd */
     43 static bool registerSystemNatives(JNIEnv* pEnv);
     44 static bool dvmInitJDWP(void);
     45 static bool dvmInitZygote(void);
     46 
     47 
     48 /* global state */
     49 struct DvmGlobals gDvm;
     50 
     51 /* JIT-specific global state */
     52 #if defined(WITH_JIT)
     53 struct DvmJitGlobals gDvmJit;
     54 
     55 #if defined(WITH_JIT_TUNING)
     56 /*
     57  * Track the number of hits in the inline cache for predicted chaining.
     58  * Use an ugly global variable here since it is accessed in assembly code.
     59  */
     60 int gDvmICHitCount;
     61 #endif
     62 
     63 #endif
     64 
     65 /*
     66  * Show usage.
     67  *
     68  * We follow the tradition of unhyphenated compound words.
     69  */
     70 static void dvmUsage(const char* progName)
     71 {
     72     dvmFprintf(stderr, "%s: [options] class [argument ...]\n", progName);
     73     dvmFprintf(stderr, "%s: [options] -jar file.jar [argument ...]\n",progName);
     74     dvmFprintf(stderr, "\n");
     75     dvmFprintf(stderr, "The following standard options are recognized:\n");
     76     dvmFprintf(stderr, "  -classpath classpath\n");
     77     dvmFprintf(stderr, "  -Dproperty=value\n");
     78     dvmFprintf(stderr, "  -verbose:tag  ('gc', 'jni', or 'class')\n");
     79     dvmFprintf(stderr, "  -ea[:<package name>... |:<class name>]\n");
     80     dvmFprintf(stderr, "  -da[:<package name>... |:<class name>]\n");
     81     dvmFprintf(stderr, "   (-enableassertions, -disableassertions)\n");
     82     dvmFprintf(stderr, "  -esa\n");
     83     dvmFprintf(stderr, "  -dsa\n");
     84     dvmFprintf(stderr,
     85                 "   (-enablesystemassertions, -disablesystemassertions)\n");
     86     dvmFprintf(stderr, "  -showversion\n");
     87     dvmFprintf(stderr, "  -help\n");
     88     dvmFprintf(stderr, "\n");
     89     dvmFprintf(stderr, "The following extended options are recognized:\n");
     90     dvmFprintf(stderr, "  -Xrunjdwp:<options>\n");
     91     dvmFprintf(stderr, "  -Xbootclasspath:bootclasspath\n");
     92     dvmFprintf(stderr, "  -Xcheck:tag  (e.g. 'jni')\n");
     93     dvmFprintf(stderr, "  -XmsN  (min heap, must be multiple of 1K, >= 1MB)\n");
     94     dvmFprintf(stderr, "  -XmxN  (max heap, must be multiple of 1K, >= 2MB)\n");
     95     dvmFprintf(stderr, "  -XssN  (stack size, >= %dKB, <= %dKB)\n",
     96         kMinStackSize / 1024, kMaxStackSize / 1024);
     97     dvmFprintf(stderr, "  -Xverify:{none,remote,all}\n");
     98     dvmFprintf(stderr, "  -Xrs\n");
     99 #if defined(WITH_JIT)
    100     dvmFprintf(stderr,
    101                 "  -Xint  (extended to accept ':portable', ':fast' and ':jit')\n");
    102 #else
    103     dvmFprintf(stderr,
    104                 "  -Xint  (extended to accept ':portable' and ':fast')\n");
    105 #endif
    106     dvmFprintf(stderr, "\n");
    107     dvmFprintf(stderr, "These are unique to Dalvik:\n");
    108     dvmFprintf(stderr, "  -Xzygote\n");
    109     dvmFprintf(stderr, "  -Xdexopt:{none,verified,all}\n");
    110     dvmFprintf(stderr, "  -Xnoquithandler\n");
    111     dvmFprintf(stderr,
    112                 "  -Xjnigreflimit:N  (must be multiple of 100, >= 200)\n");
    113     dvmFprintf(stderr, "  -Xjniopts:{warnonly,forcecopy}\n");
    114     dvmFprintf(stderr, "  -Xjnitrace:substring (eg NativeClass or nativeMethod)\n");
    115     dvmFprintf(stderr, "  -Xdeadlockpredict:{off,warn,err,abort}\n");
    116     dvmFprintf(stderr, "  -Xstacktracefile:<filename>\n");
    117     dvmFprintf(stderr, "  -Xgc:[no]precise\n");
    118     dvmFprintf(stderr, "  -Xgc:[no]preverify\n");
    119     dvmFprintf(stderr, "  -Xgc:[no]postverify\n");
    120     dvmFprintf(stderr, "  -Xgc:[no]concurrent\n");
    121     dvmFprintf(stderr, "  -Xgc:[no]verifycardtable\n");
    122     dvmFprintf(stderr, "  -Xgenregmap\n");
    123     dvmFprintf(stderr, "  -Xcheckdexsum\n");
    124 #if defined(WITH_JIT)
    125     dvmFprintf(stderr, "  -Xincludeselectedop\n");
    126     dvmFprintf(stderr, "  -Xjitop:hexopvalue[-endvalue]"
    127                        "[,hexopvalue[-endvalue]]*\n");
    128     dvmFprintf(stderr, "  -Xincludeselectedmethod\n");
    129     dvmFprintf(stderr, "  -Xjitthreshold:decimalvalue\n");
    130     dvmFprintf(stderr, "  -Xjitblocking\n");
    131     dvmFprintf(stderr, "  -Xjitmethod:signature[,signature]* "
    132                        "(eg Ljava/lang/String\\;replace)\n");
    133     dvmFprintf(stderr, "  -Xjitcheckcg\n");
    134     dvmFprintf(stderr, "  -Xjitverbose\n");
    135     dvmFprintf(stderr, "  -Xjitprofile\n");
    136     dvmFprintf(stderr, "  -Xjitdisableopt\n");
    137 #endif
    138     dvmFprintf(stderr, "\n");
    139     dvmFprintf(stderr, "Configured with:"
    140         " debugger"
    141         " profiler"
    142 #ifdef WITH_MONITOR_TRACKING
    143         " monitor_tracking"
    144 #endif
    145 #ifdef WITH_DEADLOCK_PREDICTION
    146         " deadlock_prediction"
    147 #endif
    148 #ifdef WITH_HPROF
    149         " hprof"
    150 #endif
    151 #ifdef WITH_HPROF_STACK
    152         " hprof_stack"
    153 #endif
    154 #ifdef WITH_ALLOC_LIMITS
    155         " alloc_limits"
    156 #endif
    157 #ifdef WITH_TRACKREF_CHECKS
    158         " trackref_checks"
    159 #endif
    160 #ifdef WITH_INSTR_CHECKS
    161         " instr_checks"
    162 #endif
    163 #ifdef WITH_EXTRA_OBJECT_VALIDATION
    164         " extra_object_validation"
    165 #endif
    166 #ifdef WITH_EXTRA_GC_CHECKS
    167         " extra_gc_checks"
    168 #endif
    169 #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
    170         " dalvik_assert"
    171 #endif
    172 #ifdef WITH_JNI_STACK_CHECK
    173         " jni_stack_check"
    174 #endif
    175 #ifdef EASY_GDB
    176         " easy_gdb"
    177 #endif
    178 #ifdef CHECK_MUTEX
    179         " check_mutex"
    180 #endif
    181 #ifdef PROFILE_FIELD_ACCESS
    182         " profile_field_access"
    183 #endif
    184 #if defined(WITH_JIT)
    185         " jit(" ARCH_VARIANT ")"
    186 #endif
    187 #if defined(WITH_SELF_VERIFICATION)
    188         " self_verification"
    189 #endif
    190 #if ANDROID_SMP != 0
    191         " smp"
    192 #endif
    193     );
    194 #ifdef DVM_SHOW_EXCEPTION
    195     dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
    196 #endif
    197     dvmFprintf(stderr, "\n\n");
    198 }
    199 
    200 /*
    201  * Show helpful information on JDWP options.
    202  */
    203 static void showJdwpHelp(void)
    204 {
    205     dvmFprintf(stderr,
    206         "Example: -Xrunjdwp:transport=dt_socket,address=8000,server=y\n");
    207     dvmFprintf(stderr,
    208         "Example: -Xrunjdwp:transport=dt_socket,address=localhost:6500,server=n\n");
    209 }
    210 
    211 /*
    212  * Show version and copyright info.
    213  */
    214 static void showVersion(void)
    215 {
    216     dvmFprintf(stdout, "DalvikVM version %d.%d.%d\n",
    217         DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
    218     dvmFprintf(stdout,
    219         "Copyright (C) 2007 The Android Open Source Project\n\n"
    220         "This software is built from source code licensed under the "
    221         "Apache License,\n"
    222         "Version 2.0 (the \"License\"). You may obtain a copy of the "
    223         "License at\n\n"
    224         "     http://www.apache.org/licenses/LICENSE-2.0\n\n"
    225         "See the associated NOTICE file for this software for further "
    226         "details.\n");
    227 }
    228 
    229 /*
    230  * Parse a string of the form /[0-9]+[kKmMgG]?/, which is used to specify
    231  * memory sizes.  [kK] indicates kilobytes, [mM] megabytes, and
    232  * [gG] gigabytes.
    233  *
    234  * "s" should point just past the "-Xm?" part of the string.
    235  * "min" specifies the lowest acceptable value described by "s".
    236  * "div" specifies a divisor, e.g. 1024 if the value must be a multiple
    237  * of 1024.
    238  *
    239  * The spec says the -Xmx and -Xms options must be multiples of 1024.  It
    240  * doesn't say anything about -Xss.
    241  *
    242  * Returns 0 (a useless size) if "s" is malformed or specifies a low or
    243  * non-evenly-divisible value.
    244  */
    245 static unsigned int dvmParseMemOption(const char *s, unsigned int div)
    246 {
    247     /* strtoul accepts a leading [+-], which we don't want,
    248      * so make sure our string starts with a decimal digit.
    249      */
    250     if (isdigit(*s)) {
    251         const char *s2;
    252         unsigned int val;
    253 
    254         val = (unsigned int)strtoul(s, (char **)&s2, 10);
    255         if (s2 != s) {
    256             /* s2 should be pointing just after the number.
    257              * If this is the end of the string, the user
    258              * has specified a number of bytes.  Otherwise,
    259              * there should be exactly one more character
    260              * that specifies a multiplier.
    261              */
    262             if (*s2 != '\0') {
    263                 char c;
    264 
    265                 /* The remainder of the string is either a single multiplier
    266                  * character, or nothing to indicate that the value is in
    267                  * bytes.
    268                  */
    269                 c = *s2++;
    270                 if (*s2 == '\0') {
    271                     unsigned int mul;
    272 
    273                     if (c == '\0') {
    274                         mul = 1;
    275                     } else if (c == 'k' || c == 'K') {
    276                         mul = 1024;
    277                     } else if (c == 'm' || c == 'M') {
    278                         mul = 1024 * 1024;
    279                     } else if (c == 'g' || c == 'G') {
    280                         mul = 1024 * 1024 * 1024;
    281                     } else {
    282                         /* Unknown multiplier character.
    283                          */
    284                         return 0;
    285                     }
    286 
    287                     if (val <= UINT_MAX / mul) {
    288                         val *= mul;
    289                     } else {
    290                         /* Clamp to a multiple of 1024.
    291                          */
    292                         val = UINT_MAX & ~(1024-1);
    293                     }
    294                 } else {
    295                     /* There's more than one character after the
    296                      * numeric part.
    297                      */
    298                     return 0;
    299                 }
    300             }
    301 
    302             /* The man page says that a -Xm value must be
    303              * a multiple of 1024.
    304              */
    305             if (val % div == 0) {
    306                 return val;
    307             }
    308         }
    309     }
    310 
    311     return 0;
    312 }
    313 
    314 /*
    315  * Handle one of the JDWP name/value pairs.
    316  *
    317  * JDWP options are:
    318  *  help: if specified, show help message and bail
    319  *  transport: may be dt_socket or dt_shmem
    320  *  address: for dt_socket, "host:port", or just "port" when listening
    321  *  server: if "y", wait for debugger to attach; if "n", attach to debugger
    322  *  timeout: how long to wait for debugger to connect / listen
    323  *
    324  * Useful with server=n (these aren't supported yet):
    325  *  onthrow=<exception-name>: connect to debugger when exception thrown
    326  *  onuncaught=y|n: connect to debugger when uncaught exception thrown
    327  *  launch=<command-line>: launch the debugger itself
    328  *
    329  * The "transport" option is required, as is "address" if server=n.
    330  */
    331 static bool handleJdwpOption(const char* name, const char* value)
    332 {
    333     if (strcmp(name, "transport") == 0) {
    334         if (strcmp(value, "dt_socket") == 0) {
    335             gDvm.jdwpTransport = kJdwpTransportSocket;
    336         } else if (strcmp(value, "dt_android_adb") == 0) {
    337             gDvm.jdwpTransport = kJdwpTransportAndroidAdb;
    338         } else {
    339             LOGE("JDWP transport '%s' not supported\n", value);
    340             return false;
    341         }
    342     } else if (strcmp(name, "server") == 0) {
    343         if (*value == 'n')
    344             gDvm.jdwpServer = false;
    345         else if (*value == 'y')
    346             gDvm.jdwpServer = true;
    347         else {
    348             LOGE("JDWP option 'server' must be 'y' or 'n'\n");
    349             return false;
    350         }
    351     } else if (strcmp(name, "suspend") == 0) {
    352         if (*value == 'n')
    353             gDvm.jdwpSuspend = false;
    354         else if (*value == 'y')
    355             gDvm.jdwpSuspend = true;
    356         else {
    357             LOGE("JDWP option 'suspend' must be 'y' or 'n'\n");
    358             return false;
    359         }
    360     } else if (strcmp(name, "address") == 0) {
    361         /* this is either <port> or <host>:<port> */
    362         const char* colon = strchr(value, ':');
    363         char* end;
    364         long port;
    365 
    366         if (colon != NULL) {
    367             free(gDvm.jdwpHost);
    368             gDvm.jdwpHost = (char*) malloc(colon - value +1);
    369             strncpy(gDvm.jdwpHost, value, colon - value +1);
    370             gDvm.jdwpHost[colon-value] = '\0';
    371             value = colon + 1;
    372         }
    373         if (*value == '\0') {
    374             LOGE("JDWP address missing port\n");
    375             return false;
    376         }
    377         port = strtol(value, &end, 10);
    378         if (*end != '\0') {
    379             LOGE("JDWP address has junk in port field '%s'\n", value);
    380             return false;
    381         }
    382         gDvm.jdwpPort = port;
    383     } else if (strcmp(name, "launch") == 0 ||
    384                strcmp(name, "onthrow") == 0 ||
    385                strcmp(name, "oncaught") == 0 ||
    386                strcmp(name, "timeout") == 0)
    387     {
    388         /* valid but unsupported */
    389         LOGI("Ignoring JDWP option '%s'='%s'\n", name, value);
    390     } else {
    391         LOGI("Ignoring unrecognized JDWP option '%s'='%s'\n", name, value);
    392     }
    393 
    394     return true;
    395 }
    396 
    397 /*
    398  * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
    399  * "transport=dt_socket,address=8000,server=y,suspend=n"
    400  */
    401 static bool parseJdwpOptions(const char* str)
    402 {
    403     char* mangle = strdup(str);
    404     char* name = mangle;
    405     bool result = false;
    406 
    407     /*
    408      * Process all of the name=value pairs.
    409      */
    410     while (true) {
    411         char* value;
    412         char* comma;
    413 
    414         value = strchr(name, '=');
    415         if (value == NULL) {
    416             LOGE("JDWP opts: garbage at '%s'\n", name);
    417             goto bail;
    418         }
    419 
    420         comma = strchr(name, ',');      // use name, not value, for safety
    421         if (comma != NULL) {
    422             if (comma < value) {
    423                 LOGE("JDWP opts: found comma before '=' in '%s'\n", mangle);
    424                 goto bail;
    425             }
    426             *comma = '\0';
    427         }
    428 
    429         *value++ = '\0';        // stomp the '='
    430 
    431         if (!handleJdwpOption(name, value))
    432             goto bail;
    433 
    434         if (comma == NULL) {
    435             /* out of options */
    436             break;
    437         }
    438         name = comma+1;
    439     }
    440 
    441     /*
    442      * Make sure the combination of arguments makes sense.
    443      */
    444     if (gDvm.jdwpTransport == kJdwpTransportUnknown) {
    445         LOGE("JDWP opts: must specify transport\n");
    446         goto bail;
    447     }
    448     if (!gDvm.jdwpServer && (gDvm.jdwpHost == NULL || gDvm.jdwpPort == 0)) {
    449         LOGE("JDWP opts: when server=n, must specify host and port\n");
    450         goto bail;
    451     }
    452     // transport mandatory
    453     // outbound server address
    454 
    455     gDvm.jdwpConfigured = true;
    456     result = true;
    457 
    458 bail:
    459     free(mangle);
    460     return result;
    461 }
    462 
    463 /*
    464  * Handle one of the four kinds of assertion arguments.
    465  *
    466  * "pkgOrClass" is the last part of an enable/disable line.  For a package
    467  * the arg looks like "-ea:com.google.fubar...", for a class it looks
    468  * like "-ea:com.google.fubar.Wahoo".  The string we get starts at the ':'.
    469  *
    470  * For system assertions (-esa/-dsa), "pkgOrClass" is NULL.
    471  *
    472  * Multiple instances of these arguments can be specified, e.g. you can
    473  * enable assertions for a package and then disable them for one class in
    474  * the package.
    475  */
    476 static bool enableAssertions(const char* pkgOrClass, bool enable)
    477 {
    478     AssertionControl* pCtrl = &gDvm.assertionCtrl[gDvm.assertionCtrlCount++];
    479     pCtrl->enable = enable;
    480 
    481     if (pkgOrClass == NULL) {
    482         /* enable or disable for all system classes */
    483         pCtrl->isPackage = false;
    484         pCtrl->pkgOrClass = NULL;
    485         pCtrl->pkgOrClassLen = 0;
    486     } else {
    487         if (*pkgOrClass == '\0') {
    488             /* global enable/disable for all but system */
    489             pCtrl->isPackage = false;
    490             pCtrl->pkgOrClass = strdup("");
    491             pCtrl->pkgOrClassLen = 0;
    492         } else {
    493             pCtrl->pkgOrClass = dvmDotToSlash(pkgOrClass+1);    // skip ':'
    494             if (pCtrl->pkgOrClass == NULL) {
    495                 /* can happen if class name includes an illegal '/' */
    496                 LOGW("Unable to process assertion arg '%s'\n", pkgOrClass);
    497                 return false;
    498             }
    499 
    500             int len = strlen(pCtrl->pkgOrClass);
    501             if (len >= 3 && strcmp(pCtrl->pkgOrClass + len-3, "///") == 0) {
    502                 /* mark as package, truncate two of the three slashes */
    503                 pCtrl->isPackage = true;
    504                 *(pCtrl->pkgOrClass + len-2) = '\0';
    505                 pCtrl->pkgOrClassLen = len - 2;
    506             } else {
    507                 /* just a class */
    508                 pCtrl->isPackage = false;
    509                 pCtrl->pkgOrClassLen = len;
    510             }
    511         }
    512     }
    513 
    514     return true;
    515 }
    516 
    517 /*
    518  * Turn assertions on when requested to do so by the Zygote.
    519  *
    520  * This is a bit sketchy.  We can't (easily) go back and fiddle with all
    521  * of the classes that have already been initialized, so this only
    522  * affects classes that have yet to be loaded.  If some or all assertions
    523  * have been enabled through some other means, we don't want to mess with
    524  * it here, so we do nothing.  Finally, we assume that there's room in
    525  * "assertionCtrl" to hold at least one entry; this is guaranteed by the
    526  * allocator.
    527  *
    528  * This must only be called from the main thread during zygote init.
    529  */
    530 void dvmLateEnableAssertions(void)
    531 {
    532     if (gDvm.assertionCtrl == NULL) {
    533         LOGD("Not late-enabling assertions: no assertionCtrl array\n");
    534         return;
    535     } else if (gDvm.assertionCtrlCount != 0) {
    536         LOGD("Not late-enabling assertions: some asserts already configured\n");
    537         return;
    538     }
    539     LOGD("Late-enabling assertions\n");
    540 
    541     /* global enable for all but system */
    542     AssertionControl* pCtrl = gDvm.assertionCtrl;
    543     pCtrl->pkgOrClass = strdup("");
    544     pCtrl->pkgOrClassLen = 0;
    545     pCtrl->isPackage = false;
    546     pCtrl->enable = true;
    547     gDvm.assertionCtrlCount = 1;
    548 }
    549 
    550 
    551 /*
    552  * Release memory associated with the AssertionCtrl array.
    553  */
    554 static void freeAssertionCtrl(void)
    555 {
    556     int i;
    557 
    558     for (i = 0; i < gDvm.assertionCtrlCount; i++)
    559         free(gDvm.assertionCtrl[i].pkgOrClass);
    560     free(gDvm.assertionCtrl);
    561 }
    562 
    563 #if defined(WITH_JIT)
    564 /* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
    565 static void processXjitop(const char *opt)
    566 {
    567     if (opt[7] == ':') {
    568         const char *startPtr = &opt[8];
    569         char *endPtr = NULL;
    570 
    571         do {
    572             long startValue, endValue;
    573 
    574             startValue = strtol(startPtr, &endPtr, 16);
    575             if (startPtr != endPtr) {
    576                 /* Just in case value is out of range */
    577                 startValue &= 0xff;
    578 
    579                 if (*endPtr == '-') {
    580                     endValue = strtol(endPtr+1, &endPtr, 16);
    581                     endValue &= 0xff;
    582                 } else {
    583                     endValue = startValue;
    584                 }
    585 
    586                 for (; startValue <= endValue; startValue++) {
    587                     LOGW("Dalvik opcode %x is selected for debugging",
    588                          (unsigned int) startValue);
    589                     /* Mark the corresponding bit to 1 */
    590                     gDvmJit.opList[startValue >> 3] |=
    591                         1 << (startValue & 0x7);
    592                 }
    593 
    594                 if (*endPtr == 0) {
    595                     break;
    596                 }
    597 
    598                 startPtr = endPtr + 1;
    599 
    600                 continue;
    601             } else {
    602                 if (*endPtr != 0) {
    603                     dvmFprintf(stderr,
    604                         "Warning: Unrecognized opcode value substring "
    605                         "%s\n", endPtr);
    606                 }
    607                 break;
    608             }
    609         } while (1);
    610     } else {
    611         int i;
    612         for (i = 0; i < 32; i++) {
    613             gDvmJit.opList[i] = 0xff;
    614         }
    615         dvmFprintf(stderr, "Warning: select all opcodes\n");
    616     }
    617 }
    618 
    619 /* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
    620 static void processXjitmethod(const char *opt)
    621 {
    622     char *buf = strdup(&opt[12]);
    623     char *start, *end;
    624 
    625     gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
    626 
    627     start = buf;
    628     /*
    629      * Break comma-separated method signatures and enter them into the hash
    630      * table individually.
    631      */
    632     do {
    633         int hashValue;
    634 
    635         end = strchr(start, ',');
    636         if (end) {
    637             *end = 0;
    638         }
    639 
    640         hashValue = dvmComputeUtf8Hash(start);
    641 
    642         dvmHashTableLookup(gDvmJit.methodTable, hashValue,
    643                            strdup(start),
    644                            (HashCompareFunc) strcmp, true);
    645         if (end) {
    646             start = end + 1;
    647         } else {
    648             break;
    649         }
    650     } while (1);
    651     free(buf);
    652 }
    653 #endif
    654 
    655 /*
    656  * Process an argument vector full of options.  Unlike standard C programs,
    657  * argv[0] does not contain the name of the program.
    658  *
    659  * If "ignoreUnrecognized" is set, we ignore options starting with "-X" or "_"
    660  * that we don't recognize.  Otherwise, we return with an error as soon as
    661  * we see anything we can't identify.
    662  *
    663  * Returns 0 on success, -1 on failure, and 1 for the special case of
    664  * "-version" where we want to stop without showing an error message.
    665  */
    666 static int dvmProcessOptions(int argc, const char* const argv[],
    667     bool ignoreUnrecognized)
    668 {
    669     int i;
    670 
    671     LOGV("VM options (%d):\n", argc);
    672     for (i = 0; i < argc; i++)
    673         LOGV("  %d: '%s'\n", i, argv[i]);
    674 
    675     /*
    676      * Over-allocate AssertionControl array for convenience.  If allocated,
    677      * the array must be able to hold at least one entry, so that the
    678      * zygote-time activation can do its business.
    679      */
    680     assert(gDvm.assertionCtrl == NULL);
    681     if (argc > 0) {
    682         gDvm.assertionCtrl =
    683             (AssertionControl*) malloc(sizeof(AssertionControl) * argc);
    684         if (gDvm.assertionCtrl == NULL)
    685             return -1;
    686         assert(gDvm.assertionCtrlCount == 0);
    687     }
    688 
    689     for (i = 0; i < argc; i++) {
    690         if (strcmp(argv[i], "-help") == 0) {
    691             /* show usage and stop */
    692             return -1;
    693 
    694         } else if (strcmp(argv[i], "-version") == 0) {
    695             /* show version and stop */
    696             showVersion();
    697             return 1;
    698         } else if (strcmp(argv[i], "-showversion") == 0) {
    699             /* show version and continue */
    700             showVersion();
    701 
    702         } else if (strcmp(argv[i], "-classpath") == 0 ||
    703                    strcmp(argv[i], "-cp") == 0)
    704         {
    705             /* set classpath */
    706             if (i == argc-1) {
    707                 dvmFprintf(stderr, "Missing classpath path list\n");
    708                 return -1;
    709             }
    710             free(gDvm.classPathStr); /* in case we have compiled-in default */
    711             gDvm.classPathStr = strdup(argv[++i]);
    712 
    713         } else if (strncmp(argv[i], "-Xbootclasspath:",
    714                 sizeof("-Xbootclasspath:")-1) == 0)
    715         {
    716             /* set bootclasspath */
    717             const char* path = argv[i] + sizeof("-Xbootclasspath:")-1;
    718 
    719             if (*path == '\0') {
    720                 dvmFprintf(stderr, "Missing bootclasspath path list\n");
    721                 return -1;
    722             }
    723             free(gDvm.bootClassPathStr);
    724             gDvm.bootClassPathStr = strdup(path);
    725 
    726             /*
    727              * TODO: support -Xbootclasspath/a and /p, which append or
    728              * prepend to the default bootclasspath.  We set the default
    729              * path earlier.
    730              */
    731 
    732         } else if (strncmp(argv[i], "-D", 2) == 0) {
    733             /* set property */
    734             dvmAddCommandLineProperty(argv[i] + 2);
    735 
    736         } else if (strcmp(argv[i], "-jar") == 0) {
    737             // TODO: handle this; name of jar should be in argv[i+1]
    738             dvmFprintf(stderr, "-jar not yet handled\n");
    739             assert(false);
    740 
    741         } else if (strncmp(argv[i], "-Xms", 4) == 0) {
    742             unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
    743             if (val != 0) {
    744                 if (val >= kMinHeapStartSize && val <= kMaxHeapSize) {
    745                     gDvm.heapSizeStart = val;
    746                 } else {
    747                     dvmFprintf(stderr,
    748                         "Invalid -Xms '%s', range is %dKB to %dKB\n",
    749                         argv[i], kMinHeapStartSize/1024, kMaxHeapSize/1024);
    750                     return -1;
    751                 }
    752             } else {
    753                 dvmFprintf(stderr, "Invalid -Xms option '%s'\n", argv[i]);
    754                 return -1;
    755             }
    756         } else if (strncmp(argv[i], "-Xmx", 4) == 0) {
    757             unsigned int val = dvmParseMemOption(argv[i]+4, 1024);
    758             if (val != 0) {
    759                 if (val >= kMinHeapSize && val <= kMaxHeapSize) {
    760                     gDvm.heapSizeMax = val;
    761                 } else {
    762                     dvmFprintf(stderr,
    763                         "Invalid -Xmx '%s', range is %dKB to %dKB\n",
    764                         argv[i], kMinHeapSize/1024, kMaxHeapSize/1024);
    765                     return -1;
    766                 }
    767             } else {
    768                 dvmFprintf(stderr, "Invalid -Xmx option '%s'\n", argv[i]);
    769                 return -1;
    770             }
    771         } else if (strncmp(argv[i], "-Xss", 4) == 0) {
    772             unsigned int val = dvmParseMemOption(argv[i]+4, 1);
    773             if (val != 0) {
    774                 if (val >= kMinStackSize && val <= kMaxStackSize) {
    775                     gDvm.stackSize = val;
    776                 } else {
    777                     dvmFprintf(stderr, "Invalid -Xss '%s', range is %d to %d\n",
    778                         argv[i], kMinStackSize, kMaxStackSize);
    779                     return -1;
    780                 }
    781             } else {
    782                 dvmFprintf(stderr, "Invalid -Xss option '%s'\n", argv[i]);
    783                 return -1;
    784             }
    785 
    786         } else if (strcmp(argv[i], "-verbose") == 0 ||
    787             strcmp(argv[i], "-verbose:class") == 0)
    788         {
    789             // JNI spec says "-verbose:gc,class" is valid, but cmd line
    790             // doesn't work that way; may want to support.
    791             gDvm.verboseClass = true;
    792         } else if (strcmp(argv[i], "-verbose:jni") == 0) {
    793             gDvm.verboseJni = true;
    794         } else if (strcmp(argv[i], "-verbose:gc") == 0) {
    795             gDvm.verboseGc = true;
    796         } else if (strcmp(argv[i], "-verbose:shutdown") == 0) {
    797             gDvm.verboseShutdown = true;
    798 
    799         } else if (strncmp(argv[i], "-enableassertions", 17) == 0) {
    800             enableAssertions(argv[i] + 17, true);
    801         } else if (strncmp(argv[i], "-ea", 3) == 0) {
    802             enableAssertions(argv[i] + 3, true);
    803         } else if (strncmp(argv[i], "-disableassertions", 18) == 0) {
    804             enableAssertions(argv[i] + 18, false);
    805         } else if (strncmp(argv[i], "-da", 3) == 0) {
    806             enableAssertions(argv[i] + 3, false);
    807         } else if (strcmp(argv[i], "-enablesystemassertions") == 0 ||
    808                    strcmp(argv[i], "-esa") == 0)
    809         {
    810             enableAssertions(NULL, true);
    811         } else if (strcmp(argv[i], "-disablesystemassertions") == 0 ||
    812                    strcmp(argv[i], "-dsa") == 0)
    813         {
    814             enableAssertions(NULL, false);
    815 
    816         } else if (strncmp(argv[i], "-Xcheck:jni", 11) == 0) {
    817             /* nothing to do now -- was handled during JNI init */
    818 
    819         } else if (strcmp(argv[i], "-Xdebug") == 0) {
    820             /* accept but ignore */
    821 
    822         } else if (strncmp(argv[i], "-Xrunjdwp:", 10) == 0 ||
    823             strncmp(argv[i], "-agentlib:jdwp=", 15) == 0)
    824         {
    825             const char* tail;
    826 
    827             if (argv[i][1] == 'X')
    828                 tail = argv[i] + 10;
    829             else
    830                 tail = argv[i] + 15;
    831 
    832             if (strncmp(tail, "help", 4) == 0 || !parseJdwpOptions(tail)) {
    833                 showJdwpHelp();
    834                 return 1;
    835             }
    836         } else if (strcmp(argv[i], "-Xrs") == 0) {
    837             gDvm.reduceSignals = true;
    838         } else if (strcmp(argv[i], "-Xnoquithandler") == 0) {
    839             /* disables SIGQUIT handler thread while still blocking SIGQUIT */
    840             /* (useful if we don't want thread but system still signals us) */
    841             gDvm.noQuitHandler = true;
    842         } else if (strcmp(argv[i], "-Xzygote") == 0) {
    843             gDvm.zygote = true;
    844 #if defined(WITH_JIT)
    845             gDvmJit.runningInAndroidFramework = true;
    846 #endif
    847         } else if (strncmp(argv[i], "-Xdexopt:", 9) == 0) {
    848             if (strcmp(argv[i] + 9, "none") == 0)
    849                 gDvm.dexOptMode = OPTIMIZE_MODE_NONE;
    850             else if (strcmp(argv[i] + 9, "verified") == 0)
    851                 gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
    852             else if (strcmp(argv[i] + 9, "all") == 0)
    853                 gDvm.dexOptMode = OPTIMIZE_MODE_ALL;
    854             else {
    855                 dvmFprintf(stderr, "Unrecognized dexopt option '%s'\n",argv[i]);
    856                 return -1;
    857             }
    858         } else if (strncmp(argv[i], "-Xverify:", 9) == 0) {
    859             if (strcmp(argv[i] + 9, "none") == 0)
    860                 gDvm.classVerifyMode = VERIFY_MODE_NONE;
    861             else if (strcmp(argv[i] + 9, "remote") == 0)
    862                 gDvm.classVerifyMode = VERIFY_MODE_REMOTE;
    863             else if (strcmp(argv[i] + 9, "all") == 0)
    864                 gDvm.classVerifyMode = VERIFY_MODE_ALL;
    865             else {
    866                 dvmFprintf(stderr, "Unrecognized verify option '%s'\n",argv[i]);
    867                 return -1;
    868             }
    869         } else if (strncmp(argv[i], "-Xjnigreflimit:", 15) == 0) {
    870             int lim = atoi(argv[i] + 15);
    871             if (lim < 200 || (lim % 100) != 0) {
    872                 dvmFprintf(stderr, "Bad value for -Xjnigreflimit: '%s'\n",
    873                     argv[i]+15);
    874                 return -1;
    875             }
    876             gDvm.jniGrefLimit = lim;
    877         } else if (strncmp(argv[i], "-Xjnitrace:", 11) == 0) {
    878             gDvm.jniTrace = strdup(argv[i] + 11);
    879         } else if (strcmp(argv[i], "-Xlog-stdio") == 0) {
    880             gDvm.logStdio = true;
    881 
    882         } else if (strncmp(argv[i], "-Xint", 5) == 0) {
    883             if (argv[i][5] == ':') {
    884                 if (strcmp(argv[i] + 6, "portable") == 0)
    885                     gDvm.executionMode = kExecutionModeInterpPortable;
    886                 else if (strcmp(argv[i] + 6, "fast") == 0)
    887                     gDvm.executionMode = kExecutionModeInterpFast;
    888 #ifdef WITH_JIT
    889                 else if (strcmp(argv[i] + 6, "jit") == 0)
    890                     gDvm.executionMode = kExecutionModeJit;
    891 #endif
    892                 else {
    893                     dvmFprintf(stderr,
    894                         "Warning: Unrecognized interpreter mode %s\n",argv[i]);
    895                     /* keep going */
    896                 }
    897             } else {
    898                 /* disable JIT if it was enabled by default */
    899                 gDvm.executionMode = kExecutionModeInterpFast;
    900             }
    901 
    902         } else if (strncmp(argv[i], "-Xlockprofthreshold:", 20) == 0) {
    903             gDvm.lockProfThreshold = atoi(argv[i] + 20);
    904 
    905 #ifdef WITH_JIT
    906         } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
    907             processXjitop(argv[i]);
    908         } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
    909             processXjitmethod(argv[i]);
    910         } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
    911           gDvmJit.blockingMode = true;
    912         } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
    913           gDvmJit.threshold = atoi(argv[i] + 15);
    914         } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
    915           gDvmJit.includeSelectedOp = true;
    916         } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
    917           gDvmJit.includeSelectedMethod = true;
    918         } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
    919           gDvmJit.checkCallGraph = true;
    920           /* Need to enable blocking mode due to stack crawling */
    921           gDvmJit.blockingMode = true;
    922         } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
    923           gDvmJit.printMe = true;
    924         } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
    925           gDvmJit.profile = true;
    926         } else if (strncmp(argv[i], "-Xjitdisableopt", 15) == 0) {
    927           /* Disable selected optimizations */
    928           if (argv[i][15] == ':') {
    929               sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
    930           /* Disable all optimizations */
    931           } else {
    932               gDvmJit.disableOpt = -1;
    933           }
    934 #endif
    935 
    936         } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
    937 #ifdef WITH_DEADLOCK_PREDICTION
    938             if (strcmp(argv[i] + 18, "off") == 0)
    939                 gDvm.deadlockPredictMode = kDPOff;
    940             else if (strcmp(argv[i] + 18, "warn") == 0)
    941                 gDvm.deadlockPredictMode = kDPWarn;
    942             else if (strcmp(argv[i] + 18, "err") == 0)
    943                 gDvm.deadlockPredictMode = kDPErr;
    944             else if (strcmp(argv[i] + 18, "abort") == 0)
    945                 gDvm.deadlockPredictMode = kDPAbort;
    946             else {
    947                 dvmFprintf(stderr, "Bad value for -Xdeadlockpredict");
    948                 return -1;
    949             }
    950             if (gDvm.deadlockPredictMode != kDPOff)
    951                 LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18);
    952 #endif
    953 
    954         } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) {
    955             gDvm.stackTraceFile = strdup(argv[i]+17);
    956 
    957         } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
    958             gDvm.generateRegisterMaps = true;
    959             LOGV("Register maps will be generated during verification\n");
    960 
    961         } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
    962             if (strcmp(argv[i] + 5, "precise") == 0)
    963                 gDvm.preciseGc = true;
    964             else if (strcmp(argv[i] + 5, "noprecise") == 0)
    965                 gDvm.preciseGc = false;
    966             else if (strcmp(argv[i] + 5, "preverify") == 0)
    967                 gDvm.preVerify = true;
    968             else if (strcmp(argv[i] + 5, "nopreverify") == 0)
    969                 gDvm.preVerify = false;
    970             else if (strcmp(argv[i] + 5, "postverify") == 0)
    971                 gDvm.postVerify = true;
    972             else if (strcmp(argv[i] + 5, "nopostverify") == 0)
    973                 gDvm.postVerify = false;
    974             else if (strcmp(argv[i] + 5, "concurrent") == 0)
    975                 gDvm.concurrentMarkSweep = true;
    976             else if (strcmp(argv[i] + 5, "noconcurrent") == 0)
    977                 gDvm.concurrentMarkSweep = false;
    978             else if (strcmp(argv[i] + 5, "verifycardtable") == 0)
    979                 gDvm.verifyCardTable = true;
    980             else if (strcmp(argv[i] + 5, "noverifycardtable") == 0)
    981                 gDvm.verifyCardTable = false;
    982             else {
    983                 dvmFprintf(stderr, "Bad value for -Xgc");
    984                 return -1;
    985             }
    986             LOGV("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
    987 
    988         } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
    989             gDvm.verifyDexChecksum = true;
    990 
    991         } else if (strcmp(argv[i], "-Xprofile:wallclock") == 0) {
    992             gDvm.profilerWallClock = true;
    993 
    994         } else {
    995             if (!ignoreUnrecognized) {
    996                 dvmFprintf(stderr, "Unrecognized option '%s'\n", argv[i]);
    997                 return -1;
    998             }
    999         }
   1000     }
   1001 
   1002     if (gDvm.heapSizeStart > gDvm.heapSizeMax) {
   1003         dvmFprintf(stderr, "Heap start size must be <= heap max size\n");
   1004         return -1;
   1005     }
   1006 
   1007     return 0;
   1008 }
   1009 
   1010 /*
   1011  * Set defaults for fields altered or modified by arguments.
   1012  *
   1013  * Globals are initialized to 0 (a/k/a NULL or false).
   1014  */
   1015 static void setCommandLineDefaults()
   1016 {
   1017     const char* envStr;
   1018 
   1019     envStr = getenv("CLASSPATH");
   1020     if (envStr != NULL)
   1021         gDvm.classPathStr = strdup(envStr);
   1022     else
   1023         gDvm.classPathStr = strdup(".");
   1024     envStr = getenv("BOOTCLASSPATH");
   1025     if (envStr != NULL)
   1026         gDvm.bootClassPathStr = strdup(envStr);
   1027     else
   1028         gDvm.bootClassPathStr = strdup(".");
   1029 
   1030     /* Defaults overridden by -Xms and -Xmx.
   1031      * TODO: base these on a system or application-specific default
   1032      */
   1033     gDvm.heapSizeStart = 2 * 1024 * 1024;   // Spec says 16MB; too big for us.
   1034     gDvm.heapSizeMax = 16 * 1024 * 1024;    // Spec says 75% physical mem
   1035     gDvm.stackSize = kDefaultStackSize;
   1036 
   1037     gDvm.concurrentMarkSweep = true;
   1038 
   1039     /* gDvm.jdwpSuspend = true; */
   1040 
   1041     /* allowed unless zygote config doesn't allow it */
   1042     gDvm.jdwpAllowed = true;
   1043 
   1044     /* default verification and optimization modes */
   1045     gDvm.classVerifyMode = VERIFY_MODE_ALL;
   1046     gDvm.dexOptMode = OPTIMIZE_MODE_VERIFIED;
   1047 
   1048     /*
   1049      * Default execution mode.
   1050      *
   1051      * This should probably interact with the mterp code somehow, e.g. if
   1052      * we know we're using the "desktop" build we should probably be
   1053      * using "portable" rather than "fast".
   1054      */
   1055 #if defined(WITH_JIT)
   1056     gDvm.executionMode = kExecutionModeJit;
   1057 #else
   1058     gDvm.executionMode = kExecutionModeInterpFast;
   1059 #endif
   1060 
   1061     /*
   1062      * SMP support is a compile-time define, but we may want to have
   1063      * dexopt target a differently-configured device.
   1064      */
   1065     gDvm.dexOptForSmp = (ANDROID_SMP != 0);
   1066 }
   1067 
   1068 
   1069 /*
   1070  * Handle a SIGBUS, which frequently occurs because somebody replaced an
   1071  * optimized DEX file out from under us.
   1072  */
   1073 static void busCatcher(int signum, siginfo_t* info, void* context)
   1074 {
   1075     void* addr = info->si_addr;
   1076 
   1077     LOGE("Caught a SIGBUS (%d), addr=%p\n", signum, addr);
   1078 
   1079     /*
   1080      * If we return at this point the SIGBUS just keeps happening, so we
   1081      * remove the signal handler and allow it to kill us.  TODO: restore
   1082      * the original, which points to a debuggerd stub; if we don't then
   1083      * debuggerd won't be notified.
   1084      */
   1085     signal(SIGBUS, SIG_DFL);
   1086 }
   1087 
   1088 /*
   1089  * Configure signals.  We need to block SIGQUIT so that the signal only
   1090  * reaches the dump-stack-trace thread.
   1091  *
   1092  * This can be disabled with the "-Xrs" flag.
   1093  */
   1094 static void blockSignals()
   1095 {
   1096     sigset_t mask;
   1097     int cc;
   1098 
   1099     sigemptyset(&mask);
   1100     sigaddset(&mask, SIGQUIT);
   1101     sigaddset(&mask, SIGUSR1);      // used to initiate heap dump
   1102 #if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
   1103     sigaddset(&mask, SIGUSR2);      // used to investigate JIT internals
   1104 #endif
   1105     //sigaddset(&mask, SIGPIPE);
   1106     cc = sigprocmask(SIG_BLOCK, &mask, NULL);
   1107     assert(cc == 0);
   1108 
   1109     if (false) {
   1110         /* TODO: save the old sigaction in a global */
   1111         struct sigaction sa;
   1112         memset(&sa, 0, sizeof(sa));
   1113         sa.sa_sigaction = busCatcher;
   1114         sa.sa_flags = SA_SIGINFO;
   1115         cc = sigaction(SIGBUS, &sa, NULL);
   1116         assert(cc == 0);
   1117     }
   1118 }
   1119 
   1120 /*
   1121  * VM initialization.  Pass in any options provided on the command line.
   1122  * Do not pass in the class name or the options for the class.
   1123  *
   1124  * Returns 0 on success.
   1125  */
   1126 int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized,
   1127     JNIEnv* pEnv)
   1128 {
   1129     int i, cc;
   1130 
   1131     assert(gDvm.initializing);
   1132 
   1133     LOGV("VM init args (%d):\n", argc);
   1134     for (i = 0; i < argc; i++)
   1135         LOGV("  %d: '%s'\n", i, argv[i]);
   1136 
   1137     setCommandLineDefaults();
   1138 
   1139     /* prep properties storage */
   1140     if (!dvmPropertiesStartup(argc))
   1141         goto fail;
   1142 
   1143     /*
   1144      * Process the option flags (if any).
   1145      */
   1146     cc = dvmProcessOptions(argc, argv, ignoreUnrecognized);
   1147     if (cc != 0) {
   1148         if (cc < 0) {
   1149             dvmFprintf(stderr, "\n");
   1150             dvmUsage("dalvikvm");
   1151         }
   1152         goto fail;
   1153     }
   1154 
   1155 #if WITH_EXTRA_GC_CHECKS > 1
   1156     /* only "portable" interp has the extra goodies */
   1157     if (gDvm.executionMode != kExecutionModeInterpPortable) {
   1158         LOGI("Switching to 'portable' interpreter for GC checks\n");
   1159         gDvm.executionMode = kExecutionModeInterpPortable;
   1160     }
   1161 #endif
   1162 
   1163     /* Configure group scheduling capabilities */
   1164     if (!access("/dev/cpuctl/tasks", F_OK)) {
   1165         LOGV("Using kernel group scheduling");
   1166         gDvm.kernelGroupScheduling = 1;
   1167     } else {
   1168         LOGV("Using kernel scheduler policies");
   1169     }
   1170 
   1171     /* configure signal handling */
   1172     if (!gDvm.reduceSignals)
   1173         blockSignals();
   1174 
   1175     /* verify system page size */
   1176     if (sysconf(_SC_PAGESIZE) != SYSTEM_PAGE_SIZE) {
   1177         LOGE("ERROR: expected page size %d, got %d\n",
   1178             SYSTEM_PAGE_SIZE, (int) sysconf(_SC_PAGESIZE));
   1179         goto fail;
   1180     }
   1181 
   1182     /* mterp setup */
   1183     LOGV("Using executionMode %d\n", gDvm.executionMode);
   1184     dvmCheckAsmConstants();
   1185 
   1186     /*
   1187      * Initialize components.
   1188      */
   1189     if (!dvmAllocTrackerStartup())
   1190         goto fail;
   1191     if (!dvmGcStartup())
   1192         goto fail;
   1193     if (!dvmThreadStartup())
   1194         goto fail;
   1195     if (!dvmInlineNativeStartup())
   1196         goto fail;
   1197     if (!dvmVerificationStartup())
   1198         goto fail;
   1199     if (!dvmRegisterMapStartup())
   1200         goto fail;
   1201     if (!dvmInstanceofStartup())
   1202         goto fail;
   1203     if (!dvmClassStartup())
   1204         goto fail;
   1205     if (!dvmThreadObjStartup())
   1206         goto fail;
   1207     if (!dvmExceptionStartup())
   1208         goto fail;
   1209     if (!dvmStringInternStartup())
   1210         goto fail;
   1211     if (!dvmNativeStartup())
   1212         goto fail;
   1213     if (!dvmInternalNativeStartup())
   1214         goto fail;
   1215     if (!dvmJniStartup())
   1216         goto fail;
   1217     if (!dvmReflectStartup())
   1218         goto fail;
   1219     if (!dvmProfilingStartup())
   1220         goto fail;
   1221 
   1222     /* make sure we got these [can this go away?] */
   1223     assert(gDvm.classJavaLangClass != NULL);
   1224     assert(gDvm.classJavaLangObject != NULL);
   1225     //assert(gDvm.classJavaLangString != NULL);
   1226     assert(gDvm.classJavaLangThread != NULL);
   1227     assert(gDvm.classJavaLangVMThread != NULL);
   1228     assert(gDvm.classJavaLangThreadGroup != NULL);
   1229 
   1230     /*
   1231      * Make sure these exist.  If they don't, we can return a failure out
   1232      * of main and nip the whole thing in the bud.
   1233      */
   1234     static const char* earlyClasses[] = {
   1235         "Ljava/lang/InternalError;",
   1236         "Ljava/lang/StackOverflowError;",
   1237         "Ljava/lang/UnsatisfiedLinkError;",
   1238         "Ljava/lang/NoClassDefFoundError;",
   1239         NULL
   1240     };
   1241     const char** pClassName;
   1242     for (pClassName = earlyClasses; *pClassName != NULL; pClassName++) {
   1243         if (dvmFindSystemClassNoInit(*pClassName) == NULL)
   1244             goto fail;
   1245     }
   1246 
   1247     /*
   1248      * Miscellaneous class library validation.
   1249      */
   1250     if (!dvmValidateBoxClasses())
   1251         goto fail;
   1252 
   1253     /*
   1254      * Do the last bits of Thread struct initialization we need to allow
   1255      * JNI calls to work.
   1256      */
   1257     if (!dvmPrepMainForJni(pEnv))
   1258         goto fail;
   1259 
   1260     /*
   1261      * Register the system native methods, which are registered through JNI.
   1262      */
   1263     if (!registerSystemNatives(pEnv))
   1264         goto fail;
   1265 
   1266     /*
   1267      * Do some "late" initialization for the memory allocator.  This may
   1268      * allocate storage and initialize classes.
   1269      */
   1270     if (!dvmCreateStockExceptions())
   1271         goto fail;
   1272 
   1273     /*
   1274      * At this point, the VM is in a pretty good state.  Finish prep on
   1275      * the main thread (specifically, create a java.lang.Thread object to go
   1276      * along with our Thread struct).  Note we will probably be executing
   1277      * some interpreted class initializer code in here.
   1278      */
   1279     if (!dvmPrepMainThread())
   1280         goto fail;
   1281 
   1282     /*
   1283      * Make sure we haven't accumulated any tracked references.  The main
   1284      * thread should be starting with a clean slate.
   1285      */
   1286     if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
   1287     {
   1288         LOGW("Warning: tracked references remain post-initialization\n");
   1289         dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
   1290     }
   1291 
   1292     /* general debugging setup */
   1293     if (!dvmDebuggerStartup())
   1294         goto fail;
   1295 
   1296     /*
   1297      * Init for either zygote mode or non-zygote mode.  The key difference
   1298      * is that we don't start any additional threads in Zygote mode.
   1299      */
   1300     if (gDvm.zygote) {
   1301         if (!dvmInitZygote())
   1302             goto fail;
   1303     } else {
   1304         if (!dvmInitAfterZygote())
   1305             goto fail;
   1306     }
   1307 
   1308 
   1309 #ifndef NDEBUG
   1310     if (!dvmTestHash())
   1311         LOGE("dmvTestHash FAILED\n");
   1312     if (false /*noisy!*/ && !dvmTestIndirectRefTable())
   1313         LOGE("dvmTestIndirectRefTable FAILED\n");
   1314 #endif
   1315 
   1316     assert(!dvmCheckException(dvmThreadSelf()));
   1317     gDvm.initExceptionCount = 0;
   1318 
   1319     return 0;
   1320 
   1321 fail:
   1322     dvmShutdown();
   1323     return 1;
   1324 }
   1325 
   1326 /*
   1327  * Register java.* natives from our class libraries.  We need to do
   1328  * this after we're ready for JNI registration calls, but before we
   1329  * do any class initialization.
   1330  *
   1331  * If we get this wrong, we will blow up in the ThreadGroup class init if
   1332  * interpreted code makes any reference to System.  It will likely do this
   1333  * since it wants to do some java.io.File setup (e.g. for static in/out/err).
   1334  *
   1335  * We need to have gDvm.initializing raised here so that JNI FindClass
   1336  * won't try to use the system/application class loader.
   1337  */
   1338 static bool registerSystemNatives(JNIEnv* pEnv)
   1339 {
   1340     Thread* self;
   1341 
   1342     /* main thread is always first in list */
   1343     self = gDvm.threadList;
   1344 
   1345     /* must set this before allowing JNI-based method registration */
   1346     self->status = THREAD_NATIVE;
   1347 
   1348     if (jniRegisterSystemMethods(pEnv) < 0) {
   1349         LOGW("jniRegisterSystemMethods failed\n");
   1350         return false;
   1351     }
   1352 
   1353     /* back to run mode */
   1354     self->status = THREAD_RUNNING;
   1355 
   1356     return true;
   1357 }
   1358 
   1359 
   1360 /*
   1361  * Do zygote-mode-only initialization.
   1362  */
   1363 static bool dvmInitZygote(void)
   1364 {
   1365     /* zygote goes into its own process group */
   1366     setpgid(0,0);
   1367 
   1368     return true;
   1369 }
   1370 
   1371 /*
   1372  * Do non-zygote-mode initialization.  This is done during VM init for
   1373  * standard startup, or after a "zygote fork" when creating a new process.
   1374  */
   1375 bool dvmInitAfterZygote(void)
   1376 {
   1377     u8 startHeap, startQuit, startJdwp;
   1378     u8 endHeap, endQuit, endJdwp;
   1379 
   1380     startHeap = dvmGetRelativeTimeUsec();
   1381 
   1382     /*
   1383      * Post-zygote heap initialization, including starting
   1384      * the HeapWorker thread.
   1385      */
   1386     if (!dvmGcStartupAfterZygote())
   1387         return false;
   1388 
   1389     endHeap = dvmGetRelativeTimeUsec();
   1390     startQuit = dvmGetRelativeTimeUsec();
   1391 
   1392     /* start signal catcher thread that dumps stacks on SIGQUIT */
   1393     if (!gDvm.reduceSignals && !gDvm.noQuitHandler) {
   1394         if (!dvmSignalCatcherStartup())
   1395             return false;
   1396     }
   1397 
   1398     /* start stdout/stderr copier, if requested */
   1399     if (gDvm.logStdio) {
   1400         if (!dvmStdioConverterStartup())
   1401             return false;
   1402     }
   1403 
   1404     endQuit = dvmGetRelativeTimeUsec();
   1405     startJdwp = dvmGetRelativeTimeUsec();
   1406 
   1407     /*
   1408      * Start JDWP thread.  If the command-line debugger flags specified
   1409      * "suspend=y", this will pause the VM.  We probably want this to
   1410      * come last.
   1411      */
   1412     if (!dvmInitJDWP()) {
   1413         LOGD("JDWP init failed; continuing anyway\n");
   1414     }
   1415 
   1416     endJdwp = dvmGetRelativeTimeUsec();
   1417 
   1418     LOGV("thread-start heap=%d quit=%d jdwp=%d total=%d usec\n",
   1419         (int)(endHeap-startHeap), (int)(endQuit-startQuit),
   1420         (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
   1421 
   1422 #ifdef WITH_JIT
   1423     if (gDvm.executionMode == kExecutionModeJit) {
   1424         if (!dvmCompilerStartup())
   1425             return false;
   1426     }
   1427 #endif
   1428 
   1429     return true;
   1430 }
   1431 
   1432 /*
   1433  * Prepare for a connection to a JDWP-compliant debugger.
   1434  *
   1435  * Note this needs to happen fairly late in the startup process, because
   1436  * we need to have all of the java.* native methods registered (which in
   1437  * turn requires JNI to be fully prepped).
   1438  *
   1439  * There are several ways to initialize:
   1440  *   server=n
   1441  *     We immediately try to connect to host:port.  Bail on failure.  On
   1442  *     success, send VM_START (suspending the VM if "suspend=y").
   1443  *   server=y suspend=n
   1444  *     Passively listen for a debugger to connect.  Return immediately.
   1445  *   server=y suspend=y
   1446  *     Wait until debugger connects.  Send VM_START ASAP, suspending the
   1447  *     VM after the message is sent.
   1448  *
   1449  * This gets more complicated with a nonzero value for "timeout".
   1450  */
   1451 static bool dvmInitJDWP(void)
   1452 {
   1453     assert(!gDvm.zygote);
   1454 
   1455     /*
   1456      * Init JDWP if the debugger is enabled.  This may connect out to a
   1457      * debugger, passively listen for a debugger, or block waiting for a
   1458      * debugger.
   1459      */
   1460     if (gDvm.jdwpAllowed && gDvm.jdwpConfigured) {
   1461         JdwpStartupParams params;
   1462 
   1463         if (gDvm.jdwpHost != NULL) {
   1464             if (strlen(gDvm.jdwpHost) >= sizeof(params.host)-1) {
   1465                 LOGE("ERROR: hostname too long: '%s'\n", gDvm.jdwpHost);
   1466                 return false;
   1467             }
   1468             strcpy(params.host, gDvm.jdwpHost);
   1469         } else {
   1470             params.host[0] = '\0';
   1471         }
   1472         params.transport = gDvm.jdwpTransport;
   1473         params.server = gDvm.jdwpServer;
   1474         params.suspend = gDvm.jdwpSuspend;
   1475         params.port = gDvm.jdwpPort;
   1476 
   1477         gDvm.jdwpState = dvmJdwpStartup(&params);
   1478         if (gDvm.jdwpState == NULL) {
   1479             LOGW("WARNING: debugger thread failed to initialize\n");
   1480             /* TODO: ignore? fail? need to mimic "expected" behavior */
   1481         }
   1482     }
   1483 
   1484     /*
   1485      * If a debugger has already attached, send the "welcome" message.  This
   1486      * may cause us to suspend all threads.
   1487      */
   1488     if (dvmJdwpIsActive(gDvm.jdwpState)) {
   1489         //dvmChangeStatus(NULL, THREAD_RUNNING);
   1490         if (!dvmJdwpPostVMStart(gDvm.jdwpState, gDvm.jdwpSuspend)) {
   1491             LOGW("WARNING: failed to post 'start' message to debugger\n");
   1492             /* keep going */
   1493         }
   1494         //dvmChangeStatus(NULL, THREAD_NATIVE);
   1495     }
   1496 
   1497     return true;
   1498 }
   1499 
   1500 /*
   1501  * An alternative to JNI_CreateJavaVM/dvmStartup that does the first bit
   1502  * of initialization and then returns with "initializing" still set.  (Used
   1503  * by DexOpt command-line utility.)
   1504  *
   1505  * Attempting to use JNI or internal natives will fail.  It's best if
   1506  * no bytecode gets executed, which means no <clinit>, which means no
   1507  * exception-throwing.  We check the "initializing" flag anyway when
   1508  * throwing an exception, so we can insert some code that avoids chucking
   1509  * an exception when we're optimizing stuff.
   1510  *
   1511  * Returns 0 on success.
   1512  */
   1513 int dvmPrepForDexOpt(const char* bootClassPath, DexOptimizerMode dexOptMode,
   1514     DexClassVerifyMode verifyMode, int dexoptFlags)
   1515 {
   1516     gDvm.initializing = true;
   1517     gDvm.optimizing = true;
   1518 
   1519     /* configure signal handling */
   1520     blockSignals();
   1521 
   1522     /* set some defaults */
   1523     setCommandLineDefaults();
   1524     free(gDvm.bootClassPathStr);
   1525     gDvm.bootClassPathStr = strdup(bootClassPath);
   1526 
   1527     /* set opt/verify modes */
   1528     gDvm.dexOptMode = dexOptMode;
   1529     gDvm.classVerifyMode = verifyMode;
   1530     gDvm.generateRegisterMaps = (dexoptFlags & DEXOPT_GEN_REGISTER_MAPS) != 0;
   1531     if (dexoptFlags & DEXOPT_SMP) {
   1532         assert((dexoptFlags & DEXOPT_UNIPROCESSOR) == 0);
   1533         gDvm.dexOptForSmp = true;
   1534     } else if (dexoptFlags & DEXOPT_UNIPROCESSOR) {
   1535         gDvm.dexOptForSmp = false;
   1536     } else {
   1537         gDvm.dexOptForSmp = (ANDROID_SMP != 0);
   1538     }
   1539 
   1540     /*
   1541      * Initialize the heap, some basic thread control mutexes, and
   1542      * get the bootclasspath prepped.
   1543      *
   1544      * We can't load any classes yet because we may not yet have a source
   1545      * for things like java.lang.Object and java.lang.Class.
   1546      */
   1547     if (!dvmGcStartup())
   1548         goto fail;
   1549     if (!dvmThreadStartup())
   1550         goto fail;
   1551     if (!dvmInlineNativeStartup())
   1552         goto fail;
   1553     if (!dvmVerificationStartup())
   1554         goto fail;
   1555     if (!dvmRegisterMapStartup())
   1556         goto fail;
   1557     if (!dvmInstanceofStartup())
   1558         goto fail;
   1559     if (!dvmClassStartup())
   1560         goto fail;
   1561 
   1562     /*
   1563      * We leave gDvm.initializing set to "true" so that, if we're not
   1564      * able to process the "core" classes, we don't go into a death-spin
   1565      * trying to throw a "class not found" exception.
   1566      */
   1567 
   1568     return 0;
   1569 
   1570 fail:
   1571     dvmShutdown();
   1572     return 1;
   1573 }
   1574 
   1575 
   1576 /*
   1577  * All threads have stopped.  Finish the shutdown procedure.
   1578  *
   1579  * We can also be called if startup fails partway through, so be prepared
   1580  * to deal with partially initialized data.
   1581  *
   1582  * Free any storage allocated in gGlobals.
   1583  *
   1584  * We can't dlclose() shared libs we've loaded, because it's possible a
   1585  * thread not associated with the VM is running code in one.
   1586  *
   1587  * This is called from the JNI DestroyJavaVM function, which can be
   1588  * called from any thread.  (In practice, this will usually run in the
   1589  * same thread that started the VM, a/k/a the main thread, but we don't
   1590  * want to assume that.)
   1591  */
   1592 void dvmShutdown(void)
   1593 {
   1594     LOGV("VM shutting down\n");
   1595 
   1596     if (CALC_CACHE_STATS)
   1597         dvmDumpAtomicCacheStats(gDvm.instanceofCache);
   1598 
   1599     /*
   1600      * Stop our internal threads.
   1601      */
   1602     dvmGcThreadShutdown();
   1603 
   1604     if (gDvm.jdwpState != NULL)
   1605         dvmJdwpShutdown(gDvm.jdwpState);
   1606     free(gDvm.jdwpHost);
   1607     gDvm.jdwpHost = NULL;
   1608     free(gDvm.jniTrace);
   1609     gDvm.jniTrace = NULL;
   1610     free(gDvm.stackTraceFile);
   1611     gDvm.stackTraceFile = NULL;
   1612 
   1613     /* tell signal catcher to shut down if it was started */
   1614     dvmSignalCatcherShutdown();
   1615 
   1616     /* shut down stdout/stderr conversion */
   1617     dvmStdioConverterShutdown();
   1618 
   1619 #ifdef WITH_JIT
   1620     if (gDvm.executionMode == kExecutionModeJit) {
   1621         /* shut down the compiler thread */
   1622         dvmCompilerShutdown();
   1623     }
   1624 #endif
   1625 
   1626     /*
   1627      * Kill any daemon threads that still exist.  Actively-running threads
   1628      * are likely to crash the process if they continue to execute while
   1629      * the VM shuts down.
   1630      */
   1631     dvmSlayDaemons();
   1632 
   1633     if (gDvm.verboseShutdown)
   1634         LOGD("VM cleaning up\n");
   1635 
   1636     dvmDebuggerShutdown();
   1637     dvmReflectShutdown();
   1638     dvmProfilingShutdown();
   1639     dvmJniShutdown();
   1640     dvmStringInternShutdown();
   1641     dvmExceptionShutdown();
   1642     dvmThreadShutdown();
   1643     dvmClassShutdown();
   1644     dvmVerificationShutdown();
   1645     dvmRegisterMapShutdown();
   1646     dvmInstanceofShutdown();
   1647     dvmInlineNativeShutdown();
   1648     dvmGcShutdown();
   1649     dvmAllocTrackerShutdown();
   1650     dvmPropertiesShutdown();
   1651 
   1652     /* these must happen AFTER dvmClassShutdown has walked through class data */
   1653     dvmNativeShutdown();
   1654     dvmInternalNativeShutdown();
   1655 
   1656     free(gDvm.bootClassPathStr);
   1657     free(gDvm.classPathStr);
   1658 
   1659     freeAssertionCtrl();
   1660 
   1661     /*
   1662      * We want valgrind to report anything we forget to free as "definitely
   1663      * lost".  If there's a pointer in the global chunk, it would be reported
   1664      * as "still reachable".  Erasing the memory fixes this.
   1665      *
   1666      * This must be erased to zero if we want to restart the VM within this
   1667      * process.
   1668      */
   1669     memset(&gDvm, 0xcd, sizeof(gDvm));
   1670 }
   1671 
   1672 
   1673 /*
   1674  * fprintf() wrapper that calls through the JNI-specified vfprintf hook if
   1675  * one was specified.
   1676  */
   1677 int dvmFprintf(FILE* fp, const char* format, ...)
   1678 {
   1679     va_list args;
   1680     int result;
   1681 
   1682     va_start(args, format);
   1683     if (gDvm.vfprintfHook != NULL)
   1684         result = (*gDvm.vfprintfHook)(fp, format, args);
   1685     else
   1686         result = vfprintf(fp, format, args);
   1687     va_end(args);
   1688 
   1689     return result;
   1690 }
   1691 
   1692 /*
   1693  * Abort the VM.  We get here on fatal errors.  Try very hard not to use
   1694  * this; whenever possible, return an error to somebody responsible.
   1695  */
   1696 void dvmAbort(void)
   1697 {
   1698     LOGE("VM aborting\n");
   1699 
   1700     fflush(NULL);       // flush all open file buffers
   1701 
   1702     /* JNI-supplied abort hook gets right of first refusal */
   1703     if (gDvm.abortHook != NULL)
   1704         (*gDvm.abortHook)();
   1705 
   1706     /*
   1707      * If we call abort(), all threads in the process receives a SIBABRT.
   1708      * debuggerd dumps the stack trace of the main thread, whether or not
   1709      * that was the thread that failed.
   1710      *
   1711      * By stuffing a value into a bogus address, we cause a segmentation
   1712      * fault in the current thread, and get a useful log from debuggerd.
   1713      * We can also trivially tell the difference between a VM crash and
   1714      * a deliberate abort by looking at the fault address.
   1715      */
   1716     *((char*)0xdeadd00d) = 38;
   1717     abort();
   1718 
   1719     /* notreached */
   1720 }
   1721