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