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