Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * 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;
}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/**
 * 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 */
}
Exemplo n.º 7
0
/* 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;
}
Exemplo n.º 8
0
/**
 * 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;
}
Exemplo n.º 9
0
/**
 * 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;
}
Exemplo n.º 10
0
/**
 * 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;
}
Exemplo n.º 11
0
/*
 * 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;
}
Exemplo n.º 12
0
/** 
 * Free up global refs held by the filter. 
 * free things up at the JNI level if needed. 
 */
static jint
clearFilters(HandlerNode *node)
{
    JNIEnv *env = getEnv();
    jint i;
    jint error = JVMDI_ERROR_NONE;
    Filter *filter = FILTERS_ARRAY(node);

    for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
        switch (filter->modifier) {
            case JDWP_REQUEST_MODIFIER(ThreadOnly): {
                jthread threadOnly = filter->u.ThreadOnly.thread;
                if (threadOnly != NULL) { 
                    (*env)->DeleteGlobalRef(env, threadOnly);
                }
                break;
            }
            case JDWP_REQUEST_MODIFIER(LocationOnly): {
                jclass clazz = filter->u.LocationOnly.clazz;
                (*env)->DeleteGlobalRef(env, clazz);
                break;
            }
            case JDWP_REQUEST_MODIFIER(FieldOnly): {
                jclass clazz = filter->u.FieldOnly.clazz;
                (*env)->DeleteGlobalRef(env, clazz);
                break;
            }
            case JDWP_REQUEST_MODIFIER(ExceptionOnly): {
                (*env)->DeleteGlobalRef(env, 
                          filter->u.ExceptionOnly.exception);
                break;
            }
            case JDWP_REQUEST_MODIFIER(InstanceOnly): {
                (*env)->DeleteGlobalRef(env, 
                          filter->u.InstanceOnly.instance);
                break;
            }
            case JDWP_REQUEST_MODIFIER(ClassOnly): {
                (*env)->DeleteGlobalRef(env,
                          filter->u.ClassOnly.clazz);
                break;
            }
            case JDWP_REQUEST_MODIFIER(ClassMatch): {
                jdwpFree(filter->u.ClassMatch.classPattern);
                break;
            }
            case JDWP_REQUEST_MODIFIER(ClassExclude): {
                jdwpFree(filter->u.ClassExclude.classPattern);
                break;
            }
            case JDWP_REQUEST_MODIFIER(Step): {
                jthread thread = filter->u.Step.thread;
                error = stepControl_endStep(thread);
                if (error == JVMDI_ERROR_NONE) {
                    (*env)->DeleteGlobalRef(env, thread);
                }
                break;
            }
        }
    }
    if (error == JVMDI_ERROR_NONE) {
        FILTER_COUNT(node) = 0; /* blast so we don't clear again */
    }

    return error;
}
Exemplo n.º 13
0
/**
 * This function returns true only if it is certain that
 * all events for the given node in the given stack 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 stack frame;
 * instead, it can use more efficient method entry/exit
 * events.
 */
jboolean
eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname)
{
    JNIEnv     *env;
    jboolean    willBeFiltered;
    Filter     *filter;
    jboolean    done;
    int         count;
    int         i;

    willBeFiltered = JNI_FALSE;
    env            = NULL;
    filter         = FILTERS_ARRAY(node);
    count          = FILTER_COUNT(node);
    done           = JNI_FALSE;

    for (i = 0; (i < count) && (!done); ++i, ++filter) {
        switch (filter->modifier) {
            case JDWP_REQUEST_MODIFIER(ClassOnly):
                if ( env==NULL ) {
                    env = getEnv();
                }
                if (!JNI_FUNC_PTR(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 (!patternStringMatch(classname,
                        filter->u.ClassMatch.classPattern)) {
                    willBeFiltered = JNI_TRUE;
                    done = JNI_TRUE;
                }
                break;
            }

            case JDWP_REQUEST_MODIFIER(ClassExclude): {
                if (patternStringMatch(classname,
                       filter->u.ClassExclude.classPattern)) {
                    willBeFiltered = JNI_TRUE;
                    done = JNI_TRUE;
                }
                break;
            }
        }
    }

    return willBeFiltered;
}
Exemplo n.º 14
0
/*
 * 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,
                                   char *classname,
                                   EventInfo *evinfo,
                                   HandlerNode *node,
                                   jboolean *shouldDelete)
{
    jthread thread;
    jclass clazz;
    jmethodID method;
    Filter *filter = FILTERS_ARRAY(node);
    int i;

    *shouldDelete = JNI_FALSE;
    thread = evinfo->thread;
    clazz = evinfo->clazz;
    method = evinfo->method;

    /*
     * Suppress most events if they happen in debug threads
     */
    if ((evinfo->ei != EI_CLASS_PREPARE) &&
        (evinfo->ei != EI_GC_FINISH) &&
        (evinfo->ei != EI_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 (!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 (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz,
                               filter->u.ClassOnly.clazz)) {
                    return JNI_FALSE;
                }
                break;

            /* This is kinda cheating assumming the event
             * fields will be in the same locations, but it is
             * true now.
             */
            case JDWP_REQUEST_MODIFIER(LocationOnly):
                if  (evinfo->method !=
                          filter->u.LocationOnly.method ||
                     evinfo->location !=
                          filter->u.LocationOnly.location ||
                     !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 ((evinfo->u.field_access.field !=
                     filter->u.FieldOnly.field) ||
                    !isSameObject(env, evinfo->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 (!((evinfo->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 = evinfo->object;

                    /* do we want this exception class */
                    if (!JNI_FUNC_PTR(env,IsInstanceOf)(env, exception,
                            filter->u.ExceptionOnly.exception)) {
                        return JNI_FALSE;
                    }
                }
                break;

            case JDWP_REQUEST_MODIFIER(InstanceOnly): {
                jobject eventInst = eventInstance(evinfo);
                jobject filterInst = filter->u.InstanceOnly.instance;
                /* if no error and doesn't match, don't pass
                 * filter
                 */
                if (eventInst != NULL &&
                      !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 (!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;
        }

        case JDWP_REQUEST_MODIFIER(Step):
                if (!isSameObject(env, thread, filter->u.Step.thread)) {
                    return JNI_FALSE;
                }
                if (!stepControl_handleStep(env, thread, clazz, method)) {
                    return JNI_FALSE;
                }
                break;

          case JDWP_REQUEST_MODIFIER(SourceNameMatch): {
              char* desiredNamePattern = filter->u.SourceNameOnly.sourceNamePattern;
              if (!searchAllSourceNames(env, clazz,
                           desiredNamePattern) == 1) {
                  /* The name isn't in the SDE; try the sourceName in the ref
                   * type
                   */
                  char *sourceName = 0;
                  jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
                                            (gdata->jvmti, clazz, &sourceName);
                  if (error == JVMTI_ERROR_NONE &&
                      sourceName != 0 &&
                      patternStringMatch(sourceName, desiredNamePattern)) {
                          // got a hit - report the event
                          jvmtiDeallocate(sourceName);
                          break;
                  }
                  // We have no match, we have no source file name,
                  // or we got a JVM TI error. Don't report the event.
                  jvmtiDeallocate(sourceName);
                  return JNI_FALSE;
              }
              break;
          }

        default:
            EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
            return JNI_FALSE;
        }
    }
    return JNI_TRUE;
}