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