• 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 "StackFrameImpl.h"
28 #include "inStream.h"
29 #include "outStream.h"
30 #include "threadControl.h"
31 #include "FrameID.h"
32 
33 static jdwpError
validateThreadFrame(jthread thread,FrameID frame)34 validateThreadFrame(jthread thread, FrameID frame)
35 {
36     jvmtiError error;
37     jdwpError  serror;
38     jint count;
39     error = threadControl_suspendCount(thread, &count);
40     if ( error == JVMTI_ERROR_NONE ) {
41         if ( count > 0 ) {
42             serror = validateFrameID(thread, frame);
43         } else {
44             serror = JDWP_ERROR(THREAD_NOT_SUSPENDED);
45         }
46     } else {
47         serror =  map2jdwpError(error);
48     }
49     return serror;
50 }
51 
52 static jdwpError
writeVariableValue(JNIEnv * env,PacketOutputStream * out,jthread thread,FrameNumber fnum,jint slot,jbyte typeKey)53 writeVariableValue(JNIEnv *env, PacketOutputStream *out, jthread thread,
54                    FrameNumber fnum, jint slot, jbyte typeKey)
55 {
56     jvmtiError error;
57     jvalue value;
58 
59     if (isObjectTag(typeKey)) {
60 
61         WITH_LOCAL_REFS(env, 1) {
62 
63             error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
64                         (gdata->jvmti, thread, fnum, slot, &value.l);
65 
66             if (error != JVMTI_ERROR_NONE) {
67                 outStream_setError(out, map2jdwpError(error));
68             } else {
69                 (void)outStream_writeByte(out, specificTypeKey(env, value.l));
70                 (void)outStream_writeObjectRef(env, out, value.l);
71             }
72 
73         } END_WITH_LOCAL_REFS(env);
74 
75     } else {
76         /*
77          * For primitive types, the type key is bounced back as is.
78          */
79         (void)outStream_writeByte(out, typeKey);
80         switch (typeKey) {
81             case JDWP_TAG(BYTE): {
82                     jint intValue;
83                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
84                                 (gdata->jvmti, thread, fnum, slot, &intValue);
85                     (void)outStream_writeByte(out, (jbyte)intValue);
86                     break;
87                 }
88 
89             case JDWP_TAG(CHAR): {
90                     jint intValue;
91                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
92                                 (gdata->jvmti, thread, fnum, slot, &intValue);
93                     (void)outStream_writeChar(out, (jchar)intValue);
94                     break;
95                 }
96 
97             case JDWP_TAG(FLOAT):
98                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalFloat)
99                                 (gdata->jvmti, thread, fnum, slot, &value.f);
100                 (void)outStream_writeFloat(out, value.f);
101                 break;
102 
103             case JDWP_TAG(DOUBLE):
104                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalDouble)
105                                 (gdata->jvmti, thread, fnum, slot, &value.d);
106                 (void)outStream_writeDouble(out, value.d);
107                 break;
108 
109             case JDWP_TAG(INT):
110                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
111                                 (gdata->jvmti, thread, fnum, slot, &value.i);
112                 (void)outStream_writeInt(out, value.i);
113                 break;
114 
115             case JDWP_TAG(LONG):
116                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalLong)
117                                 (gdata->jvmti, thread, fnum, slot, &value.j);
118                 (void)outStream_writeLong(out, value.j);
119                 break;
120 
121             case JDWP_TAG(SHORT): {
122                 jint intValue;
123                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
124                                 (gdata->jvmti, thread, fnum, slot, &intValue);
125                 (void)outStream_writeShort(out, (jshort)intValue);
126                 break;
127             }
128 
129             case JDWP_TAG(BOOLEAN):{
130                 jint intValue;
131                 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInt)
132                                 (gdata->jvmti, thread, fnum, slot, &intValue);
133                 (void)outStream_writeBoolean(out, (jboolean)intValue);
134                 break;
135             }
136 
137             default:
138                 return JDWP_ERROR(INVALID_TAG);
139         }
140     }
141 
142     return map2jdwpError(error);
143 }
144 
145 static jdwpError
readVariableValue(JNIEnv * env,PacketInputStream * in,jthread thread,FrameNumber fnum,jint slot,jbyte typeKey)146 readVariableValue(JNIEnv *env, PacketInputStream *in, jthread thread,
147                   FrameNumber fnum, jint slot, jbyte typeKey)
148 {
149     jvmtiError error;
150     jvalue value;
151 
152     if (isObjectTag(typeKey)) {
153 
154         value.l = inStream_readObjectRef(env, in);
155 
156         error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalObject)
157                         (gdata->jvmti, thread, fnum, slot, value.l);
158 
159     } else {
160         switch (typeKey) {
161             case JDWP_TAG(BYTE):
162                 value.b = inStream_readByte(in);
163                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
164                                 (gdata->jvmti, thread, fnum, slot, value.b);
165                 break;
166 
167             case JDWP_TAG(CHAR):
168                 value.c = inStream_readChar(in);
169                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
170                                 (gdata->jvmti, thread, fnum, slot, value.c);
171                 break;
172 
173             case JDWP_TAG(FLOAT):
174                 value.f = inStream_readFloat(in);
175                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalFloat)
176                                 (gdata->jvmti, thread, fnum, slot, value.f);
177                 break;
178 
179             case JDWP_TAG(DOUBLE):
180                 value.d = inStream_readDouble(in);
181                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalDouble)
182                                 (gdata->jvmti, thread, fnum, slot, value.d);
183                 break;
184 
185             case JDWP_TAG(INT):
186                 value.i = inStream_readInt(in);
187                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
188                                 (gdata->jvmti, thread, fnum, slot, value.i);
189                 break;
190 
191             case JDWP_TAG(LONG):
192                 value.j = inStream_readLong(in);
193                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalLong)
194                                 (gdata->jvmti, thread, fnum, slot, value.j);
195                 break;
196 
197             case JDWP_TAG(SHORT):
198                 value.s = inStream_readShort(in);
199                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
200                                 (gdata->jvmti, thread, fnum, slot, value.s);
201                 break;
202 
203             case JDWP_TAG(BOOLEAN):
204                 value.z = inStream_readBoolean(in);
205                 error = JVMTI_FUNC_PTR(gdata->jvmti,SetLocalInt)
206                                 (gdata->jvmti, thread, fnum, slot, value.z);
207                 break;
208 
209             default:
210                 return JDWP_ERROR(INVALID_TAG);
211         }
212     }
213 
214     return map2jdwpError(error);
215 }
216 
217 static jboolean
getValues(PacketInputStream * in,PacketOutputStream * out)218 getValues(PacketInputStream *in, PacketOutputStream *out)
219 {
220     JNIEnv *env;
221     int i;
222     jdwpError serror;
223     jthread thread;
224     FrameID frame;
225     jint variableCount;
226 
227     env = getEnv();
228 
229     thread = inStream_readThreadRef(env, in);
230     if (inStream_error(in)) {
231         return JNI_TRUE;
232     }
233     frame = inStream_readFrameID(in);
234     if (inStream_error(in)) {
235         return JNI_TRUE;
236     }
237     variableCount = inStream_readInt(in);
238     if (inStream_error(in)) {
239         return JNI_TRUE;
240     }
241 
242     /*
243      * Validate the frame id
244      */
245     serror = validateThreadFrame(thread, frame);
246     if (serror != JDWP_ERROR(NONE)) {
247         outStream_setError(out, serror);
248         return JNI_TRUE;
249     }
250 
251     (void)outStream_writeInt(out, variableCount);
252     for (i = 0; (i < variableCount) && !outStream_error(out); i++) {
253         jint slot;
254         jbyte typeKey;
255         FrameNumber fnum;
256 
257         slot = inStream_readInt(in);
258         if (inStream_error(in))
259             break;
260         typeKey = inStream_readByte(in);
261         if (inStream_error(in))
262             break;
263 
264         fnum = getFrameNumber(frame);
265         serror = writeVariableValue(env, out, thread, fnum, slot, typeKey);
266         if (serror != JDWP_ERROR(NONE)) {
267             outStream_setError(out, serror);
268             break;
269         }
270     }
271 
272     return JNI_TRUE;
273 }
274 
275 static jboolean
setValues(PacketInputStream * in,PacketOutputStream * out)276 setValues(PacketInputStream *in, PacketOutputStream *out)
277 {
278     JNIEnv *env;
279     jint i;
280     jdwpError serror;
281     jthread thread;
282     FrameID frame;
283     jint variableCount;
284 
285     env = getEnv();
286 
287     thread = inStream_readThreadRef(env, in);
288     if (inStream_error(in)) {
289         return JNI_TRUE;
290     }
291     frame = inStream_readFrameID(in);
292     if (inStream_error(in)) {
293         return JNI_TRUE;
294     }
295     variableCount = inStream_readInt(in);
296     if (inStream_error(in)) {
297         return JNI_TRUE;
298     }
299 
300     /*
301      * Validate the frame id
302      */
303     serror = validateThreadFrame(thread, frame);
304     if (serror != JDWP_ERROR(NONE)) {
305         outStream_setError(out, serror);
306         return JNI_TRUE;
307     }
308 
309     for (i = 0; (i < variableCount) && !inStream_error(in); i++) {
310 
311         jint slot;
312         jbyte typeKey;
313         FrameNumber fnum;
314 
315         slot = inStream_readInt(in);
316         if (inStream_error(in)) {
317             return JNI_TRUE;
318         }
319         typeKey = inStream_readByte(in);
320         if (inStream_error(in)) {
321             return JNI_TRUE;
322         }
323 
324         fnum = getFrameNumber(frame);
325         serror = readVariableValue(env, in, thread, fnum, slot, typeKey);
326         if (serror != JDWP_ERROR(NONE))
327             break;
328     }
329 
330     if (serror != JDWP_ERROR(NONE)) {
331         outStream_setError(out, serror);
332     }
333 
334     return JNI_TRUE;
335 }
336 
337 static jboolean
thisObject(PacketInputStream * in,PacketOutputStream * out)338 thisObject(PacketInputStream *in, PacketOutputStream *out)
339 {
340     JNIEnv *env;
341     jdwpError serror;
342     jthread thread;
343     FrameID frame;
344 
345     env = getEnv();
346 
347     thread = inStream_readThreadRef(env, in);
348     if (inStream_error(in)) {
349         return JNI_TRUE;
350     }
351 
352     frame = inStream_readFrameID(in);
353     if (inStream_error(in)) {
354         return JNI_TRUE;
355     }
356 
357     /*
358      * Validate the frame id
359      */
360     serror = validateThreadFrame(thread, frame);
361     if (serror != JDWP_ERROR(NONE)) {
362         outStream_setError(out, serror);
363         return JNI_TRUE;
364     }
365 
366     WITH_LOCAL_REFS(env, 2) {
367 
368         jvmtiError error;
369         jmethodID method;
370         jlocation location;
371         FrameNumber fnum;
372 
373         /*
374          * Find out if the given frame is for a static or native method.
375          */
376         fnum = getFrameNumber(frame);
377         error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
378                 (gdata->jvmti, thread, fnum, &method, &location);
379         if (error == JVMTI_ERROR_NONE) {
380 
381             jint modifiers;
382 
383             error = methodModifiers(method, &modifiers);
384             if (error == JVMTI_ERROR_NONE) {
385 
386                 jobject this_object;
387 
388                 /*
389                  * Return null for static or native methods; otherwise, the JVM
390                  * spec guarantees that "this" is in slot 0
391                  */
392                 if (modifiers & (MOD_STATIC | MOD_NATIVE)) {
393                     this_object = NULL;
394                     (void)outStream_writeByte(out, specificTypeKey(env, this_object));
395                     (void)outStream_writeObjectRef(env, out, this_object);
396                 } else {
397                     // ANDROID-CHANGED: On ART 'this' is not always in register 0. We just use
398                     // GetLocalInstance in all cases.
399                     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
400                                 (gdata->jvmti, thread, fnum, &this_object);
401                     if (error == JVMTI_ERROR_NONE) {
402                         (void)outStream_writeByte(out, specificTypeKey(env, this_object));
403                         (void)outStream_writeObjectRef(env, out, this_object);
404                     }
405                 }
406 
407             }
408         }
409         serror = map2jdwpError(error);
410 
411     } END_WITH_LOCAL_REFS(env);
412 
413     if (serror != JDWP_ERROR(NONE))
414         outStream_setError(out, serror);
415 
416     return JNI_TRUE;
417 }
418 
419 static jboolean
popFrames(PacketInputStream * in,PacketOutputStream * out)420 popFrames(PacketInputStream *in, PacketOutputStream *out)
421 {
422     jvmtiError error;
423     jdwpError serror;
424     jthread thread;
425     FrameID frame;
426     FrameNumber fnum;
427 
428     thread = inStream_readThreadRef(getEnv(), in);
429     if (inStream_error(in)) {
430         return JNI_TRUE;
431     }
432 
433     frame = inStream_readFrameID(in);
434     if (inStream_error(in)) {
435         return JNI_TRUE;
436     }
437 
438     /*
439      * Validate the frame id
440      */
441     serror = validateThreadFrame(thread, frame);
442     if (serror != JDWP_ERROR(NONE)) {
443         outStream_setError(out, serror);
444         return JNI_TRUE;
445     }
446 
447     if (threadControl_isDebugThread(thread)) {
448         outStream_setError(out, JDWP_ERROR(INVALID_THREAD));
449         return JNI_TRUE;
450     }
451 
452     fnum = getFrameNumber(frame);
453     error = threadControl_popFrames(thread, fnum);
454     if (error != JVMTI_ERROR_NONE) {
455         serror = map2jdwpError(error);
456         outStream_setError(out, serror);
457     }
458     return JNI_TRUE;
459 }
460 
461 void *StackFrame_Cmds[] = { (void *)0x4
462     ,(void *)getValues
463     ,(void *)setValues
464     ,(void *)thisObject
465     ,(void *)popFrames
466 };
467