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
length(PacketInputStream * in,PacketOutputStream * out)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 *
newComponents(PacketOutputStream * out,jint length,size_t nbytes)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
deleteComponents(void * ptr)64 deleteComponents(void *ptr)
65 {
66 jvmtiDeallocate(ptr);
67 }
68
69 static void
writeBooleanComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeByteComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeCharComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeShortComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeIntComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeLongComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeFloatComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeDoubleComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
writeObjectComponents(JNIEnv * env,PacketOutputStream * out,jarray array,jint index,jint length)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
getValues(PacketInputStream * in,PacketOutputStream * out)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
readBooleanComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readByteComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readCharComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readShortComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readIntComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readLongComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readFloatComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readDoubleComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
readObjectComponents(JNIEnv * env,PacketInputStream * in,jarray array,int index,int length)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
setValues(PacketInputStream * in,PacketOutputStream * out)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