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