blob: fc7d7434e99e1d456697b44d01da7791341936ae [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "util.h"
27#include "ThreadReferenceImpl.h"
28#include "eventHandler.h"
29#include "threadControl.h"
30#include "inStream.h"
31#include "outStream.h"
32#include "FrameID.h"
33
34static jboolean
35name(PacketInputStream *in, PacketOutputStream *out)
36{
37 JNIEnv *env;
38 jthread thread;
39
40 env = getEnv();
41
42 thread = inStream_readThreadRef(env, in);
43 if (inStream_error(in)) {
44 return JNI_TRUE;
45 }
46
47 if (threadControl_isDebugThread(thread)) {
48 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
49 return JNI_TRUE;
50 }
51
52 WITH_LOCAL_REFS(env, 1) {
53
54 jvmtiThreadInfo info;
55 jvmtiError error;
56
57 (void)memset(&info, 0, sizeof(info));
58
59 error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo)
60 (gdata->jvmti, thread, &info);
61
62 if (error != JVMTI_ERROR_NONE) {
63 outStream_setError(out, map2jdwpError(error));
64 } else {
65 (void)outStream_writeString(out, info.name);
66 }
67
68 if ( info.name != NULL )
69 jvmtiDeallocate(info.name);
70
71 } END_WITH_LOCAL_REFS(env);
72
73 return JNI_TRUE;
74}
75
76static jboolean
77suspend(PacketInputStream *in, PacketOutputStream *out)
78{
79 jvmtiError error;
80 jthread thread;
81
82 thread = inStream_readThreadRef(getEnv(), in);
83 if (inStream_error(in)) {
84 return JNI_TRUE;
85 }
86
87 if (threadControl_isDebugThread(thread)) {
88 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
89 return JNI_TRUE;
90 }
91 error = threadControl_suspendThread(thread, JNI_FALSE);
92 if (error != JVMTI_ERROR_NONE) {
93 outStream_setError(out, map2jdwpError(error));
94 }
95 return JNI_TRUE;
96}
97
98static jboolean
99resume(PacketInputStream *in, PacketOutputStream *out)
100{
101 jvmtiError error;
102 jthread thread;
103
104 thread = inStream_readThreadRef(getEnv(), in);
105 if (inStream_error(in)) {
106 return JNI_TRUE;
107 }
108
109 if (threadControl_isDebugThread(thread)) {
110 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
111 return JNI_TRUE;
112 }
113
114 /* true means it is okay to unblock the commandLoop thread */
115 error = threadControl_resumeThread(thread, JNI_TRUE);
116 if (error != JVMTI_ERROR_NONE) {
117 outStream_setError(out, map2jdwpError(error));
118 }
119 return JNI_TRUE;
120}
121
122static jboolean
123status(PacketInputStream *in, PacketOutputStream *out)
124{
125 jdwpThreadStatus threadStatus;
126 jint statusFlags;
127 jvmtiError error;
128 jthread thread;
129
130 thread = inStream_readThreadRef(getEnv(), in);
131 if (inStream_error(in)) {
132 return JNI_TRUE;
133 }
134
135 if (threadControl_isDebugThread(thread)) {
136 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
137 return JNI_TRUE;
138 }
139
140 error = threadControl_applicationThreadStatus(thread, &threadStatus,
141 &statusFlags);
142 if (error != JVMTI_ERROR_NONE) {
143 outStream_setError(out, map2jdwpError(error));
144 return JNI_TRUE;
145 }
146 (void)outStream_writeInt(out, threadStatus);
147 (void)outStream_writeInt(out, statusFlags);
148 return JNI_TRUE;
149}
150
151static jboolean
152threadGroup(PacketInputStream *in, PacketOutputStream *out)
153{
154 JNIEnv *env;
155 jthread thread;
156
157 env = getEnv();
158
159 thread = inStream_readThreadRef(env, in);
160 if (inStream_error(in)) {
161 return JNI_TRUE;
162 }
163
164 if (threadControl_isDebugThread(thread)) {
165 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
166 return JNI_TRUE;
167 }
168
169 WITH_LOCAL_REFS(env, 1) {
170
171 jvmtiThreadInfo info;
172 jvmtiError error;
173
174 (void)memset(&info, 0, sizeof(info));
175
176 error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo)
177 (gdata->jvmti, thread, &info);
178
179 if (error != JVMTI_ERROR_NONE) {
180 outStream_setError(out, map2jdwpError(error));
181 } else {
182 (void)outStream_writeObjectRef(env, out, info.thread_group);
183 }
184
185 if ( info.name!=NULL )
186 jvmtiDeallocate(info.name);
187
188 } END_WITH_LOCAL_REFS(env);
189
190 return JNI_TRUE;
191}
192
193static jboolean
194validateSuspendedThread(PacketOutputStream *out, jthread thread)
195{
196 jvmtiError error;
197 jint count;
198
199 error = threadControl_suspendCount(thread, &count);
200 if (error != JVMTI_ERROR_NONE) {
201 outStream_setError(out, map2jdwpError(error));
202 return JNI_FALSE;
203 }
204
205 if (count == 0) {
206 outStream_setError(out, JDWP_ERROR(THREAD_NOT_SUSPENDED));
207 return JNI_FALSE;
208 }
209
210 return JNI_TRUE;
211}
212
213static jboolean
214frames(PacketInputStream *in, PacketOutputStream *out)
215{
216 jvmtiError error;
217 FrameNumber fnum;
218 jint count;
219 JNIEnv *env;
220 jthread thread;
221 jint startIndex;
222 jint length;
223
224 env = getEnv();
225
226 thread = inStream_readThreadRef(env, in);
227 if (inStream_error(in)) {
228 return JNI_TRUE;
229 }
230 startIndex = inStream_readInt(in);
231 if (inStream_error(in)) {
232 return JNI_TRUE;
233 }
234 length = inStream_readInt(in);
235 if (inStream_error(in)) {
236 return JNI_TRUE;
237 }
238
239 if (threadControl_isDebugThread(thread)) {
240 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
241 return JNI_TRUE;
242 }
243
244 if (!validateSuspendedThread(out, thread)) {
245 return JNI_TRUE;
246 }
247
248 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
249 (gdata->jvmti, thread, &count);
250 if (error != JVMTI_ERROR_NONE) {
251 outStream_setError(out, map2jdwpError(error));
252 return JNI_TRUE;
253 }
254
255 if (length == -1) {
256 length = count - startIndex;
257 }
258
259 if (length == 0) {
260 (void)outStream_writeInt(out, 0);
261 return JNI_TRUE;
262 }
263
264 if ((startIndex < 0) || (startIndex > count - 1)) {
265 outStream_setError(out, JDWP_ERROR(INVALID_INDEX));
266 return JNI_TRUE;
267 }
268
269 if ((length < 0) || (length + startIndex > count)) {
270 outStream_setError(out, JDWP_ERROR(INVALID_LENGTH));
271 return JNI_TRUE;
272 }
273
274 (void)outStream_writeInt(out, length);
275
276 for(fnum = startIndex ; fnum < startIndex+length ; fnum++ ) {
277
278 WITH_LOCAL_REFS(env, 1) {
279
280 jclass clazz;
281 jmethodID method;
282 jlocation location;
283
284 /* Get location info */
285 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
286 (gdata->jvmti, thread, fnum, &method, &location);
287 if (error == JVMTI_ERROR_OPAQUE_FRAME) {
288 clazz = NULL;
289 location = -1L;
290 error = JVMTI_ERROR_NONE;
291 } else if ( error == JVMTI_ERROR_NONE ) {
292 error = methodClass(method, &clazz);
293 if ( error == JVMTI_ERROR_NONE ) {
294 FrameID frame;
295 frame = createFrameID(thread, fnum);
296 (void)outStream_writeFrameID(out, frame);
297 writeCodeLocation(out, clazz, method, location);
298 }
299 }
300
301 } END_WITH_LOCAL_REFS(env);
302
303 if (error != JVMTI_ERROR_NONE)
304 break;
305
306 }
307
308 if (error != JVMTI_ERROR_NONE) {
309 outStream_setError(out, map2jdwpError(error));
310 }
311 return JNI_TRUE;
312}
313
314static jboolean
315getFrameCount(PacketInputStream *in, PacketOutputStream *out)
316{
317 jvmtiError error;
318 jint count;
319 jthread thread;
320
321 thread = inStream_readThreadRef(getEnv(), in);
322 if (inStream_error(in)) {
323 return JNI_TRUE;
324 }
325
326 if (threadControl_isDebugThread(thread)) {
327 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
328 return JNI_TRUE;
329 }
330
331 if (!validateSuspendedThread(out, thread)) {
332 return JNI_TRUE;
333 }
334
335 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
336 (gdata->jvmti, thread, &count);
337 if (error != JVMTI_ERROR_NONE) {
338 outStream_setError(out, map2jdwpError(error));
339 return JNI_TRUE;
340 }
341 (void)outStream_writeInt(out, count);
342
343 return JNI_TRUE;
344}
345
346static jboolean
347ownedMonitors(PacketInputStream *in, PacketOutputStream *out)
348{
349 JNIEnv *env;
350 jthread thread;
351
352 env = getEnv();
353
354 thread = inStream_readThreadRef(env, in);
355 if (inStream_error(in)) {
356 return JNI_TRUE;
357 }
358
359 if (threadControl_isDebugThread(thread)) {
360 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
361 return JNI_TRUE;
362 }
363
364 if (!validateSuspendedThread(out, thread)) {
365 return JNI_TRUE;
366 }
367
368 WITH_LOCAL_REFS(env, 1) {
369
370 jvmtiError error;
371 jint count = 0;
372 jobject *monitors = NULL;
373
374 error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorInfo)
375 (gdata->jvmti, thread, &count, &monitors);
376 if (error != JVMTI_ERROR_NONE) {
377 outStream_setError(out, map2jdwpError(error));
378 } else {
379 int i;
380 (void)outStream_writeInt(out, count);
381 for (i = 0; i < count; i++) {
382 jobject monitor = monitors[i];
383 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
384 (void)outStream_writeObjectRef(env, out, monitor);
385 }
386 }
387 if (monitors != NULL)
388 jvmtiDeallocate(monitors);
389
390 } END_WITH_LOCAL_REFS(env);
391
392 return JNI_TRUE;
393}
394
395static jboolean
396currentContendedMonitor(PacketInputStream *in, PacketOutputStream *out)
397{
398 JNIEnv *env;
399 jthread thread;
400
401 env = getEnv();
402
403 thread = inStream_readThreadRef(env, in);
404 if (inStream_error(in)) {
405 return JNI_TRUE;
406 }
407
408 if (thread == NULL || threadControl_isDebugThread(thread)) {
409 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
410 return JNI_TRUE;
411 }
412
413 if (!validateSuspendedThread(out, thread)) {
414 return JNI_TRUE;
415 }
416
417 WITH_LOCAL_REFS(env, 1) {
418
419 jobject monitor;
420 jvmtiError error;
421
422 error = JVMTI_FUNC_PTR(gdata->jvmti,GetCurrentContendedMonitor)
423 (gdata->jvmti, thread, &monitor);
424
425 if (error != JVMTI_ERROR_NONE) {
426 outStream_setError(out, map2jdwpError(error));
427 } else {
428 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
429 (void)outStream_writeObjectRef(env, out, monitor);
430 }
431
432 } END_WITH_LOCAL_REFS(env);
433
434 return JNI_TRUE;
435}
436
437static jboolean
438stop(PacketInputStream *in, PacketOutputStream *out)
439{
440 jvmtiError error;
441 jthread thread;
442 jobject throwable;
443 JNIEnv *env;
444
445 env = getEnv();
446 thread = inStream_readThreadRef(env, in);
447 if (inStream_error(in)) {
448 return JNI_TRUE;
449 }
450 throwable = inStream_readObjectRef(env, in);
451 if (inStream_error(in)) {
452 return JNI_TRUE;
453 }
454
455 if (threadControl_isDebugThread(thread)) {
456 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
457 return JNI_TRUE;
458 }
459
460 error = threadControl_stop(thread, throwable);
461 if (error != JVMTI_ERROR_NONE) {
462 outStream_setError(out, map2jdwpError(error));
463 }
464 return JNI_TRUE;
465}
466
467static jboolean
468interrupt(PacketInputStream *in, PacketOutputStream *out)
469{
470 jvmtiError error;
471 jthread thread;
472
473 thread = inStream_readThreadRef(getEnv(), in);
474 if (inStream_error(in)) {
475 return JNI_TRUE;
476 }
477
478 if (threadControl_isDebugThread(thread)) {
479 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
480 return JNI_TRUE;
481 }
482
483 error = threadControl_interrupt(thread);
484 if (error != JVMTI_ERROR_NONE) {
485 outStream_setError(out, map2jdwpError(error));
486 }
487 return JNI_TRUE;
488}
489
490static jboolean
491suspendCount(PacketInputStream *in, PacketOutputStream *out)
492{
493 jvmtiError error;
494 jint count;
495 jthread thread;
496
497 thread = inStream_readThreadRef(getEnv(), in);
498 if (inStream_error(in)) {
499 return JNI_TRUE;
500 }
501
502 if (threadControl_isDebugThread(thread)) {
503 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
504 return JNI_TRUE;
505 }
506
507 error = threadControl_suspendCount(thread, &count);
508 if (error != JVMTI_ERROR_NONE) {
509 outStream_setError(out, map2jdwpError(error));
510 return JNI_TRUE;
511 }
512
513 (void)outStream_writeInt(out, count);
514 return JNI_TRUE;
515}
516
517static jboolean
518ownedMonitorsWithStackDepth(PacketInputStream *in, PacketOutputStream *out)
519{
520 JNIEnv *env;
521 jthread thread;
522
523 thread = inStream_readThreadRef(getEnv(), in);
524 if (inStream_error(in)) {
525 return JNI_TRUE;
526 }
527
528 if (thread == NULL || threadControl_isDebugThread(thread)) {
529 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
530 return JNI_TRUE;
531 }
532
533 if (!validateSuspendedThread(out, thread)) {
534 return JNI_TRUE;
535 }
536
537 env = getEnv();
538
539 WITH_LOCAL_REFS(env, 1) {
540
541 jvmtiError error = JVMTI_ERROR_NONE;
542 jint count = 0;
543 jint depth;
544 jvmtiMonitorStackDepthInfo *monitors=NULL;
545
546 error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorStackDepthInfo)
547 (gdata->jvmti, thread, &count, &monitors);
548
549 if (error != JVMTI_ERROR_NONE) {
550 outStream_setError(out, map2jdwpError(error));
551 } else {
552 int i;
553 (void)outStream_writeInt(out, count);
554 for (i = 0; i < count; i++) {
555 jobject monitor = monitors[i].monitor;
556 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
557 (void)outStream_writeObjectRef(getEnv(), out, monitor);
558 (void)outStream_writeInt(out,monitors[i].stack_depth);
559 }
560 }
561 if (monitors != NULL) {
562 jvmtiDeallocate(monitors);
563 }
564
565 } END_WITH_LOCAL_REFS(env);
566
567 return JNI_TRUE;
568}
569
570static jboolean
571forceEarlyReturn(PacketInputStream *in, PacketOutputStream *out)
572{
573 JNIEnv *env;
574 jthread thread;
575 jvalue value;
576 jbyte typeKey;
577 jvmtiError error;
578
579 env = getEnv();
580 thread = inStream_readThreadRef(env, in);
581 if (inStream_error(in)) {
582 return JNI_TRUE;
583 }
584
585 if (threadControl_isDebugThread(thread)) {
586 outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
587 return JNI_TRUE;
588 }
589
590 typeKey = inStream_readByte(in);
591 if (inStream_error(in)) {
592 return JNI_TRUE;
593 }
594
595 if (isObjectTag(typeKey)) {
596 value.l = inStream_readObjectRef(env, in);
597 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnObject)
598 (gdata->jvmti, thread, value.l);
599 } else {
600 switch (typeKey) {
601 case JDWP_TAG(VOID):
602 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnVoid)
603 (gdata->jvmti, thread);
604 break;
605 case JDWP_TAG(BYTE):
606 value.b = inStream_readByte(in);
607 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
608 (gdata->jvmti, thread, value.b);
609 break;
610
611 case JDWP_TAG(CHAR):
612 value.c = inStream_readChar(in);
613 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
614 (gdata->jvmti, thread, value.c);
615 break;
616
617 case JDWP_TAG(FLOAT):
618 value.f = inStream_readFloat(in);
619 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnFloat)
620 (gdata->jvmti, thread, value.f);
621 break;
622
623 case JDWP_TAG(DOUBLE):
624 value.d = inStream_readDouble(in);
625 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnDouble)
626 (gdata->jvmti, thread, value.d);
627 break;
628
629 case JDWP_TAG(INT):
630 value.i = inStream_readInt(in);
631 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
632 (gdata->jvmti, thread, value.i);
633 break;
634
635 case JDWP_TAG(LONG):
636 value.j = inStream_readLong(in);
637 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnLong)
638 (gdata->jvmti, thread, value.j);
639 break;
640
641 case JDWP_TAG(SHORT):
642 value.s = inStream_readShort(in);
643 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
644 (gdata->jvmti, thread, value.s);
645 break;
646
647 case JDWP_TAG(BOOLEAN):
648 value.z = inStream_readBoolean(in);
649 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
650 (gdata->jvmti, thread, value.z);
651 break;
652
653 default:
654 error = AGENT_ERROR_INVALID_TAG;
655 break;
656 }
657 }
658 {
659 jdwpError serror = map2jdwpError(error);
660 if (serror != JDWP_ERROR(NONE)) {
661 outStream_setError(out, serror);
662 }
663 }
664 return JNI_TRUE;
665}
666
667
668void *ThreadReference_Cmds[] = { (void *)14,
669 (void *)name,
670 (void *)suspend,
671 (void *)resume,
672 (void *)status,
673 (void *)threadGroup,
674 (void *)frames,
675 (void *)getFrameCount,
676 (void *)ownedMonitors,
677 (void *)currentContendedMonitor,
678 (void *)stop,
679 (void *)interrupt,
680 (void *)suspendCount,
681 (void *)ownedMonitorsWithStackDepth,
682 (void *)forceEarlyReturn
683 };