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 "EventRequestImpl.h"
28 #include "eventHandler.h"
29 #include "inStream.h"
30 #include "outStream.h"
31 #include "stepControl.h"
32
33 /**
34 * Take JDWP "modifiers" (which are JDI explicit filters, like
35 * addCountFilter(), and implicit filters, like the LocationOnly
36 * filter that goes with breakpoints) and add them as filters
37 * (eventFilter) to the HandlerNode (eventHandler).
38 */
39 static jdwpError
readAndSetFilters(JNIEnv * env,PacketInputStream * in,HandlerNode * node,jint filterCount)40 readAndSetFilters(JNIEnv *env, PacketInputStream *in, HandlerNode *node,
41 jint filterCount)
42 {
43 int i;
44 jdwpError serror = JDWP_ERROR(NONE);
45
46 for (i = 0; i < filterCount; ++i) {
47
48 jbyte modifier;
49
50 modifier = inStream_readByte(in);
51 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
52 break;
53
54 switch (modifier) {
55
56 case JDWP_REQUEST_MODIFIER(Conditional): {
57 jint exprID;
58 exprID = inStream_readInt(in);
59 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
60 break;
61 serror = map2jdwpError(
62 eventFilter_setConditionalFilter(node, i, exprID));
63 break;
64 }
65
66 case JDWP_REQUEST_MODIFIER(Count): {
67 jint count;
68 count = inStream_readInt(in);
69 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
70 break;
71 serror = map2jdwpError(
72 eventFilter_setCountFilter(node, i, count));
73 break;
74 }
75
76 case JDWP_REQUEST_MODIFIER(ThreadOnly): {
77 jthread thread;
78 thread = inStream_readThreadRef(env, in);
79 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
80 break;
81 serror = map2jdwpError(
82 eventFilter_setThreadOnlyFilter(node, i, thread));
83 break;
84 }
85
86 case JDWP_REQUEST_MODIFIER(LocationOnly): {
87 jbyte tag;
88 jclass clazz;
89 jmethodID method;
90 jlocation location;
91 tag = inStream_readByte(in); /* not currently used */
92 tag = tag; /* To shut up lint */
93 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
94 break;
95 clazz = inStream_readClassRef(env, in);
96 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
97 break;
98 method = inStream_readMethodID(in);
99 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
100 break;
101 location = inStream_readLocation(in);
102 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
103 break;
104 serror = map2jdwpError(
105 eventFilter_setLocationOnlyFilter(node, i, clazz, method, location));
106 break;
107 }
108
109 case JDWP_REQUEST_MODIFIER(FieldOnly): {
110 jclass clazz;
111 jfieldID field;
112 clazz = inStream_readClassRef(env, in);
113 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
114 break;
115 field = inStream_readFieldID(in);
116 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
117 break;
118 serror = map2jdwpError(
119 eventFilter_setFieldOnlyFilter(node, i, clazz, field));
120 break;
121 }
122
123 case JDWP_REQUEST_MODIFIER(ClassOnly): {
124 jclass clazz;
125 clazz = inStream_readClassRef(env, in);
126 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
127 break;
128 serror = map2jdwpError(
129 eventFilter_setClassOnlyFilter(node, i, clazz));
130 break;
131 }
132
133 case JDWP_REQUEST_MODIFIER(ExceptionOnly): {
134 jclass exception;
135 jboolean caught;
136 jboolean uncaught;
137 exception = inStream_readClassRef(env, in);
138 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
139 break;
140 caught = inStream_readBoolean(in);
141 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
142 break;
143 uncaught = inStream_readBoolean(in);
144 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
145 break;
146 serror = map2jdwpError(
147 eventFilter_setExceptionOnlyFilter(node, i,
148 exception, caught, uncaught));
149 break;
150 }
151
152 case JDWP_REQUEST_MODIFIER(InstanceOnly): {
153 jobject instance;
154 instance = inStream_readObjectRef(env, in);
155 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
156 break;
157 serror = map2jdwpError(
158 eventFilter_setInstanceOnlyFilter(node, i, instance));
159 break;
160 }
161
162 case JDWP_REQUEST_MODIFIER(ClassMatch): {
163 char *pattern;
164 pattern = inStream_readString(in);
165 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
166 break;
167 serror = map2jdwpError(
168 eventFilter_setClassMatchFilter(node, i,
169 pattern));
170 break;
171 }
172
173 case JDWP_REQUEST_MODIFIER(ClassExclude): {
174 char *pattern;
175 pattern = inStream_readString(in);
176 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
177 break;
178 serror = map2jdwpError(
179 eventFilter_setClassExcludeFilter(node, i, pattern));
180 break;
181 }
182 case JDWP_REQUEST_MODIFIER(Step): {
183 jthread thread;
184 jint size;
185 jint depth;
186 thread = inStream_readThreadRef(env, in);
187 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
188 break;
189 size = inStream_readInt(in);
190 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
191 break;
192 depth = inStream_readInt(in);
193 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
194 break;
195 serror = map2jdwpError(
196 eventFilter_setStepFilter(node, i, thread, size, depth));
197 break;
198 }
199 case JDWP_REQUEST_MODIFIER(SourceNameMatch): {
200 char *sourceNamePattern;
201 sourceNamePattern = inStream_readString(in);
202 if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) ) {
203 break;
204 }
205 serror = map2jdwpError(
206 eventFilter_setSourceNameMatchFilter(node, i, sourceNamePattern));
207 break;
208 }
209
210 default:
211 serror = JDWP_ERROR(ILLEGAL_ARGUMENT);
212 break;
213 }
214 if ( serror != JDWP_ERROR(NONE) )
215 break;
216 }
217 return serror;
218 }
219
220 /**
221 * This is the back-end implementation for enabling
222 * (what are at the JDI level) EventRequests.
223 *
224 * Allocate the event request handler (eventHandler).
225 * Add any filters (explicit or implicit).
226 * Install the handler.
227 * Return the handlerID which is used to map subsequent
228 * events to the EventRequest that created it.
229 */
230 static jboolean
setCommand(PacketInputStream * in,PacketOutputStream * out)231 setCommand(PacketInputStream *in, PacketOutputStream *out)
232 {
233 jdwpError serror;
234 HandlerNode *node;
235 HandlerID requestID = -1;
236 jdwpEvent eventType;
237 jbyte suspendPolicy;
238 jint filterCount;
239 EventIndex ei;
240
241 node = NULL;
242 eventType = inStream_readByte(in);
243 if (inStream_error(in)) {
244 return JNI_TRUE;
245 }
246 suspendPolicy = inStream_readByte(in);
247 if (inStream_error(in)) {
248 return JNI_TRUE;
249 }
250 filterCount = inStream_readInt(in);
251 if (inStream_error(in)) {
252 return JNI_TRUE;
253 }
254
255 ei = jdwp2EventIndex(eventType);
256 if (ei == 0) {
257 outStream_setError(out, JDWP_ERROR(INVALID_EVENT_TYPE));
258 return JNI_TRUE;
259 }
260
261 if (ei == EI_VM_INIT) {
262 /*
263 * VM is already initialized so there's no need to install a handler
264 * for this event. However we need to allocate a requestID to send in
265 * the reply to the debugger.
266 */
267 serror = JDWP_ERROR(NONE);
268 requestID = eventHandler_allocHandlerID();
269 } else {
270 node = eventHandler_alloc(filterCount, ei, suspendPolicy);
271 if (node == NULL) {
272 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
273 return JNI_TRUE;
274 }
275 if (eventType == JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)) {
276 node->needReturnValue = 1;
277 } else {
278 node->needReturnValue = 0;
279 }
280 serror = readAndSetFilters(getEnv(), in, node, filterCount);
281 if (serror == JDWP_ERROR(NONE)) {
282 jvmtiError error;
283 error = eventHandler_installExternal(node);
284 serror = map2jdwpError(error);
285 if (serror == JDWP_ERROR(NONE)) {
286 requestID = node->handlerID;
287 }
288 }
289 }
290
291 if (serror == JDWP_ERROR(NONE)) {
292 (void)outStream_writeInt(out, requestID);
293 } else {
294 (void)eventHandler_free(node);
295 outStream_setError(out, serror);
296 }
297
298 return JNI_TRUE;
299 }
300
301 /**
302 * This is the back-end implementation for disabling
303 * (what are at the JDI level) EventRequests.
304 */
305 static jboolean
clearCommand(PacketInputStream * in,PacketOutputStream * out)306 clearCommand(PacketInputStream *in, PacketOutputStream *out)
307 {
308 jvmtiError error;
309 jdwpEvent eventType;
310 HandlerID handlerID;
311 EventIndex ei;
312
313 eventType = inStream_readByte(in);
314 if (inStream_error(in)) {
315 return JNI_TRUE;
316 }
317 handlerID = inStream_readInt(in);
318 if (inStream_error(in)) {
319 return JNI_TRUE;
320 }
321
322 ei = jdwp2EventIndex(eventType);
323 if (ei == 0) {
324 /* NOTE: Clear command not yet spec'ed to return INVALID_EVENT_TYPE */
325 outStream_setError(out, JDWP_ERROR(INVALID_EVENT_TYPE));
326 return JNI_TRUE;
327 }
328
329 error = eventHandler_freeByID(ei, handlerID);
330 if (error != JVMTI_ERROR_NONE) {
331 outStream_setError(out, map2jdwpError(error));
332 }
333
334 return JNI_TRUE;
335 }
336
337 static jboolean
clearAllBreakpoints(PacketInputStream * in,PacketOutputStream * out)338 clearAllBreakpoints(PacketInputStream *in, PacketOutputStream *out)
339 {
340 jvmtiError error;
341
342 error = eventHandler_freeAll(EI_BREAKPOINT);
343 if (error != JVMTI_ERROR_NONE) {
344 outStream_setError(out, map2jdwpError(error));
345 }
346 return JNI_TRUE;
347 }
348
349 void *EventRequest_Cmds[] = { (void *)0x3
350 ,(void *)setCommand
351 ,(void *)clearCommand
352 ,(void *)clearAllBreakpoints};
353