Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2013, 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 <ctype.h>
     27 // ANDROID-CHANGED: Include time.h so we can use clock_gettime to implement milliTime.
     28 #include <time.h>
     29 
     30 #include "util.h"
     31 #include "transport.h"
     32 #include "eventHandler.h"
     33 #include "threadControl.h"
     34 #include "outStream.h"
     35 #include "inStream.h"
     36 #include "invoker.h"
     37 
     38 /* Global data area */
     39 BackendGlobalData *gdata = NULL;
     40 
     41 /* Forward declarations */
     42 static jboolean isInterface(jclass clazz);
     43 static char * getPropertyUTF8(JNIEnv *env, char *propertyName);
     44 
     45 static jvmtiError (JNICALL *ext_RawMonitorEnterNoSuspend) (jvmtiEnv* env, jrawMonitorID monitor);
     46 static jvmtiError (JNICALL *ext_RawMonitorExitNoSuspend) (jvmtiEnv* env, jrawMonitorID monitor);
     47 
     48 // ANDROID-CHANGED: Implement a helper to get the current time in milliseconds according to
     49 // CLOCK_MONOTONIC.
     50 jlong
     51 milliTime(void)
     52 {
     53   struct timespec now;
     54   memset(&now, 0, sizeof(now));
     55   (void)clock_gettime(CLOCK_MONOTONIC, &now);
     56   return ((jlong)now.tv_sec) * 1000LL + ((jlong)now.tv_nsec) / 1000000LL;
     57 }
     58 
     59 /* Save an object reference for use later (create a NewGlobalRef) */
     60 void
     61 saveGlobalRef(JNIEnv *env, jobject obj, jobject *pobj)
     62 {
     63     jobject newobj;
     64 
     65     if ( pobj == NULL ) {
     66         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef pobj");
     67     }
     68     if ( *pobj != NULL ) {
     69         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef *pobj");
     70     }
     71     if ( env == NULL ) {
     72         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef env");
     73     }
     74     if ( obj == NULL ) {
     75         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef obj");
     76     }
     77     newobj = JNI_FUNC_PTR(env,NewGlobalRef)(env, obj);
     78     if ( newobj == NULL ) {
     79         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"NewGlobalRef");
     80     }
     81     *pobj = newobj;
     82 }
     83 
     84 /* Toss a previously saved object reference */
     85 void
     86 tossGlobalRef(JNIEnv *env, jobject *pobj)
     87 {
     88     jobject obj;
     89 
     90     if ( pobj == NULL ) {
     91         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"tossGlobalRef pobj");
     92     }
     93     obj = *pobj;
     94     if ( env == NULL ) {
     95         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"tossGlobalRef env");
     96     }
     97     if ( obj == NULL ) {
     98         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"tossGlobalRef obj");
     99     }
    100     JNI_FUNC_PTR(env,DeleteGlobalRef)(env, obj);
    101     *pobj = NULL;
    102 }
    103 
    104 static jclass
    105 findClass(JNIEnv *env, const char * name)
    106 {
    107     jclass x;
    108 
    109     if ( env == NULL ) {
    110         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"findClass env");
    111     }
    112     if ( name == NULL || name[0] == 0 ) {
    113         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"findClass name");
    114     }
    115     x = JNI_FUNC_PTR(env,FindClass)(env, name);
    116     if (x == NULL) {
    117         ERROR_MESSAGE(("JDWP Can't find class %s", name));
    118         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    119     }
    120     if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) {
    121         ERROR_MESSAGE(("JDWP Exception occurred finding class %s", name));
    122         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    123     }
    124     return x;
    125 }
    126 
    127 static jmethodID
    128 getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
    129 {
    130     jmethodID method;
    131 
    132     if ( env == NULL ) {
    133         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod env");
    134     }
    135     if ( clazz == NULL ) {
    136         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod clazz");
    137     }
    138     if ( name == NULL || name[0] == 0 ) {
    139         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod name");
    140     }
    141     if ( signature == NULL || signature[0] == 0 ) {
    142         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod signature");
    143     }
    144     method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, signature);
    145     if (method == NULL) {
    146         ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
    147                                 name, signature));
    148         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    149     }
    150     if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) {
    151         ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
    152                                 name, signature));
    153         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    154     }
    155     return method;
    156 }
    157 
    158 static jmethodID
    159 getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
    160 {
    161     jmethodID method;
    162 
    163     if ( env == NULL ) {
    164         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod env");
    165     }
    166     if ( clazz == NULL ) {
    167         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod clazz");
    168     }
    169     if ( name == NULL || name[0] == 0 ) {
    170         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod name");
    171     }
    172     if ( signature == NULL || signature[0] == 0 ) {
    173         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod signature");
    174     }
    175     method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, signature);
    176     if (method == NULL) {
    177         ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
    178                                 name, signature));
    179         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    180     }
    181     if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) {
    182         ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
    183                                 name, signature));
    184         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
    185     }
    186     return method;
    187 }
    188 
    189 void
    190 util_initialize(JNIEnv *env)
    191 {
    192     WITH_LOCAL_REFS(env, 6) {
    193 
    194         jvmtiError error;
    195         jclass localClassClass;
    196         jclass localThreadClass;
    197         jclass localThreadGroupClass;
    198         jclass localClassLoaderClass;
    199         jclass localStringClass;
    200         jclass localSystemClass;
    201         jclass localPropertiesClass;
    202         jclass localVMSupportClass;
    203         jobject localAgentProperties;
    204         jmethodID getAgentProperties;
    205         jint groupCount;
    206         jthreadGroup *groups;
    207         jthreadGroup localSystemThreadGroup;
    208 
    209         /* Find some standard classes */
    210 
    211         localClassClass         = findClass(env,"java/lang/Class");
    212         localThreadClass        = findClass(env,"java/lang/Thread");
    213         localThreadGroupClass   = findClass(env,"java/lang/ThreadGroup");
    214         localClassLoaderClass   = findClass(env,"java/lang/ClassLoader");
    215         localStringClass        = findClass(env,"java/lang/String");
    216         localSystemClass        = findClass(env,"java/lang/System");
    217         localPropertiesClass    = findClass(env,"java/util/Properties");
    218 
    219         /* Save references */
    220 
    221         saveGlobalRef(env, localClassClass,       &(gdata->classClass));
    222         saveGlobalRef(env, localThreadClass,      &(gdata->threadClass));
    223         saveGlobalRef(env, localThreadGroupClass, &(gdata->threadGroupClass));
    224         saveGlobalRef(env, localClassLoaderClass, &(gdata->classLoaderClass));
    225         saveGlobalRef(env, localStringClass,      &(gdata->stringClass));
    226         saveGlobalRef(env, localSystemClass,      &(gdata->systemClass));
    227 
    228         /* Find some standard methods */
    229 
    230         gdata->threadConstructor =
    231                 getMethod(env, gdata->threadClass,
    232                     "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
    233         gdata->threadSetDaemon =
    234                 getMethod(env, gdata->threadClass, "setDaemon", "(Z)V");
    235         gdata->threadResume =
    236                 getMethod(env, gdata->threadClass, "resume", "()V");
    237         gdata->systemGetProperty =
    238                 getStaticMethod(env, gdata->systemClass,
    239                     "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
    240         gdata->setProperty =
    241                 getMethod(env, localPropertiesClass,
    242                     "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
    243 
    244         /* Find the system thread group */
    245 
    246         groups = NULL;
    247         groupCount = 0;
    248         error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
    249                     (gdata->jvmti, &groupCount, &groups);
    250         if (error != JVMTI_ERROR_NONE ) {
    251             EXIT_ERROR(error, "Can't get system thread group");
    252         }
    253         if ( groupCount == 0 ) {
    254             EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "Can't get system thread group");
    255         }
    256         localSystemThreadGroup = groups[0];
    257         saveGlobalRef(env, localSystemThreadGroup, &(gdata->systemThreadGroup));
    258 
    259         /* Get some basic Java property values we will need at some point */
    260         gdata->property_java_version
    261                         = getPropertyUTF8(env, "java.version");
    262         gdata->property_java_vm_name
    263                         = getPropertyUTF8(env, "java.vm.name");
    264         // ANDROID-CHANGED: Android doesn't provide the 'java.vm.info' property. Just provide the
    265         //                  rest of the agent with an empty string to use for it.
    266         gdata->property_java_vm_info = jvmtiAllocate(1);
    267         gdata->property_java_vm_info[0] = '\0';
    268         gdata->property_java_class_path
    269                         = getPropertyUTF8(env, "java.class.path");
    270         // ANDROID-CHANGED: Android uses java.boot.class.path to store the bootclasspath.
    271         gdata->property_sun_boot_class_path
    272                         = getPropertyUTF8(env, "java.boot.class.path");
    273         // ANDROID-CHANGED: Android uses java.library.path to store all library path information.
    274         gdata->property_sun_boot_library_path
    275                         = getPropertyUTF8(env, "java.library.path");
    276         gdata->property_path_separator
    277                         = getPropertyUTF8(env, "path.separator");
    278         gdata->property_user_dir
    279                         = getPropertyUTF8(env, "user.dir");
    280 
    281         /* Get agent properties: invoke sun.misc.VMSupport.getAgentProperties */
    282         localVMSupportClass = JNI_FUNC_PTR(env,FindClass)
    283                                           (env, "sun/misc/VMSupport");
    284         if (localVMSupportClass == NULL) {
    285             gdata->agent_properties = NULL;
    286             if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    287                 JNI_FUNC_PTR(env,ExceptionClear)(env);
    288             }
    289         } else {
    290             getAgentProperties  =
    291                 getStaticMethod(env, localVMSupportClass,
    292                                 "getAgentProperties", "()Ljava/util/Properties;");
    293             localAgentProperties =
    294                 JNI_FUNC_PTR(env,CallStaticObjectMethod)
    295                             (env, localVMSupportClass, getAgentProperties);
    296             saveGlobalRef(env, localAgentProperties, &(gdata->agent_properties));
    297             if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    298                 JNI_FUNC_PTR(env,ExceptionClear)(env);
    299                 EXIT_ERROR(AGENT_ERROR_INTERNAL,
    300                     "Exception occurred calling sun.misc.VMSupport.getAgentProperties");
    301             }
    302         }
    303 
    304     } END_WITH_LOCAL_REFS(env);
    305 
    306 }
    307 
    308 void
    309 util_reset(void)
    310 {
    311 }
    312 
    313 jboolean
    314 isObjectTag(jbyte tag) {
    315     return (tag == JDWP_TAG(OBJECT)) ||
    316            (tag == JDWP_TAG(STRING)) ||
    317            (tag == JDWP_TAG(THREAD)) ||
    318            (tag == JDWP_TAG(THREAD_GROUP)) ||
    319            (tag == JDWP_TAG(CLASS_LOADER)) ||
    320            (tag == JDWP_TAG(CLASS_OBJECT)) ||
    321            (tag == JDWP_TAG(ARRAY));
    322 }
    323 
    324 jbyte
    325 specificTypeKey(JNIEnv *env, jobject object)
    326 {
    327     if (object == NULL) {
    328         return JDWP_TAG(OBJECT);
    329     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->stringClass)) {
    330         return JDWP_TAG(STRING);
    331     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadClass)) {
    332         return JDWP_TAG(THREAD);
    333     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadGroupClass)) {
    334         return JDWP_TAG(THREAD_GROUP);
    335     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classLoaderClass)) {
    336         return JDWP_TAG(CLASS_LOADER);
    337     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classClass)) {
    338         return JDWP_TAG(CLASS_OBJECT);
    339     } else {
    340         jboolean classIsArray;
    341 
    342         WITH_LOCAL_REFS(env, 1) {
    343             jclass clazz;
    344             clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
    345             classIsArray = isArrayClass(clazz);
    346         } END_WITH_LOCAL_REFS(env);
    347 
    348         return (classIsArray ? JDWP_TAG(ARRAY) : JDWP_TAG(OBJECT));
    349     }
    350 }
    351 
    352 static void
    353 writeFieldValue(JNIEnv *env, PacketOutputStream *out, jobject object,
    354                 jfieldID field)
    355 {
    356     jclass clazz;
    357     char *signature = NULL;
    358     jvmtiError error;
    359     jbyte typeKey;
    360 
    361     clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
    362     error = fieldSignature(clazz, field, NULL, &signature, NULL);
    363     if (error != JVMTI_ERROR_NONE) {
    364         outStream_setError(out, map2jdwpError(error));
    365         return;
    366     }
    367     typeKey = signature[0];
    368     jvmtiDeallocate(signature);
    369 
    370     /*
    371      * For primitive types, the type key is bounced back as is. Objects
    372      * are handled in the switch statement below.
    373      */
    374     if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
    375         (void)outStream_writeByte(out, typeKey);
    376     }
    377 
    378     switch (typeKey) {
    379         case JDWP_TAG(OBJECT):
    380         case JDWP_TAG(ARRAY):   {
    381             jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field);
    382             (void)outStream_writeByte(out, specificTypeKey(env, value));
    383             (void)outStream_writeObjectRef(env, out, value);
    384             break;
    385         }
    386 
    387         case JDWP_TAG(BYTE):
    388             (void)outStream_writeByte(out,
    389                       JNI_FUNC_PTR(env,GetByteField)(env, object, field));
    390             break;
    391 
    392         case JDWP_TAG(CHAR):
    393             (void)outStream_writeChar(out,
    394                       JNI_FUNC_PTR(env,GetCharField)(env, object, field));
    395             break;
    396 
    397         case JDWP_TAG(FLOAT):
    398             (void)outStream_writeFloat(out,
    399                       JNI_FUNC_PTR(env,GetFloatField)(env, object, field));
    400             break;
    401 
    402         case JDWP_TAG(DOUBLE):
    403             (void)outStream_writeDouble(out,
    404                       JNI_FUNC_PTR(env,GetDoubleField)(env, object, field));
    405             break;
    406 
    407         case JDWP_TAG(INT):
    408             (void)outStream_writeInt(out,
    409                       JNI_FUNC_PTR(env,GetIntField)(env, object, field));
    410             break;
    411 
    412         case JDWP_TAG(LONG):
    413             (void)outStream_writeLong(out,
    414                       JNI_FUNC_PTR(env,GetLongField)(env, object, field));
    415             break;
    416 
    417         case JDWP_TAG(SHORT):
    418             (void)outStream_writeShort(out,
    419                       JNI_FUNC_PTR(env,GetShortField)(env, object, field));
    420             break;
    421 
    422         case JDWP_TAG(BOOLEAN):
    423             (void)outStream_writeBoolean(out,
    424                       JNI_FUNC_PTR(env,GetBooleanField)(env, object, field));
    425             break;
    426     }
    427 }
    428 
    429 static void
    430 writeStaticFieldValue(JNIEnv *env, PacketOutputStream *out, jclass clazz,
    431                       jfieldID field)
    432 {
    433     jvmtiError error;
    434     char *signature = NULL;
    435     jbyte typeKey;
    436 
    437     error = fieldSignature(clazz, field, NULL, &signature, NULL);
    438     if (error != JVMTI_ERROR_NONE) {
    439         outStream_setError(out, map2jdwpError(error));
    440         return;
    441     }
    442     typeKey = signature[0];
    443     jvmtiDeallocate(signature);
    444 
    445     /*
    446      * For primitive types, the type key is bounced back as is. Objects
    447      * are handled in the switch statement below.
    448      */
    449     if ((typeKey != JDWP_TAG(OBJECT)) && (typeKey != JDWP_TAG(ARRAY))) {
    450         (void)outStream_writeByte(out, typeKey);
    451     }
    452 
    453     switch (typeKey) {
    454         case JDWP_TAG(OBJECT):
    455         case JDWP_TAG(ARRAY):   {
    456             jobject value = JNI_FUNC_PTR(env,GetStaticObjectField)(env, clazz, field);
    457             (void)outStream_writeByte(out, specificTypeKey(env, value));
    458             (void)outStream_writeObjectRef(env, out, value);
    459             break;
    460         }
    461 
    462         case JDWP_TAG(BYTE):
    463             (void)outStream_writeByte(out,
    464                       JNI_FUNC_PTR(env,GetStaticByteField)(env, clazz, field));
    465             break;
    466 
    467         case JDWP_TAG(CHAR):
    468             (void)outStream_writeChar(out,
    469                       JNI_FUNC_PTR(env,GetStaticCharField)(env, clazz, field));
    470             break;
    471 
    472         case JDWP_TAG(FLOAT):
    473             (void)outStream_writeFloat(out,
    474                       JNI_FUNC_PTR(env,GetStaticFloatField)(env, clazz, field));
    475             break;
    476 
    477         case JDWP_TAG(DOUBLE):
    478             (void)outStream_writeDouble(out,
    479                       JNI_FUNC_PTR(env,GetStaticDoubleField)(env, clazz, field));
    480             break;
    481 
    482         case JDWP_TAG(INT):
    483             (void)outStream_writeInt(out,
    484                       JNI_FUNC_PTR(env,GetStaticIntField)(env, clazz, field));
    485             break;
    486 
    487         case JDWP_TAG(LONG):
    488             (void)outStream_writeLong(out,
    489                       JNI_FUNC_PTR(env,GetStaticLongField)(env, clazz, field));
    490             break;
    491 
    492         case JDWP_TAG(SHORT):
    493             (void)outStream_writeShort(out,
    494                       JNI_FUNC_PTR(env,GetStaticShortField)(env, clazz, field));
    495             break;
    496 
    497         case JDWP_TAG(BOOLEAN):
    498             (void)outStream_writeBoolean(out,
    499                       JNI_FUNC_PTR(env,GetStaticBooleanField)(env, clazz, field));
    500             break;
    501     }
    502 }
    503 
    504 void
    505 sharedGetFieldValues(PacketInputStream *in, PacketOutputStream *out,
    506                      jboolean isStatic)
    507 {
    508     JNIEnv *env = getEnv();
    509     jint length;
    510     jobject object;
    511     jclass clazz;
    512 
    513     object = NULL;
    514     clazz  = NULL;
    515 
    516     if (isStatic) {
    517         clazz = inStream_readClassRef(env, in);
    518     } else {
    519         object = inStream_readObjectRef(env, in);
    520     }
    521 
    522     length = inStream_readInt(in);
    523     if (inStream_error(in)) {
    524         return;
    525     }
    526 
    527     WITH_LOCAL_REFS(env, length + 1) { /* +1 for class with instance fields */
    528 
    529         int i;
    530 
    531         (void)outStream_writeInt(out, length);
    532         for (i = 0; (i < length) && !outStream_error(out); i++) {
    533             jfieldID field = inStream_readFieldID(in);
    534 
    535             if (isStatic) {
    536                 writeStaticFieldValue(env, out, clazz, field);
    537             } else {
    538                 writeFieldValue(env, out, object, field);
    539             }
    540         }
    541 
    542     } END_WITH_LOCAL_REFS(env);
    543 }
    544 
    545 jboolean
    546 sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
    547 {
    548     jvalue *arguments = NULL;
    549     jint options;
    550     jvmtiError error;
    551     jbyte invokeType;
    552     jclass clazz;
    553     jmethodID method;
    554     jint argumentCount;
    555     jobject instance;
    556     jthread thread;
    557     JNIEnv *env;
    558 
    559     /*
    560      * Instance methods start with the instance, thread and class,
    561      * and statics and constructors start with the class and then the
    562      * thread.
    563      */
    564     env = getEnv();
    565     if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) {
    566         instance = inStream_readObjectRef(env, in);
    567         thread = inStream_readThreadRef(env, in);
    568         clazz = inStream_readClassRef(env, in);
    569     } else { /* static method or constructor */
    570         instance = NULL;
    571         clazz = inStream_readClassRef(env, in);
    572         thread = inStream_readThreadRef(env, in);
    573     }
    574 
    575     /*
    576      * ... and the rest of the packet is identical for all commands
    577      */
    578     method = inStream_readMethodID(in);
    579     argumentCount = inStream_readInt(in);
    580     if (inStream_error(in)) {
    581         return JNI_TRUE;
    582     }
    583 
    584     /* If count == 0, don't try and allocate 0 bytes, you'll get NULL */
    585     if ( argumentCount > 0 ) {
    586         int i;
    587         /*LINTED*/
    588         arguments = jvmtiAllocate(argumentCount * (jint)sizeof(*arguments));
    589         if (arguments == NULL) {
    590             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
    591             return JNI_TRUE;
    592         }
    593         for (i = 0; (i < argumentCount) && !inStream_error(in); i++) {
    594             arguments[i] = inStream_readValue(in, NULL);
    595         }
    596         if (inStream_error(in)) {
    597             return JNI_TRUE;
    598         }
    599     }
    600 
    601     options = inStream_readInt(in);
    602     if (inStream_error(in)) {
    603         if ( arguments != NULL ) {
    604             jvmtiDeallocate(arguments);
    605         }
    606         return JNI_TRUE;
    607     }
    608 
    609     if (inStream_command(in) == JDWP_COMMAND(ClassType, NewInstance)) {
    610         invokeType = INVOKE_CONSTRUCTOR;
    611     } else if (inStream_command(in) == JDWP_COMMAND(ClassType, InvokeMethod)) {
    612         invokeType = INVOKE_STATIC;
    613     } else if (inStream_command(in) == JDWP_COMMAND(InterfaceType, InvokeMethod)) {
    614         invokeType = INVOKE_STATIC;
    615     } else if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) {
    616         invokeType = INVOKE_INSTANCE;
    617     } else {
    618         outStream_setError(out, JDWP_ERROR(INTERNAL));
    619         if ( arguments != NULL ) {
    620             jvmtiDeallocate(arguments);
    621         }
    622         return JNI_TRUE;
    623     }
    624 
    625     /*
    626      * Request the invoke. If there are no errors in the request,
    627      * the interrupting thread will actually do the invoke and a
    628      * reply will be generated subsequently, so we don't reply here.
    629      */
    630     error = invoker_requestInvoke(invokeType, (jbyte)options, inStream_id(in),
    631                                   thread, clazz, method,
    632                                   instance, arguments, argumentCount);
    633     if (error != JVMTI_ERROR_NONE) {
    634         outStream_setError(out, map2jdwpError(error));
    635         if ( arguments != NULL ) {
    636             jvmtiDeallocate(arguments);
    637         }
    638         return JNI_TRUE;
    639     }
    640 
    641     return JNI_FALSE;   /* Don't reply */
    642 }
    643 
    644 jint
    645 uniqueID(void)
    646 {
    647     static jint currentID = 0;
    648     // ANDROID-CHANGED: on android we sometimes need to share these id's with DDMS traffic that is
    649     // multiplexed on the same connection. Since we don't have any way to know which id's are taken
    650     // by DDMS we will instead partition the ids between them. All positive ids (sign-bit == 0) are
    651     // reserved for libjdwp. DDMS will take ids with sign-bit == 1. This condition is not expected
    652     // to ever be true on a normal debugging session.
    653     if (currentID < 0) {
    654       currentID = 0;
    655     }
    656     return currentID++;
    657 }
    658 
    659 int
    660 filterDebugThreads(jthread *threads, int count)
    661 {
    662     int i;
    663     int current;
    664 
    665     /* Squish out all of the debugger-spawned threads */
    666     for (i = 0, current = 0; i < count; i++) {
    667         jthread thread = threads[i];
    668         if (!threadControl_isDebugThread(thread)) {
    669             if (i > current) {
    670                 threads[current] = thread;
    671             }
    672             current++;
    673         }
    674     }
    675     return current;
    676 }
    677 
    678 jbyte
    679 referenceTypeTag(jclass clazz)
    680 {
    681     jbyte tag;
    682 
    683     if (isInterface(clazz)) {
    684         tag = JDWP_TYPE_TAG(INTERFACE);
    685     } else if (isArrayClass(clazz)) {
    686         tag = JDWP_TYPE_TAG(ARRAY);
    687     } else {
    688         tag = JDWP_TYPE_TAG(CLASS);
    689     }
    690 
    691     return tag;
    692 }
    693 
    694 /**
    695  * Get field modifiers
    696  */
    697 jvmtiError
    698 fieldModifiers(jclass clazz, jfieldID field, jint *pmodifiers)
    699 {
    700     jvmtiError error;
    701 
    702     *pmodifiers = 0;
    703     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldModifiers)
    704             (gdata->jvmti, clazz, field, pmodifiers);
    705     return error;
    706 }
    707 
    708 /**
    709  * Get method modifiers
    710  */
    711 jvmtiError
    712 methodModifiers(jmethodID method, jint *pmodifiers)
    713 {
    714     jvmtiError error;
    715 
    716     *pmodifiers = 0;
    717     error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodModifiers)
    718             (gdata->jvmti, method, pmodifiers);
    719     return error;
    720 }
    721 
    722 /* Returns a local ref to the declaring class for a method, or NULL. */
    723 jvmtiError
    724 methodClass(jmethodID method, jclass *pclazz)
    725 {
    726     jvmtiError error;
    727 
    728     *pclazz = NULL;
    729     error = FUNC_PTR(gdata->jvmti,GetMethodDeclaringClass)
    730                                 (gdata->jvmti, method, pclazz);
    731     return error;
    732 }
    733 
    734 /* Returns a local ref to the declaring class for a method, or NULL. */
    735 jvmtiError
    736 methodLocation(jmethodID method, jlocation *ploc1, jlocation *ploc2)
    737 {
    738     jvmtiError error;
    739 
    740     error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodLocation)
    741                                 (gdata->jvmti, method, ploc1, ploc2);
    742     return error;
    743 }
    744 
    745 /**
    746  * Get method signature
    747  */
    748 jvmtiError
    749 methodSignature(jmethodID method,
    750         char **pname, char **psignature, char **pgeneric_signature)
    751 {
    752     jvmtiError error;
    753     char *name = NULL;
    754     char *signature = NULL;
    755     char *generic_signature = NULL;
    756 
    757     error = FUNC_PTR(gdata->jvmti,GetMethodName)
    758             (gdata->jvmti, method, &name, &signature, &generic_signature);
    759 
    760     if ( pname != NULL ) {
    761         *pname = name;
    762     } else if ( name != NULL )  {
    763         jvmtiDeallocate(name);
    764     }
    765     if ( psignature != NULL ) {
    766         *psignature = signature;
    767     } else if ( signature != NULL ) {
    768         jvmtiDeallocate(signature);
    769     }
    770     if ( pgeneric_signature != NULL ) {
    771         *pgeneric_signature = generic_signature;
    772     } else if ( generic_signature != NULL )  {
    773         jvmtiDeallocate(generic_signature);
    774     }
    775     return error;
    776 }
    777 
    778 /*
    779  * Get the return type key of the method
    780  *     V or B C D F I J S Z L  [
    781  */
    782 jvmtiError
    783 methodReturnType(jmethodID method, char *typeKey)
    784 {
    785     char       *signature;
    786     jvmtiError  error;
    787 
    788     signature = NULL;
    789     error     = methodSignature(method, NULL, &signature, NULL);
    790     if (error == JVMTI_ERROR_NONE) {
    791         if (signature == NULL ) {
    792             error = AGENT_ERROR_INVALID_TAG;
    793         } else {
    794             char * xx;
    795 
    796             xx = strchr(signature, ')');
    797             if (xx == NULL || *(xx + 1) == 0) {
    798                 error = AGENT_ERROR_INVALID_TAG;
    799             } else {
    800                *typeKey = *(xx + 1);
    801             }
    802             jvmtiDeallocate(signature);
    803         }
    804     }
    805     return error;
    806 }
    807 
    808 
    809 /**
    810  * Return class loader for a class (must be inside a WITH_LOCAL_REFS)
    811  */
    812 jvmtiError
    813 classLoader(jclass clazz, jobject *pclazz)
    814 {
    815     jvmtiError error;
    816 
    817     *pclazz = NULL;
    818     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoader)
    819             (gdata->jvmti, clazz, pclazz);
    820     return error;
    821 }
    822 
    823 /**
    824  * Get field signature
    825  */
    826 jvmtiError
    827 fieldSignature(jclass clazz, jfieldID field,
    828         char **pname, char **psignature, char **pgeneric_signature)
    829 {
    830     jvmtiError error;
    831     char *name = NULL;
    832     char *signature = NULL;
    833     char *generic_signature = NULL;
    834 
    835     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldName)
    836             (gdata->jvmti, clazz, field, &name, &signature, &generic_signature);
    837 
    838     if ( pname != NULL ) {
    839         *pname = name;
    840     } else if ( name != NULL )  {
    841         jvmtiDeallocate(name);
    842     }
    843     if ( psignature != NULL ) {
    844         *psignature = signature;
    845     } else if ( signature != NULL )  {
    846         jvmtiDeallocate(signature);
    847     }
    848     if ( pgeneric_signature != NULL ) {
    849         *pgeneric_signature = generic_signature;
    850     } else if ( generic_signature != NULL )  {
    851         jvmtiDeallocate(generic_signature);
    852     }
    853     return error;
    854 }
    855 
    856 JNIEnv *
    857 getEnv(void)
    858 {
    859     JNIEnv *env = NULL;
    860     jint rc;
    861 
    862     rc = FUNC_PTR(gdata->jvm,GetEnv)
    863                 (gdata->jvm, (void **)&env, JNI_VERSION_1_2);
    864     if (rc != JNI_OK) {
    865         ERROR_MESSAGE(("JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = %d",
    866                 rc));
    867         EXIT_ERROR(AGENT_ERROR_NO_JNI_ENV,NULL);
    868     }
    869     return env;
    870 }
    871 
    872 jvmtiError
    873 spawnNewThread(jvmtiStartFunction func, void *arg, char *name)
    874 {
    875     JNIEnv *env = getEnv();
    876     jvmtiError error;
    877 
    878     LOG_MISC(("Spawning new thread: %s", name));
    879 
    880     WITH_LOCAL_REFS(env, 3) {
    881 
    882         jthread thread;
    883         jstring nameString;
    884 
    885         nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, name);
    886         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    887             JNI_FUNC_PTR(env,ExceptionClear)(env);
    888             error = AGENT_ERROR_OUT_OF_MEMORY;
    889             goto err;
    890         }
    891 
    892         thread = JNI_FUNC_PTR(env,NewObject)
    893                         (env, gdata->threadClass, gdata->threadConstructor,
    894                                    gdata->systemThreadGroup, nameString);
    895         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    896             JNI_FUNC_PTR(env,ExceptionClear)(env);
    897             error = AGENT_ERROR_OUT_OF_MEMORY;
    898             goto err;
    899         }
    900 
    901         /*
    902          * Make the debugger thread a daemon
    903          */
    904         JNI_FUNC_PTR(env,CallVoidMethod)
    905                         (env, thread, gdata->threadSetDaemon, JNI_TRUE);
    906         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    907             JNI_FUNC_PTR(env,ExceptionClear)(env);
    908             error = AGENT_ERROR_JNI_EXCEPTION;
    909             goto err;
    910         }
    911 
    912         error = threadControl_addDebugThread(thread);
    913         if (error == JVMTI_ERROR_NONE) {
    914             /*
    915              * Debugger threads need cycles in all sorts of strange
    916              * situations (e.g. infinite cpu-bound loops), so give the
    917              * thread a high priority. Note that if the VM has an application
    918              * thread running at the max priority, there is still a chance
    919              * that debugger threads will be starved. (There needs to be
    920              * a way to give debugger threads a priority higher than any
    921              * application thread).
    922              */
    923             error = JVMTI_FUNC_PTR(gdata->jvmti,RunAgentThread)
    924                         (gdata->jvmti, thread, func, arg,
    925                                         JVMTI_THREAD_MAX_PRIORITY);
    926         }
    927 
    928         err: ;
    929 
    930     } END_WITH_LOCAL_REFS(env);
    931 
    932     return error;
    933 }
    934 
    935 jvmtiError
    936 jvmtiGetCapabilities(jvmtiCapabilities *caps)
    937 {
    938     if ( gdata->vmDead ) {
    939         return AGENT_ERROR_VM_DEAD;
    940     }
    941     if (!gdata->haveCachedJvmtiCapabilities) {
    942         jvmtiError error;
    943 
    944         error = JVMTI_FUNC_PTR(gdata->jvmti,GetCapabilities)
    945                         (gdata->jvmti, &(gdata->cachedJvmtiCapabilities));
    946         if (error != JVMTI_ERROR_NONE) {
    947             return error;
    948         }
    949         gdata->haveCachedJvmtiCapabilities = JNI_TRUE;
    950     }
    951 
    952     *caps = gdata->cachedJvmtiCapabilities;
    953 
    954     return JVMTI_ERROR_NONE;
    955 }
    956 
    957 static jint
    958 jvmtiVersion(void)
    959 {
    960     if (gdata->cachedJvmtiVersion == 0) {
    961         jvmtiError error;
    962         error = JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)
    963                         (gdata->jvmti, &(gdata->cachedJvmtiVersion));
    964         if (error != JVMTI_ERROR_NONE) {
    965             EXIT_ERROR(error, "on getting the JVMTI version number");
    966         }
    967     }
    968     return gdata->cachedJvmtiVersion;
    969 }
    970 
    971 jint
    972 jvmtiMajorVersion(void)
    973 {
    974     return (jvmtiVersion() & JVMTI_VERSION_MASK_MAJOR)
    975                     >> JVMTI_VERSION_SHIFT_MAJOR;
    976 }
    977 
    978 jint
    979 jvmtiMinorVersion(void)
    980 {
    981     return (jvmtiVersion() & JVMTI_VERSION_MASK_MINOR)
    982                     >> JVMTI_VERSION_SHIFT_MINOR;
    983 }
    984 
    985 jint
    986 jvmtiMicroVersion(void)
    987 {
    988     return (jvmtiVersion() & JVMTI_VERSION_MASK_MICRO)
    989                     >> JVMTI_VERSION_SHIFT_MICRO;
    990 }
    991 
    992 jboolean
    993 canSuspendResumeThreadLists(void)
    994 {
    995     jvmtiError error;
    996     jvmtiCapabilities cap;
    997 
    998     error = jvmtiGetCapabilities(&cap);
    999     return (error == JVMTI_ERROR_NONE && cap.can_suspend);
   1000 }
   1001 
   1002 jvmtiError
   1003 getSourceDebugExtension(jclass clazz, char **extensionPtr)
   1004 {
   1005     return JVMTI_FUNC_PTR(gdata->jvmti,GetSourceDebugExtension)
   1006                 (gdata->jvmti, clazz, extensionPtr);
   1007 }
   1008 
   1009 /*
   1010  * Convert the signature "Ljava/lang/Foo;" to a
   1011  * classname "java.lang.Foo" compatible with the pattern.
   1012  * Signature is overwritten in-place.
   1013  */
   1014 void
   1015 convertSignatureToClassname(char *convert)
   1016 {
   1017     char *p;
   1018 
   1019     p = convert + 1;
   1020     while ((*p != ';') && (*p != '\0')) {
   1021         char c = *p;
   1022         if (c == '/') {
   1023             *(p-1) = '.';
   1024         } else {
   1025             *(p-1) = c;
   1026         }
   1027         p++;
   1028     }
   1029     *(p-1) = '\0';
   1030 }
   1031 
   1032 static void
   1033 handleInterrupt(void)
   1034 {
   1035     /*
   1036      * An interrupt is handled:
   1037      *
   1038      * 1) for running application threads by deferring the interrupt
   1039      * until the current event handler has concluded.
   1040      *
   1041      * 2) for debugger threads by ignoring the interrupt; this is the
   1042      * most robust solution since debugger threads don't use interrupts
   1043      * to signal any condition.
   1044      *
   1045      * 3) for application threads that have not started or already
   1046      * ended by ignoring the interrupt. In the former case, the application
   1047      * is relying on timing to determine whether or not the thread sees
   1048      * the interrupt; in the latter case, the interrupt is meaningless.
   1049      */
   1050     jthread thread = threadControl_currentThread();
   1051     if ((thread != NULL) && (!threadControl_isDebugThread(thread))) {
   1052         threadControl_setPendingInterrupt(thread);
   1053     }
   1054 }
   1055 
   1056 static jvmtiError
   1057 ignore_vm_death(jvmtiError error)
   1058 {
   1059     if (error == JVMTI_ERROR_WRONG_PHASE) {
   1060         LOG_MISC(("VM_DEAD, in debugMonitor*()?"));
   1061         return JVMTI_ERROR_NONE; /* JVMTI does this, not JVMDI? */
   1062     }
   1063     return error;
   1064 }
   1065 
   1066 void
   1067 debugMonitorEnter(jrawMonitorID monitor)
   1068 {
   1069     jvmtiError error;
   1070     while (JNI_TRUE) {
   1071         error = FUNC_PTR(gdata->jvmti,RawMonitorEnter)
   1072                         (gdata->jvmti, monitor);
   1073         error = ignore_vm_death(error);
   1074         if (error == JVMTI_ERROR_INTERRUPT) {
   1075             handleInterrupt();
   1076         } else {
   1077             break;
   1078         }
   1079     }
   1080     if (error != JVMTI_ERROR_NONE) {
   1081         EXIT_ERROR(error, "on raw monitor enter");
   1082     }
   1083 }
   1084 
   1085 void
   1086 debugMonitorExit(jrawMonitorID monitor)
   1087 {
   1088     jvmtiError error;
   1089 
   1090     error = FUNC_PTR(gdata->jvmti,RawMonitorExit)
   1091                 (gdata->jvmti, monitor);
   1092     error = ignore_vm_death(error);
   1093     if (error != JVMTI_ERROR_NONE) {
   1094         EXIT_ERROR(error, "on raw monitor exit");
   1095     }
   1096 }
   1097 
   1098 /* ANDROID-CHANGED: Add suspension ignoring raw-monitor enter. */
   1099 void debugMonitorEnterNoSuspend(jrawMonitorID monitor)
   1100 {
   1101     jvmtiError error;
   1102     while (JNI_TRUE) {
   1103         error = FUNC_PTR(&gdata,raw_monitor_enter_no_suspend)(gdata->jvmti, monitor);
   1104         error = ignore_vm_death(error);
   1105         if (error == JVMTI_ERROR_INTERRUPT) {
   1106             handleInterrupt();
   1107         } else {
   1108             break;
   1109         }
   1110     }
   1111     if (error != JVMTI_ERROR_NONE) {
   1112         EXIT_ERROR(error, "on raw monitor enter no suspend");
   1113     }
   1114 }
   1115 
   1116 void
   1117 debugMonitorWait(jrawMonitorID monitor)
   1118 {
   1119     jvmtiError error;
   1120     error = FUNC_PTR(gdata->jvmti,RawMonitorWait)
   1121         (gdata->jvmti, monitor, ((jlong)(-1)));
   1122 
   1123     /*
   1124      * According to the JLS (17.8), here we have
   1125      * either :
   1126      * a- been notified
   1127      * b- gotten a suprious wakeup
   1128      * c- been interrupted
   1129      * If both a and c have happened, the VM must choose
   1130      * which way to return - a or c.  If it chooses c
   1131      * then the notify is gone - either to some other
   1132      * thread that is also waiting, or it is dropped
   1133      * on the floor.
   1134      *
   1135      * a is what we expect.  b won't hurt us any -
   1136      * callers should be programmed to handle
   1137      * spurious wakeups.  In case of c,
   1138      * then the interrupt has been cleared, but
   1139      * we don't want to consume it.  It came from
   1140      * user code and is intended for user code, not us.
   1141      * So, we will remember that the interrupt has
   1142      * occurred and re-activate it when this thread
   1143      * goes back into user code.
   1144      * That being said, what do we do here?  Since
   1145      * we could have been notified too, here we will
   1146      * just pretend that we have been.  It won't hurt
   1147      * anything to return in the same way as if
   1148      * we were notified since callers have to be able to
   1149      * handle spurious wakeups anyway.
   1150      */
   1151     if (error == JVMTI_ERROR_INTERRUPT) {
   1152         handleInterrupt();
   1153         error = JVMTI_ERROR_NONE;
   1154     }
   1155     error = ignore_vm_death(error);
   1156     if (error != JVMTI_ERROR_NONE) {
   1157         EXIT_ERROR(error, "on raw monitor wait");
   1158     }
   1159 }
   1160 
   1161 void
   1162 debugMonitorTimedWait(jrawMonitorID monitor, jlong millis)
   1163 {
   1164     jvmtiError error;
   1165     error = FUNC_PTR(gdata->jvmti,RawMonitorWait)
   1166         (gdata->jvmti, monitor, millis);
   1167     if (error == JVMTI_ERROR_INTERRUPT) {
   1168         /* See comment above */
   1169         handleInterrupt();
   1170         error = JVMTI_ERROR_NONE;
   1171     }
   1172     error = ignore_vm_death(error);
   1173     if (error != JVMTI_ERROR_NONE) {
   1174         EXIT_ERROR(error, "on raw monitor timed wait");
   1175     }
   1176 }
   1177 
   1178 void
   1179 debugMonitorNotify(jrawMonitorID monitor)
   1180 {
   1181     jvmtiError error;
   1182 
   1183     error = FUNC_PTR(gdata->jvmti,RawMonitorNotify)
   1184                 (gdata->jvmti, monitor);
   1185     error = ignore_vm_death(error);
   1186     if (error != JVMTI_ERROR_NONE) {
   1187         EXIT_ERROR(error, "on raw monitor notify");
   1188     }
   1189 }
   1190 
   1191 void
   1192 debugMonitorNotifyAll(jrawMonitorID monitor)
   1193 {
   1194     jvmtiError error;
   1195 
   1196     error = FUNC_PTR(gdata->jvmti,RawMonitorNotifyAll)
   1197                 (gdata->jvmti, monitor);
   1198     error = ignore_vm_death(error);
   1199     if (error != JVMTI_ERROR_NONE) {
   1200         EXIT_ERROR(error, "on raw monitor notify all");
   1201     }
   1202 }
   1203 
   1204 jrawMonitorID
   1205 debugMonitorCreate(char *name)
   1206 {
   1207     jrawMonitorID monitor;
   1208     jvmtiError error;
   1209 
   1210     error = FUNC_PTR(gdata->jvmti,CreateRawMonitor)
   1211                 (gdata->jvmti, name, &monitor);
   1212     if (error != JVMTI_ERROR_NONE) {
   1213         EXIT_ERROR(error, "on creation of a raw monitor");
   1214     }
   1215     return monitor;
   1216 }
   1217 
   1218 void
   1219 debugMonitorDestroy(jrawMonitorID monitor)
   1220 {
   1221     jvmtiError error;
   1222 
   1223     error = FUNC_PTR(gdata->jvmti,DestroyRawMonitor)
   1224                 (gdata->jvmti, monitor);
   1225     error = ignore_vm_death(error);
   1226     if (error != JVMTI_ERROR_NONE) {
   1227         EXIT_ERROR(error, "on destruction of raw monitor");
   1228     }
   1229 }
   1230 
   1231 /**
   1232  * Return array of all threads (must be inside a WITH_LOCAL_REFS)
   1233  */
   1234 jthread *
   1235 allThreads(jint *count)
   1236 {
   1237     jthread *threads;
   1238     jvmtiError error;
   1239 
   1240     *count = 0;
   1241     threads = NULL;
   1242     error = JVMTI_FUNC_PTR(gdata->jvmti,GetAllThreads)
   1243                 (gdata->jvmti, count, &threads);
   1244     if (error == AGENT_ERROR_OUT_OF_MEMORY) {
   1245         return NULL; /* Let caller deal with no memory? */
   1246     }
   1247     if (error != JVMTI_ERROR_NONE) {
   1248         EXIT_ERROR(error, "getting all threads");
   1249     }
   1250     return threads;
   1251 }
   1252 
   1253 /**
   1254  * Fill the passed in structure with thread group info.
   1255  * name field is JVMTI allocated.  parent is global ref.
   1256  */
   1257 void
   1258 threadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo *info)
   1259 {
   1260     jvmtiError error;
   1261 
   1262     error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadGroupInfo)
   1263                 (gdata->jvmti, group, info);
   1264     if (error != JVMTI_ERROR_NONE) {
   1265         EXIT_ERROR(error, "on getting thread group info");
   1266     }
   1267 }
   1268 
   1269 /**
   1270  * Return class signature string
   1271  */
   1272 jvmtiError
   1273 classSignature(jclass clazz, char **psignature, char **pgeneric_signature)
   1274 {
   1275     jvmtiError error;
   1276     char *signature = NULL;
   1277 
   1278     /*
   1279      * pgeneric_signature can be NULL, and GetClassSignature
   1280      * accepts NULL.
   1281      */
   1282     error = FUNC_PTR(gdata->jvmti,GetClassSignature)
   1283                 (gdata->jvmti, clazz, &signature, pgeneric_signature);
   1284 
   1285     if ( psignature != NULL ) {
   1286         *psignature = signature;
   1287     } else if ( signature != NULL )  {
   1288         jvmtiDeallocate(signature);
   1289     }
   1290     return error;
   1291 }
   1292 
   1293 /* Get class name (not signature) */
   1294 char *
   1295 getClassname(jclass clazz)
   1296 {
   1297     char *classname;
   1298 
   1299     classname = NULL;
   1300     if ( clazz != NULL ) {
   1301         if (classSignature(clazz, &classname, NULL) != JVMTI_ERROR_NONE) {
   1302             classname = NULL;
   1303         } else {
   1304             /* Convert in place */
   1305             convertSignatureToClassname(classname);
   1306         }
   1307     }
   1308     return classname; /* Caller must free this memory */
   1309 }
   1310 
   1311 void
   1312 writeGenericSignature(PacketOutputStream *out, char *genericSignature)
   1313 {
   1314     if (genericSignature == NULL) {
   1315         (void)outStream_writeString(out, "");
   1316     } else {
   1317         (void)outStream_writeString(out, genericSignature);
   1318     }
   1319 }
   1320 
   1321 jint
   1322 classStatus(jclass clazz)
   1323 {
   1324     jint status;
   1325     jvmtiError error;
   1326 
   1327     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassStatus)
   1328                 (gdata->jvmti, clazz, &status);
   1329     if (error != JVMTI_ERROR_NONE) {
   1330         EXIT_ERROR(error, "on getting class status");
   1331     }
   1332     return status;
   1333 }
   1334 
   1335 /* ANDROID-CHANGED: Make isArrayClass public */
   1336 jboolean
   1337 isArrayClass(jclass clazz)
   1338 {
   1339     jboolean isArray = JNI_FALSE;
   1340     jvmtiError error;
   1341 
   1342     error = JVMTI_FUNC_PTR(gdata->jvmti,IsArrayClass)
   1343                 (gdata->jvmti, clazz, &isArray);
   1344     if (error != JVMTI_ERROR_NONE) {
   1345         EXIT_ERROR(error, "on checking for an array class");
   1346     }
   1347     return isArray;
   1348 }
   1349 
   1350 static jboolean
   1351 isInterface(jclass clazz)
   1352 {
   1353     jboolean isInterface = JNI_FALSE;
   1354     jvmtiError error;
   1355 
   1356     error = JVMTI_FUNC_PTR(gdata->jvmti,IsInterface)
   1357                 (gdata->jvmti, clazz, &isInterface);
   1358     if (error != JVMTI_ERROR_NONE) {
   1359         EXIT_ERROR(error, "on checking for an interface");
   1360     }
   1361     return isInterface;
   1362 }
   1363 
   1364 jvmtiError
   1365 isFieldSynthetic(jclass clazz, jfieldID field, jboolean *psynthetic)
   1366 {
   1367     jvmtiError error;
   1368 
   1369     error = JVMTI_FUNC_PTR(gdata->jvmti,IsFieldSynthetic)
   1370                 (gdata->jvmti, clazz, field, psynthetic);
   1371     if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) {
   1372         /* If the query is not supported, we assume it is not synthetic. */
   1373         *psynthetic = JNI_FALSE;
   1374         return JVMTI_ERROR_NONE;
   1375     }
   1376     return error;
   1377 }
   1378 
   1379 jvmtiError
   1380 isMethodSynthetic(jmethodID method, jboolean *psynthetic)
   1381 {
   1382     jvmtiError error;
   1383 
   1384     error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodSynthetic)
   1385                 (gdata->jvmti, method, psynthetic);
   1386     if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) {
   1387         /* If the query is not supported, we assume it is not synthetic. */
   1388         *psynthetic = JNI_FALSE;
   1389         return JVMTI_ERROR_NONE;
   1390     }
   1391     return error;
   1392 }
   1393 
   1394 jboolean
   1395 isMethodNative(jmethodID method)
   1396 {
   1397     jboolean isNative = JNI_FALSE;
   1398     jvmtiError error;
   1399 
   1400     error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodNative)
   1401                 (gdata->jvmti, method, &isNative);
   1402     if (error != JVMTI_ERROR_NONE) {
   1403         EXIT_ERROR(error, "on checking for a native interface");
   1404     }
   1405     return isNative;
   1406 }
   1407 
   1408 jboolean
   1409 isSameObject(JNIEnv *env, jobject o1, jobject o2)
   1410 {
   1411     if ( o1==o2 ) {
   1412         return JNI_TRUE;
   1413     }
   1414     return FUNC_PTR(env,IsSameObject)(env, o1, o2);
   1415 }
   1416 
   1417 jint
   1418 objectHashCode(jobject object)
   1419 {
   1420     jint hashCode = 0;
   1421     jvmtiError error;
   1422 
   1423     if ( object!=NULL ) {
   1424         error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectHashCode)
   1425                     (gdata->jvmti, object, &hashCode);
   1426         if (error != JVMTI_ERROR_NONE) {
   1427             EXIT_ERROR(error, "on getting an object hash code");
   1428         }
   1429     }
   1430     return hashCode;
   1431 }
   1432 
   1433 /* Get all implemented interfaces (must be inside a WITH_LOCAL_REFS) */
   1434 jvmtiError
   1435 allInterfaces(jclass clazz, jclass **ppinterfaces, jint *pcount)
   1436 {
   1437     jvmtiError error;
   1438 
   1439     *pcount = 0;
   1440     *ppinterfaces = NULL;
   1441     error = JVMTI_FUNC_PTR(gdata->jvmti,GetImplementedInterfaces)
   1442                 (gdata->jvmti, clazz, pcount, ppinterfaces);
   1443     return error;
   1444 }
   1445 
   1446 /* Get all loaded classes (must be inside a WITH_LOCAL_REFS) */
   1447 jvmtiError
   1448 allLoadedClasses(jclass **ppclasses, jint *pcount)
   1449 {
   1450     jvmtiError error;
   1451 
   1452     *pcount = 0;
   1453     *ppclasses = NULL;
   1454     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLoadedClasses)
   1455                 (gdata->jvmti, pcount, ppclasses);
   1456     return error;
   1457 }
   1458 
   1459 /* Get all loaded classes for a loader (must be inside a WITH_LOCAL_REFS) */
   1460 jvmtiError
   1461 allClassLoaderClasses(jobject loader, jclass **ppclasses, jint *pcount)
   1462 {
   1463     jvmtiError error;
   1464 
   1465     *pcount = 0;
   1466     *ppclasses = NULL;
   1467     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoaderClasses)
   1468                 (gdata->jvmti, loader, pcount, ppclasses);
   1469     return error;
   1470 }
   1471 
   1472 static jboolean
   1473 is_a_nested_class(char *outer_sig, int outer_sig_len, char *sig, int sep)
   1474 {
   1475     char *inner;
   1476 
   1477     /* Assumed outer class signature is  "LOUTERCLASSNAME;"
   1478      *         inner class signature is  "LOUTERCLASSNAME$INNERNAME;"
   1479      *
   1480      * INNERNAME can take the form:
   1481      *    [0-9][1-9]*        anonymous class somewhere in the file
   1482      *    [0-9][1-9]*NAME    local class somewhere in the OUTER class
   1483      *    NAME               nested class in OUTER
   1484      *
   1485      * If NAME itself contains a $ (sep) then classname is further nested
   1486      *    inside another class.
   1487      *
   1488      */
   1489 
   1490     /* Check prefix first */
   1491     if ( strncmp(sig, outer_sig, outer_sig_len-1) != 0 ) {
   1492         return JNI_FALSE;
   1493     }
   1494 
   1495     /* Prefix must be followed by a $ (sep) */
   1496     if ( sig[outer_sig_len-1] != sep ) {
   1497         return JNI_FALSE;  /* No sep follows the match, must not be nested. */
   1498     }
   1499 
   1500     /* Walk past any digits, if we reach the end, must be pure anonymous */
   1501     inner = sig + outer_sig_len;
   1502 #if 1 /* We want to return local classes */
   1503     while ( *inner && isdigit(*inner) ) {
   1504         inner++;
   1505     }
   1506     /* But anonymous class names can't be trusted. */
   1507     if ( *inner == ';' ) {
   1508         return JNI_FALSE;  /* A pure anonymous class */
   1509     }
   1510 #else
   1511     if ( *inner && isdigit(*inner) ) {
   1512         return JNI_FALSE;  /* A pure anonymous or local class */
   1513     }
   1514 #endif
   1515 
   1516     /* Nested deeper? */
   1517     if ( strchr(inner, sep) != NULL ) {
   1518         return JNI_FALSE;  /* Nested deeper than we want? */
   1519     }
   1520     return JNI_TRUE;
   1521 }
   1522 
   1523 /* Get all nested classes for a class (must be inside a WITH_LOCAL_REFS) */
   1524 jvmtiError
   1525 allNestedClasses(jclass parent_clazz, jclass **ppnested, jint *pcount)
   1526 {
   1527     jvmtiError error;
   1528     jobject parent_loader;
   1529     jclass *classes;
   1530     char *signature;
   1531     size_t len;
   1532     jint count;
   1533     jint ncount;
   1534     int i;
   1535 
   1536     *ppnested   = NULL;
   1537     *pcount     = 0;
   1538 
   1539     parent_loader = NULL;
   1540     classes       = NULL;
   1541     signature     = NULL;
   1542     count         = 0;
   1543     ncount        = 0;
   1544 
   1545     error = classLoader(parent_clazz, &parent_loader);
   1546     if (error != JVMTI_ERROR_NONE) {
   1547         return error;
   1548     }
   1549     error = classSignature(parent_clazz, &signature, NULL);
   1550     if (error != JVMTI_ERROR_NONE) {
   1551         return error;
   1552     }
   1553     len = strlen(signature);
   1554 
   1555     error = allClassLoaderClasses(parent_loader, &classes, &count);
   1556     if ( error != JVMTI_ERROR_NONE ) {
   1557         jvmtiDeallocate(signature);
   1558         return error;
   1559     }
   1560 
   1561     for (i=0; i<count; i++) {
   1562         jclass clazz;
   1563         char *candidate_signature;
   1564 
   1565         clazz = classes[i];
   1566         candidate_signature = NULL;
   1567         error = classSignature(clazz, &candidate_signature, NULL);
   1568         if (error != JVMTI_ERROR_NONE) {
   1569             break;
   1570         }
   1571 
   1572         if ( is_a_nested_class(signature, (int)len, candidate_signature, '$') ||
   1573              is_a_nested_class(signature, (int)len, candidate_signature, '#') ) {
   1574             /* Float nested classes to top */
   1575             classes[i] = classes[ncount];
   1576             classes[ncount++] = clazz;
   1577         }
   1578         jvmtiDeallocate(candidate_signature);
   1579     }
   1580 
   1581     jvmtiDeallocate(signature);
   1582 
   1583     if ( count != 0 &&  ncount == 0 ) {
   1584         jvmtiDeallocate(classes);
   1585         classes = NULL;
   1586     }
   1587 
   1588     *ppnested = classes;
   1589     *pcount = ncount;
   1590     return error;
   1591 }
   1592 
   1593 void
   1594 createLocalRefSpace(JNIEnv *env, jint capacity)
   1595 {
   1596     /*
   1597      * Save current exception since it might get overwritten by
   1598      * the calls below. Note we must depend on space in the existing
   1599      * frame because asking for a new frame may generate an exception.
   1600      */
   1601     jobject throwable = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
   1602 
   1603     /*
   1604      * Use the current frame if necessary; otherwise create a new one
   1605      */
   1606     if (JNI_FUNC_PTR(env,PushLocalFrame)(env, capacity) < 0) {
   1607         EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"PushLocalFrame: Unable to push JNI frame");
   1608     }
   1609 
   1610     /*
   1611      * TO DO: This could be more efficient if it used EnsureLocalCapacity,
   1612      * but that would not work if two functions on the call stack
   1613      * use this function. We would need to either track reserved
   1614      * references on a per-thread basis or come up with a convention
   1615      * that would prevent two functions from depending on this function
   1616      * at the same time.
   1617      */
   1618 
   1619     /*
   1620      * Restore exception state from before call
   1621      */
   1622     if (throwable != NULL) {
   1623         JNI_FUNC_PTR(env,Throw)(env, throwable);
   1624     } else {
   1625         JNI_FUNC_PTR(env,ExceptionClear)(env);
   1626     }
   1627 }
   1628 
   1629 jboolean
   1630 isClass(jobject object)
   1631 {
   1632     JNIEnv *env = getEnv();
   1633     return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classClass);
   1634 }
   1635 
   1636 jboolean
   1637 isThread(jobject object)
   1638 {
   1639     JNIEnv *env = getEnv();
   1640     return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadClass);
   1641 }
   1642 
   1643 jboolean
   1644 isThreadGroup(jobject object)
   1645 {
   1646     JNIEnv *env = getEnv();
   1647     return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadGroupClass);
   1648 }
   1649 
   1650 jboolean
   1651 isString(jobject object)
   1652 {
   1653     JNIEnv *env = getEnv();
   1654     return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->stringClass);
   1655 }
   1656 
   1657 jboolean
   1658 isClassLoader(jobject object)
   1659 {
   1660     JNIEnv *env = getEnv();
   1661     return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classLoaderClass);
   1662 }
   1663 
   1664 jboolean
   1665 isArray(jobject object)
   1666 {
   1667     JNIEnv *env = getEnv();
   1668     jboolean is;
   1669 
   1670     WITH_LOCAL_REFS(env, 1) {
   1671         jclass clazz;
   1672         clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
   1673         is = isArrayClass(clazz);
   1674     } END_WITH_LOCAL_REFS(env);
   1675 
   1676     return is;
   1677 }
   1678 
   1679 /**
   1680  * Return property value as jstring
   1681  */
   1682 static jstring
   1683 getPropertyValue(JNIEnv *env, char *propertyName)
   1684 {
   1685     jstring valueString;
   1686     jstring nameString;
   1687 
   1688     valueString = NULL;
   1689 
   1690     /* Create new String object to hold the property name */
   1691     nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName);
   1692     if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
   1693         JNI_FUNC_PTR(env,ExceptionClear)(env);
   1694         /* NULL will be returned below */
   1695     } else {
   1696         /* Call valueString = System.getProperty(nameString) */
   1697         valueString = JNI_FUNC_PTR(env,CallStaticObjectMethod)
   1698             (env, gdata->systemClass, gdata->systemGetProperty, nameString);
   1699         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
   1700             JNI_FUNC_PTR(env,ExceptionClear)(env);
   1701             valueString = NULL;
   1702         }
   1703     }
   1704     return valueString;
   1705 }
   1706 
   1707 /**
   1708  * Set an agent property
   1709  */
   1710 void
   1711 setAgentPropertyValue(JNIEnv *env, char *propertyName, char* propertyValue)
   1712 {
   1713     jstring nameString;
   1714     jstring valueString;
   1715 
   1716     if (gdata->agent_properties == NULL) {
   1717         /* VMSupport doesn't exist; so ignore */
   1718         return;
   1719     }
   1720 
   1721     /* Create jstrings for property name and value */
   1722     nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName);
   1723     if (nameString != NULL) {
   1724         valueString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyValue);
   1725         if (valueString != NULL) {
   1726             /* invoke Properties.setProperty */
   1727             JNI_FUNC_PTR(env,CallObjectMethod)
   1728                 (env, gdata->agent_properties,
   1729                  gdata->setProperty,
   1730                  nameString, valueString);
   1731         }
   1732     }
   1733     if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
   1734         JNI_FUNC_PTR(env,ExceptionClear)(env);
   1735     }
   1736 }
   1737 
   1738 /**
   1739  * Return property value as JDWP allocated string in UTF8 encoding
   1740  */
   1741 static char *
   1742 getPropertyUTF8(JNIEnv *env, char *propertyName)
   1743 {
   1744     jvmtiError  error;
   1745     char       *value;
   1746 
   1747     value = NULL;
   1748     error = JVMTI_FUNC_PTR(gdata->jvmti,GetSystemProperty)
   1749                 (gdata->jvmti, (const char *)propertyName, &value);
   1750     if (error != JVMTI_ERROR_NONE) {
   1751         jstring valueString;
   1752 
   1753         value = NULL;
   1754         valueString = getPropertyValue(env, propertyName);
   1755 
   1756         if (valueString != NULL) {
   1757             const char *utf;
   1758 
   1759             /* Get the UTF8 encoding for this property value string */
   1760             utf = JNI_FUNC_PTR(env,GetStringUTFChars)(env, valueString, NULL);
   1761             /* Make a copy for returning, release the JNI copy */
   1762             value = jvmtiAllocate((int)strlen(utf) + 1);
   1763             if (value != NULL) {
   1764                 (void)strcpy(value, utf);
   1765             }
   1766             JNI_FUNC_PTR(env,ReleaseStringUTFChars)(env, valueString, utf);
   1767         }
   1768     }
   1769     if ( value == NULL ) {
   1770         ERROR_MESSAGE(("JDWP Can't get property value for %s", propertyName));
   1771         EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
   1772     }
   1773     return value;
   1774 }
   1775 
   1776 jboolean
   1777 isMethodObsolete(jmethodID method)
   1778 {
   1779     jvmtiError error;
   1780     jboolean obsolete = JNI_TRUE;
   1781 
   1782     if ( method != NULL ) {
   1783         error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodObsolete)
   1784                     (gdata->jvmti, method, &obsolete);
   1785         if (error != JVMTI_ERROR_NONE) {
   1786             obsolete = JNI_TRUE;
   1787         }
   1788     }
   1789     return obsolete;
   1790 }
   1791 
   1792 /* Get the jvmti environment to be used with tags
   1793  * ANDROID_CHANGED: Expose this function publicly for use with class-track and other places.
   1794  */
   1795 jvmtiEnv *
   1796 getSpecialJvmti(void)
   1797 {
   1798     jvmtiEnv  *jvmti;
   1799     jvmtiError error;
   1800     int        rc;
   1801 
   1802     /* Get one time use JVMTI Env */
   1803     jvmtiCapabilities caps;
   1804 
   1805     // ANDROID-CHANGED: Always get a new jvmti-env using the same version as the main env. This
   1806     // means that everything will still work even when using a best-effort ArtTiEnv.
   1807     rc = JVM_FUNC_PTR(gdata->jvm,GetEnv)
   1808                      (gdata->jvm, (void **)&jvmti, jvmtiVersion());
   1809     if (rc != JNI_OK) {
   1810         return NULL;
   1811     }
   1812     (void)memset(&caps, 0, (int)sizeof(caps));
   1813     caps.can_tag_objects = 1;
   1814     error = JVMTI_FUNC_PTR(jvmti,AddCapabilities)(jvmti, &caps);
   1815     if ( error != JVMTI_ERROR_NONE ) {
   1816         return NULL;
   1817     }
   1818     return jvmti;
   1819 }
   1820 
   1821 void
   1822 writeCodeLocation(PacketOutputStream *out, jclass clazz,
   1823                        jmethodID method, jlocation location)
   1824 {
   1825     jbyte tag;
   1826 
   1827     if (clazz != NULL) {
   1828         tag = referenceTypeTag(clazz);
   1829     } else {
   1830         tag = JDWP_TYPE_TAG(CLASS);
   1831     }
   1832     (void)outStream_writeByte(out, tag);
   1833     (void)outStream_writeObjectRef(getEnv(), out, clazz);
   1834     (void)outStream_writeMethodID(out, isMethodObsolete(method)?NULL:method);
   1835     (void)outStream_writeLocation(out, location);
   1836 }
   1837 
   1838 void *
   1839 jvmtiAllocate(jint numBytes)
   1840 {
   1841     void *ptr;
   1842     jvmtiError error;
   1843     if ( numBytes == 0 ) {
   1844         return NULL;
   1845     }
   1846     error = FUNC_PTR(gdata->jvmti,Allocate)
   1847                 (gdata->jvmti, numBytes, (unsigned char**)&ptr);
   1848     if (error != JVMTI_ERROR_NONE ) {
   1849         EXIT_ERROR(error, "Can't allocate jvmti memory");
   1850     }
   1851     return ptr;
   1852 }
   1853 
   1854 void
   1855 jvmtiDeallocate(void *ptr)
   1856 {
   1857     jvmtiError error;
   1858     if ( ptr == NULL ) {
   1859         return;
   1860     }
   1861     error = FUNC_PTR(gdata->jvmti,Deallocate)
   1862                 (gdata->jvmti, ptr);
   1863     if (error != JVMTI_ERROR_NONE ) {
   1864         EXIT_ERROR(error, "Can't deallocate jvmti memory");
   1865     }
   1866 }
   1867 
   1868 /* Rarely needed, transport library uses JDWP errors, only use? */
   1869 jvmtiError
   1870 map2jvmtiError(jdwpError error)
   1871 {
   1872     switch ( error ) {
   1873         case JDWP_ERROR(NONE):
   1874             return JVMTI_ERROR_NONE;
   1875         case JDWP_ERROR(INVALID_THREAD):
   1876             return JVMTI_ERROR_INVALID_THREAD;
   1877         case JDWP_ERROR(INVALID_THREAD_GROUP):
   1878             return JVMTI_ERROR_INVALID_THREAD_GROUP;
   1879         case JDWP_ERROR(INVALID_PRIORITY):
   1880             return JVMTI_ERROR_INVALID_PRIORITY;
   1881         case JDWP_ERROR(THREAD_NOT_SUSPENDED):
   1882             return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
   1883         case JDWP_ERROR(THREAD_SUSPENDED):
   1884             return JVMTI_ERROR_THREAD_SUSPENDED;
   1885         case JDWP_ERROR(INVALID_OBJECT):
   1886             return JVMTI_ERROR_INVALID_OBJECT;
   1887         case JDWP_ERROR(INVALID_CLASS):
   1888             return JVMTI_ERROR_INVALID_CLASS;
   1889         case JDWP_ERROR(CLASS_NOT_PREPARED):
   1890             return JVMTI_ERROR_CLASS_NOT_PREPARED;
   1891         case JDWP_ERROR(INVALID_METHODID):
   1892             return JVMTI_ERROR_INVALID_METHODID;
   1893         case JDWP_ERROR(INVALID_LOCATION):
   1894             return JVMTI_ERROR_INVALID_LOCATION;
   1895         case JDWP_ERROR(INVALID_FIELDID):
   1896             return JVMTI_ERROR_INVALID_FIELDID;
   1897         case JDWP_ERROR(INVALID_FRAMEID):
   1898             return AGENT_ERROR_INVALID_FRAMEID;
   1899         case JDWP_ERROR(NO_MORE_FRAMES):
   1900             return JVMTI_ERROR_NO_MORE_FRAMES;
   1901         case JDWP_ERROR(OPAQUE_FRAME):
   1902             return JVMTI_ERROR_OPAQUE_FRAME;
   1903         case JDWP_ERROR(NOT_CURRENT_FRAME):
   1904             return AGENT_ERROR_NOT_CURRENT_FRAME;
   1905         case JDWP_ERROR(TYPE_MISMATCH):
   1906             return JVMTI_ERROR_TYPE_MISMATCH;
   1907         case JDWP_ERROR(INVALID_SLOT):
   1908             return JVMTI_ERROR_INVALID_SLOT;
   1909         case JDWP_ERROR(DUPLICATE):
   1910             return JVMTI_ERROR_DUPLICATE;
   1911         case JDWP_ERROR(NOT_FOUND):
   1912             return JVMTI_ERROR_NOT_FOUND;
   1913         case JDWP_ERROR(INVALID_MONITOR):
   1914             return JVMTI_ERROR_INVALID_MONITOR;
   1915         case JDWP_ERROR(NOT_MONITOR_OWNER):
   1916             return JVMTI_ERROR_NOT_MONITOR_OWNER;
   1917         case JDWP_ERROR(INTERRUPT):
   1918             return JVMTI_ERROR_INTERRUPT;
   1919         case JDWP_ERROR(INVALID_CLASS_FORMAT):
   1920             return JVMTI_ERROR_INVALID_CLASS_FORMAT;
   1921         case JDWP_ERROR(CIRCULAR_CLASS_DEFINITION):
   1922             return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION;
   1923         case JDWP_ERROR(FAILS_VERIFICATION):
   1924             return JVMTI_ERROR_FAILS_VERIFICATION;
   1925         case JDWP_ERROR(ADD_METHOD_NOT_IMPLEMENTED):
   1926             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED;
   1927         case JDWP_ERROR(SCHEMA_CHANGE_NOT_IMPLEMENTED):
   1928             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
   1929         case JDWP_ERROR(INVALID_TYPESTATE):
   1930             return JVMTI_ERROR_INVALID_TYPESTATE;
   1931         case JDWP_ERROR(HIERARCHY_CHANGE_NOT_IMPLEMENTED):
   1932             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
   1933         case JDWP_ERROR(DELETE_METHOD_NOT_IMPLEMENTED):
   1934             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED;
   1935         case JDWP_ERROR(UNSUPPORTED_VERSION):
   1936             return JVMTI_ERROR_UNSUPPORTED_VERSION;
   1937         case JDWP_ERROR(NAMES_DONT_MATCH):
   1938             return JVMTI_ERROR_NAMES_DONT_MATCH;
   1939         case JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED):
   1940             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
   1941         case JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED):
   1942             return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED;
   1943         case JDWP_ERROR(NOT_IMPLEMENTED):
   1944             return JVMTI_ERROR_NOT_AVAILABLE;
   1945         case JDWP_ERROR(NULL_POINTER):
   1946             return JVMTI_ERROR_NULL_POINTER;
   1947         case JDWP_ERROR(ABSENT_INFORMATION):
   1948             return JVMTI_ERROR_ABSENT_INFORMATION;
   1949         case JDWP_ERROR(INVALID_EVENT_TYPE):
   1950             return JVMTI_ERROR_INVALID_EVENT_TYPE;
   1951         case JDWP_ERROR(ILLEGAL_ARGUMENT):
   1952             return JVMTI_ERROR_ILLEGAL_ARGUMENT;
   1953         case JDWP_ERROR(OUT_OF_MEMORY):
   1954             return JVMTI_ERROR_OUT_OF_MEMORY;
   1955         case JDWP_ERROR(ACCESS_DENIED):
   1956             return JVMTI_ERROR_ACCESS_DENIED;
   1957         case JDWP_ERROR(VM_DEAD):
   1958             return JVMTI_ERROR_WRONG_PHASE;
   1959         case JDWP_ERROR(UNATTACHED_THREAD):
   1960             return JVMTI_ERROR_UNATTACHED_THREAD;
   1961         case JDWP_ERROR(INVALID_TAG):
   1962             return AGENT_ERROR_INVALID_TAG;
   1963         case JDWP_ERROR(ALREADY_INVOKING):
   1964             return AGENT_ERROR_ALREADY_INVOKING;
   1965         case JDWP_ERROR(INVALID_INDEX):
   1966             return AGENT_ERROR_INVALID_INDEX;
   1967         case JDWP_ERROR(INVALID_LENGTH):
   1968             return AGENT_ERROR_INVALID_LENGTH;
   1969         case JDWP_ERROR(INVALID_STRING):
   1970             return AGENT_ERROR_INVALID_STRING;
   1971         case JDWP_ERROR(INVALID_CLASS_LOADER):
   1972             return AGENT_ERROR_INVALID_CLASS_LOADER;
   1973         case JDWP_ERROR(INVALID_ARRAY):
   1974             return AGENT_ERROR_INVALID_ARRAY;
   1975         case JDWP_ERROR(TRANSPORT_LOAD):
   1976             return AGENT_ERROR_TRANSPORT_LOAD;
   1977         case JDWP_ERROR(TRANSPORT_INIT):
   1978             return AGENT_ERROR_TRANSPORT_INIT;
   1979         case JDWP_ERROR(NATIVE_METHOD):
   1980             return AGENT_ERROR_NATIVE_METHOD;
   1981         case JDWP_ERROR(INVALID_COUNT):
   1982             return AGENT_ERROR_INVALID_COUNT;
   1983         case JDWP_ERROR(INTERNAL):
   1984             return AGENT_ERROR_JDWP_INTERNAL;
   1985     }
   1986     return AGENT_ERROR_INTERNAL;
   1987 }
   1988 
   1989 static jvmtiEvent index2jvmti[EI_max-EI_min+1];
   1990 static jdwpEvent  index2jdwp [EI_max-EI_min+1];
   1991 
   1992 void
   1993 eventIndexInit(void)
   1994 {
   1995     (void)memset(index2jvmti, 0, (int)sizeof(index2jvmti));
   1996     (void)memset(index2jdwp,  0, (int)sizeof(index2jdwp));
   1997 
   1998     index2jvmti[EI_SINGLE_STEP        -EI_min] = JVMTI_EVENT_SINGLE_STEP;
   1999     index2jvmti[EI_BREAKPOINT         -EI_min] = JVMTI_EVENT_BREAKPOINT;
   2000     index2jvmti[EI_FRAME_POP          -EI_min] = JVMTI_EVENT_FRAME_POP;
   2001     index2jvmti[EI_EXCEPTION          -EI_min] = JVMTI_EVENT_EXCEPTION;
   2002     index2jvmti[EI_THREAD_START       -EI_min] = JVMTI_EVENT_THREAD_START;
   2003     index2jvmti[EI_THREAD_END         -EI_min] = JVMTI_EVENT_THREAD_END;
   2004     index2jvmti[EI_CLASS_PREPARE      -EI_min] = JVMTI_EVENT_CLASS_PREPARE;
   2005     index2jvmti[EI_GC_FINISH          -EI_min] = JVMTI_EVENT_GARBAGE_COLLECTION_FINISH;
   2006     index2jvmti[EI_CLASS_LOAD         -EI_min] = JVMTI_EVENT_CLASS_LOAD;
   2007     index2jvmti[EI_FIELD_ACCESS       -EI_min] = JVMTI_EVENT_FIELD_ACCESS;
   2008     index2jvmti[EI_FIELD_MODIFICATION -EI_min] = JVMTI_EVENT_FIELD_MODIFICATION;
   2009     index2jvmti[EI_EXCEPTION_CATCH    -EI_min] = JVMTI_EVENT_EXCEPTION_CATCH;
   2010     index2jvmti[EI_METHOD_ENTRY       -EI_min] = JVMTI_EVENT_METHOD_ENTRY;
   2011     index2jvmti[EI_METHOD_EXIT        -EI_min] = JVMTI_EVENT_METHOD_EXIT;
   2012     index2jvmti[EI_MONITOR_CONTENDED_ENTER      -EI_min] = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
   2013     index2jvmti[EI_MONITOR_CONTENDED_ENTERED    -EI_min] = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
   2014     index2jvmti[EI_MONITOR_WAIT       -EI_min] = JVMTI_EVENT_MONITOR_WAIT;
   2015     index2jvmti[EI_MONITOR_WAITED     -EI_min] = JVMTI_EVENT_MONITOR_WAITED;
   2016     index2jvmti[EI_VM_INIT            -EI_min] = JVMTI_EVENT_VM_INIT;
   2017     index2jvmti[EI_VM_DEATH           -EI_min] = JVMTI_EVENT_VM_DEATH;
   2018 
   2019     index2jdwp[EI_SINGLE_STEP         -EI_min] = JDWP_EVENT(SINGLE_STEP);
   2020     index2jdwp[EI_BREAKPOINT          -EI_min] = JDWP_EVENT(BREAKPOINT);
   2021     index2jdwp[EI_FRAME_POP           -EI_min] = JDWP_EVENT(FRAME_POP);
   2022     index2jdwp[EI_EXCEPTION           -EI_min] = JDWP_EVENT(EXCEPTION);
   2023     index2jdwp[EI_THREAD_START        -EI_min] = JDWP_EVENT(THREAD_START);
   2024     index2jdwp[EI_THREAD_END          -EI_min] = JDWP_EVENT(THREAD_END);
   2025     index2jdwp[EI_CLASS_PREPARE       -EI_min] = JDWP_EVENT(CLASS_PREPARE);
   2026     index2jdwp[EI_GC_FINISH           -EI_min] = JDWP_EVENT(CLASS_UNLOAD);
   2027     index2jdwp[EI_CLASS_LOAD          -EI_min] = JDWP_EVENT(CLASS_LOAD);
   2028     index2jdwp[EI_FIELD_ACCESS        -EI_min] = JDWP_EVENT(FIELD_ACCESS);
   2029     index2jdwp[EI_FIELD_MODIFICATION  -EI_min] = JDWP_EVENT(FIELD_MODIFICATION);
   2030     index2jdwp[EI_EXCEPTION_CATCH     -EI_min] = JDWP_EVENT(EXCEPTION_CATCH);
   2031     index2jdwp[EI_METHOD_ENTRY        -EI_min] = JDWP_EVENT(METHOD_ENTRY);
   2032     index2jdwp[EI_METHOD_EXIT         -EI_min] = JDWP_EVENT(METHOD_EXIT);
   2033     index2jdwp[EI_MONITOR_CONTENDED_ENTER             -EI_min] = JDWP_EVENT(MONITOR_CONTENDED_ENTER);
   2034     index2jdwp[EI_MONITOR_CONTENDED_ENTERED           -EI_min] = JDWP_EVENT(MONITOR_CONTENDED_ENTERED);
   2035     index2jdwp[EI_MONITOR_WAIT        -EI_min] = JDWP_EVENT(MONITOR_WAIT);
   2036     index2jdwp[EI_MONITOR_WAITED      -EI_min] = JDWP_EVENT(MONITOR_WAITED);
   2037     index2jdwp[EI_VM_INIT             -EI_min] = JDWP_EVENT(VM_INIT);
   2038     index2jdwp[EI_VM_DEATH            -EI_min] = JDWP_EVENT(VM_DEATH);
   2039 }
   2040 
   2041 jdwpEvent
   2042 eventIndex2jdwp(EventIndex i)
   2043 {
   2044     if ( i < EI_min || i > EI_max ) {
   2045         EXIT_ERROR(AGENT_ERROR_INVALID_INDEX,"bad EventIndex");
   2046     }
   2047     return index2jdwp[i-EI_min];
   2048 }
   2049 
   2050 jvmtiEvent
   2051 eventIndex2jvmti(EventIndex i)
   2052 {
   2053     if ( i < EI_min || i > EI_max ) {
   2054         EXIT_ERROR(AGENT_ERROR_INVALID_INDEX,"bad EventIndex");
   2055     }
   2056     return index2jvmti[i-EI_min];
   2057 }
   2058 
   2059 EventIndex
   2060 jdwp2EventIndex(jdwpEvent eventType)
   2061 {
   2062     switch ( eventType ) {
   2063         case JDWP_EVENT(SINGLE_STEP):
   2064             return EI_SINGLE_STEP;
   2065         case JDWP_EVENT(BREAKPOINT):
   2066             return EI_BREAKPOINT;
   2067         case JDWP_EVENT(FRAME_POP):
   2068             return EI_FRAME_POP;
   2069         case JDWP_EVENT(EXCEPTION):
   2070             return EI_EXCEPTION;
   2071         case JDWP_EVENT(THREAD_START):
   2072             return EI_THREAD_START;
   2073         case JDWP_EVENT(THREAD_END):
   2074             return EI_THREAD_END;
   2075         case JDWP_EVENT(CLASS_PREPARE):
   2076             return EI_CLASS_PREPARE;
   2077         case JDWP_EVENT(CLASS_UNLOAD):
   2078             return EI_GC_FINISH;
   2079         case JDWP_EVENT(CLASS_LOAD):
   2080             return EI_CLASS_LOAD;
   2081         case JDWP_EVENT(FIELD_ACCESS):
   2082             return EI_FIELD_ACCESS;
   2083         case JDWP_EVENT(FIELD_MODIFICATION):
   2084             return EI_FIELD_MODIFICATION;
   2085         case JDWP_EVENT(EXCEPTION_CATCH):
   2086             return EI_EXCEPTION_CATCH;
   2087         case JDWP_EVENT(METHOD_ENTRY):
   2088             return EI_METHOD_ENTRY;
   2089         case JDWP_EVENT(METHOD_EXIT):
   2090             return EI_METHOD_EXIT;
   2091         case JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE):
   2092             return EI_METHOD_EXIT;
   2093         case JDWP_EVENT(MONITOR_CONTENDED_ENTER):
   2094             return EI_MONITOR_CONTENDED_ENTER;
   2095         case JDWP_EVENT(MONITOR_CONTENDED_ENTERED):
   2096             return EI_MONITOR_CONTENDED_ENTERED;
   2097         case JDWP_EVENT(MONITOR_WAIT):
   2098             return EI_MONITOR_WAIT;
   2099         case JDWP_EVENT(MONITOR_WAITED):
   2100             return EI_MONITOR_WAITED;
   2101         case JDWP_EVENT(VM_INIT):
   2102             return EI_VM_INIT;
   2103         case JDWP_EVENT(VM_DEATH):
   2104             return EI_VM_DEATH;
   2105         default:
   2106             break;
   2107     }
   2108 
   2109     /*
   2110      * Event type not recognized - don't exit with error as caller
   2111      * may wish to return error to debugger.
   2112      */
   2113     return (EventIndex)0;
   2114 }
   2115 
   2116 EventIndex
   2117 jvmti2EventIndex(jvmtiEvent kind)
   2118 {
   2119     switch ( kind ) {
   2120         case JVMTI_EVENT_SINGLE_STEP:
   2121             return EI_SINGLE_STEP;
   2122         case JVMTI_EVENT_BREAKPOINT:
   2123             return EI_BREAKPOINT;
   2124         case JVMTI_EVENT_FRAME_POP:
   2125             return EI_FRAME_POP;
   2126         case JVMTI_EVENT_EXCEPTION:
   2127             return EI_EXCEPTION;
   2128         case JVMTI_EVENT_THREAD_START:
   2129             return EI_THREAD_START;
   2130         case JVMTI_EVENT_THREAD_END:
   2131             return EI_THREAD_END;
   2132         case JVMTI_EVENT_CLASS_PREPARE:
   2133             return EI_CLASS_PREPARE;
   2134         case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH:
   2135             return EI_GC_FINISH;
   2136         case JVMTI_EVENT_CLASS_LOAD:
   2137             return EI_CLASS_LOAD;
   2138         case JVMTI_EVENT_FIELD_ACCESS:
   2139             return EI_FIELD_ACCESS;
   2140         case JVMTI_EVENT_FIELD_MODIFICATION:
   2141             return EI_FIELD_MODIFICATION;
   2142         case JVMTI_EVENT_EXCEPTION_CATCH:
   2143             return EI_EXCEPTION_CATCH;
   2144         case JVMTI_EVENT_METHOD_ENTRY:
   2145             return EI_METHOD_ENTRY;
   2146         case JVMTI_EVENT_METHOD_EXIT:
   2147             return EI_METHOD_EXIT;
   2148         /*
   2149          * There is no JVMTI_EVENT_METHOD_EXIT_WITH_RETURN_VALUE.
   2150          * The normal JVMTI_EVENT_METHOD_EXIT always contains the return value.
   2151          */
   2152         case JVMTI_EVENT_MONITOR_CONTENDED_ENTER:
   2153             return EI_MONITOR_CONTENDED_ENTER;
   2154         case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED:
   2155             return EI_MONITOR_CONTENDED_ENTERED;
   2156         case JVMTI_EVENT_MONITOR_WAIT:
   2157             return EI_MONITOR_WAIT;
   2158         case JVMTI_EVENT_MONITOR_WAITED:
   2159             return EI_MONITOR_WAITED;
   2160         case JVMTI_EVENT_VM_INIT:
   2161             return EI_VM_INIT;
   2162         case JVMTI_EVENT_VM_DEATH:
   2163             return EI_VM_DEATH;
   2164         default:
   2165             EXIT_ERROR(AGENT_ERROR_INVALID_INDEX,"JVMTI to EventIndex mapping");
   2166             break;
   2167     }
   2168     return (EventIndex)0;
   2169 }
   2170 
   2171 /* This routine is commonly used, maps jvmti and agent errors to the best
   2172  *    jdwp error code we can map to.
   2173  */
   2174 jdwpError
   2175 map2jdwpError(jvmtiError error)
   2176 {
   2177     switch ( error ) {
   2178         case JVMTI_ERROR_NONE:
   2179             return JDWP_ERROR(NONE);
   2180         case AGENT_ERROR_INVALID_THREAD:
   2181         case JVMTI_ERROR_INVALID_THREAD:
   2182             return JDWP_ERROR(INVALID_THREAD);
   2183         case JVMTI_ERROR_INVALID_THREAD_GROUP:
   2184             return JDWP_ERROR(INVALID_THREAD_GROUP);
   2185         case JVMTI_ERROR_INVALID_PRIORITY:
   2186             return JDWP_ERROR(INVALID_PRIORITY);
   2187         case JVMTI_ERROR_THREAD_NOT_SUSPENDED:
   2188             return JDWP_ERROR(THREAD_NOT_SUSPENDED);
   2189         case JVMTI_ERROR_THREAD_SUSPENDED:
   2190             return JDWP_ERROR(THREAD_SUSPENDED);
   2191         case JVMTI_ERROR_THREAD_NOT_ALIVE:
   2192             return JDWP_ERROR(INVALID_THREAD);
   2193         case AGENT_ERROR_INVALID_OBJECT:
   2194         case JVMTI_ERROR_INVALID_OBJECT:
   2195             return JDWP_ERROR(INVALID_OBJECT);
   2196         case JVMTI_ERROR_INVALID_CLASS:
   2197             return JDWP_ERROR(INVALID_CLASS);
   2198         case JVMTI_ERROR_CLASS_NOT_PREPARED:
   2199             return JDWP_ERROR(CLASS_NOT_PREPARED);
   2200         case JVMTI_ERROR_INVALID_METHODID:
   2201             return JDWP_ERROR(INVALID_METHODID);
   2202         case JVMTI_ERROR_INVALID_LOCATION:
   2203             return JDWP_ERROR(INVALID_LOCATION);
   2204         case JVMTI_ERROR_INVALID_FIELDID:
   2205             return JDWP_ERROR(INVALID_FIELDID);
   2206         case AGENT_ERROR_NO_MORE_FRAMES:
   2207         case JVMTI_ERROR_NO_MORE_FRAMES:
   2208             return JDWP_ERROR(NO_MORE_FRAMES);
   2209         case JVMTI_ERROR_OPAQUE_FRAME:
   2210             return JDWP_ERROR(OPAQUE_FRAME);
   2211         case JVMTI_ERROR_TYPE_MISMATCH:
   2212             return JDWP_ERROR(TYPE_MISMATCH);
   2213         case JVMTI_ERROR_INVALID_SLOT:
   2214             return JDWP_ERROR(INVALID_SLOT);
   2215         case JVMTI_ERROR_DUPLICATE:
   2216             return JDWP_ERROR(DUPLICATE);
   2217         case JVMTI_ERROR_NOT_FOUND:
   2218             return JDWP_ERROR(NOT_FOUND);
   2219         case JVMTI_ERROR_INVALID_MONITOR:
   2220             return JDWP_ERROR(INVALID_MONITOR);
   2221         case JVMTI_ERROR_NOT_MONITOR_OWNER:
   2222             return JDWP_ERROR(NOT_MONITOR_OWNER);
   2223         case JVMTI_ERROR_INTERRUPT:
   2224             return JDWP_ERROR(INTERRUPT);
   2225         case JVMTI_ERROR_INVALID_CLASS_FORMAT:
   2226             return JDWP_ERROR(INVALID_CLASS_FORMAT);
   2227         case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION:
   2228             return JDWP_ERROR(CIRCULAR_CLASS_DEFINITION);
   2229         case JVMTI_ERROR_FAILS_VERIFICATION:
   2230             return JDWP_ERROR(FAILS_VERIFICATION);
   2231         case JVMTI_ERROR_INVALID_TYPESTATE:
   2232             return JDWP_ERROR(INVALID_TYPESTATE);
   2233         case JVMTI_ERROR_UNSUPPORTED_VERSION:
   2234             return JDWP_ERROR(UNSUPPORTED_VERSION);
   2235         case JVMTI_ERROR_NAMES_DONT_MATCH:
   2236             return JDWP_ERROR(NAMES_DONT_MATCH);
   2237         case AGENT_ERROR_NULL_POINTER:
   2238         case JVMTI_ERROR_NULL_POINTER:
   2239             return JDWP_ERROR(NULL_POINTER);
   2240         case JVMTI_ERROR_ABSENT_INFORMATION:
   2241             return JDWP_ERROR(ABSENT_INFORMATION);
   2242         case AGENT_ERROR_INVALID_EVENT_TYPE:
   2243         case JVMTI_ERROR_INVALID_EVENT_TYPE:
   2244             return JDWP_ERROR(INVALID_EVENT_TYPE);
   2245         case AGENT_ERROR_ILLEGAL_ARGUMENT:
   2246         case JVMTI_ERROR_ILLEGAL_ARGUMENT:
   2247             return JDWP_ERROR(ILLEGAL_ARGUMENT);
   2248         case JVMTI_ERROR_OUT_OF_MEMORY:
   2249         case AGENT_ERROR_OUT_OF_MEMORY:
   2250             return JDWP_ERROR(OUT_OF_MEMORY);
   2251         case JVMTI_ERROR_ACCESS_DENIED:
   2252             return JDWP_ERROR(ACCESS_DENIED);
   2253         case JVMTI_ERROR_WRONG_PHASE:
   2254         case AGENT_ERROR_VM_DEAD:
   2255         case AGENT_ERROR_NO_JNI_ENV:
   2256             return JDWP_ERROR(VM_DEAD);
   2257         case AGENT_ERROR_JNI_EXCEPTION:
   2258         case JVMTI_ERROR_UNATTACHED_THREAD:
   2259             return JDWP_ERROR(UNATTACHED_THREAD);
   2260         case JVMTI_ERROR_NOT_AVAILABLE:
   2261         case JVMTI_ERROR_MUST_POSSESS_CAPABILITY:
   2262             return JDWP_ERROR(NOT_IMPLEMENTED);
   2263         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED:
   2264             return JDWP_ERROR(HIERARCHY_CHANGE_NOT_IMPLEMENTED);
   2265         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED:
   2266             return JDWP_ERROR(DELETE_METHOD_NOT_IMPLEMENTED);
   2267         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED:
   2268             return JDWP_ERROR(ADD_METHOD_NOT_IMPLEMENTED);
   2269         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED:
   2270             return JDWP_ERROR(SCHEMA_CHANGE_NOT_IMPLEMENTED);
   2271         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED:
   2272             return JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED);
   2273         case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
   2274             return JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED);
   2275         case AGENT_ERROR_NOT_CURRENT_FRAME:
   2276             return JDWP_ERROR(NOT_CURRENT_FRAME);
   2277         case AGENT_ERROR_INVALID_TAG:
   2278             return JDWP_ERROR(INVALID_TAG);
   2279         case AGENT_ERROR_ALREADY_INVOKING:
   2280             return JDWP_ERROR(ALREADY_INVOKING);
   2281         case AGENT_ERROR_INVALID_INDEX:
   2282             return JDWP_ERROR(INVALID_INDEX);
   2283         case AGENT_ERROR_INVALID_LENGTH:
   2284             return JDWP_ERROR(INVALID_LENGTH);
   2285         case AGENT_ERROR_INVALID_STRING:
   2286             return JDWP_ERROR(INVALID_STRING);
   2287         case AGENT_ERROR_INVALID_CLASS_LOADER:
   2288             return JDWP_ERROR(INVALID_CLASS_LOADER);
   2289         case AGENT_ERROR_INVALID_ARRAY:
   2290             return JDWP_ERROR(INVALID_ARRAY);
   2291         case AGENT_ERROR_TRANSPORT_LOAD:
   2292             return JDWP_ERROR(TRANSPORT_LOAD);
   2293         case AGENT_ERROR_TRANSPORT_INIT:
   2294             return JDWP_ERROR(TRANSPORT_INIT);
   2295         case AGENT_ERROR_NATIVE_METHOD:
   2296             return JDWP_ERROR(NATIVE_METHOD);
   2297         case AGENT_ERROR_INVALID_COUNT:
   2298             return JDWP_ERROR(INVALID_COUNT);
   2299         case AGENT_ERROR_INVALID_FRAMEID:
   2300             return JDWP_ERROR(INVALID_FRAMEID);
   2301         case JVMTI_ERROR_INTERNAL:
   2302         case JVMTI_ERROR_INVALID_ENVIRONMENT:
   2303         case AGENT_ERROR_INTERNAL:
   2304         case AGENT_ERROR_JVMTI_INTERNAL:
   2305         case AGENT_ERROR_JDWP_INTERNAL:
   2306             return JDWP_ERROR(INTERNAL);
   2307         default:
   2308             break;
   2309     }
   2310     return JDWP_ERROR(INTERNAL);
   2311 }
   2312 
   2313 jint
   2314 map2jdwpSuspendStatus(jint state)
   2315 {
   2316     jint status = 0;
   2317     if ( ( state & JVMTI_THREAD_STATE_SUSPENDED ) != 0 )  {
   2318         status = JDWP_SUSPEND_STATUS(SUSPENDED);
   2319     }
   2320     return status;
   2321 }
   2322 
   2323 jdwpThreadStatus
   2324 map2jdwpThreadStatus(jint state)
   2325 {
   2326     jdwpThreadStatus status;
   2327 
   2328     status = (jdwpThreadStatus)(-1);
   2329 
   2330     if ( ! ( state & JVMTI_THREAD_STATE_ALIVE ) ) {
   2331         if ( state & JVMTI_THREAD_STATE_TERMINATED ) {
   2332             status = JDWP_THREAD_STATUS(ZOMBIE);
   2333         } else {
   2334             /* FIXUP? New JDWP #define for not started? */
   2335             status = (jdwpThreadStatus)(-1);
   2336         }
   2337     } else {
   2338         if ( state & JVMTI_THREAD_STATE_SLEEPING ) {
   2339             status = JDWP_THREAD_STATUS(SLEEPING);
   2340         } else if ( state & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) {
   2341             status = JDWP_THREAD_STATUS(MONITOR);
   2342         } else if ( state & JVMTI_THREAD_STATE_WAITING ) {
   2343             status = JDWP_THREAD_STATUS(WAIT);
   2344         } else if ( state & JVMTI_THREAD_STATE_RUNNABLE ) {
   2345             status = JDWP_THREAD_STATUS(RUNNING);
   2346         }
   2347     }
   2348     return status;
   2349 }
   2350 
   2351 jint
   2352 map2jdwpClassStatus(jint classStatus)
   2353 {
   2354     jint status = 0;
   2355     if ( ( classStatus & JVMTI_CLASS_STATUS_VERIFIED ) != 0 ) {
   2356         status |= JDWP_CLASS_STATUS(VERIFIED);
   2357     }
   2358     if ( ( classStatus & JVMTI_CLASS_STATUS_PREPARED ) != 0 ) {
   2359         status |= JDWP_CLASS_STATUS(PREPARED);
   2360     }
   2361     if ( ( classStatus & JVMTI_CLASS_STATUS_INITIALIZED ) != 0 ) {
   2362         status |= JDWP_CLASS_STATUS(INITIALIZED);
   2363     }
   2364     if ( ( classStatus & JVMTI_CLASS_STATUS_ERROR ) != 0 ) {
   2365         status |= JDWP_CLASS_STATUS(ERROR);
   2366     }
   2367     return status;
   2368 }
   2369 
   2370 void
   2371 log_debugee_location(const char *func,
   2372         jthread thread, jmethodID method, jlocation location)
   2373 {
   2374     int logging_locations = LOG_TEST(JDWP_LOG_LOC);
   2375 
   2376     if ( logging_locations ) {
   2377         char *method_name;
   2378         char *class_sig;
   2379         jvmtiError error;
   2380         jvmtiThreadInfo info;
   2381         jint state;
   2382 
   2383         /* Get thread information */
   2384         info.name = NULL;
   2385         error = FUNC_PTR(gdata->jvmti,GetThreadInfo)
   2386                                 (gdata->jvmti, thread, &info);
   2387         if ( error != JVMTI_ERROR_NONE) {
   2388             info.name = NULL;
   2389         }
   2390         error = FUNC_PTR(gdata->jvmti,GetThreadState)
   2391                                 (gdata->jvmti, thread, &state);
   2392         if ( error != JVMTI_ERROR_NONE) {
   2393             state = 0;
   2394         }
   2395 
   2396         /* Get method if necessary */
   2397         if ( method==NULL ) {
   2398             error = FUNC_PTR(gdata->jvmti,GetFrameLocation)
   2399                         (gdata->jvmti, thread, 0, &method, &location);
   2400             if ( error != JVMTI_ERROR_NONE ) {
   2401                 method = NULL;
   2402                 location = 0;
   2403             }
   2404         }
   2405 
   2406         /* Get method name */
   2407         method_name = NULL;
   2408         if ( method != NULL ) {
   2409             error = methodSignature(method, &method_name, NULL, NULL);
   2410             if ( error != JVMTI_ERROR_NONE ) {
   2411                 method_name = NULL;
   2412             }
   2413         }
   2414 
   2415         /* Get class signature */
   2416         class_sig = NULL;
   2417         if ( method != NULL ) {
   2418             jclass clazz;
   2419 
   2420             error = methodClass(method, &clazz);
   2421             if ( error == JVMTI_ERROR_NONE ) {
   2422                 error = classSignature(clazz, &class_sig, NULL);
   2423                 if ( error != JVMTI_ERROR_NONE ) {
   2424                     class_sig = NULL;
   2425                 }
   2426             }
   2427         }
   2428 
   2429         /* Issue log message */
   2430         LOG_LOC(("%s: debugee: thread=%p(%s:0x%x),method=%p(%s@%d;%s)",
   2431                 func,
   2432                 thread, info.name==NULL ? "?" : info.name, state,
   2433                 method, method_name==NULL ? "?" : method_name,
   2434                 (int)location, class_sig==NULL ? "?" : class_sig));
   2435 
   2436         /* Free memory */
   2437         if ( class_sig != NULL ) {
   2438             jvmtiDeallocate(class_sig);
   2439         }
   2440         if ( method_name != NULL ) {
   2441             jvmtiDeallocate(method_name);
   2442         }
   2443         if ( info.name != NULL ) {
   2444             jvmtiDeallocate(info.name);
   2445         }
   2446     }
   2447 }
   2448 
   2449 /* ********************************************************************* */
   2450 /* JDK 6.0: Use of new Heap Iteration functions */
   2451 /* ********************************************************************* */
   2452 
   2453 /* ********************************************************************* */
   2454 /* Instances */
   2455 
   2456 /* Structure to hold class instances heap iteration data (arg user_data) */
   2457 typedef struct ClassInstancesData {
   2458     jint         instCount;
   2459     jint         maxInstances;
   2460     jlong        objTag;
   2461     jvmtiError   error;
   2462 } ClassInstancesData;
   2463 
   2464 /* Callback for instance object tagging (heap_reference_callback). */
   2465 static jint JNICALL
   2466 cbObjectTagInstance(jvmtiHeapReferenceKind reference_kind,
   2467      const jvmtiHeapReferenceInfo* reference_info, jlong class_tag,
   2468      jlong referrer_class_tag, jlong size,
   2469      jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data)
   2470 {
   2471     ClassInstancesData  *data;
   2472 
   2473     /* Check data structure */
   2474     data = (ClassInstancesData*)user_data;
   2475     if (data == NULL) {
   2476         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2477         return JVMTI_VISIT_ABORT;
   2478     }
   2479 
   2480     /* If we have tagged enough objects, just abort */
   2481     if ( data->maxInstances != 0 && data->instCount >= data->maxInstances ) {
   2482         return JVMTI_VISIT_ABORT;
   2483     }
   2484 
   2485     /* If tagged already, just continue */
   2486     if ( (*tag_ptr) != (jlong)0 ) {
   2487         return JVMTI_VISIT_OBJECTS;
   2488     }
   2489 
   2490     /* Tag the object so we don't count it again, and so we can retrieve it */
   2491     (*tag_ptr) = data->objTag;
   2492     data->instCount++;
   2493     return JVMTI_VISIT_OBJECTS;
   2494 }
   2495 
   2496 /* Get instances for one class */
   2497 jvmtiError
   2498 classInstances(jclass klass, ObjectBatch *instances, int maxInstances)
   2499 {
   2500     ClassInstancesData data;
   2501     jvmtiHeapCallbacks heap_callbacks;
   2502     jvmtiError         error;
   2503     jvmtiEnv          *jvmti;
   2504 
   2505     /* Check interface assumptions */
   2506 
   2507     if (klass == NULL) {
   2508         return AGENT_ERROR_INVALID_OBJECT;
   2509     }
   2510 
   2511     if ( maxInstances < 0 || instances == NULL) {
   2512         return AGENT_ERROR_ILLEGAL_ARGUMENT;
   2513     }
   2514 
   2515     /* Initialize return information */
   2516     instances->count   = 0;
   2517     instances->objects = NULL;
   2518 
   2519     /* Get jvmti environment to use */
   2520     jvmti = getSpecialJvmti();
   2521     if ( jvmti == NULL ) {
   2522         return AGENT_ERROR_INTERNAL;
   2523     }
   2524 
   2525     /* Setup data to passed around the callbacks */
   2526     data.instCount    = 0;
   2527     data.maxInstances = maxInstances;
   2528     data.objTag       = (jlong)1;
   2529     data.error        = JVMTI_ERROR_NONE;
   2530 
   2531     /* Clear out callbacks structure */
   2532     (void)memset(&heap_callbacks,0,sizeof(heap_callbacks));
   2533 
   2534     /* Set the callbacks we want */
   2535     heap_callbacks.heap_reference_callback = &cbObjectTagInstance;
   2536 
   2537     /* Follow references, no initiating object, just this class, all objects */
   2538     error = JVMTI_FUNC_PTR(jvmti,FollowReferences)
   2539                  (jvmti, 0, klass, NULL, &heap_callbacks, &data);
   2540     if ( error == JVMTI_ERROR_NONE ) {
   2541         error = data.error;
   2542     }
   2543 
   2544     /* Get all the instances now that they are tagged */
   2545     if ( error == JVMTI_ERROR_NONE ) {
   2546         error = JVMTI_FUNC_PTR(jvmti,GetObjectsWithTags)
   2547                       (jvmti, 1, &(data.objTag), &(instances->count),
   2548                        &(instances->objects), NULL);
   2549         /* Verify we got the count we expected */
   2550         if ( data.instCount != instances->count ) {
   2551             error = AGENT_ERROR_INTERNAL;
   2552         }
   2553     }
   2554 
   2555     /* Dispose of any special jvmti environment */
   2556     (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti);
   2557     return error;
   2558 }
   2559 
   2560 /* ********************************************************************* */
   2561 /* Instance counts. */
   2562 
   2563 /* Macros to convert a class or instance tag to an index and back again */
   2564 #define INDEX2CLASSTAG(i)      ((jlong)((i)+1))
   2565 #define CLASSTAG2INDEX(t)      (((int)(t))-1)
   2566 #define JLONG_ABS(x)           (((x)<(jlong)0)?-(x):(x))
   2567 
   2568 /* Structure to hold class count heap traversal data (arg user_data) */
   2569 typedef struct ClassCountData {
   2570     int          classCount;
   2571     jlong       *counts;
   2572     jlong        negObjTag;
   2573     jvmtiError   error;
   2574 } ClassCountData;
   2575 
   2576 /* Two different cbObjectCounter's, one for FollowReferences, one for
   2577  *    IterateThroughHeap. Pick a card, any card.
   2578  */
   2579 
   2580 /* Callback for object count heap traversal (heap_reference_callback) */
   2581 static jint JNICALL
   2582 cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind,
   2583      const jvmtiHeapReferenceInfo* reference_info, jlong class_tag,
   2584      jlong referrer_class_tag, jlong size,
   2585      jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data)
   2586 {
   2587     ClassCountData  *data;
   2588     int              index;
   2589     jlong            jindex;
   2590     jlong            tag;
   2591 
   2592     /* Check data structure */
   2593     data = (ClassCountData*)user_data;
   2594     if (data == NULL) {
   2595         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2596         return JVMTI_VISIT_ABORT;
   2597     }
   2598 
   2599     /* Classes with no class_tag should have been filtered out. */
   2600     if ( class_tag == (jlong)0 ) {
   2601         data->error = AGENT_ERROR_INTERNAL;
   2602         return JVMTI_VISIT_ABORT;
   2603     }
   2604 
   2605     /* Class tag not one we really want (jclass not in supplied list) */
   2606     if ( class_tag == data->negObjTag ) {
   2607         return JVMTI_VISIT_OBJECTS;
   2608     }
   2609 
   2610     /* If object tag is negative, just continue, we counted it */
   2611     tag = (*tag_ptr);
   2612     if ( tag < (jlong)0 ) {
   2613         return JVMTI_VISIT_OBJECTS;
   2614     }
   2615 
   2616     /* Tag the object with a negative value just so we don't count it again */
   2617     if ( tag == (jlong)0 ) {
   2618         /* This object had no tag value, so we give it the negObjTag value */
   2619         (*tag_ptr) = data->negObjTag;
   2620     } else {
   2621         /* If this object had a positive tag value, it must be one of the
   2622          *    jclass objects we tagged. We need to preserve the value of
   2623          *    this tag for later objects that might have this as a class
   2624          *    tag, so we just make the existing tag value negative.
   2625          */
   2626         (*tag_ptr) = -tag;
   2627     }
   2628 
   2629     /* Absolute value of class tag is an index into the counts[] array */
   2630     jindex = JLONG_ABS(class_tag);
   2631     index = CLASSTAG2INDEX(jindex);
   2632     if (index < 0 || index >= data->classCount) {
   2633         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2634         return JVMTI_VISIT_ABORT;
   2635     }
   2636 
   2637     /* Bump instance count on this class */
   2638     data->counts[index]++;
   2639     return JVMTI_VISIT_OBJECTS;
   2640 }
   2641 
   2642 /* Callback for instance count heap traversal (heap_iteration_callback) */
   2643 static jint JNICALL
   2644 cbObjectCounter(jlong class_tag, jlong size, jlong* tag_ptr, jint length,
   2645                         void* user_data)
   2646 {
   2647     ClassCountData  *data;
   2648     int              index;
   2649 
   2650     /* Check data structure */
   2651     data = (ClassCountData*)user_data;
   2652     if (data == NULL) {
   2653         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2654         return JVMTI_VISIT_ABORT;
   2655     }
   2656 
   2657     /* Classes with no tag should be filtered out. */
   2658     if ( class_tag == (jlong)0 ) {
   2659         data->error = AGENT_ERROR_INTERNAL;
   2660         return JVMTI_VISIT_ABORT;
   2661     }
   2662 
   2663     /* Class tag is actually an index into data arrays */
   2664     index = CLASSTAG2INDEX(class_tag);
   2665     if (index < 0 || index >= data->classCount) {
   2666         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2667         return JVMTI_VISIT_ABORT;
   2668     }
   2669 
   2670     /* Bump instance count on this class */
   2671     data->counts[index]++;
   2672     return JVMTI_VISIT_OBJECTS;
   2673 }
   2674 
   2675 /* Get instance counts for a set of classes */
   2676 jvmtiError
   2677 classInstanceCounts(jint classCount, jclass *classes, jlong *counts)
   2678 {
   2679     jvmtiHeapCallbacks heap_callbacks;
   2680     ClassCountData     data;
   2681     jvmtiError         error;
   2682     jvmtiEnv          *jvmti;
   2683     int                i;
   2684 
   2685     /* Check interface assumptions */
   2686     if ( classes == NULL || classCount <= 0 || counts == NULL ) {
   2687         return AGENT_ERROR_ILLEGAL_ARGUMENT;
   2688     }
   2689 
   2690     /* Initialize return information */
   2691     for ( i = 0 ; i < classCount ; i++ ) {
   2692         counts[i] = (jlong)0;
   2693     }
   2694 
   2695     /* Get jvmti environment to use */
   2696     jvmti = getSpecialJvmti();
   2697     if ( jvmti == NULL ) {
   2698         return AGENT_ERROR_INTERNAL;
   2699     }
   2700 
   2701     /* Setup class data structure */
   2702     data.error        = JVMTI_ERROR_NONE;
   2703     data.classCount   = classCount;
   2704     data.counts       = counts;
   2705 
   2706     error = JVMTI_ERROR_NONE;
   2707     /* Set tags on classes, use index in classes[] as the tag value. */
   2708     error             = JVMTI_ERROR_NONE;
   2709     for ( i = 0 ; i < classCount ; i++ ) {
   2710         if (classes[i] != NULL) {
   2711             jlong tag;
   2712 
   2713             tag = INDEX2CLASSTAG(i);
   2714             error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, classes[i], tag);
   2715             if ( error != JVMTI_ERROR_NONE ) {
   2716                 break;
   2717             }
   2718         }
   2719     }
   2720 
   2721     /* Traverse heap, two ways to do this for instance counts. */
   2722     if ( error == JVMTI_ERROR_NONE ) {
   2723 
   2724         /* Clear out callbacks structure */
   2725         (void)memset(&heap_callbacks,0,sizeof(heap_callbacks));
   2726 
   2727         /* Check debug flags to see how to do this. */
   2728         if ( (gdata->debugflags & USE_ITERATE_THROUGH_HEAP) == 0 ) {
   2729 
   2730             /* Using FollowReferences only gives us live objects, but we
   2731              *   need to tag the objects to avoid counting them twice since
   2732              *   the callback is per reference.
   2733              *   The jclass objects have been tagged with their index in the
   2734              *   supplied list, and that tag may flip to negative if it
   2735              *   is also an object of interest.
   2736              *   All other objects being counted that weren't in the
   2737              *   supplied classes list will have a negative classCount
   2738              *   tag value. So all objects counted will have negative tags.
   2739              *   If the absolute tag value is an index in the supplied
   2740              *   list, then it's one of the supplied classes.
   2741              */
   2742             data.negObjTag = -INDEX2CLASSTAG(classCount);
   2743 
   2744             /* Setup callbacks, only using object reference callback */
   2745             heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef;
   2746 
   2747             /* Follow references, no initiating object, tagged classes only */
   2748             error = JVMTI_FUNC_PTR(jvmti,FollowReferences)
   2749                           (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED,
   2750                            NULL, NULL, &heap_callbacks, &data);
   2751 
   2752         } else {
   2753 
   2754             /* Using IterateThroughHeap means that we will visit each object
   2755              *   once, so no special tag tricks here. Just simple counting.
   2756              *   However in this case the object might not be live, so we do
   2757              *   a GC beforehand to make sure we minimize this.
   2758              */
   2759 
   2760             /* FIXUP: Need some kind of trigger here to avoid excessive GC's? */
   2761             error = JVMTI_FUNC_PTR(jvmti,ForceGarbageCollection)(jvmti);
   2762             if ( error != JVMTI_ERROR_NONE ) {
   2763 
   2764                 /* Setup callbacks, just need object callback */
   2765                 heap_callbacks.heap_iteration_callback = &cbObjectCounter;
   2766 
   2767                 /* Iterate through entire heap, tagged classes only */
   2768                 error = JVMTI_FUNC_PTR(jvmti,IterateThroughHeap)
   2769                               (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED,
   2770                                NULL, &heap_callbacks, &data);
   2771 
   2772             }
   2773         }
   2774 
   2775         /* Use data error if needed */
   2776         if ( error == JVMTI_ERROR_NONE ) {
   2777             error = data.error;
   2778         }
   2779 
   2780     }
   2781 
   2782     /* Dispose of any special jvmti environment */
   2783     (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti);
   2784     return error;
   2785 }
   2786 
   2787 /* ********************************************************************* */
   2788 /* Referrers */
   2789 
   2790 /* Structure to hold object referrer heap traversal data (arg user_data) */
   2791 typedef struct ReferrerData {
   2792   int        refCount;
   2793   int        maxObjects;
   2794   jlong      refTag;
   2795   jlong      objTag;
   2796   jboolean   selfRef;
   2797   jvmtiError error;
   2798 } ReferrerData;
   2799 
   2800 /* Callback for referrers object tagging (heap_reference_callback). */
   2801 static jint JNICALL
   2802 cbObjectTagReferrer(jvmtiHeapReferenceKind reference_kind,
   2803      const jvmtiHeapReferenceInfo* reference_info, jlong class_tag,
   2804      jlong referrer_class_tag, jlong size,
   2805      jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data)
   2806 {
   2807     ReferrerData  *data;
   2808 
   2809     /* Check data structure */
   2810     data = (ReferrerData*)user_data;
   2811     if (data == NULL) {
   2812         data->error = AGENT_ERROR_ILLEGAL_ARGUMENT;
   2813         return JVMTI_VISIT_ABORT;
   2814     }
   2815 
   2816     /* If we have tagged enough objects, just abort */
   2817     if ( data->maxObjects != 0 && data->refCount >= data->maxObjects ) {
   2818         return JVMTI_VISIT_ABORT;
   2819     }
   2820 
   2821     /* If not of interest, just continue */
   2822     if ( (*tag_ptr) != data->objTag ) {
   2823         return JVMTI_VISIT_OBJECTS;
   2824     }
   2825 
   2826     /* Self reference that we haven't counted? */
   2827     if ( tag_ptr == referrer_tag_ptr ) {
   2828         if ( data->selfRef == JNI_FALSE ) {
   2829             data->selfRef = JNI_TRUE;
   2830             data->refCount++;
   2831         }
   2832         return JVMTI_VISIT_OBJECTS;
   2833     }
   2834 
   2835     /* If the referrer can be tagged, and hasn't been tagged, tag it */
   2836     if ( referrer_tag_ptr != NULL ) {
   2837         if ( (*referrer_tag_ptr) == (jlong)0 ) {
   2838             *referrer_tag_ptr = data->refTag;
   2839             data->refCount++;
   2840         }
   2841     }
   2842     return JVMTI_VISIT_OBJECTS;
   2843 }
   2844 
   2845 /* Heap traversal to find referrers of an object */
   2846 jvmtiError
   2847 objectReferrers(jobject obj, ObjectBatch *referrers, int maxObjects)
   2848 {
   2849     jvmtiHeapCallbacks heap_callbacks;
   2850     ReferrerData       data;
   2851     jvmtiError         error;
   2852     jvmtiEnv          *jvmti;
   2853 
   2854     /* Check interface assumptions */
   2855     if (obj == NULL) {
   2856         return AGENT_ERROR_INVALID_OBJECT;
   2857     }
   2858     if (referrers == NULL || maxObjects < 0 ) {
   2859         return AGENT_ERROR_ILLEGAL_ARGUMENT;
   2860     }
   2861 
   2862     /* Initialize return information */
   2863     referrers->count = 0;
   2864     referrers->objects = NULL;
   2865 
   2866     /* Get jvmti environment to use */
   2867     jvmti = getSpecialJvmti();
   2868     if ( jvmti == NULL ) {
   2869         return AGENT_ERROR_INTERNAL;
   2870     }
   2871 
   2872     /* Fill in the data structure passed around the callbacks */
   2873     data.refCount   = 0;
   2874     data.maxObjects = maxObjects;
   2875     data.objTag     = (jlong)1;
   2876     data.refTag     = (jlong)2;
   2877     data.selfRef    = JNI_FALSE;
   2878     data.error      = JVMTI_ERROR_NONE;
   2879 
   2880     /* Tag the object of interest */
   2881     error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, obj, data.objTag);
   2882 
   2883     /* No need to go any further if we can't tag the object */
   2884     if ( error == JVMTI_ERROR_NONE ) {
   2885 
   2886         /* Clear out callbacks structure */
   2887         (void)memset(&heap_callbacks,0,sizeof(heap_callbacks));
   2888 
   2889         /* Setup callbacks we want */
   2890         heap_callbacks.heap_reference_callback = &cbObjectTagReferrer;
   2891 
   2892         /* Follow references, no initiating object, all classes, 1 tagged objs */
   2893         error = JVMTI_FUNC_PTR(jvmti,FollowReferences)
   2894                       (jvmti, JVMTI_HEAP_FILTER_UNTAGGED,
   2895                        NULL, NULL, &heap_callbacks, &data);
   2896 
   2897         /* Use data error if needed */
   2898         if ( error == JVMTI_ERROR_NONE ) {
   2899             error = data.error;
   2900         }
   2901 
   2902     }
   2903 
   2904     /* Watch out for self-reference */
   2905     if ( error == JVMTI_ERROR_NONE && data.selfRef == JNI_TRUE ) {
   2906         /* Tag itself as a referer */
   2907         error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, obj, data.refTag);
   2908     }
   2909 
   2910     /* Get the jobjects for the tagged referrer objects.  */
   2911     if ( error == JVMTI_ERROR_NONE ) {
   2912         error = JVMTI_FUNC_PTR(jvmti,GetObjectsWithTags)
   2913                     (jvmti, 1, &(data.refTag), &(referrers->count),
   2914                           &(referrers->objects), NULL);
   2915         /* Verify we got the count we expected */
   2916         if ( data.refCount != referrers->count ) {
   2917             error = AGENT_ERROR_INTERNAL;
   2918         }
   2919     }
   2920 
   2921     /* Dispose of any special jvmti environment */
   2922     (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti);
   2923     return error;
   2924 }
   2925