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