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)) ? JNI_TRUE : JNI_FALSE;
 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 }