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