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