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 "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 
 34 static jboolean
 35 name(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 
 76 static jboolean
 77 suspend(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 
 98 static jboolean
 99 resume(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 
122 static jboolean
123 status(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 
151 static jboolean
152 threadGroup(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 
193 static jboolean
194 validateSuspendedThread(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 
213 static jboolean
214 frames(PacketInputStream *in, PacketOutputStream *out)
215 {
216     jvmtiError error;
217     FrameNumber index;
218     jint count;
219     jint filledIn;
220     JNIEnv *env;
221     jthread thread;
222     jint startIndex;
223     jint length;
224     jvmtiFrameInfo* frames;
225 
226     env = getEnv();
227 
228     thread = inStream_readThreadRef(env, in);
229     if (inStream_error(in)) {
230         return JNI_TRUE;
231     }
232     startIndex = inStream_readInt(in);
233     if (inStream_error(in)) {
234         return JNI_TRUE;
235     }
236     length = inStream_readInt(in);
237     if (inStream_error(in)) {
238         return JNI_TRUE;
239     }
240 
241     if (threadControl_isDebugThread(thread)) {
242         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
243         return JNI_TRUE;
244     }
245 
246     if (!validateSuspendedThread(out, thread)) {
247         return JNI_TRUE;
248     }
249 
250     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
251                         (gdata->jvmti, thread, &count);
252     if (error != JVMTI_ERROR_NONE) {
253         outStream_setError(out, map2jdwpError(error));
254         return JNI_TRUE;
255     }
256 
257     if (length == -1) {
258         length = count - startIndex;
259     }
260 
261     if (length == 0) {
262         (void)outStream_writeInt(out, 0);
263         return JNI_TRUE;
264     }
265 
266     if ((startIndex < 0) || (startIndex > count - 1)) {
267         outStream_setError(out, JDWP_ERROR(INVALID_INDEX));
268         return JNI_TRUE;
269     }
270 
271     if ((length < 0) || (length + startIndex > count)) {
272         outStream_setError(out, JDWP_ERROR(INVALID_LENGTH));
273         return JNI_TRUE;
274     }
275 
276     (void)outStream_writeInt(out, length);
277 
278     frames = jvmtiAllocate(sizeof(jvmtiFrameInfo) * length);
279 
280     if (frames == NULL) {
281         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
282         return JNI_TRUE;
283     }
284 
285     error = JVMTI_FUNC_PTR(gdata->jvmti, GetStackTrace)
286                           (gdata->jvmti, thread, startIndex, length, frames,
287                            &filledIn);
288 
289     /* Should not happen. */
290     if (error == JVMTI_ERROR_NONE && length != filledIn) {
291         error = JVMTI_ERROR_INTERNAL;
292     }
293 
294     for (index = 0; index < filledIn && error == JVMTI_ERROR_NONE; ++index) {
295         WITH_LOCAL_REFS(env, 1) {
296             jclass clazz;
297             error = methodClass(frames[index].method, &clazz);
298 
299             if (error == JVMTI_ERROR_NONE) {
300                 FrameID frame = createFrameID(thread, index + startIndex);
301                 outStream_writeFrameID(out, frame);
302                 writeCodeLocation(out, clazz, frames[index].method,
303                                   frames[index].location);
304             }
305         } END_WITH_LOCAL_REFS(env);
306     }
307 
308     jvmtiDeallocate(frames);
309 
310     if (error != JVMTI_ERROR_NONE) {
311         outStream_setError(out, map2jdwpError(error));
312     }
313     return JNI_TRUE;
314 }
315 
316 static jboolean
317 getFrameCount(PacketInputStream *in, PacketOutputStream *out)
318 {
319     jvmtiError error;
320     jint count;
321     jthread thread;
322 
323     thread = inStream_readThreadRef(getEnv(), in);
324     if (inStream_error(in)) {
325         return JNI_TRUE;
326     }
327 
328     if (threadControl_isDebugThread(thread)) {
329         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
330         return JNI_TRUE;
331     }
332 
333     if (!validateSuspendedThread(out, thread)) {
334         return JNI_TRUE;
335     }
336 
337     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
338                         (gdata->jvmti, thread, &count);
339     if (error != JVMTI_ERROR_NONE) {
340         outStream_setError(out, map2jdwpError(error));
341         return JNI_TRUE;
342     }
343     (void)outStream_writeInt(out, count);
344 
345     return JNI_TRUE;
346 }
347 
348 static jboolean
349 ownedMonitors(PacketInputStream *in, PacketOutputStream *out)
350 {
351     JNIEnv *env;
352     jthread thread;
353 
354     env = getEnv();
355 
356     thread = inStream_readThreadRef(env, in);
357     if (inStream_error(in)) {
358         return JNI_TRUE;
359     }
360 
361     if (threadControl_isDebugThread(thread)) {
362         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
363         return JNI_TRUE;
364     }
365 
366     if (!validateSuspendedThread(out, thread)) {
367         return JNI_TRUE;
368     }
369 
370     WITH_LOCAL_REFS(env, 1) {
371 
372         jvmtiError error;
373         jint count = 0;
374         jobject *monitors = NULL;
375 
376         error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorInfo)
377                                 (gdata->jvmti, thread, &count, &monitors);
378         if (error != JVMTI_ERROR_NONE) {
379             outStream_setError(out, map2jdwpError(error));
380         } else {
381             int i;
382             (void)outStream_writeInt(out, count);
383             for (i = 0; i < count; i++) {
384                 jobject monitor = monitors[i];
385                 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
386                 (void)outStream_writeObjectRef(env, out, monitor);
387             }
388         }
389         if (monitors != NULL)
390             jvmtiDeallocate(monitors);
391 
392     } END_WITH_LOCAL_REFS(env);
393 
394     return JNI_TRUE;
395 }
396 
397 static jboolean
398 currentContendedMonitor(PacketInputStream *in, PacketOutputStream *out)
399 {
400     JNIEnv *env;
401     jthread thread;
402 
403     env = getEnv();
404 
405     thread = inStream_readThreadRef(env, in);
406     if (inStream_error(in)) {
407         return JNI_TRUE;
408     }
409 
410     if (thread == NULL || threadControl_isDebugThread(thread)) {
411         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
412         return JNI_TRUE;
413     }
414 
415     if (!validateSuspendedThread(out, thread)) {
416         return JNI_TRUE;
417     }
418 
419     WITH_LOCAL_REFS(env, 1) {
420 
421         jobject monitor;
422         jvmtiError error;
423 
424         error = JVMTI_FUNC_PTR(gdata->jvmti,GetCurrentContendedMonitor)
425                                 (gdata->jvmti, thread, &monitor);
426 
427         if (error != JVMTI_ERROR_NONE) {
428             outStream_setError(out, map2jdwpError(error));
429         } else {
430             (void)outStream_writeByte(out, specificTypeKey(env, monitor));
431             (void)outStream_writeObjectRef(env, out, monitor);
432         }
433 
434     } END_WITH_LOCAL_REFS(env);
435 
436     return JNI_TRUE;
437 }
438 
439 static jboolean
440 stop(PacketInputStream *in, PacketOutputStream *out)
441 {
442     jvmtiError error;
443     jthread thread;
444     jobject throwable;
445     JNIEnv *env;
446 
447     env = getEnv();
448     thread = inStream_readThreadRef(env, in);
449     if (inStream_error(in)) {
450         return JNI_TRUE;
451     }
452     throwable = inStream_readObjectRef(env, in);
453     if (inStream_error(in)) {
454         return JNI_TRUE;
455     }
456 
457     if (threadControl_isDebugThread(thread)) {
458         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
459         return JNI_TRUE;
460     }
461 
462     error = threadControl_stop(thread, throwable);
463     if (error != JVMTI_ERROR_NONE) {
464         outStream_setError(out, map2jdwpError(error));
465     }
466     return JNI_TRUE;
467 }
468 
469 static jboolean
470 interrupt(PacketInputStream *in, PacketOutputStream *out)
471 {
472     jvmtiError error;
473     jthread thread;
474 
475     thread = inStream_readThreadRef(getEnv(), in);
476     if (inStream_error(in)) {
477         return JNI_TRUE;
478     }
479 
480     if (threadControl_isDebugThread(thread)) {
481         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
482         return JNI_TRUE;
483     }
484 
485     error = threadControl_interrupt(thread);
486     if (error != JVMTI_ERROR_NONE) {
487         outStream_setError(out, map2jdwpError(error));
488     }
489     return JNI_TRUE;
490 }
491 
492 static jboolean
493 suspendCount(PacketInputStream *in, PacketOutputStream *out)
494 {
495     jvmtiError error;
496     jint count;
497     jthread thread;
498 
499     thread = inStream_readThreadRef(getEnv(), in);
500     if (inStream_error(in)) {
501         return JNI_TRUE;
502     }
503 
504     if (threadControl_isDebugThread(thread)) {
505         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
506         return JNI_TRUE;
507     }
508 
509     error = threadControl_suspendCount(thread, &count);
510     if (error != JVMTI_ERROR_NONE) {
511         outStream_setError(out, map2jdwpError(error));
512         return JNI_TRUE;
513     }
514 
515     (void)outStream_writeInt(out, count);
516     return JNI_TRUE;
517 }
518 
519 static jboolean
520 ownedMonitorsWithStackDepth(PacketInputStream *in, PacketOutputStream *out)
521 {
522     JNIEnv *env;
523     jthread thread;
524 
525     thread = inStream_readThreadRef(getEnv(), in);
526     if (inStream_error(in)) {
527         return JNI_TRUE;
528     }
529 
530     if (thread == NULL || threadControl_isDebugThread(thread)) {
531         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
532         return JNI_TRUE;
533     }
534 
535     if (!validateSuspendedThread(out, thread)) {
536         return JNI_TRUE;
537     }
538 
539     env = getEnv();
540 
541     WITH_LOCAL_REFS(env, 1) {
542 
543         jvmtiError error = JVMTI_ERROR_NONE;
544         jint count = 0;
545         jvmtiMonitorStackDepthInfo *monitors=NULL;
546 
547         error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorStackDepthInfo)
548                                 (gdata->jvmti, thread, &count, &monitors);
549 
550         if (error != JVMTI_ERROR_NONE) {
551             outStream_setError(out, map2jdwpError(error));
552         } else {
553             int i;
554             (void)outStream_writeInt(out, count);
555             for (i = 0; i < count; i++) {
556                 jobject monitor = monitors[i].monitor;
557                 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
558                 (void)outStream_writeObjectRef(getEnv(), out, monitor);
559                 (void)outStream_writeInt(out,monitors[i].stack_depth);
560             }
561         }
562         if (monitors != NULL) {
563             jvmtiDeallocate(monitors);
564         }
565 
566     } END_WITH_LOCAL_REFS(env);
567 
568     return JNI_TRUE;
569 }
570 
571 static jboolean
572 forceEarlyReturn(PacketInputStream *in, PacketOutputStream *out)
573 {
574     JNIEnv *env;
575     jthread thread;
576     jvalue value;
577     jbyte typeKey;
578     jvmtiError error;
579 
580     env = getEnv();
581     thread = inStream_readThreadRef(env, in);
582     if (inStream_error(in)) {
583         return JNI_TRUE;
584     }
585 
586     if (threadControl_isDebugThread(thread)) {
587         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
588         return JNI_TRUE;
589     }
590 
591     typeKey = inStream_readByte(in);
592     if (inStream_error(in)) {
593         return JNI_TRUE;
594     }
595 
596     if (isObjectTag(typeKey)) {
597         value.l = inStream_readObjectRef(env, in);
598         error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnObject)
599                         (gdata->jvmti, thread, value.l);
600     } else {
601         switch (typeKey) {
602             case JDWP_TAG(VOID):
603                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnVoid)
604                                 (gdata->jvmti, thread);
605                 break;
606             case JDWP_TAG(BYTE):
607                 value.b = inStream_readByte(in);
608                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
609                                 (gdata->jvmti, thread, value.b);
610                 break;
611 
612             case JDWP_TAG(CHAR):
613                 value.c = inStream_readChar(in);
614                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
615                                 (gdata->jvmti, thread, value.c);
616                 break;
617 
618             case JDWP_TAG(FLOAT):
619                 value.f = inStream_readFloat(in);
620                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnFloat)
621                                 (gdata->jvmti, thread, value.f);
622                 break;
623 
624             case JDWP_TAG(DOUBLE):
625                 value.d = inStream_readDouble(in);
626                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnDouble)
627                                 (gdata->jvmti, thread, value.d);
628                 break;
629 
630             case JDWP_TAG(INT):
631                 value.i = inStream_readInt(in);
632                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
633                                 (gdata->jvmti, thread, value.i);
634                 break;
635 
636             case JDWP_TAG(LONG):
637                 value.j = inStream_readLong(in);
638                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnLong)
639                                 (gdata->jvmti, thread, value.j);
640                 break;
641 
642             case JDWP_TAG(SHORT):
643                 value.s = inStream_readShort(in);
644                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
645                                 (gdata->jvmti, thread, value.s);
646                 break;
647 
648             case JDWP_TAG(BOOLEAN):
649                 value.z = inStream_readBoolean(in);
650                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
651                                 (gdata->jvmti, thread, value.z);
652                 break;
653 
654             default:
655                 error =  AGENT_ERROR_INVALID_TAG;
656                 break;
657         }
658     }
659     {
660       jdwpError serror = map2jdwpError(error);
661       if (serror != JDWP_ERROR(NONE)) {
662         outStream_setError(out, serror);
663       }
664     }
665     return JNI_TRUE;
666 }
667 
668 Command ThreadReference_Commands[] = {
669     {name, "Name"},
670     {suspend, "Suspend"},
671     {resume, "Resume"},
672     {status, "Status"},
673     {threadGroup, "ThreadGroup"},
674     {frames, "Frames"},
675     {getFrameCount, "GetFrameCount"},
676     {ownedMonitors, "OwnedMonitors"},
677     {currentContendedMonitor, "CurrentContendedMonitor"},
678     {stop, "Stop"},
679     {interrupt, "Interrupt"},
680     {suspendCount, "SuspendCount"},
681     {ownedMonitorsWithStackDepth, "OwnedMonitorsWithStackDepth"},
682     {forceEarlyReturn, "ForceEarlyReturn"}
683 };
684 
685 DEBUG_DISPATCH_DEFINE_CMDSET(ThreadReference)