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