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 "ArrayTypeImpl.h"
27 #include "util.h"
28 #include "inStream.h"
29 #include "outStream.h"
30 
31 /*
32  * Determine the component class by looking thru all classes for
33  * one that has the signature of the component and the same class loadeer
34  * as the array.  See JVM spec 5.3.3:
35  *     If the component type is a reference type, C is marked as having
36  *     been defined by the defining class loader of the component type.
37  */
38 static jdwpError
getComponentClass(JNIEnv * env,jclass arrayClass,char * componentSignature,jclass * componentClassPtr)39 getComponentClass(JNIEnv *env, jclass arrayClass, char *componentSignature,
40                 jclass *componentClassPtr)
41 {
42     jobject arrayClassLoader;
43     jclass *classes;
44     jint count;
45     jclass componentClass = NULL;
46     jdwpError serror;
47     jvmtiError error;
48 
49     serror = JDWP_ERROR(NONE);
50 
51     error = classLoader(arrayClass, &arrayClassLoader);
52     if (error != JVMTI_ERROR_NONE) {
53         return map2jdwpError(error);
54     }
55 
56     error = allLoadedClasses(&classes, &count);
57     if (error != JVMTI_ERROR_NONE) {
58         serror = map2jdwpError(error);
59     } else {
60         int i;
61         for (i = 0; (i < count) && (componentClass == NULL); i++) {
62             char *signature = NULL;
63             jclass clazz = classes[i];
64             jboolean match;
65             jvmtiError error;
66 
67             /* signature must match */
68             error = classSignature(clazz, &signature, NULL);
69             if (error != JVMTI_ERROR_NONE) {
70                 serror = map2jdwpError(error);
71                 break;
72             }
73             match = strcmp(signature, componentSignature) == 0;
74             jvmtiDeallocate(signature);
75 
76             /* if signature matches, get class loader to check if
77              * it matches
78              */
79             if (match) {
80                 jobject loader;
81                 error = classLoader(clazz, &loader);
82                 if (error != JVMTI_ERROR_NONE) {
83                     return map2jdwpError(error);
84                 }
85                 match = isSameObject(env, loader, arrayClassLoader);
86             }
87 
88             if (match) {
89                 componentClass = clazz;
90             }
91         }
92         jvmtiDeallocate(classes);
93 
94         *componentClassPtr = componentClass;
95     }
96 
97     if (serror == JDWP_ERROR(NONE) && componentClass == NULL) {
98         /* per JVM spec, component class is always loaded
99          * before array class, so this should never occur.
100          */
101         serror = JDWP_ERROR(NOT_FOUND);
102     }
103 
104     return serror;
105 }
106 
107 static void
writeNewObjectArray(JNIEnv * env,PacketOutputStream * out,jclass arrayClass,jint size,char * componentSignature)108 writeNewObjectArray(JNIEnv *env, PacketOutputStream *out,
109                  jclass arrayClass, jint size, char *componentSignature)
110 {
111 
112     WITH_LOCAL_REFS(env, 1) {
113 
114         jarray array;
115         jclass componentClass = NULL;
116         jdwpError serror;
117 
118         serror = getComponentClass(env, arrayClass,
119                                        componentSignature, &componentClass);
120         if (serror != JDWP_ERROR(NONE)) {
121             outStream_setError(out, serror);
122         } else {
123 
124             array = JNI_FUNC_PTR(env,NewObjectArray)(env, size, componentClass, 0);
125             if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
126                 JNI_FUNC_PTR(env,ExceptionClear)(env);
127                 array = NULL;
128             }
129 
130             if (array == NULL) {
131                 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
132             } else {
133                 (void)outStream_writeByte(out, specificTypeKey(env, array));
134                 (void)outStream_writeObjectRef(env, out, array);
135             }
136 
137         }
138 
139     } END_WITH_LOCAL_REFS(env);
140 }
141 
142 static void
writeNewPrimitiveArray(JNIEnv * env,PacketOutputStream * out,jclass arrayClass,jint size,char * componentSignature)143 writeNewPrimitiveArray(JNIEnv *env, PacketOutputStream *out,
144                        jclass arrayClass, jint size, char *componentSignature)
145 {
146 
147     WITH_LOCAL_REFS(env, 1) {
148 
149         jarray array = NULL;
150 
151         switch (componentSignature[0]) {
152             case JDWP_TAG(BYTE):
153                 array = JNI_FUNC_PTR(env,NewByteArray)(env, size);
154                 break;
155 
156             case JDWP_TAG(CHAR):
157                 array = JNI_FUNC_PTR(env,NewCharArray)(env, size);
158                 break;
159 
160             case JDWP_TAG(FLOAT):
161                 array = JNI_FUNC_PTR(env,NewFloatArray)(env, size);
162                 break;
163 
164             case JDWP_TAG(DOUBLE):
165                 array = JNI_FUNC_PTR(env,NewDoubleArray)(env, size);
166                 break;
167 
168             case JDWP_TAG(INT):
169                 array = JNI_FUNC_PTR(env,NewIntArray)(env, size);
170                 break;
171 
172             case JDWP_TAG(LONG):
173                 array = JNI_FUNC_PTR(env,NewLongArray)(env, size);
174                 break;
175 
176             case JDWP_TAG(SHORT):
177                 array = JNI_FUNC_PTR(env,NewShortArray)(env, size);
178                 break;
179 
180             case JDWP_TAG(BOOLEAN):
181                 array = JNI_FUNC_PTR(env,NewBooleanArray)(env, size);
182                 break;
183 
184             default:
185                 outStream_setError(out, JDWP_ERROR(TYPE_MISMATCH));
186                 break;
187         }
188 
189         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
190             JNI_FUNC_PTR(env,ExceptionClear)(env);
191             array = NULL;
192         }
193 
194         if (array == NULL) {
195             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
196         } else {
197             (void)outStream_writeByte(out, specificTypeKey(env, array));
198             (void)outStream_writeObjectRef(env, out, array);
199         }
200 
201     } END_WITH_LOCAL_REFS(env);
202 }
203 
204 static jboolean
newInstance(PacketInputStream * in,PacketOutputStream * out)205 newInstance(PacketInputStream *in, PacketOutputStream *out)
206 {
207     JNIEnv *env;
208     char *signature = NULL;
209     char *componentSignature;
210     jclass arrayClass;
211     jint size;
212     jvmtiError error;
213 
214     env = getEnv();
215 
216     arrayClass = inStream_readClassRef(env, in);
217     if (inStream_error(in)) {
218         return JNI_TRUE;
219     }
220     size = inStream_readInt(in);
221     if (inStream_error(in)) {
222         return JNI_TRUE;
223     }
224 
225     error = classSignature(arrayClass, &signature, NULL);
226     if ( error != JVMTI_ERROR_NONE ) {
227         outStream_setError(out, map2jdwpError(error));
228         return JNI_FALSE;
229     }
230     componentSignature = &signature[1];
231 
232     if ((componentSignature[0] == JDWP_TAG(OBJECT)) ||
233         (componentSignature[0] == JDWP_TAG(ARRAY))) {
234         writeNewObjectArray(env, out, arrayClass, size, componentSignature);
235     } else {
236         writeNewPrimitiveArray(env, out, arrayClass, size, componentSignature);
237     }
238 
239     jvmtiDeallocate(signature);
240     return JNI_TRUE;
241 }
242 
243 void *ArrayType_Cmds[] = { (void *)0x1
244                           ,(void *)newInstance};
245