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