Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 2001, 2013, 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  * eventFilter
     27  *
     28  * This module handles event filteration and the enabling/disabling
     29  * of the corresponding events. Used for filters on JDI EventRequests
     30  * and also internal requests.  Our data is in a private hidden section
     31  * of the HandlerNode's data.  See comment for enclosing
     32  * module eventHandler.
     33  */
     34 
     35 #include "util.h"
     36 #include "eventFilter.h"
     37 #include "eventFilterRestricted.h"
     38 #include "eventHandlerRestricted.h"
     39 #include "stepControl.h"
     40 #include "threadControl.h"
     41 #include "SDE.h"
     42 #include "jvmti.h"
     43 
     44 typedef struct ClassFilter {
     45     jclass clazz;
     46 } ClassFilter;
     47 
     48 typedef struct LocationFilter {
     49     jclass clazz;
     50     jmethodID method;
     51     jlocation location;
     52 } LocationFilter;
     53 
     54 typedef struct ThreadFilter {
     55     jthread thread;
     56 } ThreadFilter;
     57 
     58 typedef struct CountFilter {
     59     jint count;
     60 } CountFilter;
     61 
     62 typedef struct ConditionalFilter {
     63     jint exprID;
     64 } ConditionalFilter;
     65 
     66 typedef struct FieldFilter {
     67     jclass clazz;
     68     jfieldID field;
     69 } FieldFilter;
     70 
     71 typedef struct ExceptionFilter {
     72     jclass exception;
     73     jboolean caught;
     74     jboolean uncaught;
     75 } ExceptionFilter;
     76 
     77 typedef struct InstanceFilter {
     78     jobject instance;
     79 } InstanceFilter;
     80 
     81 typedef struct StepFilter {
     82     jint size;
     83     jint depth;
     84     jthread thread;
     85 } StepFilter;
     86 
     87 typedef struct MatchFilter {
     88     char *classPattern;
     89 } MatchFilter;
     90 
     91 typedef struct SourceNameFilter {
     92     char *sourceNamePattern;
     93 } SourceNameFilter;
     94 
     95 typedef struct Filter_ {
     96     jbyte modifier;
     97     union {
     98         struct ClassFilter ClassOnly;
     99         struct LocationFilter LocationOnly;
    100         struct ThreadFilter ThreadOnly;
    101         struct CountFilter Count;
    102         struct ConditionalFilter Conditional;
    103         struct FieldFilter FieldOnly;
    104         struct ExceptionFilter ExceptionOnly;
    105         struct InstanceFilter InstanceOnly;
    106         struct StepFilter Step;
    107         struct MatchFilter ClassMatch;
    108         struct MatchFilter ClassExclude;
    109         struct SourceNameFilter SourceNameOnly;
    110     } u;
    111 } Filter;
    112 
    113 /* The filters array is allocated to the specified filterCount.
    114  * Theoretically, some compiler could do range checking on this
    115  * array - so, we define it to have a ludicrously large size so
    116  * that this range checking won't get upset.
    117  *
    118  * The actual allocated number of bytes is computed using the
    119  * offset of "filters" and so is not effected by this number.
    120  */
    121 #define MAX_FILTERS 10000
    122 
    123 typedef struct EventFilters_ {
    124     jint filterCount;
    125     Filter filters[MAX_FILTERS];
    126 } EventFilters;
    127 
    128 typedef struct EventFilterPrivate_HandlerNode_ {
    129     EventHandlerRestricted_HandlerNode   not_for_us;
    130     EventFilters                         ef;
    131 } EventFilterPrivate_HandlerNode;
    132 
    133 /**
    134  * The following macros extract filter info (EventFilters) from private
    135  * data at the end of a HandlerNode
    136  */
    137 #define EVENT_FILTERS(node) (&(((EventFilterPrivate_HandlerNode*)(void*)node)->ef))
    138 #define FILTER_COUNT(node)  (EVENT_FILTERS(node)->filterCount)
    139 #define FILTERS_ARRAY(node) (EVENT_FILTERS(node)->filters)
    140 #define FILTER(node,index)  ((FILTERS_ARRAY(node))[index])
    141 #define NODE_EI(node)          (node->ei)
    142 
    143 /***** filter set-up / destruction *****/
    144 
    145 /**
    146  * Allocate a HandlerNode.
    147  * We do it because eventHandler doesn't know how big to make it.
    148  */
    149 HandlerNode *
    150 eventFilterRestricted_alloc(jint filterCount)
    151 {
    152     /*LINTED*/
    153     size_t size = offsetof(EventFilterPrivate_HandlerNode, ef) +
    154                   offsetof(EventFilters, filters) +
    155                   (filterCount * (int)sizeof(Filter));
    156     HandlerNode *node = jvmtiAllocate((jint)size);
    157 
    158     if (node != NULL) {
    159         int i;
    160         Filter *filter;
    161 
    162         (void)memset(node, 0, size);
    163 
    164         FILTER_COUNT(node) = filterCount;
    165 
    166         /* Initialize all modifiers
    167          */
    168         for (i = 0, filter = FILTERS_ARRAY(node);
    169                                     i < filterCount;
    170                                     i++, filter++) {
    171             filter->modifier = JDWP_REQUEST_NONE;
    172         }
    173     }
    174 
    175     return node;
    176 }
    177 
    178 /**
    179  * Free up global refs held by the filter.
    180  * free things up at the JNI level if needed.
    181  */
    182 static jvmtiError
    183 clearFilters(HandlerNode *node)
    184 {
    185     JNIEnv *env = getEnv();
    186     jint i;
    187     jvmtiError error = JVMTI_ERROR_NONE;
    188     Filter *filter = FILTERS_ARRAY(node);
    189 
    190     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
    191         switch (filter->modifier) {
    192             case JDWP_REQUEST_MODIFIER(ThreadOnly):
    193                 if ( filter->u.ThreadOnly.thread != NULL ) {
    194                     tossGlobalRef(env, &(filter->u.ThreadOnly.thread));
    195                 }
    196                 break;
    197             case JDWP_REQUEST_MODIFIER(LocationOnly):
    198                 tossGlobalRef(env, &(filter->u.LocationOnly.clazz));
    199                 break;
    200             case JDWP_REQUEST_MODIFIER(FieldOnly):
    201                 tossGlobalRef(env, &(filter->u.FieldOnly.clazz));
    202                 break;
    203             case JDWP_REQUEST_MODIFIER(ExceptionOnly):
    204                 if ( filter->u.ExceptionOnly.exception != NULL ) {
    205                     tossGlobalRef(env, &(filter->u.ExceptionOnly.exception));
    206                 }
    207                 break;
    208             case JDWP_REQUEST_MODIFIER(InstanceOnly):
    209                 if ( filter->u.InstanceOnly.instance != NULL ) {
    210                     tossGlobalRef(env, &(filter->u.InstanceOnly.instance));
    211                 }
    212                 break;
    213             case JDWP_REQUEST_MODIFIER(ClassOnly):
    214                 tossGlobalRef(env, &(filter->u.ClassOnly.clazz));
    215                 break;
    216             case JDWP_REQUEST_MODIFIER(ClassMatch):
    217                 jvmtiDeallocate(filter->u.ClassMatch.classPattern);
    218                 break;
    219             case JDWP_REQUEST_MODIFIER(ClassExclude):
    220                 jvmtiDeallocate(filter->u.ClassExclude.classPattern);
    221                 break;
    222             case JDWP_REQUEST_MODIFIER(Step): {
    223                 jthread thread = filter->u.Step.thread;
    224                 error = stepControl_endStep(thread);
    225                 if (error == JVMTI_ERROR_NONE) {
    226                     tossGlobalRef(env, &(filter->u.Step.thread));
    227                 }
    228                 break;
    229             }
    230         }
    231     }
    232     if (error == JVMTI_ERROR_NONE) {
    233         FILTER_COUNT(node) = 0; /* blast so we don't clear again */
    234     }
    235 
    236     return error;
    237 }
    238 
    239 
    240 /***** filtering *****/
    241 
    242 /*
    243  * Match a string against a wildcard
    244  * string pattern.
    245  */
    246 static jboolean
    247 patternStringMatch(char *classname, const char *pattern)
    248 {
    249     int pattLen;
    250     int compLen;
    251     char *start;
    252     int offset;
    253 
    254     if ( pattern==NULL || classname==NULL ) {
    255         return JNI_FALSE;
    256     }
    257     pattLen = (int)strlen(pattern);
    258 
    259     if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) {
    260         /* An exact match is required when there is no *: bug 4331522 */
    261         return strcmp(pattern, classname) == 0;
    262     } else {
    263         compLen = pattLen - 1;
    264         offset = (int)strlen(classname) - compLen;
    265         if (offset < 0) {
    266             return JNI_FALSE;
    267         } else {
    268             if (pattern[0] == '*') {
    269                 pattern++;
    270                 start = classname + offset;
    271             }  else {
    272                 start = classname;
    273             }
    274             return strncmp(pattern, start, compLen) == 0;
    275         }
    276     }
    277 }
    278 
    279 static jboolean isVersionGte12x() {
    280     jint version;
    281     jvmtiError err =
    282         JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version);
    283 
    284     if (err == JVMTI_ERROR_NONE) {
    285         jint major, minor;
    286 
    287         major = (version & JVMTI_VERSION_MASK_MAJOR)
    288                     >> JVMTI_VERSION_SHIFT_MAJOR;
    289         minor = (version & JVMTI_VERSION_MASK_MINOR)
    290                     >> JVMTI_VERSION_SHIFT_MINOR;
    291         return (major > 1 || major == 1 && minor >= 2);
    292     } else {
    293         return JNI_FALSE;
    294     }
    295 }
    296 
    297 /* Return the object instance in which the event occurred */
    298 /* Return NULL if static or if an error occurs */
    299 static jobject
    300 eventInstance(EventInfo *evinfo)
    301 {
    302     jobject     object          = NULL;
    303     jthread     thread          ;
    304     jmethodID   method          ;
    305     jint        modifiers       = 0;
    306     jvmtiError  error;
    307 
    308     static jboolean got_version = JNI_FALSE;
    309     static jboolean is_version_gte_12x = JNI_FALSE;
    310 
    311     if (!got_version) {
    312         is_version_gte_12x = isVersionGte12x();
    313         got_version = JNI_TRUE;
    314     }
    315 
    316     switch (evinfo->ei) {
    317         case EI_SINGLE_STEP:
    318         case EI_BREAKPOINT:
    319         case EI_FRAME_POP:
    320         case EI_METHOD_ENTRY:
    321         case EI_METHOD_EXIT:
    322         case EI_EXCEPTION:
    323         case EI_EXCEPTION_CATCH:
    324         case EI_MONITOR_CONTENDED_ENTER:
    325         case EI_MONITOR_CONTENDED_ENTERED:
    326         case EI_MONITOR_WAIT:
    327         case EI_MONITOR_WAITED:
    328             thread      = evinfo->thread;
    329             method      = evinfo->method;
    330             break;
    331         case EI_FIELD_ACCESS:
    332         case EI_FIELD_MODIFICATION:
    333             object = evinfo->object;
    334             return object;
    335         default:
    336             return object; /* NULL */
    337     }
    338 
    339     error = methodModifiers(method, &modifiers);
    340 
    341     /* fail if error or static (0x8) */
    342     if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {
    343         FrameNumber fnum            = 0;
    344         if (is_version_gte_12x) {
    345             /* Use new 1.2.x function, GetLocalInstance */
    346             error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
    347                         (gdata->jvmti, thread, fnum, &object);
    348         } else {
    349             /* get slot zero object "this" */
    350             error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
    351                         (gdata->jvmti, thread, fnum, 0, &object);
    352         }
    353         if (error != JVMTI_ERROR_NONE) {
    354             object = NULL;
    355         }
    356     }
    357 
    358     return object;
    359 }
    360 
    361 /*
    362  * Determine if this event is interesting to this handler.
    363  * Do so by checking each of the handler's filters.
    364  * Return false if any of the filters fail,
    365  * true if the handler wants this event.
    366  * Anyone modifying this function should check
    367  * eventFilterRestricted_passesUnloadFilter and
    368  * eventFilter_predictFiltering as well.
    369  *
    370  * If shouldDelete is returned true, a count filter has expired
    371  * and the corresponding node should be deleted.
    372  */
    373 jboolean
    374 eventFilterRestricted_passesFilter(JNIEnv *env,
    375                                    char *classname,
    376                                    EventInfo *evinfo,
    377                                    HandlerNode *node,
    378                                    jboolean *shouldDelete)
    379 {
    380     jthread thread;
    381     jclass clazz;
    382     jmethodID method;
    383     Filter *filter = FILTERS_ARRAY(node);
    384     int i;
    385 
    386     *shouldDelete = JNI_FALSE;
    387     thread = evinfo->thread;
    388     clazz = evinfo->clazz;
    389     method = evinfo->method;
    390 
    391     /*
    392      * Suppress most events if they happen in debug threads
    393      */
    394     if ((evinfo->ei != EI_CLASS_PREPARE) &&
    395         (evinfo->ei != EI_GC_FINISH) &&
    396         (evinfo->ei != EI_CLASS_LOAD) &&
    397         threadControl_isDebugThread(thread)) {
    398         return JNI_FALSE;
    399     }
    400 
    401     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
    402         switch (filter->modifier) {
    403             case JDWP_REQUEST_MODIFIER(ThreadOnly):
    404                 if (!isSameObject(env, thread, filter->u.ThreadOnly.thread)) {
    405                     return JNI_FALSE;
    406                 }
    407                 break;
    408 
    409             case JDWP_REQUEST_MODIFIER(ClassOnly):
    410                 /* Class filters catch events in the specified
    411                  * class and any subclass/subinterface.
    412                  */
    413                 if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz,
    414                                filter->u.ClassOnly.clazz)) {
    415                     return JNI_FALSE;
    416                 }
    417                 break;
    418 
    419             /* This is kinda cheating assumming the event
    420              * fields will be in the same locations, but it is
    421              * true now.
    422              */
    423             case JDWP_REQUEST_MODIFIER(LocationOnly):
    424                 if  (evinfo->method !=
    425                           filter->u.LocationOnly.method ||
    426                      evinfo->location !=
    427                           filter->u.LocationOnly.location ||
    428                      !isSameObject(env, clazz, filter->u.LocationOnly.clazz)) {
    429                     return JNI_FALSE;
    430                 }
    431                 break;
    432 
    433             case JDWP_REQUEST_MODIFIER(FieldOnly):
    434                 /* Field watchpoints can be triggered from the
    435                  * declared class or any subclass/subinterface.
    436                  */
    437                 if ((evinfo->u.field_access.field !=
    438                      filter->u.FieldOnly.field) ||
    439                     !isSameObject(env, evinfo->u.field_access.field_clazz,
    440                                filter->u.FieldOnly.clazz)) {
    441                     return JNI_FALSE;
    442                 }
    443                 break;
    444 
    445             case JDWP_REQUEST_MODIFIER(ExceptionOnly):
    446                 /* do we want caught/uncaught exceptions */
    447                 if (!((evinfo->u.exception.catch_clazz == NULL)?
    448                       filter->u.ExceptionOnly.uncaught :
    449                       filter->u.ExceptionOnly.caught)) {
    450                     return JNI_FALSE;
    451                 }
    452 
    453                 /* do we care about exception class */
    454                 if (filter->u.ExceptionOnly.exception != NULL) {
    455                     jclass exception = evinfo->object;
    456 
    457                     /* do we want this exception class */
    458                     if (!JNI_FUNC_PTR(env,IsInstanceOf)(env, exception,
    459                             filter->u.ExceptionOnly.exception)) {
    460                         return JNI_FALSE;
    461                     }
    462                 }
    463                 break;
    464 
    465             case JDWP_REQUEST_MODIFIER(InstanceOnly): {
    466                 jobject eventInst = eventInstance(evinfo);
    467                 jobject filterInst = filter->u.InstanceOnly.instance;
    468                 /* if no error and doesn't match, don't pass
    469                  * filter
    470                  */
    471                 if (eventInst != NULL &&
    472                       !isSameObject(env, eventInst, filterInst)) {
    473                     return JNI_FALSE;
    474                 }
    475                 break;
    476             }
    477             case JDWP_REQUEST_MODIFIER(Count): {
    478                 JDI_ASSERT(filter->u.Count.count > 0);
    479                 if (--filter->u.Count.count > 0) {
    480                     return JNI_FALSE;
    481                 }
    482                 *shouldDelete = JNI_TRUE;
    483                 break;
    484             }
    485 
    486             case JDWP_REQUEST_MODIFIER(Conditional):
    487 /***
    488                 if (...  filter->u.Conditional.exprID ...) {
    489                     return JNI_FALSE;
    490                 }
    491 ***/
    492                 break;
    493 
    494         case JDWP_REQUEST_MODIFIER(ClassMatch): {
    495             if (!patternStringMatch(classname,
    496                        filter->u.ClassMatch.classPattern)) {
    497                 return JNI_FALSE;
    498             }
    499             break;
    500         }
    501 
    502         case JDWP_REQUEST_MODIFIER(ClassExclude): {
    503             if (patternStringMatch(classname,
    504                       filter->u.ClassExclude.classPattern)) {
    505                 return JNI_FALSE;
    506             }
    507             break;
    508         }
    509 
    510         case JDWP_REQUEST_MODIFIER(Step):
    511                 if (!isSameObject(env, thread, filter->u.Step.thread)) {
    512                     return JNI_FALSE;
    513                 }
    514                 if (!stepControl_handleStep(env, thread, clazz, method)) {
    515                     return JNI_FALSE;
    516                 }
    517                 break;
    518 
    519           case JDWP_REQUEST_MODIFIER(SourceNameMatch): {
    520               char* desiredNamePattern = filter->u.SourceNameOnly.sourceNamePattern;
    521               if (!searchAllSourceNames(env, clazz,
    522                            desiredNamePattern) == 1) {
    523                   /* The name isn't in the SDE; try the sourceName in the ref
    524                    * type
    525                    */
    526                   char *sourceName = 0;
    527                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
    528                                             (gdata->jvmti, clazz, &sourceName);
    529                   if (error == JVMTI_ERROR_NONE &&
    530                       sourceName != 0 &&
    531                       patternStringMatch(sourceName, desiredNamePattern)) {
    532                           // got a hit - report the event
    533                           jvmtiDeallocate(sourceName);
    534                           break;
    535                   }
    536                   // We have no match, we have no source file name,
    537                   // or we got a JVM TI error. Don't report the event.
    538                   jvmtiDeallocate(sourceName);
    539                   return JNI_FALSE;
    540               }
    541               break;
    542           }
    543 
    544         default:
    545             EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
    546             return JNI_FALSE;
    547         }
    548     }
    549     return JNI_TRUE;
    550 }
    551 
    552 /* Determine if this event is interesting to this handler.  Do so
    553  * by checking each of the handler's filters.  Return false if any
    554  * of the filters fail, true if the handler wants this event.
    555  * Special version of filter for unloads since they don't have an
    556  * event structure or a jclass.
    557  *
    558  * If shouldDelete is returned true, a count filter has expired
    559  * and the corresponding node should be deleted.
    560  */
    561 jboolean
    562 eventFilterRestricted_passesUnloadFilter(JNIEnv *env,
    563                                          char *classname,
    564                                          HandlerNode *node,
    565                                          jboolean *shouldDelete)
    566 {
    567     Filter *filter = FILTERS_ARRAY(node);
    568     int i;
    569 
    570     *shouldDelete = JNI_FALSE;
    571     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
    572         switch (filter->modifier) {
    573 
    574             case JDWP_REQUEST_MODIFIER(Count): {
    575                 JDI_ASSERT(filter->u.Count.count > 0);
    576                 if (--filter->u.Count.count > 0) {
    577                     return JNI_FALSE;
    578                 }
    579                 *shouldDelete = JNI_TRUE;
    580                 break;
    581             }
    582 
    583             case JDWP_REQUEST_MODIFIER(ClassMatch): {
    584                 if (!patternStringMatch(classname,
    585                         filter->u.ClassMatch.classPattern)) {
    586                     return JNI_FALSE;
    587                 }
    588                 break;
    589             }
    590 
    591             case JDWP_REQUEST_MODIFIER(ClassExclude): {
    592                 if (patternStringMatch(classname,
    593                        filter->u.ClassExclude.classPattern)) {
    594                     return JNI_FALSE;
    595                 }
    596                 break;
    597             }
    598 
    599             default:
    600                 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
    601                 return JNI_FALSE;
    602         }
    603     }
    604     return JNI_TRUE;
    605 }
    606 
    607 /**
    608  * This function returns true only if it is certain that
    609  * all events for the given node in the given stack frame will
    610  * be filtered. It is used to optimize stepping. (If this
    611  * function returns true the stepping algorithm does not
    612  * have to step through every instruction in this stack frame;
    613  * instead, it can use more efficient method entry/exit
    614  * events.
    615  */
    616 jboolean
    617 eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname)
    618 {
    619     JNIEnv     *env;
    620     jboolean    willBeFiltered;
    621     Filter     *filter;
    622     jboolean    done;
    623     int         count;
    624     int         i;
    625 
    626     willBeFiltered = JNI_FALSE;
    627     env            = NULL;
    628     filter         = FILTERS_ARRAY(node);
    629     count          = FILTER_COUNT(node);
    630     done           = JNI_FALSE;
    631 
    632     for (i = 0; (i < count) && (!done); ++i, ++filter) {
    633         switch (filter->modifier) {
    634             case JDWP_REQUEST_MODIFIER(ClassOnly):
    635                 if ( env==NULL ) {
    636                     env = getEnv();
    637                 }
    638                 if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz,
    639                                  filter->u.ClassOnly.clazz)) {
    640                     willBeFiltered = JNI_TRUE;
    641                     done = JNI_TRUE;
    642                 }
    643                 break;
    644 
    645             case JDWP_REQUEST_MODIFIER(Count): {
    646                 /*
    647                  * If preceding filters have determined that events will
    648                  * be filtered out, that is fine and we won't get here.
    649                  * However, the count must be decremented - even if
    650                  * subsequent filters will filter these events.  We
    651                  * thus must end now unable to predict
    652                  */
    653                 done = JNI_TRUE;
    654                 break;
    655             }
    656 
    657             case JDWP_REQUEST_MODIFIER(ClassMatch): {
    658                 if (!patternStringMatch(classname,
    659                         filter->u.ClassMatch.classPattern)) {
    660                     willBeFiltered = JNI_TRUE;
    661                     done = JNI_TRUE;
    662                 }
    663                 break;
    664             }
    665 
    666             case JDWP_REQUEST_MODIFIER(ClassExclude): {
    667                 if (patternStringMatch(classname,
    668                        filter->u.ClassExclude.classPattern)) {
    669                     willBeFiltered = JNI_TRUE;
    670                     done = JNI_TRUE;
    671                 }
    672                 break;
    673             }
    674         }
    675     }
    676 
    677     return willBeFiltered;
    678 }
    679 
    680 /**
    681  * Determine if the given breakpoint node is in the specified class.
    682  */
    683 jboolean
    684 eventFilterRestricted_isBreakpointInClass(JNIEnv *env, jclass clazz,
    685                                           HandlerNode *node)
    686 {
    687     Filter *filter = FILTERS_ARRAY(node);
    688     int i;
    689 
    690     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
    691         switch (filter->modifier) {
    692             case JDWP_REQUEST_MODIFIER(LocationOnly):
    693                 return isSameObject(env, clazz, filter->u.LocationOnly.clazz);
    694         }
    695     }
    696     return JNI_TRUE; /* should never come here */
    697 }
    698 
    699 /***** filter set-up *****/
    700 
    701 jvmtiError
    702 eventFilter_setConditionalFilter(HandlerNode *node, jint index,
    703                                  jint exprID)
    704 {
    705     ConditionalFilter *filter = &FILTER(node, index).u.Conditional;
    706     if (index >= FILTER_COUNT(node)) {
    707         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    708     }
    709     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Conditional);
    710     filter->exprID = exprID;
    711     return JVMTI_ERROR_NONE;
    712 }
    713 
    714 jvmtiError
    715 eventFilter_setCountFilter(HandlerNode *node, jint index,
    716                            jint count)
    717 {
    718     CountFilter *filter = &FILTER(node, index).u.Count;
    719     if (index >= FILTER_COUNT(node)) {
    720         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    721     }
    722     if (count <= 0) {
    723         return JDWP_ERROR(INVALID_COUNT);
    724     } else {
    725         FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Count);
    726         filter->count = count;
    727         return JVMTI_ERROR_NONE;
    728     }
    729 }
    730 
    731 jvmtiError
    732 eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index,
    733                                 jthread thread)
    734 {
    735     JNIEnv *env = getEnv();
    736     ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly;
    737     if (index >= FILTER_COUNT(node)) {
    738         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    739     }
    740     if (NODE_EI(node) == EI_GC_FINISH) {
    741         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    742     }
    743 
    744     /* Create a thread ref that will live beyond */
    745     /* the end of this call */
    746     saveGlobalRef(env, thread, &(filter->thread));
    747     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly);
    748     return JVMTI_ERROR_NONE;
    749 }
    750 
    751 jvmtiError
    752 eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index,
    753                                   jclass clazz, jmethodID method,
    754                                   jlocation location)
    755 {
    756     JNIEnv *env = getEnv();
    757     LocationFilter *filter = &FILTER(node, index).u.LocationOnly;
    758     if (index >= FILTER_COUNT(node)) {
    759         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    760     }
    761     if ((NODE_EI(node) != EI_BREAKPOINT) &&
    762         (NODE_EI(node) != EI_FIELD_ACCESS) &&
    763         (NODE_EI(node) != EI_FIELD_MODIFICATION) &&
    764         (NODE_EI(node) != EI_SINGLE_STEP) &&
    765         (NODE_EI(node) != EI_EXCEPTION)) {
    766 
    767         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    768     }
    769 
    770     /* Create a class ref that will live beyond */
    771     /* the end of this call */
    772     saveGlobalRef(env, clazz, &(filter->clazz));
    773     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly);
    774     filter->method = method;
    775     filter->location = location;
    776     return JVMTI_ERROR_NONE;
    777 }
    778 
    779 jvmtiError
    780 eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index,
    781                                jclass clazz, jfieldID field)
    782 {
    783     JNIEnv *env = getEnv();
    784     FieldFilter *filter = &FILTER(node, index).u.FieldOnly;
    785     if (index >= FILTER_COUNT(node)) {
    786         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    787     }
    788     if ((NODE_EI(node) != EI_FIELD_ACCESS) &&
    789         (NODE_EI(node) != EI_FIELD_MODIFICATION)) {
    790 
    791         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    792     }
    793 
    794     /* Create a class ref that will live beyond */
    795     /* the end of this call */
    796     saveGlobalRef(env, clazz, &(filter->clazz));
    797     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly);
    798     filter->field = field;
    799     return JVMTI_ERROR_NONE;
    800 }
    801 
    802 jvmtiError
    803 eventFilter_setClassOnlyFilter(HandlerNode *node, jint index,
    804                                jclass clazz)
    805 {
    806     JNIEnv *env = getEnv();
    807     ClassFilter *filter = &FILTER(node, index).u.ClassOnly;
    808     if (index >= FILTER_COUNT(node)) {
    809         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    810     }
    811     if (
    812         (NODE_EI(node) == EI_GC_FINISH) ||
    813         (NODE_EI(node) == EI_THREAD_START) ||
    814         (NODE_EI(node) == EI_THREAD_END)) {
    815 
    816         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    817     }
    818 
    819     /* Create a class ref that will live beyond */
    820     /* the end of this call */
    821     saveGlobalRef(env, clazz, &(filter->clazz));
    822     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly);
    823     return JVMTI_ERROR_NONE;
    824 }
    825 
    826 jvmtiError
    827 eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index,
    828                                    jclass exceptionClass,
    829                                    jboolean caught,
    830                                    jboolean uncaught)
    831 {
    832     JNIEnv *env = getEnv();
    833     ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly;
    834     if (index >= FILTER_COUNT(node)) {
    835         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    836     }
    837     if (NODE_EI(node) != EI_EXCEPTION) {
    838         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    839     }
    840 
    841     filter->exception = NULL;
    842     if (exceptionClass != NULL) {
    843         /* Create a class ref that will live beyond */
    844         /* the end of this call */
    845         saveGlobalRef(env, exceptionClass, &(filter->exception));
    846     }
    847     FILTER(node, index).modifier =
    848                        JDWP_REQUEST_MODIFIER(ExceptionOnly);
    849     filter->caught = caught;
    850     filter->uncaught = uncaught;
    851     return JVMTI_ERROR_NONE;
    852 }
    853 
    854 jvmtiError
    855 eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index,
    856                                   jobject instance)
    857 {
    858     JNIEnv *env = getEnv();
    859     InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly;
    860     if (index >= FILTER_COUNT(node)) {
    861         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    862     }
    863 
    864     filter->instance = NULL;
    865     if (instance != NULL) {
    866         /* Create an object ref that will live beyond
    867          * the end of this call
    868          */
    869         saveGlobalRef(env, instance, &(filter->instance));
    870     }
    871     FILTER(node, index).modifier =
    872                        JDWP_REQUEST_MODIFIER(InstanceOnly);
    873     return JVMTI_ERROR_NONE;
    874 }
    875 
    876 jvmtiError
    877 eventFilter_setClassMatchFilter(HandlerNode *node, jint index,
    878                                 char *classPattern)
    879 {
    880     MatchFilter *filter = &FILTER(node, index).u.ClassMatch;
    881     if (index >= FILTER_COUNT(node)) {
    882         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    883     }
    884     if (
    885         (NODE_EI(node) == EI_THREAD_START) ||
    886         (NODE_EI(node) == EI_THREAD_END)) {
    887 
    888         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    889     }
    890 
    891     FILTER(node, index).modifier =
    892                        JDWP_REQUEST_MODIFIER(ClassMatch);
    893     filter->classPattern = classPattern;
    894     return JVMTI_ERROR_NONE;
    895 }
    896 
    897 jvmtiError
    898 eventFilter_setClassExcludeFilter(HandlerNode *node, jint index,
    899                                   char *classPattern)
    900 {
    901     MatchFilter *filter = &FILTER(node, index).u.ClassExclude;
    902     if (index >= FILTER_COUNT(node)) {
    903         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    904     }
    905     if (
    906         (NODE_EI(node) == EI_THREAD_START) ||
    907         (NODE_EI(node) == EI_THREAD_END)) {
    908 
    909         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    910     }
    911 
    912     FILTER(node, index).modifier =
    913                        JDWP_REQUEST_MODIFIER(ClassExclude);
    914     filter->classPattern = classPattern;
    915     return JVMTI_ERROR_NONE;
    916 }
    917 
    918 jvmtiError
    919 eventFilter_setStepFilter(HandlerNode *node, jint index,
    920                           jthread thread, jint size, jint depth)
    921 {
    922     jvmtiError error;
    923     JNIEnv *env = getEnv();
    924     StepFilter *filter = &FILTER(node, index).u.Step;
    925     if (index >= FILTER_COUNT(node)) {
    926         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    927     }
    928     if (NODE_EI(node) != EI_SINGLE_STEP) {
    929         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    930     }
    931 
    932     /* Create a thread ref that will live beyond */
    933     /* the end of this call */
    934     saveGlobalRef(env, thread, &(filter->thread));
    935     error = stepControl_beginStep(env, filter->thread, size, depth, node);
    936     if (error != JVMTI_ERROR_NONE) {
    937         tossGlobalRef(env, &(filter->thread));
    938         return error;
    939     }
    940     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step);
    941     filter->depth = depth;
    942     filter->size = size;
    943     return JVMTI_ERROR_NONE;
    944 }
    945 
    946 
    947 jvmtiError
    948 eventFilter_setSourceNameMatchFilter(HandlerNode *node,
    949                                     jint index,
    950                                     char *sourceNamePattern) {
    951     SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly;
    952     if (index >= FILTER_COUNT(node)) {
    953         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    954     }
    955     if (NODE_EI(node) != EI_CLASS_PREPARE) {
    956         return AGENT_ERROR_ILLEGAL_ARGUMENT;
    957     }
    958 
    959     FILTER(node, index).modifier =
    960                        JDWP_REQUEST_MODIFIER(SourceNameMatch);
    961     filter->sourceNamePattern = sourceNamePattern;
    962     return JVMTI_ERROR_NONE;
    963 
    964 }
    965 
    966 /***** JVMTI event enabling / disabling *****/
    967 
    968 /**
    969  * Return the Filter that is of the specified type (modifier).
    970  * Return NULL if not found.
    971  */
    972 static Filter *
    973 findFilter(HandlerNode *node, jint modifier)
    974 {
    975     int i;
    976     Filter *filter;
    977     for (i = 0, filter = FILTERS_ARRAY(node);
    978                       i <FILTER_COUNT(node);
    979                       i++, filter++) {
    980         if (filter->modifier == modifier) {
    981             return filter;
    982         }
    983     }
    984     return NULL;
    985 }
    986 
    987 /**
    988  * Determine if the specified breakpoint node is in the
    989  * same location as the LocationFilter passed in arg.
    990  *
    991  * This is a match function called by a
    992  * eventHandlerRestricted_iterator invokation.
    993  */
    994 static jboolean
    995 matchBreakpoint(JNIEnv *env, HandlerNode *node, void *arg)
    996 {
    997     LocationFilter *goal = (LocationFilter *)arg;
    998     Filter *filter = FILTERS_ARRAY(node);
    999     int i;
   1000 
   1001     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
   1002         switch (filter->modifier) {
   1003         case JDWP_REQUEST_MODIFIER(LocationOnly): {
   1004             LocationFilter *trial = &(filter->u.LocationOnly);
   1005             if (trial->method == goal->method &&
   1006                 trial->location == goal->location &&
   1007                 isSameObject(env, trial->clazz, goal->clazz)) {
   1008                 return JNI_TRUE;
   1009             }
   1010         }
   1011         }
   1012     }
   1013     return JNI_FALSE;
   1014 }
   1015 
   1016 /**
   1017  * Set a breakpoint if this is the first one at this location.
   1018  */
   1019 static jvmtiError
   1020 setBreakpoint(HandlerNode *node)
   1021 {
   1022     jvmtiError error = JVMTI_ERROR_NONE;
   1023     Filter *filter;
   1024 
   1025     filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly));
   1026     if (filter == NULL) {
   1027         /* bp event with no location filter */
   1028         error = AGENT_ERROR_INTERNAL;
   1029     } else {
   1030         LocationFilter *lf = &(filter->u.LocationOnly);
   1031 
   1032         /* if this is the first handler for this
   1033          * location, set bp at JVMTI level
   1034          */
   1035         if (!eventHandlerRestricted_iterator(
   1036                 EI_BREAKPOINT, matchBreakpoint, lf)) {
   1037             LOG_LOC(("SetBreakpoint at location: method=%p,location=%d",
   1038                         lf->method, (int)lf->location));
   1039             error = JVMTI_FUNC_PTR(gdata->jvmti,SetBreakpoint)
   1040                         (gdata->jvmti, lf->method, lf->location);
   1041         }
   1042     }
   1043     return error;
   1044 }
   1045 
   1046 /**
   1047  * Clear a breakpoint if this is the last one at this location.
   1048  */
   1049 static jvmtiError
   1050 clearBreakpoint(HandlerNode *node)
   1051 {
   1052     jvmtiError error = JVMTI_ERROR_NONE;
   1053     Filter *filter;
   1054 
   1055     filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly));
   1056     if (filter == NULL) {
   1057         /* bp event with no location filter */
   1058         error = AGENT_ERROR_INTERNAL;
   1059     } else {
   1060         LocationFilter *lf = &(filter->u.LocationOnly);
   1061 
   1062         /* if this is the last handler for this
   1063          * location, clear bp at JVMTI level
   1064          */
   1065         if (!eventHandlerRestricted_iterator(
   1066                 EI_BREAKPOINT, matchBreakpoint, lf)) {
   1067             LOG_LOC(("ClearBreakpoint at location: method=%p,location=%d",
   1068                         lf->method, (int)lf->location));
   1069             error = JVMTI_FUNC_PTR(gdata->jvmti,ClearBreakpoint)
   1070                         (gdata->jvmti, lf->method, lf->location);
   1071         }
   1072     }
   1073     return error;
   1074 }
   1075 
   1076 /**
   1077  * Return true if a breakpoint is set at the specified location.
   1078  */
   1079 jboolean
   1080 isBreakpointSet(jclass clazz, jmethodID method, jlocation location)
   1081 {
   1082     LocationFilter lf;
   1083 
   1084     lf.clazz    = clazz;
   1085     lf.method   = method;
   1086     lf.location = location;
   1087 
   1088     return eventHandlerRestricted_iterator(EI_BREAKPOINT,
   1089                                            matchBreakpoint, &lf);
   1090 }
   1091 
   1092 /**
   1093  * Determine if the specified watchpoint node has the
   1094  * same field as the FieldFilter passed in arg.
   1095  *
   1096  * This is a match function called by a
   1097  * eventHandlerRestricted_iterator invokation.
   1098  */
   1099 static jboolean
   1100 matchWatchpoint(JNIEnv *env, HandlerNode *node, void *arg)
   1101 {
   1102     FieldFilter *goal = (FieldFilter *)arg;
   1103     Filter *filter = FILTERS_ARRAY(node);
   1104     int i;
   1105 
   1106     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
   1107         switch (filter->modifier) {
   1108         case JDWP_REQUEST_MODIFIER(FieldOnly): {
   1109             FieldFilter *trial = &(filter->u.FieldOnly);
   1110             if (trial->field == goal->field &&
   1111                 isSameObject(env, trial->clazz, goal->clazz)) {
   1112                 return JNI_TRUE;
   1113             }
   1114         }
   1115         }
   1116     }
   1117     return JNI_FALSE;
   1118 }
   1119 
   1120 /**
   1121  * Set a watchpoint if this is the first one on this field.
   1122  */
   1123 static jvmtiError
   1124 setWatchpoint(HandlerNode *node)
   1125 {
   1126     jvmtiError error = JVMTI_ERROR_NONE;
   1127     Filter *filter;
   1128 
   1129     filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly));
   1130     if (filter == NULL) {
   1131         /* event with no field filter */
   1132         error = AGENT_ERROR_INTERNAL;
   1133     } else {
   1134         FieldFilter *ff = &(filter->u.FieldOnly);
   1135 
   1136         /* if this is the first handler for this
   1137          * field, set wp at JVMTI level
   1138          */
   1139         if (!eventHandlerRestricted_iterator(
   1140                 NODE_EI(node), matchWatchpoint, ff)) {
   1141             error = (NODE_EI(node) == EI_FIELD_ACCESS) ?
   1142                 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldAccessWatch)
   1143                         (gdata->jvmti, ff->clazz, ff->field) :
   1144                 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldModificationWatch)
   1145                         (gdata->jvmti, ff->clazz, ff->field);
   1146         }
   1147     }
   1148     return error;
   1149 }
   1150 
   1151 /**
   1152  * Clear a watchpoint if this is the last one on this field.
   1153  */
   1154 static jvmtiError
   1155 clearWatchpoint(HandlerNode *node)
   1156 {
   1157     jvmtiError error = JVMTI_ERROR_NONE;
   1158     Filter *filter;
   1159 
   1160     filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly));
   1161     if (filter == NULL) {
   1162         /* event with no field filter */
   1163         error = AGENT_ERROR_INTERNAL;
   1164     } else {
   1165         FieldFilter *ff = &(filter->u.FieldOnly);
   1166 
   1167         /* if this is the last handler for this
   1168          * field, clear wp at JVMTI level
   1169          */
   1170         if (!eventHandlerRestricted_iterator(
   1171                 NODE_EI(node), matchWatchpoint, ff)) {
   1172             error = (NODE_EI(node) == EI_FIELD_ACCESS) ?
   1173                 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldAccessWatch)
   1174                         (gdata->jvmti, ff->clazz, ff->field) :
   1175                 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldModificationWatch)
   1176                                 (gdata->jvmti, ff->clazz, ff->field);
   1177         }
   1178     }
   1179     return error;
   1180 }
   1181 
   1182 /**
   1183  * Determine the thread this node is filtered on.
   1184  * NULL if not thread filtered.
   1185  */
   1186 static jthread
   1187 requestThread(HandlerNode *node)
   1188 {
   1189     int i;
   1190     Filter *filter = FILTERS_ARRAY(node);
   1191 
   1192     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
   1193         switch (filter->modifier) {
   1194             case JDWP_REQUEST_MODIFIER(ThreadOnly):
   1195                 return filter->u.ThreadOnly.thread;
   1196         }
   1197     }
   1198 
   1199     return NULL;
   1200 }
   1201 
   1202 /**
   1203  * Determine if the specified node has a
   1204  * thread filter with the thread passed in arg.
   1205  *
   1206  * This is a match function called by a
   1207  * eventHandlerRestricted_iterator invokation.
   1208  */
   1209 static jboolean
   1210 matchThread(JNIEnv *env, HandlerNode *node, void *arg)
   1211 {
   1212     jthread goalThread = (jthread)arg;
   1213     jthread reqThread = requestThread(node);
   1214 
   1215     /* If the event's thread and the passed thread are the same
   1216      * (or both are NULL), we have a match.
   1217      */
   1218     return isSameObject(env, reqThread, goalThread);
   1219 }
   1220 
   1221 /**
   1222  * Do any enabling of events (including setting breakpoints etc)
   1223  * needed to get the events requested by this handler node.
   1224  */
   1225 static jvmtiError
   1226 enableEvents(HandlerNode *node)
   1227 {
   1228     jvmtiError error = JVMTI_ERROR_NONE;
   1229 
   1230     switch (NODE_EI(node)) {
   1231         /* The stepping code directly enables/disables stepping as
   1232          * necessary
   1233          */
   1234         case EI_SINGLE_STEP:
   1235         /* Internal thread event handlers are always present
   1236          * (hardwired in the event hook), so we don't change the
   1237          * notification mode here.
   1238          */
   1239         case EI_THREAD_START:
   1240         case EI_THREAD_END:
   1241         case EI_VM_INIT:
   1242         case EI_VM_DEATH:
   1243         case EI_CLASS_PREPARE:
   1244         case EI_GC_FINISH:
   1245             return error;
   1246 
   1247         case EI_FIELD_ACCESS:
   1248         case EI_FIELD_MODIFICATION:
   1249             error = setWatchpoint(node);
   1250             break;
   1251 
   1252         case EI_BREAKPOINT:
   1253             error = setBreakpoint(node);
   1254             break;
   1255 
   1256         default:
   1257             break;
   1258     }
   1259 
   1260     /* Don't globally enable if the above failed */
   1261     if (error == JVMTI_ERROR_NONE) {
   1262         jthread thread = requestThread(node);
   1263 
   1264         /* If this is the first request of it's kind on this
   1265          * thread (or all threads (thread == NULL)) then enable
   1266          * these events on this thread.
   1267          */
   1268         if (!eventHandlerRestricted_iterator(
   1269                 NODE_EI(node), matchThread, thread)) {
   1270             error = threadControl_setEventMode(JVMTI_ENABLE,
   1271                                                NODE_EI(node), thread);
   1272         }
   1273     }
   1274     return error;
   1275 }
   1276 
   1277 /**
   1278  * Do any disabling of events (including clearing breakpoints etc)
   1279  * needed to no longer get the events requested by this handler node.
   1280  */
   1281 static jvmtiError
   1282 disableEvents(HandlerNode *node)
   1283 {
   1284     jvmtiError error = JVMTI_ERROR_NONE;
   1285     jvmtiError error2 = JVMTI_ERROR_NONE;
   1286     jthread thread;
   1287 
   1288 
   1289     switch (NODE_EI(node)) {
   1290         /* The stepping code directly enables/disables stepping as
   1291          * necessary
   1292          */
   1293         case EI_SINGLE_STEP:
   1294         /* Internal thread event handlers are always present
   1295          * (hardwired in the event hook), so we don't change the
   1296          * notification mode here.
   1297          */
   1298         case EI_THREAD_START:
   1299         case EI_THREAD_END:
   1300         case EI_VM_INIT:
   1301         case EI_VM_DEATH:
   1302         case EI_CLASS_PREPARE:
   1303         case EI_GC_FINISH:
   1304             return error;
   1305 
   1306         case EI_FIELD_ACCESS:
   1307         case EI_FIELD_MODIFICATION:
   1308             error = clearWatchpoint(node);
   1309             break;
   1310 
   1311         case EI_BREAKPOINT:
   1312             error = clearBreakpoint(node);
   1313             break;
   1314 
   1315         default:
   1316             break;
   1317     }
   1318 
   1319     thread = requestThread(node);
   1320 
   1321     /* If this is the last request of it's kind on this thread
   1322      * (or all threads (thread == NULL)) then disable these
   1323      * events on this thread.
   1324      *
   1325      * Disable even if the above caused an error
   1326      */
   1327     if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) {
   1328         error2 = threadControl_setEventMode(JVMTI_DISABLE,
   1329                                             NODE_EI(node), thread);
   1330     }
   1331     return error != JVMTI_ERROR_NONE? error : error2;
   1332 }
   1333 
   1334 
   1335 /***** filter (and event) installation and deinstallation *****/
   1336 
   1337 /**
   1338  * Make the set of event filters that correspond with this
   1339  * node active (including enabling the corresponding events).
   1340  */
   1341 jvmtiError
   1342 eventFilterRestricted_install(HandlerNode *node)
   1343 {
   1344     return enableEvents(node);
   1345 }
   1346 
   1347 /**
   1348  * Make the set of event filters that correspond with this
   1349  * node inactive (including disabling the corresponding events
   1350  * and freeing resources).
   1351  */
   1352 jvmtiError
   1353 eventFilterRestricted_deinstall(HandlerNode *node)
   1354 {
   1355     jvmtiError error1, error2;
   1356 
   1357     error1 = disableEvents(node);
   1358     error2 = clearFilters(node);
   1359 
   1360     return error1 != JVMTI_ERROR_NONE? error1 : error2;
   1361 }
   1362