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