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