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