Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2005, 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 "StackFrameImpl.h"
     28 #include "inStream.h"
     29 #include "outStream.h"
     30 #include "threadControl.h"
     31 #include "FrameID.h"
     32 
     33 static jdwpError
     34 validateThreadFrame(jthread thread, FrameID frame)
     35 {
     36     jvmtiError error;
     37     jdwpError  serror;
     38     jint count;
     39     error = threadControl_suspendCount(thread, &count);
     40     if ( error == JVMTI_ERROR_NONE ) {
     41         if ( count > 0 ) {
     42             serror = validateFrameID(thread, frame);
     43         } else {
     44             serror = JDWP_ERROR(THREAD_NOT_SUSPENDED);
     45         }
     46     } else {
     47         serror =  map2jdwpError(error);
     48     }
     49     return serror;
     50 }
     51 
     52 static jdwpError
     53 writeVariableValue(JNIEnv *env, PacketOutputStream *out, jthread thread,
     54                    FrameNumber fnum, jint slot, jbyte typeKey)
     55 {
     56     jvmtiError error;
     57     jvalue value;
     58 
     59     if (isObjectTag(typeKey)) {
     60 
     61         WITH_LOCAL_REFS(env, 1) {
     62 
     63             error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
     64                         (gdata->jvmti, thread, fnum, slot, &value.l);
     65 
     66             if (error != JVMTI_ERROR_NONE) {
     67                 outStream_setError(out, map2jdwpError(error));
     68             } else {
     69                 (void)outStream_writeByte(out, specificTypeKey(env, value.l));
     70                 (void)outStream_writeObjectRef(env, out, value.l);
     71             }
     72 
     73         } END_WITH_LOCAL_REFS(env);
     74 
     75     } else {
     76         /*
     77          * For primitive types, the type key is bounced back as is.
     78          */
     79         (void)outStream_writeByte(out, typeKey);
     80         switch (typeKey) {
     81             case JDWP_TAG(BYTE): {
     82                     jint intValue;
     83                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
     84                                 (gdata->jvmti, thread, fnum, slot, &intValue);
     85                     (void)outStream_writeByte(out, (jbyte)intValue);
     86                     break;
     87                 }
     88 
     89             case JDWP_TAG(CHAR): {
     90                     jint intValue;
     91                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
     92                                 (gdata->jvmti, thread, fnum, slot, &intValue);
     93                     (void)outStream_writeChar(out, (jchar)intValue);
     94                     break;
     95                 }
     96 
     97             case JDWP_TAG(FLOAT):
     98                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalFloat)
     99                                 (gdata->jvmti, thread, fnum, slot, &value.f);
    100                 (void)outStream_writeFloat(out, value.f);
    101                 break;
    102 
    103             case JDWP_TAG(DOUBLE):
    104                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalDouble)
    105                                 (gdata->jvmti, thread, fnum, slot, &value.d);
    106                 (void)outStream_writeDouble(out, value.d);
    107                 break;
    108 
    109             case JDWP_TAG(INT):
    110                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
    111                                 (gdata->jvmti, thread, fnum, slot, &value.i);
    112                 (void)outStream_writeInt(out, value.i);
    113                 break;
    114 
    115             case JDWP_TAG(LONG):
    116                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalLong)
    117                                 (gdata->jvmti, thread, fnum, slot, &value.j);
    118                 (void)outStream_writeLong(out, value.j);
    119                 break;
    120 
    121             case JDWP_TAG(SHORT): {
    122                 jint intValue;
    123                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
    124                                 (gdata->jvmti, thread, fnum, slot, &intValue);
    125                 (void)outStream_writeShort(out, (jshort)intValue);
    126                 break;
    127             }
    128 
    129             case JDWP_TAG(BOOLEAN):{
    130                 jint intValue;
    131                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
    132                                 (gdata->jvmti, thread, fnum, slot, &intValue);
    133                 (void)outStream_writeBoolean(out, (jboolean)intValue);
    134                 break;
    135             }
    136 
    137             default:
    138                 return JDWP_ERROR(INVALID_TAG);
    139         }
    140     }
    141 
    142     return map2jdwpError(error);
    143 }
    144 
    145 static jdwpError
    146 readVariableValue(JNIEnv *env, PacketInputStream *in, jthread thread,
    147                   FrameNumber fnum, jint slot, jbyte typeKey)
    148 {
    149     jvmtiError error;
    150     jvalue value;
    151 
    152     if (isObjectTag(typeKey)) {
    153 
    154         value.l = inStream_readObjectRef(env, in);
    155 
    156         error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalObject)
    157                         (gdata->jvmti, thread, fnum, slot, value.l);
    158 
    159     } else {
    160         switch (typeKey) {
    161             case JDWP_TAG(BYTE):
    162                 value.b = inStream_readByte(in);
    163                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
    164                                 (gdata->jvmti, thread, fnum, slot, value.b);
    165                 break;
    166 
    167             case JDWP_TAG(CHAR):
    168                 value.c = inStream_readChar(in);
    169                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
    170                                 (gdata->jvmti, thread, fnum, slot, value.c);
    171                 break;
    172 
    173             case JDWP_TAG(FLOAT):
    174                 value.f = inStream_readFloat(in);
    175                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalFloat)
    176                                 (gdata->jvmti, thread, fnum, slot, value.f);
    177                 break;
    178 
    179             case JDWP_TAG(DOUBLE):
    180                 value.d = inStream_readDouble(in);
    181                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalDouble)
    182                                 (gdata->jvmti, thread, fnum, slot, value.d);
    183                 break;
    184 
    185             case JDWP_TAG(INT):
    186                 value.i = inStream_readInt(in);
    187                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
    188                                 (gdata->jvmti, thread, fnum, slot, value.i);
    189                 break;
    190 
    191             case JDWP_TAG(LONG):
    192                 value.j = inStream_readLong(in);
    193                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalLong)
    194                                 (gdata->jvmti, thread, fnum, slot, value.j);
    195                 break;
    196 
    197             case JDWP_TAG(SHORT):
    198                 value.s = inStream_readShort(in);
    199                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
    200                                 (gdata->jvmti, thread, fnum, slot, value.s);
    201                 break;
    202 
    203             case JDWP_TAG(BOOLEAN):
    204                 value.z = inStream_readBoolean(in);
    205                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
    206                                 (gdata->jvmti, thread, fnum, slot, value.z);
    207                 break;
    208 
    209             default:
    210                 return JDWP_ERROR(INVALID_TAG);
    211         }
    212     }
    213 
    214     return map2jdwpError(error);
    215 }
    216 
    217 static jboolean
    218 getValues(PacketInputStream *in, PacketOutputStream *out)
    219 {
    220     JNIEnv *env;
    221     int i;
    222     jdwpError serror;
    223     jthread thread;
    224     FrameID frame;
    225     jint variableCount;
    226 
    227     env = getEnv();
    228 
    229     thread = inStream_readThreadRef(env, in);
    230     if (inStream_error(in)) {
    231         return JNI_TRUE;
    232     }
    233     frame = inStream_readFrameID(in);
    234     if (inStream_error(in)) {
    235         return JNI_TRUE;
    236     }
    237     variableCount = inStream_readInt(in);
    238     if (inStream_error(in)) {
    239         return JNI_TRUE;
    240     }
    241 
    242     /*
    243      * Validate the frame id
    244      */
    245     serror = validateThreadFrame(thread, frame);
    246     if (serror != JDWP_ERROR(NONE)) {
    247         outStream_setError(out, serror);
    248         return JNI_TRUE;
    249     }
    250 
    251     (void)outStream_writeInt(out, variableCount);
    252     for (i = 0; (i < variableCount) && !outStream_error(out); i++) {
    253         jint slot;
    254         jbyte typeKey;
    255         FrameNumber fnum;
    256 
    257         slot = inStream_readInt(in);
    258         if (inStream_error(in))
    259             break;
    260         typeKey = inStream_readByte(in);
    261         if (inStream_error(in))
    262             break;
    263 
    264         fnum = getFrameNumber(frame);
    265         serror = writeVariableValue(env, out, thread, fnum, slot, typeKey);
    266         if (serror != JDWP_ERROR(NONE)) {
    267             outStream_setError(out, serror);
    268             break;
    269         }
    270     }
    271 
    272     return JNI_TRUE;
    273 }
    274 
    275 static jboolean
    276 setValues(PacketInputStream *in, PacketOutputStream *out)
    277 {
    278     JNIEnv *env;
    279     jint i;
    280     jdwpError serror;
    281     jthread thread;
    282     FrameID frame;
    283     jint variableCount;
    284 
    285     env = getEnv();
    286 
    287     thread = inStream_readThreadRef(env, in);
    288     if (inStream_error(in)) {
    289         return JNI_TRUE;
    290     }
    291     frame = inStream_readFrameID(in);
    292     if (inStream_error(in)) {
    293         return JNI_TRUE;
    294     }
    295     variableCount = inStream_readInt(in);
    296     if (inStream_error(in)) {
    297         return JNI_TRUE;
    298     }
    299 
    300     /*
    301      * Validate the frame id
    302      */
    303     serror = validateThreadFrame(thread, frame);
    304     if (serror != JDWP_ERROR(NONE)) {
    305         outStream_setError(out, serror);
    306         return JNI_TRUE;
    307     }
    308 
    309     for (i = 0; (i < variableCount) && !inStream_error(in); i++) {
    310 
    311         jint slot;
    312         jbyte typeKey;
    313         FrameNumber fnum;
    314 
    315         slot = inStream_readInt(in);
    316         if (inStream_error(in)) {
    317             return JNI_TRUE;
    318         }
    319         typeKey = inStream_readByte(in);
    320         if (inStream_error(in)) {
    321             return JNI_TRUE;
    322         }
    323 
    324         fnum = getFrameNumber(frame);
    325         serror = readVariableValue(env, in, thread, fnum, slot, typeKey);
    326         if (serror != JDWP_ERROR(NONE))
    327             break;
    328     }
    329 
    330     if (serror != JDWP_ERROR(NONE)) {
    331         outStream_setError(out, serror);
    332     }
    333 
    334     return JNI_TRUE;
    335 }
    336 
    337 static jboolean
    338 thisObject(PacketInputStream *in, PacketOutputStream *out)
    339 {
    340     JNIEnv *env;
    341     jdwpError serror;
    342     jthread thread;
    343     FrameID frame;
    344 
    345     env = getEnv();
    346 
    347     thread = inStream_readThreadRef(env, in);
    348     if (inStream_error(in)) {
    349         return JNI_TRUE;
    350     }
    351 
    352     frame = inStream_readFrameID(in);
    353     if (inStream_error(in)) {
    354         return JNI_TRUE;
    355     }
    356 
    357     /*
    358      * Validate the frame id
    359      */
    360     serror = validateThreadFrame(thread, frame);
    361     if (serror != JDWP_ERROR(NONE)) {
    362         outStream_setError(out, serror);
    363         return JNI_TRUE;
    364     }
    365 
    366     WITH_LOCAL_REFS(env, 2) {
    367 
    368         jvmtiError error;
    369         jmethodID method;
    370         jlocation location;
    371         FrameNumber fnum;
    372 
    373         /*
    374          * Find out if the given frame is for a static or native method.
    375          */
    376         fnum = getFrameNumber(frame);
    377         error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
    378                 (gdata->jvmti, thread, fnum, &method, &location);
    379         if (error == JVMTI_ERROR_NONE) {
    380 
    381             jint modifiers;
    382 
    383             error = methodModifiers(method, &modifiers);
    384             if (error == JVMTI_ERROR_NONE) {
    385 
    386                 jobject this_object;
    387 
    388                 /*
    389                  * Return null for static or native methods; otherwise, the JVM
    390                  * spec guarantees that "this" is in slot 0
    391                  */
    392                 if (modifiers & (MOD_STATIC | MOD_NATIVE)) {
    393                     this_object = NULL;
    394                     (void)outStream_writeByte(out, specificTypeKey(env, this_object));
    395                     (void)outStream_writeObjectRef(env, out, this_object);
    396                 } else {
    397                     // ANDROID-CHANGED: On ART 'this' is not always in register 0. We just use
    398                     // GetLocalInstance in all cases.
    399                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
    400                                 (gdata->jvmti, thread, fnum, &this_object);
    401                     if (error == JVMTI_ERROR_NONE) {
    402                         (void)outStream_writeByte(out, specificTypeKey(env, this_object));
    403                         (void)outStream_writeObjectRef(env, out, this_object);
    404                     }
    405                 }
    406 
    407             }
    408         }
    409         serror = map2jdwpError(error);
    410 
    411     } END_WITH_LOCAL_REFS(env);
    412 
    413     if (serror != JDWP_ERROR(NONE))
    414         outStream_setError(out, serror);
    415 
    416     return JNI_TRUE;
    417 }
    418 
    419 static jboolean
    420 popFrames(PacketInputStream *in, PacketOutputStream *out)
    421 {
    422     jvmtiError error;
    423     jdwpError serror;
    424     jthread thread;
    425     FrameID frame;
    426     FrameNumber fnum;
    427 
    428     thread = inStream_readThreadRef(getEnv(), in);
    429     if (inStream_error(in)) {
    430         return JNI_TRUE;
    431     }
    432 
    433     frame = inStream_readFrameID(in);
    434     if (inStream_error(in)) {
    435         return JNI_TRUE;
    436     }
    437 
    438     /*
    439      * Validate the frame id
    440      */
    441     serror = validateThreadFrame(thread, frame);
    442     if (serror != JDWP_ERROR(NONE)) {
    443         outStream_setError(out, serror);
    444         return JNI_TRUE;
    445     }
    446 
    447     if (threadControl_isDebugThread(thread)) {
    448         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
    449         return JNI_TRUE;
    450     }
    451 
    452     fnum = getFrameNumber(frame);
    453     error = threadControl_popFrames(thread, fnum);
    454     if (error != JVMTI_ERROR_NONE) {
    455         serror = map2jdwpError(error);
    456         outStream_setError(out, serror);
    457     }
    458     return JNI_TRUE;
    459 }
    460 
    461 void *StackFrame_Cmds[] = { (void *)0x4
    462     ,(void *)getValues
    463     ,(void *)setValues
    464     ,(void *)thisObject
    465     ,(void *)popFrames
    466 };
    467