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 "ArrayReferenceImpl.h"
     28 #include "inStream.h"
     29 #include "outStream.h"
     30 
     31 static jboolean
     32 length(PacketInputStream *in, PacketOutputStream *out)
     33 {
     34     JNIEnv *env = getEnv();
     35     jsize arrayLength;
     36 
     37     jarray  array = inStream_readArrayRef(env, in);
     38     if (inStream_error(in)) {
     39         return JNI_TRUE;
     40     }
     41 
     42     arrayLength = JNI_FUNC_PTR(env,GetArrayLength)(env, array);
     43     (void)outStream_writeInt(out, arrayLength);
     44     return JNI_TRUE;
     45 }
     46 
     47 static void *
     48 newComponents(PacketOutputStream *out, jint length, size_t nbytes)
     49 {
     50     void *ptr = NULL;
     51 
     52     if ( length > 0 ) {
     53         ptr = jvmtiAllocate(length*((jint)nbytes));
     54         if ( ptr == NULL ) {
     55             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
     56         } else {
     57             (void)memset(ptr, 0, length*nbytes);
     58         }
     59     }
     60     return ptr;
     61 }
     62 
     63 static void
     64 deleteComponents(void *ptr)
     65 {
     66     jvmtiDeallocate(ptr);
     67 }
     68 
     69 static void
     70 writeBooleanComponents(JNIEnv *env, PacketOutputStream *out,
     71                     jarray array, jint index, jint length)
     72 {
     73     jboolean *components;
     74 
     75     components = newComponents(out, length, sizeof(jboolean));
     76     if (components != NULL) {
     77         jint i;
     78         JNI_FUNC_PTR(env,GetBooleanArrayRegion)(env, array, index, length, components);
     79         for (i = 0; i < length; i++) {
     80             (void)outStream_writeBoolean(out, components[i]);
     81         }
     82         deleteComponents(components);
     83     }
     84 }
     85 
     86 static void
     87 writeByteComponents(JNIEnv *env, PacketOutputStream *out,
     88                     jarray array, jint index, jint length)
     89 {
     90     jbyte *components;
     91 
     92     components = newComponents(out, length, sizeof(jbyte));
     93     if (components != NULL) {
     94         jint i;
     95         JNI_FUNC_PTR(env,GetByteArrayRegion)(env, array, index, length, components);
     96         for (i = 0; i < length; i++) {
     97             (void)outStream_writeByte(out, components[i]);
     98         }
     99         deleteComponents(components);
    100     }
    101 }
    102 
    103 static void
    104 writeCharComponents(JNIEnv *env, PacketOutputStream *out,
    105                     jarray array, jint index, jint length)
    106 {
    107     jchar *components;
    108 
    109     components = newComponents(out, length, sizeof(jchar));
    110     if (components != NULL) {
    111         jint i;
    112         JNI_FUNC_PTR(env,GetCharArrayRegion)(env, array, index, length, components);
    113         for (i = 0; i < length; i++) {
    114             (void)outStream_writeChar(out, components[i]);
    115         }
    116         deleteComponents(components);
    117     }
    118 }
    119 
    120 static void
    121 writeShortComponents(JNIEnv *env, PacketOutputStream *out,
    122                     jarray array, jint index, jint length)
    123 {
    124     jshort *components;
    125 
    126     components = newComponents(out, length, sizeof(jshort));
    127     if (components != NULL) {
    128         jint i;
    129         JNI_FUNC_PTR(env,GetShortArrayRegion)(env, array, index, length, components);
    130         for (i = 0; i < length; i++) {
    131             (void)outStream_writeShort(out, components[i]);
    132         }
    133         deleteComponents(components);
    134     }
    135 }
    136 
    137 static void
    138 writeIntComponents(JNIEnv *env, PacketOutputStream *out,
    139                     jarray array, jint index, jint length)
    140 {
    141     jint *components;
    142 
    143     components = newComponents(out, length, sizeof(jint));
    144     if (components != NULL) {
    145         jint i;
    146         JNI_FUNC_PTR(env,GetIntArrayRegion)(env, array, index, length, components);
    147         for (i = 0; i < length; i++) {
    148             (void)outStream_writeInt(out, components[i]);
    149         }
    150         deleteComponents(components);
    151     }
    152 }
    153 
    154 static void
    155 writeLongComponents(JNIEnv *env, PacketOutputStream *out,
    156                     jarray array, jint index, jint length)
    157 {
    158     jlong *components;
    159 
    160     components = newComponents(out, length, sizeof(jlong));
    161     if (components != NULL) {
    162         jint i;
    163         JNI_FUNC_PTR(env,GetLongArrayRegion)(env, array, index, length, components);
    164         for (i = 0; i < length; i++) {
    165             (void)outStream_writeLong(out, components[i]);
    166         }
    167         deleteComponents(components);
    168     }
    169 }
    170 
    171 static void
    172 writeFloatComponents(JNIEnv *env, PacketOutputStream *out,
    173                     jarray array, jint index, jint length)
    174 {
    175     jfloat *components;
    176 
    177     components = newComponents(out, length, sizeof(jfloat));
    178     if (components != NULL) {
    179         jint i;
    180         JNI_FUNC_PTR(env,GetFloatArrayRegion)(env, array, index, length, components);
    181         for (i = 0; i < length; i++) {
    182             (void)outStream_writeFloat(out, components[i]);
    183         }
    184         deleteComponents(components);
    185     }
    186 }
    187 
    188 static void
    189 writeDoubleComponents(JNIEnv *env, PacketOutputStream *out,
    190                     jarray array, jint index, jint length)
    191 {
    192     jdouble *components;
    193 
    194     components = newComponents(out, length, sizeof(jdouble));
    195     if (components != NULL) {
    196         jint i;
    197         JNI_FUNC_PTR(env,GetDoubleArrayRegion)(env, array, index, length, components);
    198         for (i = 0; i < length; i++) {
    199             (void)outStream_writeDouble(out, components[i]);
    200         }
    201         deleteComponents(components);
    202     }
    203 }
    204 
    205 static void
    206 writeObjectComponents(JNIEnv *env, PacketOutputStream *out,
    207                     jarray array, jint index, jint length)
    208 {
    209 
    210     WITH_LOCAL_REFS(env, length) {
    211 
    212         int i;
    213         jobject component;
    214 
    215         for (i = 0; i < length; i++) {
    216             component = JNI_FUNC_PTR(env,GetObjectArrayElement)(env, array, index + i);
    217             if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    218                 /* cleared by caller */
    219                 break;
    220             }
    221             (void)outStream_writeByte(out, specificTypeKey(env, component));
    222             (void)outStream_writeObjectRef(env, out, component);
    223         }
    224 
    225     } END_WITH_LOCAL_REFS(env);
    226 }
    227 
    228 static jboolean
    229 getValues(PacketInputStream *in, PacketOutputStream *out)
    230 {
    231     JNIEnv *env = getEnv();
    232     jint arrayLength;
    233     jarray array;
    234     jint index;
    235     jint length;
    236 
    237     array = inStream_readArrayRef(env, in);
    238     if (inStream_error(in)) {
    239         return JNI_TRUE;
    240     }
    241     index = inStream_readInt(in);
    242     if (inStream_error(in)) {
    243         return JNI_TRUE;
    244     }
    245     length = inStream_readInt(in);
    246     if (inStream_error(in)) {
    247         return JNI_TRUE;
    248     }
    249 
    250     arrayLength = JNI_FUNC_PTR(env,GetArrayLength)(env, array);
    251 
    252     if (length == -1) {
    253         length = arrayLength - index;
    254     }
    255 
    256     if ((index < 0) || (index > arrayLength - 1)) {
    257         outStream_setError(out, JDWP_ERROR(INVALID_INDEX));
    258         return JNI_TRUE;
    259     }
    260 
    261     if ((length < 0) || (length + index > arrayLength)) {
    262         outStream_setError(out, JDWP_ERROR(INVALID_LENGTH));
    263         return JNI_TRUE;
    264     }
    265 
    266     WITH_LOCAL_REFS(env, 1) {
    267 
    268         jclass arrayClass;
    269         char *signature = NULL;
    270         char *componentSignature;
    271         jbyte typeKey;
    272         jvmtiError error;
    273 
    274         arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
    275         error = classSignature(arrayClass, &signature, NULL);
    276         if (error != JVMTI_ERROR_NONE) {
    277             goto err;
    278         }
    279         componentSignature = &signature[1];
    280         typeKey = componentSignature[0];
    281 
    282         (void)outStream_writeByte(out, typeKey);
    283         (void)outStream_writeInt(out, length);
    284 
    285         if (isObjectTag(typeKey)) {
    286             writeObjectComponents(env, out, array, index, length);
    287         } else {
    288             switch (typeKey) {
    289                 case JDWP_TAG(BYTE):
    290                     writeByteComponents(env, out, array, index, length);
    291                     break;
    292 
    293                 case JDWP_TAG(CHAR):
    294                     writeCharComponents(env, out, array, index, length);
    295                     break;
    296 
    297                 case JDWP_TAG(FLOAT):
    298                     writeFloatComponents(env, out, array, index, length);
    299                     break;
    300 
    301                 case JDWP_TAG(DOUBLE):
    302                     writeDoubleComponents(env, out, array, index, length);
    303                     break;
    304 
    305                 case JDWP_TAG(INT):
    306                     writeIntComponents(env, out, array, index, length);
    307                     break;
    308 
    309                 case JDWP_TAG(LONG):
    310                     writeLongComponents(env, out, array, index, length);
    311                     break;
    312 
    313                 case JDWP_TAG(SHORT):
    314                     writeShortComponents(env, out, array, index, length);
    315                     break;
    316 
    317                 case JDWP_TAG(BOOLEAN):
    318                     writeBooleanComponents(env, out, array, index, length);
    319                     break;
    320 
    321                 default:
    322                     outStream_setError(out, JDWP_ERROR(INVALID_TAG));
    323                     break;
    324             }
    325         }
    326 
    327         jvmtiDeallocate(signature);
    328 
    329     err:;
    330 
    331     } END_WITH_LOCAL_REFS(env);
    332 
    333     if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    334         outStream_setError(out, JDWP_ERROR(INTERNAL));
    335         JNI_FUNC_PTR(env,ExceptionClear)(env);
    336     }
    337 
    338     return JNI_TRUE;
    339 }
    340 
    341 static jdwpError
    342 readBooleanComponents(JNIEnv *env, PacketInputStream *in,
    343                    jarray array, int index, int length)
    344 {
    345     int i;
    346     jboolean component;
    347 
    348     for (i = 0; (i < length) && !inStream_error(in); i++) {
    349         component = inStream_readBoolean(in);
    350         JNI_FUNC_PTR(env,SetBooleanArrayRegion)(env, array, index + i, 1, &component);
    351     }
    352     return inStream_error(in);
    353 }
    354 
    355 static jdwpError
    356 readByteComponents(JNIEnv *env, PacketInputStream *in,
    357                    jarray array, int index, int length)
    358 {
    359     int i;
    360     jbyte component;
    361 
    362     for (i = 0; (i < length) && !inStream_error(in); i++) {
    363         component = inStream_readByte(in);
    364         JNI_FUNC_PTR(env,SetByteArrayRegion)(env, array, index + i, 1, &component);
    365     }
    366     return inStream_error(in);
    367 }
    368 
    369 static jdwpError
    370 readCharComponents(JNIEnv *env, PacketInputStream *in,
    371                    jarray array, int index, int length)
    372 {
    373     int i;
    374     jchar component;
    375 
    376     for (i = 0; (i < length) && !inStream_error(in); i++) {
    377         component = inStream_readChar(in);
    378         JNI_FUNC_PTR(env,SetCharArrayRegion)(env, array, index + i, 1, &component);
    379     }
    380     return inStream_error(in);
    381 }
    382 
    383 static jdwpError
    384 readShortComponents(JNIEnv *env, PacketInputStream *in,
    385                    jarray array, int index, int length)
    386 {
    387     int i;
    388     jshort component;
    389 
    390     for (i = 0; (i < length) && !inStream_error(in); i++) {
    391         component = inStream_readShort(in);
    392         JNI_FUNC_PTR(env,SetShortArrayRegion)(env, array, index + i, 1, &component);
    393     }
    394     return inStream_error(in);
    395 }
    396 
    397 static jdwpError
    398 readIntComponents(JNIEnv *env, PacketInputStream *in,
    399                    jarray array, int index, int length)
    400 {
    401     int i;
    402     jint component;
    403 
    404     for (i = 0; (i < length) && !inStream_error(in); i++) {
    405         component = inStream_readInt(in);
    406         JNI_FUNC_PTR(env,SetIntArrayRegion)(env, array, index + i, 1, &component);
    407     }
    408     return inStream_error(in);
    409 }
    410 
    411 static jdwpError
    412 readLongComponents(JNIEnv *env, PacketInputStream *in,
    413                    jarray array, int index, int length)
    414 {
    415     int i;
    416     jlong component;
    417 
    418     for (i = 0; (i < length) && !inStream_error(in); i++) {
    419         component = inStream_readLong(in);
    420         JNI_FUNC_PTR(env,SetLongArrayRegion)(env, array, index + i, 1, &component);
    421     }
    422     return inStream_error(in);
    423 }
    424 
    425 static jdwpError
    426 readFloatComponents(JNIEnv *env, PacketInputStream *in,
    427                    jarray array, int index, int length)
    428 {
    429     int i;
    430     jfloat component;
    431 
    432     for (i = 0; (i < length) && !inStream_error(in); i++) {
    433         component = inStream_readFloat(in);
    434         JNI_FUNC_PTR(env,SetFloatArrayRegion)(env, array, index + i, 1, &component);
    435     }
    436     return inStream_error(in);
    437 }
    438 
    439 static jdwpError
    440 readDoubleComponents(JNIEnv *env, PacketInputStream *in,
    441                    jarray array, int index, int length)
    442 {
    443     int i;
    444     jdouble component;
    445 
    446     for (i = 0; (i < length) && !inStream_error(in); i++) {
    447         component = inStream_readDouble(in);
    448         JNI_FUNC_PTR(env,SetDoubleArrayRegion)(env, array, index + i, 1, &component);
    449     }
    450     return inStream_error(in);
    451 }
    452 
    453 
    454 static jdwpError
    455 readObjectComponents(JNIEnv *env, PacketInputStream *in,
    456                    jarray array, int index, int length)
    457                    /* char *componentSignature) */
    458 {
    459     int i;
    460 
    461     for (i = 0; i < length; i++) {
    462         jobject object = inStream_readObjectRef(env, in);
    463 
    464         JNI_FUNC_PTR(env,SetObjectArrayElement)(env, array, index + i, object);
    465         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    466             /* caller will clear */
    467             break;
    468         }
    469     }
    470 
    471     return JDWP_ERROR(NONE);
    472 }
    473 
    474 
    475 static jboolean
    476 setValues(PacketInputStream *in, PacketOutputStream *out)
    477 {
    478     JNIEnv *env = getEnv();
    479     jdwpError serror = JDWP_ERROR(NONE);
    480     int arrayLength;
    481     jarray array;
    482     jint index;
    483     jint length;
    484 
    485     array = inStream_readArrayRef(env, in);
    486     if (inStream_error(in)) {
    487         return JNI_TRUE;
    488     }
    489     index = inStream_readInt(in);
    490     if (inStream_error(in)) {
    491         return JNI_TRUE;
    492     }
    493     length = inStream_readInt(in);
    494     if (inStream_error(in)) {
    495         return JNI_TRUE;
    496     }
    497 
    498     arrayLength = JNI_FUNC_PTR(env,GetArrayLength)(env, array);
    499 
    500     if ((index < 0) || (index > arrayLength - 1)) {
    501         outStream_setError(out, JDWP_ERROR(INVALID_INDEX));
    502         return JNI_TRUE;
    503     }
    504 
    505     if ((length < 0) || (length + index > arrayLength)) {
    506         outStream_setError(out, JDWP_ERROR(INVALID_LENGTH));
    507         return JNI_TRUE;
    508     }
    509 
    510     WITH_LOCAL_REFS(env, 1)  {
    511 
    512         jclass arrayClass;
    513         char *signature = NULL;
    514         char *componentSignature;
    515         jvmtiError error;
    516 
    517         arrayClass = JNI_FUNC_PTR(env,GetObjectClass)(env, array);
    518         error = classSignature(arrayClass, &signature, NULL);
    519         if (error != JVMTI_ERROR_NONE) {
    520             goto err;
    521         }
    522         componentSignature = &signature[1];
    523 
    524         switch (componentSignature[0]) {
    525             case JDWP_TAG(OBJECT):
    526             case JDWP_TAG(ARRAY):
    527                 serror = readObjectComponents(env, in, array, index, length);
    528                 break;
    529 
    530             case JDWP_TAG(BYTE):
    531                 serror = readByteComponents(env, in, array, index, length);
    532                 break;
    533 
    534             case JDWP_TAG(CHAR):
    535                 serror = readCharComponents(env, in, array, index, length);
    536                 break;
    537 
    538             case JDWP_TAG(FLOAT):
    539                 serror = readFloatComponents(env, in, array, index, length);
    540                 break;
    541 
    542             case JDWP_TAG(DOUBLE):
    543                 serror = readDoubleComponents(env, in, array, index, length);
    544                 break;
    545 
    546             case JDWP_TAG(INT):
    547                 serror = readIntComponents(env, in, array, index, length);
    548                 break;
    549 
    550             case JDWP_TAG(LONG):
    551                 serror = readLongComponents(env, in, array, index, length);
    552                 break;
    553 
    554             case JDWP_TAG(SHORT):
    555                 serror = readShortComponents(env, in, array, index, length);
    556                 break;
    557 
    558             case JDWP_TAG(BOOLEAN):
    559                 serror = readBooleanComponents(env, in, array, index, length);
    560                 break;
    561 
    562             default:
    563                 {
    564                     ERROR_MESSAGE(("Invalid array component signature: %s",
    565                                         componentSignature));
    566                     EXIT_ERROR(AGENT_ERROR_INVALID_OBJECT,NULL);
    567                 }
    568                 break;
    569         }
    570 
    571         jvmtiDeallocate(signature);
    572 
    573     err:;
    574 
    575     } END_WITH_LOCAL_REFS(env);
    576 
    577     if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
    578         /*
    579          * TO DO: Check exception type
    580          */
    581         serror = JDWP_ERROR(TYPE_MISMATCH);
    582         JNI_FUNC_PTR(env,ExceptionClear)(env);
    583     }
    584 
    585     outStream_setError(out, serror);
    586     return JNI_TRUE;
    587 }
    588 
    589 
    590 void *ArrayReference_Cmds[] = { (void *)0x3
    591     ,(void *)length
    592     ,(void *)getValues
    593     ,(void *)setValues};
    594