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