/** * Free up global refs held by the filter. * free things up at the JNI level if needed. */ static jvmtiError clearFilters(HandlerNode *node) { JNIEnv *env = getEnv(); jint i; jvmtiError error = JVMTI_ERROR_NONE; Filter *filter = FILTERS_ARRAY(node); for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): if ( filter->u.ThreadOnly.thread != NULL ) { tossGlobalRef(env, &(filter->u.ThreadOnly.thread)); } break; case JDWP_REQUEST_MODIFIER(LocationOnly): tossGlobalRef(env, &(filter->u.LocationOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(FieldOnly): tossGlobalRef(env, &(filter->u.FieldOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(ExceptionOnly): if ( filter->u.ExceptionOnly.exception != NULL ) { tossGlobalRef(env, &(filter->u.ExceptionOnly.exception)); } break; case JDWP_REQUEST_MODIFIER(InstanceOnly): if ( filter->u.InstanceOnly.instance != NULL ) { tossGlobalRef(env, &(filter->u.InstanceOnly.instance)); } break; case JDWP_REQUEST_MODIFIER(ClassOnly): tossGlobalRef(env, &(filter->u.ClassOnly.clazz)); break; case JDWP_REQUEST_MODIFIER(ClassMatch): jvmtiDeallocate(filter->u.ClassMatch.classPattern); break; case JDWP_REQUEST_MODIFIER(ClassExclude): jvmtiDeallocate(filter->u.ClassExclude.classPattern); break; case JDWP_REQUEST_MODIFIER(Step): { jthread thread = filter->u.Step.thread; error = stepControl_endStep(thread); if (error == JVMTI_ERROR_NONE) { tossGlobalRef(env, &(filter->u.Step.thread)); } break; } } } if (error == JVMTI_ERROR_NONE) { FILTER_COUNT(node) = 0; /* blast so we don't clear again */ } return error; }
jvmtiError eventFilter_setStepFilter(HandlerNode *node, jint index, jthread thread, jint size, jint depth) { jvmtiError error; JNIEnv *env = getEnv(); StepFilter *filter = &FILTER(node, index).u.Step; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) != EI_SINGLE_STEP) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, thread, &(filter->thread)); error = stepControl_beginStep(env, filter->thread, size, depth, node); if (error != JVMTI_ERROR_NONE) { tossGlobalRef(env, &(filter->thread)); return error; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step); filter->depth = depth; filter->size = size; return JVMTI_ERROR_NONE; }
jint eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index, jclass clazz, jmethodID method, jlocation location) { JNIEnv *env = getEnv(); LocationFilter *filter = &FILTER(node, index).u.LocationOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if ((KIND(node) != JVMDI_EVENT_BREAKPOINT) && (KIND(node) != JVMDI_EVENT_FIELD_ACCESS) && (KIND(node) != JVMDI_EVENT_FIELD_MODIFICATION) && (KIND(node) != JVMDI_EVENT_SINGLE_STEP) && (KIND(node) != JVMDI_EVENT_EXCEPTION)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ clazz = (*env)->NewGlobalRef(env, clazz); if (clazz == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly); filter->clazz = clazz; filter->method = method; filter->location = location; return JVMDI_ERROR_NONE; }
jvmtiError eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index, jclass exceptionClass, jboolean caught, jboolean uncaught) { JNIEnv *env = getEnv(); ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) != EI_EXCEPTION) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } filter->exception = NULL; if (exceptionClass != NULL) { /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, exceptionClass, &(filter->exception)); } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ExceptionOnly); filter->caught = caught; filter->uncaught = uncaught; return JVMTI_ERROR_NONE; }
jint eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index, jclass clazz, jfieldID field) { JNIEnv *env = getEnv(); FieldFilter *filter = &FILTER(node, index).u.FieldOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if ((KIND(node) != JVMDI_EVENT_FIELD_ACCESS) && (KIND(node) != JVMDI_EVENT_FIELD_MODIFICATION)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ clazz = (*env)->NewGlobalRef(env, clazz); if (clazz == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly); filter->clazz = clazz; filter->field = field; return JVMDI_ERROR_NONE; }
jint eventFilter_setClassOnlyFilter(HandlerNode *node, jint index, jclass clazz) { JNIEnv *env = getEnv(); ClassFilter *filter = &FILTER(node, index).u.ClassOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if ((KIND(node) == JVMDI_EVENT_USER_DEFINED) || (KIND(node) == JVMDI_EVENT_CLASS_UNLOAD) || (KIND(node) == JVMDI_EVENT_THREAD_START) || (KIND(node) == JVMDI_EVENT_THREAD_END)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ clazz = (*env)->NewGlobalRef(env, clazz); if (clazz == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly); filter->clazz = clazz; return JVMDI_ERROR_NONE; }
jvmtiError eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index, jclass clazz, jmethodID method, jlocation location) { JNIEnv *env = getEnv(); LocationFilter *filter = &FILTER(node, index).u.LocationOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ((NODE_EI(node) != EI_BREAKPOINT) && (NODE_EI(node) != EI_FIELD_ACCESS) && (NODE_EI(node) != EI_FIELD_MODIFICATION) && (NODE_EI(node) != EI_SINGLE_STEP) && (NODE_EI(node) != EI_EXCEPTION)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly); filter->method = method; filter->location = location; return JVMTI_ERROR_NONE; }
jint eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index, jclass exceptionClass, jboolean caught, jboolean uncaught) { JNIEnv *env = getEnv(); ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (KIND(node) != JVMDI_EVENT_EXCEPTION) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (exceptionClass != NULL) { /* Create a class ref that will live beyond */ /* the end of this call */ exceptionClass = (*env)->NewGlobalRef(env, exceptionClass); if (exceptionClass == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ExceptionOnly); filter->exception = exceptionClass; filter->caught = caught; filter->uncaught = uncaught; return JVMDI_ERROR_NONE; }
jint eventFilter_setStepFilter(HandlerNode *node, jint index, jthread thread, jint size, jint depth) { jint error; JNIEnv *env = getEnv(); StepFilter *filter = &FILTER(node, index).u.Step; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (KIND(node) != JVMDI_EVENT_SINGLE_STEP) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ thread = (*env)->NewGlobalRef(env, thread); if (thread == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } error = stepControl_beginStep(thread, size,depth, node); if (error != JVMDI_ERROR_NONE) { (*env)->DeleteGlobalRef(env, thread); return error; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step); filter->thread = thread; filter->depth = depth; filter->size = size; return JVMDI_ERROR_NONE; }
/** * Allocate a HandlerNode. * We do it because eventHandler doesn't know how big to make it. */ HandlerNode * eventFilterRestricted_alloc(jint filterCount) { /*LINTED*/ size_t size = offsetof(EventFilterPrivate_HandlerNode, ef) + offsetof(EventFilters, filters) + (filterCount * (int)sizeof(Filter)); HandlerNode *node = jvmtiAllocate((jint)size); if (node != NULL) { int i; Filter *filter; (void)memset(node, 0, size); FILTER_COUNT(node) = filterCount; /* Initialize all modifiers */ for (i = 0, filter = FILTERS_ARRAY(node); i < filterCount; i++, filter++) { filter->modifier = JDWP_REQUEST_NONE; } } return node; }
/** * Allocate a HandlerNode. * We do it because eventHandler doesn't know how big to make it. */ HandlerNode * eventFilterRestricted_alloc(jint filterCount) { size_t size = offsetof(EventFilterPrivate_HandlerNode, ef) + offsetof(EventFilters, filters) + (filterCount * sizeof(Filter)); HandlerNode *node = jdwpClearedAlloc(size); if (node != NULL) { int i; Filter *filter; FILTER_COUNT(node) = filterCount; /* Initialize all modifiers */ for (i = 0, filter = FILTERS_ARRAY(node); i < filterCount; i++, filter++) { filter->modifier = JDWP_REQUEST_NONE; } } return node; }
jint eventFilter_setConditionalFilter(HandlerNode *node, jint index, jint exprID) { ConditionalFilter *filter = &FILTER(node, index).u.Conditional; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Conditional); filter->exprID = exprID; return JVMDI_ERROR_NONE; }
/** * Return the Filter that is of the specified type (modifier). * Return NULL if not found. */ static Filter * findFilter(HandlerNode *node, jint modifier) { int i; Filter *filter; for (i = 0, filter = FILTERS_ARRAY(node); i <FILTER_COUNT(node); i++, filter++) { if (filter->modifier == modifier) { return filter; } } return NULL; }
/** * Determine if the given breakpoint node is in the specified class. */ jboolean eventFilterRestricted_isBreakpointInClass(JNIEnv *env, jclass clazz, HandlerNode *node) { Filter *filter = FILTERS_ARRAY(node); int i; for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(LocationOnly): return isSameObject(env, clazz, filter->u.LocationOnly.clazz); } } return JNI_TRUE; /* should never come here */ }
/** * Determine the thread this node is filtered on. * NULL if not thread filtered. */ static jthread requestThread(HandlerNode *node) { int i; Filter *filter = FILTERS_ARRAY(node); for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): return filter->u.ThreadOnly.thread; } } return NULL; }
jint eventFilter_setCountFilter(HandlerNode *node, jint index, jint count) { CountFilter *filter = &FILTER(node, index).u.Count; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (count <= 0) { return JDWP_ERROR(INVALID_COUNT); } else { FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Count); filter->count = count; return JVMDI_ERROR_NONE; } }
/* Determine if this event is interesting to this handler. Do so * by checking each of the handler's filters. Return false if any * of the filters fail, true if the handler wants this event. * Special version of filter for unloads since they don't have an * event structure or a jclass. * * If shouldDelete is returned true, a count filter has expired * and the corresponding node should be deleted. */ jboolean eventFilterRestricted_passesUnloadFilter(JNIEnv *env, char *classname, HandlerNode *node, jboolean *shouldDelete) { Filter *filter = FILTERS_ARRAY(node); int i; *shouldDelete = JNI_FALSE; for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(Count): { JDI_ASSERT(filter->u.Count.count > 0); if (--filter->u.Count.count > 0) { return JNI_FALSE; } *shouldDelete = JNI_TRUE; break; } case JDWP_REQUEST_MODIFIER(ClassMatch): { if (!patternStringMatch(classname, filter->u.ClassMatch.classPattern)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(ClassExclude): { if (patternStringMatch(classname, filter->u.ClassExclude.classPattern)) { return JNI_FALSE; } break; } default: ERROR_MESSAGE_EXIT("Invalid filter modifier"); return JNI_FALSE; } } return JNI_TRUE; }
jvmtiError eventFilter_setSourceNameMatchFilter(HandlerNode *node, jint index, char *sourceNamePattern) { SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) != EI_CLASS_PREPARE) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(SourceNameMatch); filter->sourceNamePattern = sourceNamePattern; return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index, jthread thread) { JNIEnv *env = getEnv(); ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if (NODE_EI(node) == EI_GC_FINISH) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, thread, &(filter->thread)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly); return JVMTI_ERROR_NONE; }
jvmtiError eventFilter_setClassExcludeFilter(HandlerNode *node, jint index, char *classPattern) { MatchFilter *filter = &FILTER(node, index).u.ClassExclude; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ( (NODE_EI(node) == EI_THREAD_START) || (NODE_EI(node) == EI_THREAD_END)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassExclude); filter->classPattern = classPattern; return JVMTI_ERROR_NONE; }
jint eventFilter_setClassExcludeFilter(HandlerNode *node, jint index, char *classPattern) { MatchFilter *filter = &FILTER(node, index).u.ClassExclude; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if ((KIND(node) == JVMDI_EVENT_USER_DEFINED) || (KIND(node) == JVMDI_EVENT_THREAD_START) || (KIND(node) == JVMDI_EVENT_THREAD_END)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassExclude); filter->classPattern = classPattern; return JVMDI_ERROR_NONE; }
/** * Determine if the specified watchpoint node has the * same field as the FieldFilter passed in arg. * * This is a match function called by a * eventHandlerRestricted_iterator invokation. */ static jboolean matchWatchpoint(JNIEnv *env, HandlerNode *node, void *arg) { FieldFilter *goal = (FieldFilter *)arg; Filter *filter = FILTERS_ARRAY(node); int i; for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(FieldOnly): { FieldFilter *trial = &(filter->u.FieldOnly); if (trial->field == goal->field && isSameObject(env, trial->clazz, goal->clazz)) { return JNI_TRUE; } } } } return JNI_FALSE; }
jvmtiError eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index, jobject instance) { JNIEnv *env = getEnv(); InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } filter->instance = NULL; if (instance != NULL) { /* Create an object ref that will live beyond * the end of this call */ saveGlobalRef(env, instance, &(filter->instance)); } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(InstanceOnly); return JVMTI_ERROR_NONE; }
/** * Determine if the specified breakpoint node is in the * same location as the LocationFilter passed in arg. * * This is a match function called by a * eventHandlerRestricted_iterator invokation. */ static jboolean matchBreakpoint(JNIEnv *env, HandlerNode *node, void *arg) { LocationFilter *goal = (LocationFilter *)arg; Filter *filter = FILTERS_ARRAY(node); int i; for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(LocationOnly): { LocationFilter *trial = &(filter->u.LocationOnly); if (trial->method == goal->method && trial->location == goal->location && isSameObject(env, trial->clazz, goal->clazz)) { return JNI_TRUE; } } } } return JNI_FALSE; }
jvmtiError eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index, jclass clazz, jfieldID field) { JNIEnv *env = getEnv(); FieldFilter *filter = &FILTER(node, index).u.FieldOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ((NODE_EI(node) != EI_FIELD_ACCESS) && (NODE_EI(node) != EI_FIELD_MODIFICATION)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly); filter->field = field; return JVMTI_ERROR_NONE; }
jint eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index, jthread thread) { JNIEnv *env = getEnv(); ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (KIND(node) == JVMDI_EVENT_CLASS_UNLOAD) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } /* Create a thread ref that will live beyond */ /* the end of this call */ thread = (*env)->NewGlobalRef(env, thread); if (thread == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly); filter->thread = thread; return JVMDI_ERROR_NONE; }
jvmtiError eventFilter_setClassOnlyFilter(HandlerNode *node, jint index, jclass clazz) { JNIEnv *env = getEnv(); ClassFilter *filter = &FILTER(node, index).u.ClassOnly; if (index >= FILTER_COUNT(node)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } if ( (NODE_EI(node) == EI_GC_FINISH) || (NODE_EI(node) == EI_THREAD_START) || (NODE_EI(node) == EI_THREAD_END)) { return AGENT_ERROR_ILLEGAL_ARGUMENT; } /* Create a class ref that will live beyond */ /* the end of this call */ saveGlobalRef(env, clazz, &(filter->clazz)); FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly); return JVMTI_ERROR_NONE; }
jint eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index, jobject instance) { JNIEnv *env = getEnv(); InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly; if (index >= FILTER_COUNT(node)) { return JVMDI_ERROR_ILLEGAL_ARGUMENT; } if (instance != NULL) { /* Create an object ref that will live beyond * the end of this call */ instance = (*env)->NewGlobalRef(env, instance); if (instance == NULL) { return JVMDI_ERROR_OUT_OF_MEMORY; } } FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(InstanceOnly); filter->instance = instance; return JVMDI_ERROR_NONE; }
/* * Determine if this event is interesting to this handler. * Do so by checking each of the handler's filters. * Return false if any of the filters fail, * true if the handler wants this event. * Anyone modifying this function should check * eventFilterRestricted_passesUnloadFilter and * eventFilter_predictFiltering as well. * * If shouldDelete is returned true, a count filter has expired * and the corresponding node should be deleted. */ jboolean eventFilterRestricted_passesFilter(JNIEnv *env, JVMDI_Event *event, HandlerNode *node, jboolean *shouldDelete) { jthread thread; jclass clazz; Filter *filter = FILTERS_ARRAY(node); int i; *shouldDelete = JNI_FALSE; eventThreadAndClass(event, &thread, &clazz); /* * Suppress most events if they happen in debug threads */ if ((event->kind != JVMDI_EVENT_CLASS_PREPARE) && (event->kind != JVMDI_EVENT_CLASS_UNLOAD) && (event->kind != JVMDI_EVENT_CLASS_LOAD) && threadControl_isDebugThread(thread)) { return JNI_FALSE; } for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ThreadOnly): if (!(*env)->IsSameObject(env, thread, filter->u.ThreadOnly.thread)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(ClassOnly): /* Class filters catch events in the specified * class and any subclass/subinterface. */ if (!(*env)->IsAssignableFrom(env, clazz, filter->u.ClassOnly.clazz)) { return JNI_FALSE; } break; /* This is kinda cheating assumming the JVMDI event * fields will be in the same locations, but it is * true now. */ case JDWP_REQUEST_MODIFIER(LocationOnly): if (event->u.breakpoint.method != filter->u.LocationOnly.method || event->u.breakpoint.location != filter->u.LocationOnly.location || !(*env)->IsSameObject(env, clazz, filter->u.LocationOnly.clazz)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(FieldOnly): /* Field watchpoints can be triggered from the * declared class or any subclass/subinterface. */ if ((event->u.field_access.field != filter->u.FieldOnly.field) || !(*env)->IsSameObject(env, event->u.field_access.field_clazz, filter->u.FieldOnly.clazz)) { return JNI_FALSE; } break; case JDWP_REQUEST_MODIFIER(ExceptionOnly): /* do we want caught/uncaught exceptions */ if (!((event->u.exception.catch_clazz == NULL)? filter->u.ExceptionOnly.uncaught : filter->u.ExceptionOnly.caught)) { return JNI_FALSE; } /* do we care about exception class */ if (filter->u.ExceptionOnly.exception != NULL) { jclass exception = event->u.exception.exception; /* do we want this exception class */ if (!(*env)->IsInstanceOf(env, exception, filter->u.ExceptionOnly.exception)) { return JNI_FALSE; } } break; case JDWP_REQUEST_MODIFIER(InstanceOnly): { jobject eventInst = eventInstance(event); jobject filterInst = filter->u.InstanceOnly.instance; /* if no error and doesn't match, don't pass * filter */ if (eventInst != NULL && !(*env)->IsSameObject(env, eventInst, filterInst)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(Count): { JDI_ASSERT(filter->u.Count.count > 0); if (--filter->u.Count.count > 0) { return JNI_FALSE; } *shouldDelete = JNI_TRUE; break; } case JDWP_REQUEST_MODIFIER(Conditional): /*** if (... filter->u.Conditional.exprID ...) { return JNI_FALSE; } ***/ break; case JDWP_REQUEST_MODIFIER(ClassMatch): { if (!patternMatch(clazz, filter->u.ClassMatch.classPattern)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(ClassExclude): { if (patternMatch(clazz, filter->u.ClassExclude.classPattern)) { return JNI_FALSE; } break; } case JDWP_REQUEST_MODIFIER(Step): if (!(*env)->IsSameObject(env, thread, filter->u.Step.thread)) { return JNI_FALSE; } if (!stepControl_handleStep(env, event)) { return JNI_FALSE; } break; default: ERROR_MESSAGE_EXIT("Invalid filter modifier"); return JNI_FALSE; } } return JNI_TRUE; }
/** * This function returns true only if it is certain that * all events for the given node in the given frame will * be filtered. It is used to optimize stepping. (If this * function returns true the stepping algorithm does not * have to step through every instruction in this frame; * instead, it can use more efficient method entry/exit * events. */ jboolean eventFilter_predictFiltering(HandlerNode *node, jframeID frame) { Filter *filter = FILTERS_ARRAY(node); int i; jclass clazz; jmethodID method; jlocation location; jboolean willBeFiltered = JNI_FALSE; jboolean done = JNI_FALSE; JNIEnv *env = getEnv(); jint error; error = jvmdi->GetFrameLocation(frame, &clazz, &method, &location); if (error != JVMDI_ERROR_NONE) { return JNI_FALSE; } for (i = 0; (i < FILTER_COUNT(node)) && (!done); ++i, ++filter) { switch (filter->modifier) { case JDWP_REQUEST_MODIFIER(ClassOnly): if (!(*env)->IsAssignableFrom(env, clazz, filter->u.ClassOnly.clazz)) { willBeFiltered = JNI_TRUE; done = JNI_TRUE; } break; case JDWP_REQUEST_MODIFIER(Count): { /* * If preceeding filters have determined that events will * be filtered out, that is fine and we won't get here. * However, the count must be decremented - even if * subsequent filters will filter these events. We * thus must end now unable to predict */ done = JNI_TRUE; break; } case JDWP_REQUEST_MODIFIER(ClassMatch): { if (!patternMatch(clazz, filter->u.ClassMatch.classPattern)) { willBeFiltered = JNI_TRUE; done = JNI_TRUE; } break; } case JDWP_REQUEST_MODIFIER(ClassExclude): { if (patternMatch(clazz, filter->u.ClassExclude.classPattern)) { willBeFiltered = JNI_TRUE; done = JNI_TRUE; } break; } } } (*env)->DeleteGlobalRef(env, clazz); return willBeFiltered; }