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 ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
 105         JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
 106         ERROR_MESSAGE(("JNI Exception occurred finding class %s", name));
 107         EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
 108     }
 109     return x;
 110 }
 111 
 112 jmethodID
 113 getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
 114 {
 115     jmethodID method;
 116 
 117     if ( env == NULL ) {
 118         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod env");
 119     }
 120     if ( clazz == NULL ) {
 121         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod clazz");
 122     }
 123     if ( name == NULL || name[0] == 0 ) {
 124         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod name");
 125     }
 126     if ( signature == NULL || signature[0] == 0 ) {
 127         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod signature");
 128     }
 129     method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, signature);
 130     if ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
 131         JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
 132         ERROR_MESSAGE(("JNI Exception occurred finding method %s with signature %s",
 133                        name, signature));
 134         EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
 135     }
 136     return method;
 137 }
 138 
 139 static jmethodID
 140 getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
 141 {
 142     jmethodID method;
 143 
 144     if ( env == NULL ) {
 145         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod env");
 146     }
 147     if ( clazz == NULL ) {
 148         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod clazz");
 149     }
 150     if ( name == NULL || name[0] == 0 ) {
 151         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod name");
 152     }
 153     if ( signature == NULL || signature[0] == 0 ) {
 154         EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod signature");
 155     }
 156     method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, signature);
 157     if ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
 158         JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
 159         ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
 160                        name, signature));
 161         EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
 162     }
 163     return method;
 164 }
 165 
 166 
 167 
 168 void
 169 util_initialize(JNIEnv *env)
 170 {
 171     WITH_LOCAL_REFS(env, 6) {
 172 
 173         jvmtiError error;
 174         jclass localClassClass;
 175         jclass localThreadClass;
 176         jclass localThreadGroupClass;
 177         jclass localClassLoaderClass;
 178         jclass localStringClass;
 179         jclass localSystemClass;
 180         jclass localPropertiesClass;
 181         jclass localVMSupportClass;
 182         jobject localAgentProperties;
 183         jmethodID getAgentProperties;
 184         jint groupCount;
 185         jthreadGroup *groups;
 186         jthreadGroup localSystemThreadGroup;
 187 
 188         /* Find some standard classes */
 189 
 190         localClassClass         = findClass(env,"java/lang/Class");
 191         localThreadClass        = findClass(env,"java/lang/Thread");
 192         localThreadGroupClass   = findClass(env,"java/lang/ThreadGroup");
 193         localClassLoaderClass   = findClass(env,"java/lang/ClassLoader");
 194         localStringClass        = findClass(env,"java/lang/String");
 195         localSystemClass        = findClass(env,"java/lang/System");
 196         localPropertiesClass    = findClass(env,"java/util/Properties");
 197 
 198         /* Save references */
 199 
 200         saveGlobalRef(env, localClassClass,       &(gdata->classClass));
 201         saveGlobalRef(env, localThreadClass,      &(gdata->threadClass));
 202         saveGlobalRef(env, localThreadGroupClass, &(gdata->threadGroupClass));
 203         saveGlobalRef(env, localClassLoaderClass, &(gdata->classLoaderClass));
 204         saveGlobalRef(env, localStringClass,      &(gdata->stringClass));
 205         saveGlobalRef(env, localSystemClass,      &(gdata->systemClass));
 206 
 207         /* Find some standard methods */
 208 
 209         gdata->threadConstructor =
 210                 getMethod(env, gdata->threadClass,
 211                     "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
 212         gdata->threadSetDaemon =
 213                 getMethod(env, gdata->threadClass, "setDaemon", "(Z)V");
 214         gdata->systemGetProperty =
 215                 getStaticMethod(env, gdata->systemClass,
 216                     "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
 217         gdata->setProperty =
 218                 getMethod(env, localPropertiesClass,
 219                     "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
 220 
 221         /* Find the system thread group */
 222 
 223         groups = NULL;
 224         groupCount = 0;
 225         error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
 226                     (gdata->jvmti, &groupCount, &groups);
 227         if (error != JVMTI_ERROR_NONE ) {
 228             EXIT_ERROR(error, "Can't get system thread group");
 229         }
 230         if ( groupCount == 0 ) {
 231             EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "Can't get system thread group");
 232         }
 233         localSystemThreadGroup = groups[0];
 234         saveGlobalRef(env, localSystemThreadGroup, &(gdata->systemThreadGroup));
 235         jvmtiDeallocate(groups);
 236 
 237         /* Get some basic Java property values we will need at some point */
 238         gdata->property_java_version
 239                         = getPropertyUTF8(env, "java.version");
 240         gdata->property_java_vm_name
 241                         = getPropertyUTF8(env, "java.vm.name");
 242         gdata->property_java_vm_info
 243                         = getPropertyUTF8(env, "java.vm.info");
 244         gdata->property_java_class_path
 245                         = getPropertyUTF8(env, "java.class.path");
 246         gdata->property_sun_boot_library_path
 247                         = getPropertyUTF8(env, "sun.boot.library.path");
 248         gdata->property_path_separator
 249                         = getPropertyUTF8(env, "path.separator");
 250         gdata->property_user_dir
 251                         = getPropertyUTF8(env, "user.dir");
 252 
 253         /* Get agent properties: invoke VMSupport.getAgentProperties */
 254         localVMSupportClass = JNI_FUNC_PTR(env,FindClass)
 255                                           (env, "jdk/internal/vm/VMSupport");
 256         if (localVMSupportClass == NULL) {
 257             gdata->agent_properties = NULL;
 258             if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
 259                 JNI_FUNC_PTR(env,ExceptionClear)(env);
 260             }
 261         } else {
 262             getAgentProperties  =
 263                 getStaticMethod(env, localVMSupportClass,
 264                                 "getAgentProperties", "()Ljava/util/Properties;");
 265             localAgentProperties =
 266                 JNI_FUNC_PTR(env,CallStaticObjectMethod)
 267                             (env, localVMSupportClass, getAgentProperties);
 268             if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
 269                 JNI_FUNC_PTR(env,ExceptionClear)(env);
 270                 EXIT_ERROR(AGENT_ERROR_INTERNAL,
 271                     "Exception occurred calling VMSupport.getAgentProperties");
 272             }
 273             saveGlobalRef(env, localAgentProperties, &(gdata->agent_properties));
 274         }
 275 
 276     } END_WITH_LOCAL_REFS(env);
 277 
 278 }
 279 
 280 void
 281 util_reset(void)
 282 {
 283 }
 284 
 285 jboolean
 286 isObjectTag(jbyte tag) {
 287     return (tag == JDWP_TAG(OBJECT)) ||
 288            (tag == JDWP_TAG(STRING)) ||
 289            (tag == JDWP_TAG(THREAD)) ||
 290            (tag == JDWP_TAG(THREAD_GROUP)) ||
 291            (tag == JDWP_TAG(CLASS_LOADER)) ||
 292            (tag == JDWP_TAG(CLASS_OBJECT)) ||
 293            (tag == JDWP_TAG(ARRAY));
 294 }
 295 
 296 jbyte
 297 specificTypeKey(JNIEnv *env, jobject object)
 298 {
 299     if (object == NULL) {
 300         return JDWP_TAG(OBJECT);
 301     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->stringClass)) {
 302         return JDWP_TAG(STRING);
 303     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadClass)) {
 304         return JDWP_TAG(THREAD);
 305     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadGroupClass)) {
 306         return JDWP_TAG(THREAD_GROUP);
 307     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classLoaderClass)) {
 308         return JDWP_TAG(CLASS_LOADER);
 309     } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classClass)) {
 310         return JDWP_TAG(CLASS_OBJECT);
 311     } else {
 312         jboolean classIsArray;
 313 
 314         WITH_LOCAL_REFS(env, 1) {
 315             jclass clazz;
 316             clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
 317             classIsArray = isArrayClass(clazz);
 318         } END_WITH_LOCAL_REFS(env);
 319 
 320         return (classIsArray ? JDWP_TAG(ARRAY) : JDWP_TAG(OBJECT));
 321     }
 322 }
 323 
 324 static void
 325 writeFieldValue(JNIEnv *env, PacketOutputStream *out, jobject object,
 326                 jfieldID field)
 327 {
 328     jclass clazz;
 329     char *signature = NULL;
 330     jvmtiError error;
 331     jbyte typeKey;
 332 
 333     clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object);
 334     error = fieldSignature(clazz, field, NULL, &signature, NULL);
 335     if (error != JVMTI_ERROR_NONE) {
 336         outStream_setError(out, map2jdwpError(error));
 337         return;
 338     }
 339     typeKey = jdwpTag(signature);
 340     jvmtiDeallocate(signature);
 341 
 342     if (isReferenceTag(typeKey)) {
 343 
 344         jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field);
 345         (void)outStream_writeByte(out, specificTypeKey(env, value));
 346         (void)outStream_writeObjectRef(env, out, value);
 347         return;
 348 
 349     }
 350 
 351     /*
 352      * For primitive types, the type key is bounced back as is.
 353      */

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