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 "MethodImpl.h"
     28 #include "inStream.h"
     29 #include "outStream.h"
     30 
     31 static jboolean
     32 lineTable(PacketInputStream *in, PacketOutputStream *out)
     33 {
     34     jvmtiError error;
     35     jint count = 0;
     36     jvmtiLineNumberEntry *table = NULL;
     37     jmethodID method;
     38     jlocation firstCodeIndex;
     39     jlocation lastCodeIndex;
     40     jboolean isNative;
     41 
     42     /* JVMDI needed the class, but JVMTI does not so we ignore it */
     43     (void)inStream_readClassRef(getEnv(), in);
     44     if (inStream_error(in)) {
     45         return JNI_TRUE;
     46     }
     47     method = inStream_readMethodID(in);
     48     if (inStream_error(in)) {
     49         return JNI_TRUE;
     50     }
     51 
     52     /*
     53      * JVMTI behavior for the calls below is unspecified for native
     54      * methods, so we must check explicitly.
     55      */
     56     isNative = isMethodNative(method);
     57     if (isNative) {
     58         outStream_setError(out, JDWP_ERROR(NATIVE_METHOD));
     59         return JNI_TRUE;
     60     }
     61 
     62     error = methodLocation(method, &firstCodeIndex, &lastCodeIndex);
     63     if (error != JVMTI_ERROR_NONE) {
     64         outStream_setError(out, map2jdwpError(error));
     65         return JNI_TRUE;
     66     }
     67     (void)outStream_writeLocation(out, firstCodeIndex);
     68     (void)outStream_writeLocation(out, lastCodeIndex);
     69 
     70     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)
     71                 (gdata->jvmti, method, &count, &table);
     72     if (error == JVMTI_ERROR_ABSENT_INFORMATION) {
     73         /*
     74          * Indicate no line info with an empty table. The code indices
     75          * are still useful, so we don't want to return an error
     76          */
     77         (void)outStream_writeInt(out, 0);
     78     } else if (error == JVMTI_ERROR_NONE) {
     79         jint i;
     80         (void)outStream_writeInt(out, count);
     81         for (i = 0; (i < count) && !outStream_error(out); i++) {
     82             (void)outStream_writeLocation(out, table[i].start_location);
     83             (void)outStream_writeInt(out, table[i].line_number);
     84         }
     85         jvmtiDeallocate(table);
     86     } else {
     87         outStream_setError(out, map2jdwpError(error));
     88     }
     89     return JNI_TRUE;
     90 }
     91 
     92 
     93 static jboolean
     94 doVariableTable(PacketInputStream *in, PacketOutputStream *out,
     95                 int outputGenerics)
     96 {
     97     jvmtiError error;
     98     jint count;
     99     jvmtiLocalVariableEntry *table;
    100     jmethodID method;
    101     jint argsSize;
    102     jboolean isNative;
    103 
    104     /* JVMDI needed the class, but JVMTI does not so we ignore it */
    105     (void)inStream_readClassRef(getEnv(), in);
    106     if (inStream_error(in)) {
    107         return JNI_TRUE;
    108     }
    109     method = inStream_readMethodID(in);
    110     if (inStream_error(in)) {
    111         return JNI_TRUE;
    112     }
    113 
    114     /*
    115      * JVMTI behavior for the calls below is unspecified for native
    116      * methods, so we must check explicitly.
    117      */
    118     isNative = isMethodNative(method);
    119     if (isNative) {
    120         outStream_setError(out, JDWP_ERROR(NATIVE_METHOD));
    121         return JNI_TRUE;
    122     }
    123 
    124     error = JVMTI_FUNC_PTR(gdata->jvmti,GetArgumentsSize)
    125                 (gdata->jvmti, method, &argsSize);
    126     if (error != JVMTI_ERROR_NONE) {
    127         outStream_setError(out, map2jdwpError(error));
    128         return JNI_TRUE;
    129     }
    130 
    131     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalVariableTable)
    132                 (gdata->jvmti, method, &count, &table);
    133     if (error == JVMTI_ERROR_NONE) {
    134         jint i;
    135         (void)outStream_writeInt(out, argsSize);
    136         (void)outStream_writeInt(out, count);
    137         for (i = 0; (i < count) && !outStream_error(out); i++) {
    138             jvmtiLocalVariableEntry *entry = &table[i];
    139             (void)outStream_writeLocation(out, entry->start_location);
    140             (void)outStream_writeString(out, entry->name);
    141             (void)outStream_writeString(out, entry->signature);
    142             if (outputGenerics == 1) {
    143                 writeGenericSignature(out, entry->generic_signature);
    144             }
    145             (void)outStream_writeInt(out, entry->length);
    146             (void)outStream_writeInt(out, entry->slot);
    147 
    148             jvmtiDeallocate(entry->name);
    149             jvmtiDeallocate(entry->signature);
    150             if (entry->generic_signature != NULL) {
    151               jvmtiDeallocate(entry->generic_signature);
    152             }
    153         }
    154 
    155         jvmtiDeallocate(table);
    156     } else {
    157         outStream_setError(out, map2jdwpError(error));
    158     }
    159     return JNI_TRUE;
    160 }
    161 
    162 
    163 static jboolean
    164 variableTable(PacketInputStream *in, PacketOutputStream *out) {
    165     return doVariableTable(in, out, 0);
    166 }
    167 
    168 static jboolean
    169 variableTableWithGenerics(PacketInputStream *in, PacketOutputStream *out) {
    170     return doVariableTable(in, out, 1);
    171 }
    172 
    173 
    174 static jboolean
    175 bytecodes(PacketInputStream *in, PacketOutputStream *out)
    176 {
    177     jvmtiError error;
    178     unsigned char * bcp;
    179     jint bytecodeCount;
    180     jmethodID method;
    181 
    182     /* JVMDI needed the class, but JVMTI does not so we ignore it */
    183     (void)inStream_readClassRef(getEnv(), in);
    184     if (inStream_error(in)) {
    185         return JNI_TRUE;
    186     }
    187     method = inStream_readMethodID(in);
    188     if (inStream_error(in)) {
    189         return JNI_TRUE;
    190     }
    191 
    192     /* Initialize assuming no bytecodes and no error */
    193     error         = JVMTI_ERROR_NONE;
    194     bytecodeCount = 0;
    195     bcp           = NULL;
    196 
    197     /* Only non-native methods have bytecodes, don't even ask if native. */
    198     if ( !isMethodNative(method) ) {
    199         error = JVMTI_FUNC_PTR(gdata->jvmti,GetBytecodes)
    200                     (gdata->jvmti, method, &bytecodeCount, &bcp);
    201     }
    202     if (error != JVMTI_ERROR_NONE) {
    203         outStream_setError(out, map2jdwpError(error));
    204     } else {
    205         (void)outStream_writeByteArray(out, bytecodeCount, (jbyte *)bcp);
    206         jvmtiDeallocate(bcp);
    207     }
    208 
    209     return JNI_TRUE;
    210 }
    211 
    212 static jboolean
    213 isObsolete(PacketInputStream *in, PacketOutputStream *out)
    214 {
    215     jboolean isObsolete;
    216     jmethodID method;
    217 
    218     /* JVMDI needed the class, but JVMTI does not so we ignore it */
    219     (void)inStream_readClassRef(getEnv(), in);
    220     if (inStream_error(in)) {
    221         return JNI_TRUE;
    222     }
    223     method = inStream_readMethodID(in);
    224     if (inStream_error(in)) {
    225         return JNI_TRUE;
    226     }
    227 
    228     isObsolete = isMethodObsolete(method);
    229     (void)outStream_writeBoolean(out, isObsolete);
    230 
    231     return JNI_TRUE;
    232 }
    233 
    234 void *Method_Cmds[] = { (void *)0x5
    235     ,(void *)lineTable
    236     ,(void *)variableTable
    237     ,(void *)bytecodes
    238     ,(void *)isObsolete
    239     ,(void *)variableTableWithGenerics
    240 };
    241