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