• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
signature(PacketInputStream * in,PacketOutputStream * out)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
signatureWithGeneric(PacketInputStream * in,PacketOutputStream * out)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
getClassLoader(PacketInputStream * in,PacketOutputStream * out)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
modifiers(PacketInputStream * in,PacketOutputStream * out)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
writeMethodInfo(PacketOutputStream * out,jclass clazz,jmethodID method,int outputGenerics)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
methods1(PacketInputStream * in,PacketOutputStream * out,int outputGenerics)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
methods(PacketInputStream * in,PacketOutputStream * out,int outputGenerics)216 methods(PacketInputStream *in, PacketOutputStream *out,
217          int outputGenerics)
218 {
219     return methods1(in, out, 0);
220 }
221 
222 static jboolean
methodsWithGeneric(PacketInputStream * in,PacketOutputStream * out)223 methodsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
224 {
225     return methods1(in, out, 1);
226 }
227 
228 
229 
230 static jboolean
instances(PacketInputStream * in,PacketOutputStream * out)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
getClassVersion(PacketInputStream * in,PacketOutputStream * out)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
getConstantPool(PacketInputStream * in,PacketOutputStream * out)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
writeFieldInfo(PacketOutputStream * out,jclass clazz,jfieldID fieldID,int outputGenerics)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
fields1(PacketInputStream * in,PacketOutputStream * out,int outputGenerics)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
fields(PacketInputStream * in,PacketOutputStream * out)425 fields(PacketInputStream *in, PacketOutputStream *out)
426 {
427     return fields1(in, out, 0);
428 }
429 
430 static jboolean
fieldsWithGeneric(PacketInputStream * in,PacketOutputStream * out)431 fieldsWithGeneric(PacketInputStream *in, PacketOutputStream *out)
432 {
433     return fields1(in, out, 1);
434 
435 }
436 
437 static jboolean
getValues(PacketInputStream * in,PacketOutputStream * out)438 getValues(PacketInputStream *in, PacketOutputStream *out)
439 {
440     sharedGetFieldValues(in, out, JNI_TRUE);
441     return JNI_TRUE;
442 }
443 
444 static jboolean
sourceFile(PacketInputStream * in,PacketOutputStream * out)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
sourceDebugExtension(PacketInputStream * in,PacketOutputStream * out)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
nestedTypes(PacketInputStream * in,PacketOutputStream * out)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
getClassStatus(PacketInputStream * in,PacketOutputStream * out)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
interfaces(PacketInputStream * in,PacketOutputStream * out)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
classObject(PacketInputStream * in,PacketOutputStream * out)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