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