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 "ReferenceTypeImpl.h"
     28 #include "inStream.h"
     29 #include "outStream.h"
     30 
     31 
     32 static jboolean
     33 signature(PacketInputStream *in, PacketOutputStream *out)
     34 {
     35     char *signature = NULL;
     36     jclass clazz;
     37     jvmtiError error;
     38 
     39     clazz = inStream_readClassRef(getEnv(), in);
     40     if (inStream_error(in)) {
     41         return JNI_TRUE;
     42     }
     43 
     44     error = classSignature(clazz, &signature, NULL);
     45     if (error != JVMTI_ERROR_NONE) {
     46         outStream_setError(out, map2jdwpError(error));
     47         return JNI_TRUE;
     48     }
     49 
     50     (void)outStream_writeString(out, signature);
     51     jvmtiDeallocate(signature);
     52 
     53     return JNI_TRUE;
     54 }
     55 
     56 static jboolean
     57 signatureWithGeneric(PacketInputStream *in, PacketOutputStream *out)
     58 {
     59   /* Returns both the signature and the generic signature */
     60     char *signature = NULL;
     61     char *genericSignature = NULL;
     62     jclass clazz;
     63     jvmtiError error;
     64 
     65     clazz = inStream_readClassRef(getEnv(), in);
     66     if (inStream_error(in)) {
     67         return JNI_TRUE;
     68     }
     69     error = classSignature(clazz, &signature, &genericSignature);
     70     if (error != JVMTI_ERROR_NONE) {
     71         outStream_setError(out, map2jdwpError(error));
     72         return JNI_TRUE;
     73     }
     74 
     75     (void)outStream_writeString(out, signature);
     76     writeGenericSignature(out, genericSignature);
     77     jvmtiDeallocate(signature);
     78     if (genericSignature != NULL) {
     79       jvmtiDeallocate(genericSignature);
     80     }
     81 
     82 
     83     return JNI_TRUE;
     84 }
     85 
     86 static jboolean
     87 getClassLoader(PacketInputStream *in, PacketOutputStream *out)
     88 {
     89     jclass clazz;
     90     jobject loader;
     91     jvmtiError error;
     92     JNIEnv *env;
     93 
     94     env = getEnv();
     95 
     96     clazz = inStream_readClassRef(env, in);
     97     if (inStream_error(in)) {
     98         return JNI_TRUE;
     99     }
    100 
    101     error = classLoader(clazz, &loader);
    102     if (error != JVMTI_ERROR_NONE) {
    103         outStream_setError(out, map2jdwpError(error));
    104         return JNI_TRUE;
    105     }
    106 
    107     (void)outStream_writeObjectRef(env, out, loader);
    108     return JNI_TRUE;
    109 }
    110 
    111 static jboolean
    112 modifiers(PacketInputStream *in, PacketOutputStream *out)
    113 {
    114     jint modifiers;
    115     jclass clazz;
    116     jvmtiError error;
    117 
    118     clazz = inStream_readClassRef(getEnv(), in);
    119     if (inStream_error(in)) {
    120         return JNI_TRUE;
    121     }
    122 
    123     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassModifiers)
    124                 (gdata->jvmti, clazz, &modifiers);
    125     if (error != JVMTI_ERROR_NONE) {
    126         outStream_setError(out, map2jdwpError(error));
    127         return JNI_TRUE;
    128     }
    129 
    130     (void)outStream_writeInt(out, modifiers);
    131 
    132     return JNI_TRUE;
    133 }
    134 
    135 static void
    136 writeMethodInfo(PacketOutputStream *out, jclass clazz, jmethodID method,
    137                 int outputGenerics)
    138 {
    139     char *name = NULL;
    140     char *signature = NULL;
    141     char *genericSignature = NULL;
    142     jint modifiers;
    143     jvmtiError error;
    144     jboolean isSynthetic;
    145 
    146     error = isMethodSynthetic(method, &isSynthetic);
    147     if (error != JVMTI_ERROR_NONE) {
    148         outStream_setError(out, map2jdwpError(error));
    149         return;
    150     }
    151 
    152     error = methodModifiers(method, &modifiers);
    153     if (error != JVMTI_ERROR_NONE) {
    154         outStream_setError(out, map2jdwpError(error));
    155         return;
    156     }
    157 
    158     error = methodSignature(method, &name, &signature, &genericSignature);
    159     if (error != JVMTI_ERROR_NONE) {
    160         outStream_setError(out, map2jdwpError(error));
    161         return;
    162     }
    163 
    164     if (isSynthetic) {
    165         modifiers |= MOD_SYNTHETIC;
    166     }
    167     (void)outStream_writeMethodID(out, method);
    168     (void)outStream_writeString(out, name);
    169     (void)outStream_writeString(out, signature);
    170     if (outputGenerics == 1) {
    171         writeGenericSignature(out, genericSignature);
    172     }
    173     (void)outStream_writeInt(out, modifiers);
    174     jvmtiDeallocate(name);
    175     jvmtiDeallocate(signature);
    176     if (genericSignature != NULL) {
    177       jvmtiDeallocate(genericSignature);
    178     }
    179 }
    180 
    181 static jboolean
    182 methods1(PacketInputStream *in, PacketOutputStream *out,
    183          int outputGenerics)
    184 {
    185     int i;
    186     jclass clazz;
    187     jint methodCount = 0;
    188     jmethodID *methods = NULL;
    189     jvmtiError error;
    190 
    191     clazz = inStream_readClassRef(getEnv(), in);
    192     if (inStream_error(in)) {
    193         return JNI_TRUE;
    194     }
    195 
    196     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassMethods)
    197                 (gdata->jvmti, clazz, &methodCount, &methods);
    198     if (error != JVMTI_ERROR_NONE) {
    199         outStream_setError(out, map2jdwpError(error));
    200         return JNI_TRUE;
    201     }
    202 
    203     (void)outStream_writeInt(out, methodCount);
    204     for (i = 0; (i < methodCount) && !outStream_error(out); i++) {
    205         writeMethodInfo(out, clazz, methods[i], outputGenerics);
    206     }
    207 
    208     /* Free methods array */
    209     if ( methods != NULL ) {
    210         jvmtiDeallocate(methods);
    211     }
    212     return JNI_TRUE;
    213 }
    214 
    215 static jboolean
    216 methods(PacketInputStream *in, PacketOutputStream *out,
    217          int outputGenerics)
    218 {
    219     return methods1(in, out, 0);
    220 }
    221 
    222 static jboolean
    223 methodsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
    224 {
    225     return methods1(in, out, 1);
    226 }
    227 
    228 
    229 
    230 static jboolean
    231 instances(PacketInputStream *in, PacketOutputStream *out)
    232 {
    233     jint maxInstances;
    234     jclass clazz;
    235     JNIEnv *env;
    236 
    237     if (gdata->vmDead) {
    238         outStream_setError(out, JDWP_ERROR(VM_DEAD));
    239         return JNI_TRUE;
    240     }
    241 
    242     env = getEnv();
    243     clazz = inStream_readClassRef(env, in);
    244     maxInstances = inStream_readInt(in);
    245     if (inStream_error(in)) {
    246         return JNI_TRUE;
    247     }
    248 
    249     WITH_LOCAL_REFS(env, 1) {
    250         jvmtiError   error;
    251         ObjectBatch  batch;
    252 
    253         error = classInstances(clazz, &batch, maxInstances);
    254         if (error != JVMTI_ERROR_NONE) {
    255             outStream_setError(out, map2jdwpError(error));
    256         } else {
    257             int kk;
    258             jbyte typeKey;
    259 
    260             (void)outStream_writeInt(out, batch.count);
    261             if (batch.count > 0) {
    262                 /*
    263                  * They are all instances of this class and will all have
    264                  * the same typeKey, so just compute it once.
    265                  */
    266                 typeKey = specificTypeKey(env, batch.objects[0]);
    267 
    268                 for (kk = 0; kk < batch.count; kk++) {
    269                   jobject inst;
    270 
    271                   inst = batch.objects[kk];
    272                   (void)outStream_writeByte(out, typeKey);
    273                   (void)outStream_writeObjectRef(env, out, inst);
    274                 }
    275             }
    276             jvmtiDeallocate(batch.objects);
    277         }
    278     } END_WITH_LOCAL_REFS(env);
    279 
    280     return JNI_TRUE;
    281 }
    282 
    283 static jboolean
    284 getClassVersion(PacketInputStream *in, PacketOutputStream *out)
    285 {
    286     jclass clazz;
    287     jvmtiError error;
    288     jint majorVersion;
    289     jint minorVersion;
    290 
    291     clazz = inStream_readClassRef(getEnv(), in);
    292     if (inStream_error(in)) {
    293         return JNI_TRUE;
    294     }
    295 
    296     error = JVMTI_FUNC_PTR(gdata->jvmti, GetClassVersionNumbers)
    297                 (gdata->jvmti, clazz, &minorVersion, &majorVersion);
    298     if (error != JVMTI_ERROR_NONE) {
    299         outStream_setError(out, map2jdwpError(error));
    300         return JNI_TRUE;
    301     }
    302 
    303     (void)outStream_writeInt(out, majorVersion);
    304     (void)outStream_writeInt(out, minorVersion);
    305 
    306     return JNI_TRUE;
    307 }
    308 
    309 static jboolean
    310 getConstantPool(PacketInputStream *in, PacketOutputStream *out)
    311 {
    312 
    313     jclass clazz;
    314     jvmtiError error;
    315     jint cpCount;
    316     jint cpByteCount;
    317     unsigned char* cpBytesPtr;
    318 
    319 
    320     clazz = inStream_readClassRef(getEnv(), in);
    321     if (inStream_error(in)) {
    322         return JNI_TRUE;
    323     }
    324 
    325     /* Initialize assuming no bytecodes and no error */
    326     error         = JVMTI_ERROR_NONE;
    327     cpCount       = 0;
    328     cpByteCount   = 0;
    329     cpBytesPtr    = NULL;
    330 
    331 
    332     error = JVMTI_FUNC_PTR(gdata->jvmti,GetConstantPool)
    333                 (gdata->jvmti, clazz, &cpCount, &cpByteCount, &cpBytesPtr);
    334     if (error != JVMTI_ERROR_NONE) {
    335         outStream_setError(out, map2jdwpError(error));
    336     } else {
    337         (void)outStream_writeInt(out, cpCount);
    338         (void)outStream_writeByteArray(out, cpByteCount, (jbyte *)cpBytesPtr);
    339         jvmtiDeallocate(cpBytesPtr);
    340     }
    341 
    342     return JNI_TRUE;
    343 }
    344 
    345 static void
    346 writeFieldInfo(PacketOutputStream *out, jclass clazz, jfieldID fieldID,
    347                int outputGenerics)
    348 {
    349     char *name;
    350     char *signature = NULL;
    351     char *genericSignature = NULL;
    352     jint modifiers;
    353     jboolean isSynthetic;
    354     jvmtiError error;
    355 
    356     error = isFieldSynthetic(clazz, fieldID, &isSynthetic);
    357     if (error != JVMTI_ERROR_NONE) {
    358         outStream_setError(out, map2jdwpError(error));
    359         return;
    360     }
    361 
    362     error = fieldModifiers(clazz, fieldID, &modifiers);
    363     if (error != JVMTI_ERROR_NONE) {
    364         outStream_setError(out, map2jdwpError(error));
    365         return;
    366     }
    367 
    368     error = fieldSignature(clazz, fieldID, &name, &signature, &genericSignature);
    369     if (error != JVMTI_ERROR_NONE) {
    370         outStream_setError(out, map2jdwpError(error));
    371         return;
    372     }
    373     if (isSynthetic) {
    374         modifiers |= MOD_SYNTHETIC;
    375     }
    376     (void)outStream_writeFieldID(out, fieldID);
    377     (void)outStream_writeString(out, name);
    378     (void)outStream_writeString(out, signature);
    379     if (outputGenerics == 1) {
    380         writeGenericSignature(out, genericSignature);
    381     }
    382     (void)outStream_writeInt(out, modifiers);
    383     jvmtiDeallocate(name);
    384     jvmtiDeallocate(signature);
    385     if (genericSignature != NULL) {
    386       jvmtiDeallocate(genericSignature);
    387     }
    388 }
    389 
    390 static jboolean
    391 fields1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics)
    392 {
    393     int i;
    394     jclass clazz;
    395     jint fieldCount = 0;
    396     jfieldID *fields = NULL;
    397     jvmtiError error;
    398 
    399     clazz = inStream_readClassRef(getEnv(), in);
    400     if (inStream_error(in)) {
    401         return JNI_TRUE;
    402     }
    403 
    404     error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassFields)
    405                 (gdata->jvmti, clazz, &fieldCount, &fields);
    406     if (error != JVMTI_ERROR_NONE) {
    407         outStream_setError(out, map2jdwpError(error));
    408         return JNI_TRUE;
    409     }
    410 
    411     (void)outStream_writeInt(out, fieldCount);
    412     for (i = 0; (i < fieldCount) && !outStream_error(out); i++) {
    413         writeFieldInfo(out, clazz, fields[i], outputGenerics);
    414     }
    415 
    416     /* Free fields array */
    417     if ( fields != NULL ) {
    418         jvmtiDeallocate(fields);
    419     }
    420     return JNI_TRUE;
    421 }
    422 
    423 
    424 static jboolean
    425 fields(PacketInputStream *in, PacketOutputStream *out)
    426 {
    427     return fields1(in, out, 0);
    428 }
    429 
    430 static jboolean
    431 fieldsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
    432 {
    433     return fields1(in, out, 1);
    434 
    435 }
    436 
    437 static jboolean
    438 getValues(PacketInputStream *in, PacketOutputStream *out)
    439 {
    440     sharedGetFieldValues(in, out, JNI_TRUE);
    441     return JNI_TRUE;
    442 }
    443 
    444 static jboolean
    445 sourceFile(PacketInputStream *in, PacketOutputStream *out)
    446 {
    447     char *fileName;
    448     jvmtiError error;
    449     jclass clazz;
    450 
    451     clazz = inStream_readClassRef(getEnv(), in);
    452     if (inStream_error(in)) {
    453         return JNI_TRUE;
    454     }
    455 
    456     error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
    457                 (gdata->jvmti, clazz, &fileName);
    458     if (error != JVMTI_ERROR_NONE) {
    459         outStream_setError(out, map2jdwpError(error));
    460         return JNI_TRUE;
    461     }
    462 
    463     (void)outStream_writeString(out, fileName);
    464     jvmtiDeallocate(fileName);
    465     return JNI_TRUE;
    466 }
    467 
    468 static jboolean
    469 sourceDebugExtension(PacketInputStream *in, PacketOutputStream *out)
    470 {
    471     char *extension;
    472     jvmtiError error;
    473     jclass clazz;
    474 
    475     clazz = inStream_readClassRef(getEnv(), in);
    476     if (inStream_error(in)) {
    477         return JNI_TRUE;
    478     }
    479 
    480     error = getSourceDebugExtension(clazz, &extension);
    481     if (error != JVMTI_ERROR_NONE) {
    482         outStream_setError(out, map2jdwpError(error));
    483         return JNI_TRUE;
    484     }
    485 
    486     (void)outStream_writeString(out, extension);
    487     jvmtiDeallocate(extension);
    488     return JNI_TRUE;
    489 }
    490 
    491 static jboolean
    492 nestedTypes(PacketInputStream *in, PacketOutputStream *out)
    493 {
    494     JNIEnv *env;
    495     jclass clazz;
    496 
    497     env = getEnv();
    498 
    499     clazz = inStream_readClassRef(env, in);
    500     if (inStream_error(in)) {
    501         return JNI_TRUE;
    502     }
    503 
    504     WITH_LOCAL_REFS(env, 1) {
    505 
    506         jvmtiError error;
    507         jint count;
    508         jclass *nested;
    509 
    510         error = allNestedClasses(clazz, &nested, &count);
    511         if (error != JVMTI_ERROR_NONE) {
    512             outStream_setError(out, map2jdwpError(error));
    513         } else {
    514             int i;
    515             (void)outStream_writeInt(out, count);
    516             for (i = 0; i < count; i++) {
    517                 (void)outStream_writeByte(out, referenceTypeTag(nested[i]));
    518                 (void)outStream_writeObjectRef(env, out, nested[i]);
    519             }
    520             if ( nested != NULL ) {
    521                 jvmtiDeallocate(nested);
    522             }
    523         }
    524 
    525     } END_WITH_LOCAL_REFS(env);
    526 
    527     return JNI_TRUE;
    528 }
    529 
    530 static jboolean
    531 getClassStatus(PacketInputStream *in, PacketOutputStream *out)
    532 {
    533     jint status;
    534     jclass clazz;
    535 
    536     clazz = inStream_readClassRef(getEnv(), in);
    537     if (inStream_error(in)) {
    538         return JNI_TRUE;
    539     }
    540 
    541     status = classStatus(clazz);
    542     (void)outStream_writeInt(out, map2jdwpClassStatus(status));
    543     return JNI_TRUE;
    544 }
    545 
    546 static jboolean
    547 interfaces(PacketInputStream *in, PacketOutputStream *out)
    548 {
    549     JNIEnv *env;
    550     jclass clazz;
    551 
    552     env = getEnv();
    553 
    554     clazz = inStream_readClassRef(env, in);
    555     if (inStream_error(in)) {
    556         return JNI_TRUE;
    557     }
    558 
    559     WITH_LOCAL_REFS(env, 1) {
    560 
    561         jvmtiError error;
    562         jint interfaceCount;
    563         jclass *interfaces;
    564 
    565         error = allInterfaces(clazz, &interfaces, &interfaceCount);
    566         if (error != JVMTI_ERROR_NONE) {
    567             outStream_setError(out, map2jdwpError(error));
    568         } else {
    569             int i;
    570 
    571             (void)outStream_writeInt(out, interfaceCount);
    572             for (i = 0; i < interfaceCount; i++) {
    573                 (void)outStream_writeObjectRef(env, out, interfaces[i]);
    574             }
    575             if ( interfaces != NULL ) {
    576                 jvmtiDeallocate(interfaces);
    577             }
    578         }
    579 
    580     } END_WITH_LOCAL_REFS(env);
    581 
    582     return JNI_TRUE;
    583 }
    584 
    585 static jboolean
    586 classObject(PacketInputStream *in, PacketOutputStream *out)
    587 {
    588     jclass clazz;
    589     JNIEnv *env;
    590 
    591     env = getEnv();
    592     clazz = inStream_readClassRef(env, in);
    593     if (inStream_error(in)) {
    594         return JNI_TRUE;
    595     }
    596 
    597     /*
    598      * In our implementation, the reference type id is the same as the
    599      * class object id, so we bounce it right back.
    600      *
    601      */
    602 
    603     (void)outStream_writeObjectRef(env, out, clazz);
    604 
    605     return JNI_TRUE;
    606 }
    607 
    608 void *ReferenceType_Cmds[] = { (void *)18
    609     ,(void *)signature
    610     ,(void *)getClassLoader
    611     ,(void *)modifiers
    612     ,(void *)fields
    613     ,(void *)methods
    614     ,(void *)getValues
    615     ,(void *)sourceFile
    616     ,(void *)nestedTypes
    617     ,(void *)getClassStatus
    618     ,(void *)interfaces
    619     ,(void *)classObject
    620     ,(void *)sourceDebugExtension
    621     ,(void *)signatureWithGeneric
    622     ,(void *)fieldsWithGeneric
    623     ,(void *)methodsWithGeneric
    624     ,(void *)instances
    625     ,(void *)getClassVersion
    626     ,(void *)getConstantPool
    627 };
    628