Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include "util.h"
     27 #include "VirtualMachineImpl.h"
     28 #include "commonRef.h"
     29 #include "inStream.h"
     30 #include "outStream.h"
     31 #include "eventHandler.h"
     32 #include "eventHelper.h"
     33 #include "threadControl.h"
     34 #include "SDE.h"
     35 #include "FrameID.h"
     36 
     37 static char *versionName = "Java Debug Wire Protocol (Reference Implementation)";
     38 static int majorVersion = 1;  /* JDWP major version */
     39 static int minorVersion = 8;  /* JDWP minor version */
     40 
     41 static jboolean
     42 version(PacketInputStream *in, PacketOutputStream *out)
     43 {
     44     char buf[500];
     45     char *vmName;
     46     char *vmVersion;
     47     char *vmInfo;
     48 
     49     if (gdata->vmDead) {
     50         outStream_setError(out, JDWP_ERROR(VM_DEAD));
     51         return JNI_TRUE;
     52     }
     53 
     54     vmVersion = gdata->property_java_version;
     55     if (vmVersion == NULL) {
     56         vmVersion = "<unknown>";
     57     }
     58     // ANDROID-CHANGED: The runtime value of the java.version property has always been "0" on
     59     //                  android but the old debugger just sent a different value. Simply sending "0"
     60     //                  can confuse some JDWP clients so we will simply say that we are version "8".
     61     if (strcmp(gdata->property_java_vm_name, "Dalvik") == 0 && strcmp(vmVersion, "0") == 0) {
     62       vmVersion = "8";
     63     }
     64     vmName = gdata->property_java_vm_name;
     65     if (vmName == NULL) {
     66         vmName = "<unknown>";
     67     }
     68     vmInfo = gdata->property_java_vm_info;
     69     if (vmInfo == NULL) {
     70         vmInfo = "<unknown>";
     71     }
     72 
     73     /*
     74      * Write the descriptive version information
     75      */
     76     (void)snprintf(buf, sizeof(buf),
     77                 "%s version %d.%d\nJVM Debug Interface version %d.%d\n"
     78                  "JVM version %s (%s, %s)",
     79                   versionName, majorVersion, minorVersion,
     80                   jvmtiMajorVersion(), jvmtiMinorVersion(),
     81                   vmVersion, vmName, vmInfo);
     82     (void)outStream_writeString(out, buf);
     83 
     84     /*
     85      * Write the JDWP version numbers
     86      */
     87     (void)outStream_writeInt(out, majorVersion);
     88     (void)outStream_writeInt(out, minorVersion);
     89 
     90     /*
     91      * Write the VM version and name
     92      */
     93     (void)outStream_writeString(out, vmVersion);
     94     (void)outStream_writeString(out, vmName);
     95 
     96     return JNI_TRUE;
     97 }
     98 
     99 static jboolean
    100 classesForSignature(PacketInputStream *in, PacketOutputStream *out)
    101 {
    102     JNIEnv *env;
    103     char *signature;
    104 
    105     if (gdata->vmDead) {
    106         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    107         return JNI_TRUE;
    108     }
    109 
    110     signature = inStream_readString(in);
    111     if (signature == NULL) {
    112         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    113         return JNI_TRUE;
    114     }
    115     if (inStream_error(in)) {
    116         return JNI_TRUE;
    117     }
    118 
    119     env = getEnv();
    120 
    121     WITH_LOCAL_REFS(env, 1) {
    122 
    123         jint classCount;
    124         jclass *theClasses;
    125         jvmtiError error;
    126 
    127         error = allLoadedClasses(&theClasses, &classCount);
    128         if ( error == JVMTI_ERROR_NONE ) {
    129             /* Count classes in theClasses which match signature */
    130             int matchCount = 0;
    131             /* Count classes written to the JDWP connection */
    132             int writtenCount = 0;
    133             int i;
    134 
    135             for (i=0; i<classCount; i++) {
    136                 jclass clazz = theClasses[i];
    137                 jint status = classStatus(clazz);
    138                 char *candidate_signature = NULL;
    139                 jint wanted =
    140                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY|
    141                      JVMTI_CLASS_STATUS_PRIMITIVE);
    142 
    143                 /* We want prepared classes, primitives, and arrays only */
    144                 if ((status & wanted) == 0) {
    145                     continue;
    146                 }
    147 
    148                 error = classSignature(clazz, &candidate_signature, NULL);
    149                 if (error != JVMTI_ERROR_NONE) {
    150                     break;
    151                 }
    152 
    153                 if (strcmp(candidate_signature, signature) == 0) {
    154                     /* Float interesting classes (those that
    155                      * are matching and are prepared) to the
    156                      * beginning of the array.
    157                      */
    158                     theClasses[i] = theClasses[matchCount];
    159                     theClasses[matchCount++] = clazz;
    160                 }
    161                 jvmtiDeallocate(candidate_signature);
    162             }
    163 
    164             /* At this point matching prepared classes occupy
    165              * indicies 0 thru matchCount-1 of theClasses.
    166              */
    167 
    168             if ( error ==  JVMTI_ERROR_NONE ) {
    169                 (void)outStream_writeInt(out, matchCount);
    170                 for (; writtenCount < matchCount; writtenCount++) {
    171                     jclass clazz = theClasses[writtenCount];
    172                     jint status = classStatus(clazz);
    173                     jbyte tag = referenceTypeTag(clazz);
    174                     (void)outStream_writeByte(out, tag);
    175                     (void)outStream_writeObjectRef(env, out, clazz);
    176                     (void)outStream_writeInt(out, map2jdwpClassStatus(status));
    177                     /* No point in continuing if there's an error */
    178                     if (outStream_error(out)) {
    179                         break;
    180                     }
    181                 }
    182             }
    183 
    184             jvmtiDeallocate(theClasses);
    185         }
    186 
    187         if ( error != JVMTI_ERROR_NONE ) {
    188             outStream_setError(out, map2jdwpError(error));
    189         }
    190 
    191     } END_WITH_LOCAL_REFS(env);
    192 
    193     jvmtiDeallocate(signature);
    194 
    195     return JNI_TRUE;
    196 }
    197 
    198 static jboolean
    199 allClasses1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics)
    200 {
    201     JNIEnv *env;
    202 
    203     if (gdata->vmDead) {
    204         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    205         return JNI_TRUE;
    206     }
    207 
    208     env = getEnv();
    209 
    210     WITH_LOCAL_REFS(env, 1) {
    211 
    212         jint classCount;
    213         jclass *theClasses;
    214         jvmtiError error;
    215 
    216         error = allLoadedClasses(&theClasses, &classCount);
    217         if ( error != JVMTI_ERROR_NONE ) {
    218             outStream_setError(out, map2jdwpError(error));
    219         } else {
    220             /* Count classes in theClasses which are prepared */
    221             int prepCount = 0;
    222             /* Count classes written to the JDWP connection */
    223             int writtenCount = 0;
    224             int i;
    225 
    226             for (i=0; i<classCount; i++) {
    227                 jclass clazz = theClasses[i];
    228                 jint status = classStatus(clazz);
    229                 jint wanted =
    230                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY);
    231 
    232                 /* We want prepared classes and arrays only */
    233                 if ((status & wanted) != 0) {
    234                     /* Float interesting classes (those that
    235                      * are prepared) to the beginning of the array.
    236                      */
    237                     theClasses[i] = theClasses[prepCount];
    238                     theClasses[prepCount++] = clazz;
    239                 }
    240             }
    241 
    242             /* At this point prepared classes occupy
    243              * indicies 0 thru prepCount-1 of theClasses.
    244              */
    245 
    246             (void)outStream_writeInt(out, prepCount);
    247             for (; writtenCount < prepCount; writtenCount++) {
    248                 char *signature = NULL;
    249                 char *genericSignature = NULL;
    250                 jclass clazz = theClasses[writtenCount];
    251                 jint status = classStatus(clazz);
    252                 jbyte tag = referenceTypeTag(clazz);
    253                 jvmtiError error;
    254 
    255                 error = classSignature(clazz, &signature, &genericSignature);
    256                 if (error != JVMTI_ERROR_NONE) {
    257                     outStream_setError(out, map2jdwpError(error));
    258                     break;
    259                 }
    260 
    261                 (void)outStream_writeByte(out, tag);
    262                 (void)outStream_writeObjectRef(env, out, clazz);
    263                 (void)outStream_writeString(out, signature);
    264                 if (outputGenerics == 1) {
    265                     writeGenericSignature(out, genericSignature);
    266                 }
    267 
    268                 (void)outStream_writeInt(out, map2jdwpClassStatus(status));
    269                 jvmtiDeallocate(signature);
    270                 if (genericSignature != NULL) {
    271                   jvmtiDeallocate(genericSignature);
    272                 }
    273 
    274                 /* No point in continuing if there's an error */
    275                 if (outStream_error(out)) {
    276                     break;
    277                 }
    278             }
    279             jvmtiDeallocate(theClasses);
    280         }
    281 
    282     } END_WITH_LOCAL_REFS(env);
    283 
    284     return JNI_TRUE;
    285 }
    286 
    287 static jboolean
    288 allClasses(PacketInputStream *in, PacketOutputStream *out)
    289 {
    290     return allClasses1(in, out, 0);
    291 }
    292 
    293 static jboolean
    294 allClassesWithGeneric(PacketInputStream *in, PacketOutputStream *out)
    295 {
    296     return allClasses1(in, out, 1);
    297 }
    298 
    299   /***********************************************************/
    300 
    301 
    302 static jboolean
    303 instanceCounts(PacketInputStream *in, PacketOutputStream *out)
    304 {
    305     jint classCount;
    306     jclass *classes;
    307     JNIEnv *env;
    308     int ii;
    309 
    310     if (gdata->vmDead) {
    311         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    312         return JNI_TRUE;
    313     }
    314 
    315     classCount = inStream_readInt(in);
    316 
    317     if (inStream_error(in)) {
    318         return JNI_TRUE;
    319     }
    320     if (classCount == 0) {
    321         (void)outStream_writeInt(out, 0);
    322         return JNI_TRUE;
    323     }
    324     if (classCount < 0) {
    325         outStream_setError(out, JDWP_ERROR(ILLEGAL_ARGUMENT));
    326         return JNI_TRUE;
    327     }
    328     env = getEnv();
    329     classes = jvmtiAllocate(classCount * (int)sizeof(jclass));
    330     for (ii = 0; ii < classCount; ii++) {
    331         jdwpError errorCode;
    332         classes[ii] = inStream_readClassRef(env, in);
    333         errorCode = inStream_error(in);
    334         if (errorCode != JDWP_ERROR(NONE)) {
    335             /*
    336              * A class could have been unloaded/gc'd so
    337              * if we get an error, just ignore it and keep
    338              * going.  An instanceCount of 0 will be returned.
    339              */
    340             if (errorCode == JDWP_ERROR(INVALID_OBJECT) ||
    341                 errorCode == JDWP_ERROR(INVALID_CLASS)) {
    342                 inStream_clearError(in);
    343                 classes[ii] = NULL;
    344                 continue;
    345             }
    346             jvmtiDeallocate(classes);
    347             return JNI_TRUE;
    348         }
    349     }
    350 
    351     WITH_LOCAL_REFS(env, 1) {
    352         jlong      *counts;
    353         jvmtiError error;
    354 
    355         counts = jvmtiAllocate(classCount * (int)sizeof(jlong));
    356         /* Iterate over heap getting info on these classes */
    357         error = classInstanceCounts(classCount, classes, counts);
    358         if (error != JVMTI_ERROR_NONE) {
    359             outStream_setError(out, map2jdwpError(error));
    360         } else {
    361             (void)outStream_writeInt(out, classCount);
    362             for (ii = 0; ii < classCount; ii++) {
    363                 (void)outStream_writeLong(out, counts[ii]);
    364             }
    365         }
    366         jvmtiDeallocate(counts);
    367     } END_WITH_LOCAL_REFS(env);
    368     jvmtiDeallocate(classes);
    369     return JNI_TRUE;
    370 }
    371 
    372 static jboolean
    373 redefineClasses(PacketInputStream *in, PacketOutputStream *out)
    374 {
    375     jvmtiClassDefinition *classDefs;
    376     jboolean ok = JNI_TRUE;
    377     jint classCount;
    378     jint i;
    379     JNIEnv *env;
    380 
    381     if (gdata->vmDead) {
    382         /* quietly ignore */
    383         return JNI_TRUE;
    384     }
    385 
    386     classCount = inStream_readInt(in);
    387     if (inStream_error(in)) {
    388         return JNI_TRUE;
    389     }
    390     if ( classCount == 0 ) {
    391         return JNI_TRUE;
    392     }
    393     /*LINTED*/
    394     classDefs = jvmtiAllocate(classCount*(int)sizeof(jvmtiClassDefinition));
    395     if (classDefs == NULL) {
    396         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    397         return JNI_TRUE;
    398     }
    399     /*LINTED*/
    400     (void)memset(classDefs, 0, classCount*sizeof(jvmtiClassDefinition));
    401 
    402     env = getEnv();
    403     for (i = 0; i < classCount; ++i) {
    404         int byteCount;
    405         unsigned char * bytes;
    406         jclass clazz;
    407 
    408         clazz = inStream_readClassRef(env, in);
    409         if (inStream_error(in)) {
    410             ok = JNI_FALSE;
    411             break;
    412         }
    413         byteCount = inStream_readInt(in);
    414         if (inStream_error(in)) {
    415             ok = JNI_FALSE;
    416             break;
    417         }
    418         if ( byteCount <= 0 ) {
    419             outStream_setError(out, JDWP_ERROR(INVALID_CLASS_FORMAT));
    420             ok = JNI_FALSE;
    421             break;
    422         }
    423         bytes = (unsigned char *)jvmtiAllocate(byteCount);
    424         if (bytes == NULL) {
    425             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    426             ok = JNI_FALSE;
    427             break;
    428         }
    429         (void)inStream_readBytes(in, byteCount, (jbyte *)bytes);
    430         if (inStream_error(in)) {
    431             ok = JNI_FALSE;
    432             break;
    433         }
    434 
    435         classDefs[i].klass = clazz;
    436         classDefs[i].class_byte_count = byteCount;
    437         classDefs[i].class_bytes = bytes;
    438     }
    439 
    440     if (ok == JNI_TRUE) {
    441         jvmtiError error;
    442 
    443         error = JVMTI_FUNC_PTR(gdata->jvmti,RedefineClasses)
    444                         (gdata->jvmti, classCount, classDefs);
    445         if (error != JVMTI_ERROR_NONE) {
    446             outStream_setError(out, map2jdwpError(error));
    447         } else {
    448             /* zap our BP info */
    449             for ( i = 0 ; i < classCount; i++ ) {
    450                 eventHandler_freeClassBreakpoints(classDefs[i].klass);
    451             }
    452         }
    453     }
    454 
    455     /* free up allocated memory */
    456     for ( i = 0 ; i < classCount; i++ ) {
    457         if ( classDefs[i].class_bytes != NULL ) {
    458             jvmtiDeallocate((void*)classDefs[i].class_bytes);
    459         }
    460     }
    461     jvmtiDeallocate(classDefs);
    462 
    463     return JNI_TRUE;
    464 }
    465 
    466 static jboolean
    467 setDefaultStratum(PacketInputStream *in, PacketOutputStream *out)
    468 {
    469     char *stratumId;
    470 
    471     if (gdata->vmDead) {
    472         /* quietly ignore */
    473         return JNI_TRUE;
    474     }
    475 
    476     stratumId = inStream_readString(in);
    477     if (inStream_error(in)) {
    478         return JNI_TRUE;
    479     } else if (strcmp(stratumId, "") == 0) {
    480         stratumId = NULL;
    481     }
    482     setGlobalStratumId(stratumId);
    483 
    484     return JNI_TRUE;
    485 }
    486 
    487 static jboolean
    488 getAllThreads(PacketInputStream *in, PacketOutputStream *out)
    489 {
    490     JNIEnv *env;
    491 
    492     if (gdata->vmDead) {
    493         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    494         return JNI_TRUE;
    495     }
    496 
    497     env = getEnv();
    498 
    499     WITH_LOCAL_REFS(env, 1) {
    500 
    501         int i;
    502         jint threadCount;
    503         jthread *theThreads;
    504 
    505         theThreads = allThreads(&threadCount);
    506         if (theThreads == NULL) {
    507             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    508         } else {
    509             /* Squish out all of the debugger-spawned threads */
    510             threadCount = filterDebugThreads(theThreads, threadCount);
    511 
    512             (void)outStream_writeInt(out, threadCount);
    513             for (i = 0; i <threadCount; i++) {
    514                 (void)outStream_writeObjectRef(env, out, theThreads[i]);
    515             }
    516 
    517             jvmtiDeallocate(theThreads);
    518         }
    519 
    520     } END_WITH_LOCAL_REFS(env);
    521 
    522     return JNI_TRUE;
    523 }
    524 
    525 static jboolean
    526 topLevelThreadGroups(PacketInputStream *in, PacketOutputStream *out)
    527 {
    528     JNIEnv *env;
    529 
    530     if (gdata->vmDead) {
    531         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    532         return JNI_TRUE;
    533     }
    534 
    535     env = getEnv();
    536 
    537     WITH_LOCAL_REFS(env, 1) {
    538 
    539         jvmtiError error;
    540         jint groupCount;
    541         jthreadGroup *groups;
    542 
    543         groups = NULL;
    544         error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
    545                     (gdata->jvmti, &groupCount, &groups);
    546         if (error != JVMTI_ERROR_NONE) {
    547             outStream_setError(out, map2jdwpError(error));
    548         } else {
    549             int i;
    550 
    551             (void)outStream_writeInt(out, groupCount);
    552             for (i = 0; i < groupCount; i++) {
    553                 (void)outStream_writeObjectRef(env, out, groups[i]);
    554             }
    555 
    556             jvmtiDeallocate(groups);
    557         }
    558 
    559     } END_WITH_LOCAL_REFS(env);
    560 
    561     return JNI_TRUE;
    562 }
    563 
    564 static jboolean
    565 dispose(PacketInputStream *in, PacketOutputStream *out)
    566 {
    567     return JNI_TRUE;
    568 }
    569 
    570 static jboolean
    571 idSizes(PacketInputStream *in, PacketOutputStream *out)
    572 {
    573     (void)outStream_writeInt(out, sizeof(jfieldID));    /* fields */
    574     (void)outStream_writeInt(out, sizeof(jmethodID));   /* methods */
    575     (void)outStream_writeInt(out, sizeof(jlong));       /* objects */
    576     (void)outStream_writeInt(out, sizeof(jlong));       /* referent types */
    577     (void)outStream_writeInt(out, sizeof(FrameID));    /* frames */
    578     return JNI_TRUE;
    579 }
    580 
    581 static jboolean
    582 suspend(PacketInputStream *in, PacketOutputStream *out)
    583 {
    584     jvmtiError error;
    585 
    586     if (gdata->vmDead) {
    587         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    588         return JNI_TRUE;
    589     }
    590     error = threadControl_suspendAll();
    591     if (error != JVMTI_ERROR_NONE) {
    592         outStream_setError(out, map2jdwpError(error));
    593     }
    594     return JNI_TRUE;
    595 }
    596 
    597 static jboolean
    598 resume(PacketInputStream *in, PacketOutputStream *out)
    599 {
    600     jvmtiError error;
    601 
    602     if (gdata->vmDead) {
    603         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    604         return JNI_TRUE;
    605     }
    606     error = threadControl_resumeAll();
    607     if (error != JVMTI_ERROR_NONE) {
    608         outStream_setError(out, map2jdwpError(error));
    609     }
    610     return JNI_TRUE;
    611 }
    612 
    613 static jboolean
    614 doExit(PacketInputStream *in, PacketOutputStream *out)
    615 {
    616     jint exitCode;
    617 
    618     exitCode = inStream_readInt(in);
    619     if (gdata->vmDead) {
    620         /* quietly ignore */
    621         return JNI_FALSE;
    622     }
    623 
    624     /* We send the reply from here because we are about to exit. */
    625     if (inStream_error(in)) {
    626         outStream_setError(out, inStream_error(in));
    627     }
    628     outStream_sendReply(out);
    629 
    630     forceExit(exitCode);
    631 
    632     /* Shouldn't get here */
    633     JDI_ASSERT(JNI_FALSE);
    634 
    635     /* Shut up the compiler */
    636     return JNI_FALSE;
    637 
    638 }
    639 
    640 static jboolean
    641 createString(PacketInputStream *in, PacketOutputStream *out)
    642 {
    643     JNIEnv *env;
    644     char *cstring;
    645 
    646     if (gdata->vmDead) {
    647         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    648         return JNI_TRUE;
    649     }
    650 
    651     cstring = inStream_readString(in);
    652     if (cstring == NULL) {
    653         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    654         return JNI_TRUE;
    655     }
    656     if (inStream_error(in)) {
    657         return JNI_TRUE;
    658     }
    659 
    660     env = getEnv();
    661 
    662     WITH_LOCAL_REFS(env, 1) {
    663 
    664         jstring string;
    665 
    666         string = JNI_FUNC_PTR(env,NewStringUTF)(env, cstring);
    667         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    668             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    669         } else {
    670             (void)outStream_writeObjectRef(env, out, string);
    671         }
    672 
    673     } END_WITH_LOCAL_REFS(env);
    674 
    675     jvmtiDeallocate(cstring);
    676 
    677     return JNI_TRUE;
    678 }
    679 
    680 static jboolean
    681 capabilities(PacketInputStream *in, PacketOutputStream *out)
    682 {
    683     jvmtiCapabilities caps;
    684     jvmtiError error;
    685 
    686     if (gdata->vmDead) {
    687         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    688         return JNI_TRUE;
    689     }
    690     error = jvmtiGetCapabilities(&caps);
    691     if (error != JVMTI_ERROR_NONE) {
    692         outStream_setError(out, map2jdwpError(error));
    693         return JNI_TRUE;
    694     }
    695 
    696     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_modification_events);
    697     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_access_events);
    698     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_bytecodes);
    699     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_synthetic_attribute);
    700     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_info);
    701     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_current_contended_monitor);
    702     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_monitor_info);
    703     return JNI_TRUE;
    704 }
    705 
    706 static jboolean
    707 capabilitiesNew(PacketInputStream *in, PacketOutputStream *out)
    708 {
    709     jvmtiCapabilities caps;
    710     jvmtiError error;
    711 
    712     if (gdata->vmDead) {
    713         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    714         return JNI_TRUE;
    715     }
    716     error = jvmtiGetCapabilities(&caps);
    717     if (error != JVMTI_ERROR_NONE) {
    718         outStream_setError(out, map2jdwpError(error));
    719         return JNI_TRUE;
    720     }
    721 
    722     // ANDROID-CHANGED: We want to adjust the capabilities slightly if we are on android.
    723     jboolean is_android_runtime = strcmp(gdata->property_java_vm_name, "Dalvik") == 0;
    724 
    725     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_modification_events);
    726     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_access_events);
    727     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_bytecodes);
    728     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_synthetic_attribute);
    729     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_info);
    730     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_current_contended_monitor);
    731     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_monitor_info);
    732 
    733     /* new since JDWP version 1.4 */
    734     /* ANDROID-CHANGED: some jdwp clients will send us class files for redefineClasses which we do
    735      * not support. Set this capability to false and set reserved32 instead to indicate that we do
    736      * support .dex file class redefinition.
    737      */
    738     (void)outStream_writeBoolean(out, (jboolean)caps.can_redefine_classes && !is_android_runtime);
    739     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE /* can_add_method */ );
    740     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE /* can_unrestrictedly_redefine_classes */ );
    741     /* 11: canPopFrames */
    742     (void)outStream_writeBoolean(out, (jboolean)caps.can_pop_frame);
    743     /* 12: canUseInstanceFilters */
    744     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
    745     /* 13: canGetSourceDebugExtension */
    746     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_source_debug_extension);
    747     /* 14: canRequestVMDeathEvent */
    748     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
    749     /* 15: canSetDefaultStratum */
    750     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
    751     /* 16: canGetInstanceInfo */
    752     (void)outStream_writeBoolean(out, (jboolean)caps.can_tag_objects);
    753     /* 17: canRequestMonitorEvents */
    754     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_monitor_events);
    755     /* 18: canGetMonitorFrameInfo */
    756     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_stack_depth_info);
    757     /* remaining reserved */
    758     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 19 */
    759     /* 20 Can get constant pool information */
    760     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_constant_pool);
    761     /* 21 Can force early return */
    762     (void)outStream_writeBoolean(out, (jboolean)caps.can_force_early_return);
    763     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 22 */
    764     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 23 */
    765     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 24 */
    766     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 25 */
    767     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 26 */
    768     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 27 */
    769     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 28 */
    770     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 29 */
    771     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 30 */
    772     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 31 */
    773     /* ANDROID-CHANGED: Use the reserved32 capability to notify clients that we can support dex
    774      * class redefinition.
    775      */
    776     (void)outStream_writeBoolean(out, (jboolean)caps.can_redefine_classes && is_android_runtime);
    777     return JNI_TRUE;
    778 }
    779 
    780 static int
    781 countPaths(char *string) {
    782     int cnt = 1; /* always have one */
    783     char *pos = string;
    784     char *ps;
    785 
    786     ps = gdata->property_path_separator;
    787     if ( ps == NULL ) {
    788         ps = ";";
    789     }
    790     while ((pos = strchr(pos, ps[0])) != NULL) {
    791         ++cnt;
    792         ++pos;
    793     }
    794     return cnt;
    795 }
    796 
    797 static void
    798 writePaths(PacketOutputStream *out, char *string) {
    799     char *pos;
    800     char *ps;
    801     char *buf;
    802     int   npaths;
    803     int   i;
    804 
    805     buf = jvmtiAllocate((int)strlen(string)+1);
    806 
    807     npaths = countPaths(string);
    808     (void)outStream_writeInt(out, npaths);
    809 
    810     ps = gdata->property_path_separator;
    811     if ( ps == NULL ) {
    812         ps = ";";
    813     }
    814 
    815     pos = string;
    816     for ( i = 0 ; i < npaths ; i++ ) {
    817         char *psPos;
    818         int   plen;
    819 
    820         psPos = strchr(pos, ps[0]);
    821         if ( psPos == NULL ) {
    822             plen = (int)strlen(pos);
    823         } else {
    824             plen = (int)(psPos-pos);
    825             psPos++;
    826         }
    827         (void)memcpy(buf, pos, plen);
    828         buf[plen] = 0;
    829         (void)outStream_writeString(out, buf);
    830         pos = psPos;
    831     }
    832 
    833     jvmtiDeallocate(buf);
    834 }
    835 
    836 
    837 
    838 static jboolean
    839 classPaths(PacketInputStream *in, PacketOutputStream *out)
    840 {
    841     char *ud;
    842     char *bp;
    843     char *cp;
    844 
    845     ud = gdata->property_user_dir;
    846     if ( ud == NULL ) {
    847         ud = "";
    848     }
    849     cp = gdata->property_java_class_path;
    850     if ( cp == NULL ) {
    851         cp = "";
    852     }
    853     bp = gdata->property_sun_boot_class_path;
    854     if ( bp == NULL ) {
    855         bp = "";
    856     }
    857     (void)outStream_writeString(out, ud);
    858     writePaths(out, cp);
    859     writePaths(out, bp);
    860     return JNI_TRUE;
    861 }
    862 
    863 static jboolean
    864 disposeObjects(PacketInputStream *in, PacketOutputStream *out)
    865 {
    866     int i;
    867     int refCount;
    868     jlong id;
    869     int requestCount;
    870     JNIEnv *env;
    871 
    872     if (gdata->vmDead) {
    873         /* quietly ignore */
    874         return JNI_TRUE;
    875     }
    876 
    877     requestCount = inStream_readInt(in);
    878     if (inStream_error(in)) {
    879         return JNI_TRUE;
    880     }
    881 
    882     env = getEnv();
    883     for (i = 0; i < requestCount; i++) {
    884         id = inStream_readObjectID(in);
    885         refCount = inStream_readInt(in);
    886         if (inStream_error(in)) {
    887             return JNI_TRUE;
    888         }
    889         commonRef_releaseMultiple(env, id, refCount);
    890     }
    891 
    892     return JNI_TRUE;
    893 }
    894 
    895 static jboolean
    896 holdEvents(PacketInputStream *in, PacketOutputStream *out)
    897 {
    898     eventHelper_holdEvents();
    899     return JNI_TRUE;
    900 }
    901 
    902 static jboolean
    903 releaseEvents(PacketInputStream *in, PacketOutputStream *out)
    904 {
    905     eventHelper_releaseEvents();
    906     return JNI_TRUE;
    907 }
    908 
    909 void *VirtualMachine_Cmds[] = { (void *)21
    910     ,(void *)version
    911     ,(void *)classesForSignature
    912     ,(void *)allClasses
    913     ,(void *)getAllThreads
    914     ,(void *)topLevelThreadGroups
    915     ,(void *)dispose
    916     ,(void *)idSizes
    917     ,(void *)suspend
    918     ,(void *)resume
    919     ,(void *)doExit
    920     ,(void *)createString
    921     ,(void *)capabilities
    922     ,(void *)classPaths
    923     ,(void *)disposeObjects
    924     ,(void *)holdEvents
    925     ,(void *)releaseEvents
    926     ,(void *)capabilitiesNew
    927     ,(void *)redefineClasses
    928     ,(void *)setDefaultStratum
    929     ,(void *)allClassesWithGeneric
    930     ,(void *)instanceCounts
    931 };
    932