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