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 */ 39static jdwpError 40readAndSetFilters(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 */ 230static jboolean 231setCommand(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 */ 305static jboolean 306clearCommand(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 337static jboolean 338clearAllBreakpoints(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 349void *EventRequest_Cmds[] = { (void *)0x3 350 ,(void *)setCommand 351 ,(void *)clearCommand 352 ,(void *)clearAllBreakpoints}; 353