Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2008, 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 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 
    314 static jboolean
    315 getFrameCount(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 
    346 static jboolean
    347 ownedMonitors(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 
    395 static jboolean
    396 currentContendedMonitor(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 
    437 static jboolean
    438 stop(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 
    467 static jboolean
    468 interrupt(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 
    490 static jboolean
    491 suspendCount(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 
    517 static jboolean
    518 ownedMonitorsWithStackDepth(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         jvmtiMonitorStackDepthInfo *monitors=NULL;
    544 
    545         error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorStackDepthInfo)
    546                                 (gdata->jvmti, thread, &count, &monitors);
    547 
    548         if (error != JVMTI_ERROR_NONE) {
    549             outStream_setError(out, map2jdwpError(error));
    550         } else {
    551             int i;
    552             (void)outStream_writeInt(out, count);
    553             for (i = 0; i < count; i++) {
    554                 jobject monitor = monitors[i].monitor;
    555                 (void)outStream_writeByte(out, specificTypeKey(env, monitor));
    556                 (void)outStream_writeObjectRef(getEnv(), out, monitor);
    557                 (void)outStream_writeInt(out,monitors[i].stack_depth);
    558             }
    559         }
    560         if (monitors != NULL) {
    561             jvmtiDeallocate(monitors);
    562         }
    563 
    564     } END_WITH_LOCAL_REFS(env);
    565 
    566     return JNI_TRUE;
    567 }
    568 
    569 static jboolean
    570 forceEarlyReturn(PacketInputStream *in, PacketOutputStream *out)
    571 {
    572     JNIEnv *env;
    573     jthread thread;
    574     jvalue value;
    575     jbyte typeKey;
    576     jvmtiError error;
    577 
    578     env = getEnv();
    579     thread = inStream_readThreadRef(env, in);
    580     if (inStream_error(in)) {
    581         return JNI_TRUE;
    582     }
    583 
    584     if (threadControl_isDebugThread(thread)) {
    585         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
    586         return JNI_TRUE;
    587     }
    588 
    589     typeKey = inStream_readByte(in);
    590     if (inStream_error(in)) {
    591         return JNI_TRUE;
    592     }
    593 
    594     if (isObjectTag(typeKey)) {
    595         value.l = inStream_readObjectRef(env, in);
    596         error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnObject)
    597                         (gdata->jvmti, thread, value.l);
    598     } else {
    599         switch (typeKey) {
    600             case JDWP_TAG(VOID):
    601                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnVoid)
    602                                 (gdata->jvmti, thread);
    603                 break;
    604             case JDWP_TAG(BYTE):
    605                 value.b = inStream_readByte(in);
    606                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
    607                                 (gdata->jvmti, thread, value.b);
    608                 break;
    609 
    610             case JDWP_TAG(CHAR):
    611                 value.c = inStream_readChar(in);
    612                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
    613                                 (gdata->jvmti, thread, value.c);
    614                 break;
    615 
    616             case JDWP_TAG(FLOAT):
    617                 value.f = inStream_readFloat(in);
    618                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnFloat)
    619                                 (gdata->jvmti, thread, value.f);
    620                 break;
    621 
    622             case JDWP_TAG(DOUBLE):
    623                 value.d = inStream_readDouble(in);
    624                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnDouble)
    625                                 (gdata->jvmti, thread, value.d);
    626                 break;
    627 
    628             case JDWP_TAG(INT):
    629                 value.i = inStream_readInt(in);
    630                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
    631                                 (gdata->jvmti, thread, value.i);
    632                 break;
    633 
    634             case JDWP_TAG(LONG):
    635                 value.j = inStream_readLong(in);
    636                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnLong)
    637                                 (gdata->jvmti, thread, value.j);
    638                 break;
    639 
    640             case JDWP_TAG(SHORT):
    641                 value.s = inStream_readShort(in);
    642                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
    643                                 (gdata->jvmti, thread, value.s);
    644                 break;
    645 
    646             case JDWP_TAG(BOOLEAN):
    647                 value.z = inStream_readBoolean(in);
    648                 error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt)
    649                                 (gdata->jvmti, thread, value.z);
    650                 break;
    651 
    652             default:
    653                 error =  AGENT_ERROR_INVALID_TAG;
    654                 break;
    655         }
    656     }
    657     {
    658       jdwpError serror = map2jdwpError(error);
    659       if (serror != JDWP_ERROR(NONE)) {
    660         outStream_setError(out, serror);
    661       }
    662     }
    663     return JNI_TRUE;
    664 }
    665 
    666 
    667 void *ThreadReference_Cmds[] = { (void *)14,
    668     (void *)name,
    669     (void *)suspend,
    670     (void *)resume,
    671     (void *)status,
    672     (void *)threadGroup,
    673     (void *)frames,
    674     (void *)getFrameCount,
    675     (void *)ownedMonitors,
    676     (void *)currentContendedMonitor,
    677     (void *)stop,
    678     (void *)interrupt,
    679     (void *)suspendCount,
    680     (void *)ownedMonitorsWithStackDepth,
    681     (void *)forceEarlyReturn
    682     };
    683