blob: cb8d1f35ad96fc20e917a05cbb26167e04804fba [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "util.h"
27#include "ReferenceTypeImpl.h"
28#include "inStream.h"
29#include "outStream.h"
30
31
32static jboolean
33signature(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
56static jboolean
57signatureWithGeneric(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
86static jboolean
87getClassLoader(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
111static jboolean
112modifiers(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
135static void
136writeMethodInfo(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
181static jboolean
182methods1(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
215static jboolean
216methods(PacketInputStream *in, PacketOutputStream *out,
217 int outputGenerics)
218{
219 return methods1(in, out, 0);
220}
221
222static jboolean
223methodsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
224{
225 return methods1(in, out, 1);
226}
227
228
229
230static jboolean
231instances(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
283static jboolean
284getClassVersion(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
309static jboolean
310getConstantPool(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
345static void
346writeFieldInfo(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
390static jboolean
391fields1(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
424static jboolean
425fields(PacketInputStream *in, PacketOutputStream *out)
426{
427 return fields1(in, out, 0);
428}
429
430static jboolean
431fieldsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
432{
433 return fields1(in, out, 1);
434
435}
436
437static jboolean
438getValues(PacketInputStream *in, PacketOutputStream *out)
439{
440 sharedGetFieldValues(in, out, JNI_TRUE);
441 return JNI_TRUE;
442}
443
444static jboolean
445sourceFile(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
468static jboolean
469sourceDebugExtension(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
491static jboolean
492nestedTypes(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
530static jboolean
531getClassStatus(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
546static jboolean
547interfaces(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
585static jboolean
586classObject(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
608void *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};