1 /*
   2  * Copyright (c) 2001, 2021, 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, desiredNamePattern) != 1) {
 522                   /* The name isn't in the SDE; try the sourceName in the ref
 523                    * type
 524                    */
 525                   char *sourceName = 0;
 526                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
 527                                             (gdata->jvmti, clazz, &sourceName);
 528                   if (error == JVMTI_ERROR_NONE &&
 529                       sourceName != 0 &&
 530                       patternStringMatch(sourceName, desiredNamePattern)) {
 531                           // got a hit - report the event
 532                           jvmtiDeallocate(sourceName);
 533                           break;
 534                   }
 535                   // We have no match, we have no source file name,
 536                   // or we got a JVM TI error. Don't report the event.
 537                   jvmtiDeallocate(sourceName);
 538                   return JNI_FALSE;
 539               }
 540               break;
 541           }
 542 
 543         default:
 544             EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
 545             return JNI_FALSE;
 546         }
 547     }
 548     return JNI_TRUE;
 549 }
 550 
 551 /* Determine if this event is interesting to this handler.  Do so
 552  * by checking each of the handler's filters.  Return false if any
 553  * of the filters fail, true if the handler wants this event.
 554  * Special version of filter for unloads since they don't have an
 555  * event structure or a jclass.
 556  *
 557  * If shouldDelete is returned true, a count filter has expired
 558  * and the corresponding node should be deleted.
 559  */
 560 jboolean
 561 eventFilterRestricted_passesUnloadFilter(JNIEnv *env,
 562                                          char *classname,
 563                                          HandlerNode *node,
 564                                          jboolean *shouldDelete)
 565 {
 566     Filter *filter = FILTERS_ARRAY(node);
 567     int i;
 568 
 569     *shouldDelete = JNI_FALSE;
 570     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
 571         switch (filter->modifier) {
 572 
 573             case JDWP_REQUEST_MODIFIER(Count): {
 574                 JDI_ASSERT(filter->u.Count.count > 0);
 575                 if (--filter->u.Count.count > 0) {
 576                     return JNI_FALSE;
 577                 }
 578                 *shouldDelete = JNI_TRUE;
 579                 break;
 580             }
 581 
 582             case JDWP_REQUEST_MODIFIER(ClassMatch): {
 583                 if (!patternStringMatch(classname,
 584                         filter->u.ClassMatch.classPattern)) {
 585                     return JNI_FALSE;
 586                 }
 587                 break;
 588             }
 589 
 590             case JDWP_REQUEST_MODIFIER(ClassExclude): {
 591                 if (patternStringMatch(classname,
 592                        filter->u.ClassExclude.classPattern)) {
 593                     return JNI_FALSE;
 594                 }
 595                 break;
 596             }
 597 
 598             default:
 599                 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
 600                 return JNI_FALSE;
 601         }
 602     }
 603     return JNI_TRUE;
 604 }
 605 
 606 /**
 607  * This function returns true only if it is certain that
 608  * all events for the given node in the given stack frame will
 609  * be filtered. It is used to optimize stepping. (If this
 610  * function returns true the stepping algorithm does not
 611  * have to step through every instruction in this stack frame;
 612  * instead, it can use more efficient method entry/exit
 613  * events.
 614  */
 615 jboolean
 616 eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname)
 617 {
 618     JNIEnv     *env;
 619     jboolean    willBeFiltered;
 620     Filter     *filter;
 621     jboolean    done;
 622     int         count;
 623     int         i;
 624 
 625     willBeFiltered = JNI_FALSE;
 626     env            = NULL;
 627     filter         = FILTERS_ARRAY(node);
 628     count          = FILTER_COUNT(node);
 629     done           = JNI_FALSE;
 630 
 631     for (i = 0; (i < count) && (!done); ++i, ++filter) {
 632         switch (filter->modifier) {
 633             case JDWP_REQUEST_MODIFIER(ClassOnly):
 634                 if ( env==NULL ) {
 635                     env = getEnv();
 636                 }
 637                 if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz,
 638                                  filter->u.ClassOnly.clazz)) {
 639                     willBeFiltered = JNI_TRUE;
 640                     done = JNI_TRUE;
 641                 }
 642                 break;
 643 
 644             case JDWP_REQUEST_MODIFIER(Count): {
 645                 /*
 646                  * If preceding filters have determined that events will
 647                  * be filtered out, that is fine and we won't get here.
 648                  * However, the count must be decremented - even if
 649                  * subsequent filters will filter these events.  We
 650                  * thus must end now unable to predict
 651                  */
 652                 done = JNI_TRUE;
 653                 break;
 654             }
 655 
 656             case JDWP_REQUEST_MODIFIER(ClassMatch): {
 657                 if (!patternStringMatch(classname,
 658                         filter->u.ClassMatch.classPattern)) {
 659                     willBeFiltered = JNI_TRUE;
 660                     done = JNI_TRUE;
 661                 }
 662                 break;
 663             }
 664 
 665             case JDWP_REQUEST_MODIFIER(ClassExclude): {
 666                 if (patternStringMatch(classname,
 667                        filter->u.ClassExclude.classPattern)) {
 668                     willBeFiltered = JNI_TRUE;
 669                     done = JNI_TRUE;
 670                 }
 671                 break;
 672             }
 673         }
 674     }
 675 
 676     return willBeFiltered;
 677 }
 678 
 679 /**
 680  * Determine if the given breakpoint node is in the specified class.
 681  */
 682 jboolean
 683 eventFilterRestricted_isBreakpointInClass(JNIEnv *env, jclass clazz,
 684                                           HandlerNode *node)
 685 {
 686     Filter *filter = FILTERS_ARRAY(node);
 687     int i;
 688 
 689     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
 690         switch (filter->modifier) {
 691             case JDWP_REQUEST_MODIFIER(LocationOnly):
 692                 return isSameObject(env, clazz, filter->u.LocationOnly.clazz);
 693         }
 694     }
 695     return JNI_TRUE; /* should never come here */
 696 }
 697 
 698 /***** filter set-up *****/
 699 
 700 jvmtiError
 701 eventFilter_setConditionalFilter(HandlerNode *node, jint index,
 702                                  jint exprID)
 703 {
 704     ConditionalFilter *filter = &FILTER(node, index).u.Conditional;
 705     if (index >= FILTER_COUNT(node)) {
 706         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 707     }
 708     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Conditional);
 709     filter->exprID = exprID;
 710     return JVMTI_ERROR_NONE;
 711 }
 712 
 713 jvmtiError
 714 eventFilter_setCountFilter(HandlerNode *node, jint index,
 715                            jint count)
 716 {
 717     CountFilter *filter = &FILTER(node, index).u.Count;
 718     if (index >= FILTER_COUNT(node)) {
 719         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 720     }
 721     if (count <= 0) {
 722         return JDWP_ERROR(INVALID_COUNT);
 723     } else {
 724         FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Count);
 725         filter->count = count;
 726         return JVMTI_ERROR_NONE;
 727     }
 728 }
 729 
 730 jvmtiError
 731 eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index,
 732                                 jthread thread)
 733 {
 734     JNIEnv *env = getEnv();
 735     ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly;
 736     if (index >= FILTER_COUNT(node)) {
 737         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 738     }
 739     if (NODE_EI(node) == EI_GC_FINISH) {
 740         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 741     }
 742 
 743     /* Create a thread ref that will live beyond */
 744     /* the end of this call */
 745     saveGlobalRef(env, thread, &(filter->thread));
 746     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly);
 747     return JVMTI_ERROR_NONE;
 748 }
 749 
 750 jvmtiError
 751 eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index,
 752                                   jclass clazz, jmethodID method,
 753                                   jlocation location)
 754 {
 755     JNIEnv *env = getEnv();
 756     LocationFilter *filter = &FILTER(node, index).u.LocationOnly;
 757     if (index >= FILTER_COUNT(node)) {
 758         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 759     }
 760     if ((NODE_EI(node) != EI_BREAKPOINT) &&
 761         (NODE_EI(node) != EI_FIELD_ACCESS) &&
 762         (NODE_EI(node) != EI_FIELD_MODIFICATION) &&
 763         (NODE_EI(node) != EI_SINGLE_STEP) &&
 764         (NODE_EI(node) != EI_EXCEPTION)) {
 765 
 766         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 767     }
 768 
 769     /* Create a class ref that will live beyond */
 770     /* the end of this call */
 771     saveGlobalRef(env, clazz, &(filter->clazz));
 772     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly);
 773     filter->method = method;
 774     filter->location = location;
 775     return JVMTI_ERROR_NONE;
 776 }
 777 
 778 jvmtiError
 779 eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index,
 780                                jclass clazz, jfieldID field)
 781 {
 782     JNIEnv *env = getEnv();
 783     FieldFilter *filter = &FILTER(node, index).u.FieldOnly;
 784     if (index >= FILTER_COUNT(node)) {
 785         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 786     }
 787     if ((NODE_EI(node) != EI_FIELD_ACCESS) &&
 788         (NODE_EI(node) != EI_FIELD_MODIFICATION)) {
 789 
 790         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 791     }
 792 
 793     /* Create a class ref that will live beyond */
 794     /* the end of this call */
 795     saveGlobalRef(env, clazz, &(filter->clazz));
 796     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly);
 797     filter->field = field;
 798     return JVMTI_ERROR_NONE;
 799 }
 800 
 801 jvmtiError
 802 eventFilter_setClassOnlyFilter(HandlerNode *node, jint index,
 803                                jclass clazz)
 804 {
 805     JNIEnv *env = getEnv();
 806     ClassFilter *filter = &FILTER(node, index).u.ClassOnly;
 807     if (index >= FILTER_COUNT(node)) {
 808         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 809     }
 810     if (
 811         (NODE_EI(node) == EI_GC_FINISH) ||
 812         (NODE_EI(node) == EI_THREAD_START) ||
 813         (NODE_EI(node) == EI_THREAD_END)) {
 814 
 815         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 816     }
 817 
 818     /* Create a class ref that will live beyond */
 819     /* the end of this call */
 820     saveGlobalRef(env, clazz, &(filter->clazz));
 821     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly);
 822     return JVMTI_ERROR_NONE;
 823 }
 824 
 825 jvmtiError
 826 eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index,
 827                                    jclass exceptionClass,
 828                                    jboolean caught,
 829                                    jboolean uncaught)
 830 {
 831     JNIEnv *env = getEnv();
 832     ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly;
 833     if (index >= FILTER_COUNT(node)) {
 834         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 835     }
 836     if (NODE_EI(node) != EI_EXCEPTION) {
 837         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 838     }
 839 
 840     filter->exception = NULL;
 841     if (exceptionClass != NULL) {
 842         /* Create a class ref that will live beyond */
 843         /* the end of this call */
 844         saveGlobalRef(env, exceptionClass, &(filter->exception));
 845     }
 846     FILTER(node, index).modifier =
 847                        JDWP_REQUEST_MODIFIER(ExceptionOnly);
 848     filter->caught = caught;
 849     filter->uncaught = uncaught;
 850     return JVMTI_ERROR_NONE;
 851 }
 852 
 853 jvmtiError
 854 eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index,
 855                                   jobject instance)
 856 {
 857     JNIEnv *env = getEnv();
 858     InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly;
 859     if (index >= FILTER_COUNT(node)) {
 860         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 861     }
 862 
 863     filter->instance = NULL;
 864     if (instance != NULL) {
 865         /* Create an object ref that will live beyond
 866          * the end of this call
 867          */
 868         saveGlobalRef(env, instance, &(filter->instance));
 869     }
 870     FILTER(node, index).modifier =
 871                        JDWP_REQUEST_MODIFIER(InstanceOnly);
 872     return JVMTI_ERROR_NONE;
 873 }
 874 
 875 jvmtiError
 876 eventFilter_setClassMatchFilter(HandlerNode *node, jint index,
 877                                 char *classPattern)
 878 {
 879     MatchFilter *filter = &FILTER(node, index).u.ClassMatch;
 880     if (index >= FILTER_COUNT(node)) {
 881         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 882     }
 883     if (
 884         (NODE_EI(node) == EI_THREAD_START) ||
 885         (NODE_EI(node) == EI_THREAD_END)) {
 886 
 887         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 888     }
 889 
 890     FILTER(node, index).modifier =
 891                        JDWP_REQUEST_MODIFIER(ClassMatch);
 892     filter->classPattern = classPattern;
 893     return JVMTI_ERROR_NONE;
 894 }
 895 
 896 jvmtiError
 897 eventFilter_setClassExcludeFilter(HandlerNode *node, jint index,
 898                                   char *classPattern)
 899 {
 900     MatchFilter *filter = &FILTER(node, index).u.ClassExclude;
 901     if (index >= FILTER_COUNT(node)) {
 902         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 903     }
 904     if (
 905         (NODE_EI(node) == EI_THREAD_START) ||
 906         (NODE_EI(node) == EI_THREAD_END)) {
 907 
 908         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 909     }
 910 
 911     FILTER(node, index).modifier =
 912                        JDWP_REQUEST_MODIFIER(ClassExclude);
 913     filter->classPattern = classPattern;
 914     return JVMTI_ERROR_NONE;
 915 }
 916 
 917 jvmtiError
 918 eventFilter_setStepFilter(HandlerNode *node, jint index,
 919                           jthread thread, jint size, jint depth)
 920 {
 921     jvmtiError error;
 922     JNIEnv *env = getEnv();
 923     StepFilter *filter = &FILTER(node, index).u.Step;
 924     if (index >= FILTER_COUNT(node)) {
 925         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 926     }
 927     if (NODE_EI(node) != EI_SINGLE_STEP) {
 928         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 929     }
 930 
 931     /* Create a thread ref that will live beyond */
 932     /* the end of this call */
 933     saveGlobalRef(env, thread, &(filter->thread));
 934     error = stepControl_beginStep(env, filter->thread, size, depth, node);
 935     if (error != JVMTI_ERROR_NONE) {
 936         tossGlobalRef(env, &(filter->thread));
 937         return error;
 938     }
 939     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step);
 940     filter->depth = depth;
 941     filter->size = size;
 942     return JVMTI_ERROR_NONE;
 943 }
 944 
 945 jvmtiError
 946 eventFilter_setSourceNameMatchFilter(HandlerNode *node,
 947                                     jint index,
 948                                     char *sourceNamePattern) {
 949     SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly;
 950     if (index >= FILTER_COUNT(node)) {
 951         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 952     }
 953     if (NODE_EI(node) != EI_CLASS_PREPARE) {
 954         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 955     }
 956 
 957     FILTER(node, index).modifier =
 958                        JDWP_REQUEST_MODIFIER(SourceNameMatch);
 959     filter->sourceNamePattern = sourceNamePattern;
 960     return JVMTI_ERROR_NONE;
 961 
 962 }
 963 
 964 /***** JVMTI event enabling / disabling *****/
 965 
 966 /**
 967  * Return the Filter that is of the specified type (modifier).
 968  * Return NULL if not found.
 969  */
 970 static Filter *
 971 findFilter(HandlerNode *node, jint modifier)
 972 {
 973     int i;
 974     Filter *filter;
 975     for (i = 0, filter = FILTERS_ARRAY(node);
 976                       i <FILTER_COUNT(node);
 977                       i++, filter++) {
 978         if (filter->modifier == modifier) {
 979             return filter;
 980         }
 981     }
 982     return NULL;
 983 }
 984 
 985 /**
 986  * Determine if the specified breakpoint node is in the
 987  * same location as the LocationFilter passed in arg.
 988  *
 989  * This is a match function called by a
 990  * eventHandlerRestricted_iterator invokation.
 991  */
 992 static jboolean
 993 matchBreakpoint(JNIEnv *env, HandlerNode *node, void *arg)
 994 {
 995     LocationFilter *goal = (LocationFilter *)arg;
 996     Filter *filter = FILTERS_ARRAY(node);
 997     int i;
 998 
 999     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1000         switch (filter->modifier) {
1001         case JDWP_REQUEST_MODIFIER(LocationOnly): {
1002             LocationFilter *trial = &(filter->u.LocationOnly);
1003             if (trial->method == goal->method &&
1004                 trial->location == goal->location &&
1005                 isSameObject(env, trial->clazz, goal->clazz)) {
1006                 return JNI_TRUE;
1007             }
1008         }
1009         }
1010     }
1011     return JNI_FALSE;
1012 }
1013 
1014 /**
1015  * Set a breakpoint if this is the first one at this location.
1016  */
1017 static jvmtiError
1018 setBreakpoint(HandlerNode *node)
1019 {
1020     jvmtiError error = JVMTI_ERROR_NONE;
1021     Filter *filter;
1022 
1023     filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly));
1024     if (filter == NULL) {
1025         /* bp event with no location filter */
1026         error = AGENT_ERROR_INTERNAL;
1027     } else {
1028         LocationFilter *lf = &(filter->u.LocationOnly);
1029 
1030         /* if this is the first handler for this
1031          * location, set bp at JVMTI level
1032          */
1033         if (!eventHandlerRestricted_iterator(
1034                 EI_BREAKPOINT, matchBreakpoint, lf)) {
1035             LOG_LOC(("SetBreakpoint at location: method=%p,location=%d",
1036                         lf->method, (int)lf->location));
1037             error = JVMTI_FUNC_PTR(gdata->jvmti,SetBreakpoint)
1038                         (gdata->jvmti, lf->method, lf->location);
1039         }
1040     }
1041     return error;
1042 }
1043 
1044 /**
1045  * Clear a breakpoint if this is the last one at this location.
1046  */
1047 static jvmtiError
1048 clearBreakpoint(HandlerNode *node)
1049 {
1050     jvmtiError error = JVMTI_ERROR_NONE;
1051     Filter *filter;
1052 
1053     filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly));
1054     if (filter == NULL) {
1055         /* bp event with no location filter */
1056         error = AGENT_ERROR_INTERNAL;
1057     } else {
1058         LocationFilter *lf = &(filter->u.LocationOnly);
1059 
1060         /* if this is the last handler for this
1061          * location, clear bp at JVMTI level
1062          */
1063         if (!eventHandlerRestricted_iterator(
1064                 EI_BREAKPOINT, matchBreakpoint, lf)) {
1065             LOG_LOC(("ClearBreakpoint at location: method=%p,location=%d",
1066                         lf->method, (int)lf->location));
1067             error = JVMTI_FUNC_PTR(gdata->jvmti,ClearBreakpoint)
1068                         (gdata->jvmti, lf->method, lf->location);
1069         }
1070     }
1071     return error;
1072 }
1073 
1074 /**
1075  * Return true if a breakpoint is set at the specified location.
1076  */
1077 jboolean
1078 isBreakpointSet(jclass clazz, jmethodID method, jlocation location)
1079 {
1080     LocationFilter lf;
1081 
1082     lf.clazz    = clazz;
1083     lf.method   = method;
1084     lf.location = location;
1085 
1086     return eventHandlerRestricted_iterator(EI_BREAKPOINT,
1087                                            matchBreakpoint, &lf);
1088 }
1089 
1090 /**
1091  * Determine if the specified watchpoint node has the
1092  * same field as the FieldFilter passed in arg.
1093  *
1094  * This is a match function called by a
1095  * eventHandlerRestricted_iterator invokation.
1096  */
1097 static jboolean
1098 matchWatchpoint(JNIEnv *env, HandlerNode *node, void *arg)
1099 {
1100     FieldFilter *goal = (FieldFilter *)arg;
1101     Filter *filter = FILTERS_ARRAY(node);
1102     int i;
1103 
1104     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1105         switch (filter->modifier) {
1106         case JDWP_REQUEST_MODIFIER(FieldOnly): {
1107             FieldFilter *trial = &(filter->u.FieldOnly);
1108             if (trial->field == goal->field &&
1109                 isSameObject(env, trial->clazz, goal->clazz)) {
1110                 return JNI_TRUE;
1111             }
1112         }
1113         }
1114     }
1115     return JNI_FALSE;
1116 }
1117 
1118 /**
1119  * Set a watchpoint if this is the first one on this field.
1120  */
1121 static jvmtiError
1122 setWatchpoint(HandlerNode *node)
1123 {
1124     jvmtiError error = JVMTI_ERROR_NONE;
1125     Filter *filter;
1126 
1127     filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly));
1128     if (filter == NULL) {
1129         /* event with no field filter */
1130         error = AGENT_ERROR_INTERNAL;
1131     } else {
1132         FieldFilter *ff = &(filter->u.FieldOnly);
1133 
1134         /* if this is the first handler for this
1135          * field, set wp at JVMTI level
1136          */
1137         if (!eventHandlerRestricted_iterator(
1138                 NODE_EI(node), matchWatchpoint, ff)) {
1139             error = (NODE_EI(node) == EI_FIELD_ACCESS) ?
1140                 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldAccessWatch)
1141                         (gdata->jvmti, ff->clazz, ff->field) :
1142                 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldModificationWatch)
1143                         (gdata->jvmti, ff->clazz, ff->field);
1144         }
1145     }
1146     return error;
1147 }
1148 
1149 /**
1150  * Clear a watchpoint if this is the last one on this field.
1151  */
1152 static jvmtiError
1153 clearWatchpoint(HandlerNode *node)
1154 {
1155     jvmtiError error = JVMTI_ERROR_NONE;
1156     Filter *filter;
1157 
1158     filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly));
1159     if (filter == NULL) {
1160         /* event with no field filter */
1161         error = AGENT_ERROR_INTERNAL;
1162     } else {
1163         FieldFilter *ff = &(filter->u.FieldOnly);
1164 
1165         /* if this is the last handler for this
1166          * field, clear wp at JVMTI level
1167          */
1168         if (!eventHandlerRestricted_iterator(
1169                 NODE_EI(node), matchWatchpoint, ff)) {
1170             error = (NODE_EI(node) == EI_FIELD_ACCESS) ?
1171                 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldAccessWatch)
1172                         (gdata->jvmti, ff->clazz, ff->field) :
1173                 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldModificationWatch)
1174                                 (gdata->jvmti, ff->clazz, ff->field);
1175         }
1176     }
1177     return error;
1178 }
1179 
1180 /**
1181  * Determine the thread this node is filtered on.
1182  * NULL if not thread filtered.
1183  */
1184 static jthread
1185 requestThread(HandlerNode *node)
1186 {
1187     int i;
1188     Filter *filter = FILTERS_ARRAY(node);
1189 
1190     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1191         switch (filter->modifier) {
1192             case JDWP_REQUEST_MODIFIER(ThreadOnly):
1193                 return filter->u.ThreadOnly.thread;
1194         }
1195     }
1196 
1197     return NULL;
1198 }
1199 
1200 /**
1201  * Determine if the specified node has a
1202  * thread filter with the thread passed in arg.
1203  *
1204  * This is a match function called by a
1205  * eventHandlerRestricted_iterator invokation.
1206  */
1207 static jboolean
1208 matchThread(JNIEnv *env, HandlerNode *node, void *arg)
1209 {
1210     jthread goalThread = (jthread)arg;
1211     jthread reqThread = requestThread(node);
1212 
1213     /* If the event's thread and the passed thread are the same
1214      * (or both are NULL), we have a match.
1215      */
1216     return isSameObject(env, reqThread, goalThread);
1217 }
1218 
1219 /**
1220  * Do any enabling of events (including setting breakpoints etc)
1221  * needed to get the events requested by this handler node.
1222  */
1223 static jvmtiError
1224 enableEvents(HandlerNode *node)
1225 {
1226     jvmtiError error = JVMTI_ERROR_NONE;
1227 
1228     switch (NODE_EI(node)) {
1229         /* The stepping code directly enables/disables stepping as
1230          * necessary
1231          */
1232         case EI_SINGLE_STEP:
1233         /* Internal thread event handlers are always present
1234          * (hardwired in the event hook), so we don't change the
1235          * notification mode here.
1236          */
1237         case EI_THREAD_START:
1238         case EI_THREAD_END:
1239         case EI_VM_INIT:
1240         case EI_VM_DEATH:
1241         case EI_CLASS_PREPARE:
1242         case EI_GC_FINISH:
1243             return error;
1244 
1245         case EI_FIELD_ACCESS:
1246         case EI_FIELD_MODIFICATION:
1247             error = setWatchpoint(node);
1248             break;
1249 
1250         case EI_BREAKPOINT:
1251             error = setBreakpoint(node);
1252             break;
1253 
1254         default:
1255             break;
1256     }
1257 
1258     /* Don't globally enable if the above failed */
1259     if (error == JVMTI_ERROR_NONE) {
1260         jthread thread = requestThread(node);
1261 
1262         /* If this is the first request of it's kind on this
1263          * thread (or all threads (thread == NULL)) then enable
1264          * these events on this thread.
1265          */
1266         if (!eventHandlerRestricted_iterator(
1267                 NODE_EI(node), matchThread, thread)) {
1268             error = threadControl_setEventMode(JVMTI_ENABLE,
1269                                                NODE_EI(node), thread);
1270         }
1271     }
1272     return error;
1273 }
1274 
1275 /**
1276  * Do any disabling of events (including clearing breakpoints etc)
1277  * needed to no longer get the events requested by this handler node.
1278  */
1279 static jvmtiError
1280 disableEvents(HandlerNode *node)
1281 {
1282     jvmtiError error = JVMTI_ERROR_NONE;
1283     jvmtiError error2 = JVMTI_ERROR_NONE;
1284     jthread thread;
1285 
1286 
1287     switch (NODE_EI(node)) {
1288         /* The stepping code directly enables/disables stepping as
1289          * necessary
1290          */
1291         case EI_SINGLE_STEP:
1292         /* Internal thread event handlers are always present
1293          * (hardwired in the event hook), so we don't change the
1294          * notification mode here.
1295          */
1296         case EI_THREAD_START:
1297         case EI_THREAD_END:
1298         case EI_VM_INIT:
1299         case EI_VM_DEATH:
1300         case EI_CLASS_PREPARE:
1301         case EI_GC_FINISH:
1302             return error;
1303 
1304         case EI_FIELD_ACCESS:
1305         case EI_FIELD_MODIFICATION:
1306             error = clearWatchpoint(node);
1307             break;
1308 
1309         case EI_BREAKPOINT:
1310             error = clearBreakpoint(node);
1311             break;
1312 
1313         default:
1314             break;
1315     }
1316 
1317     thread = requestThread(node);
1318 
1319     /* If this is the last request of it's kind on this thread
1320      * (or all threads (thread == NULL)) then disable these
1321      * events on this thread.
1322      *
1323      * Disable even if the above caused an error
1324      */
1325     if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) {
1326         error2 = threadControl_setEventMode(JVMTI_DISABLE,
1327                                             NODE_EI(node), thread);
1328     }
1329     return error != JVMTI_ERROR_NONE? error : error2;
1330 }
1331 
1332 
1333 /***** filter (and event) installation and deinstallation *****/
1334 
1335 /**
1336  * Make the set of event filters that correspond with this
1337  * node active (including enabling the corresponding events).
1338  */
1339 jvmtiError
1340 eventFilterRestricted_install(HandlerNode *node)
1341 {
1342     return enableEvents(node);
1343 }
1344 
1345 /**
1346  * Make the set of event filters that correspond with this
1347  * node inactive (including disabling the corresponding events
1348  * and freeing resources).
1349  */
1350 jvmtiError
1351 eventFilterRestricted_deinstall(HandlerNode *node)
1352 {
1353     jvmtiError error1, error2;
1354 
1355     error1 = disableEvents(node);
1356     error2 = clearFilters(node);
1357 
1358     return error1 != JVMTI_ERROR_NONE? error1 : error2;
1359 }
1360 
1361 /***** debugging *****/
1362 
1363 #ifdef DEBUG
1364 
1365 void
1366 eventFilter_dumpHandlerFilters(HandlerNode *node)
1367 {
1368     int i;
1369     Filter *filter = FILTERS_ARRAY(node);
1370 
1371     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1372         switch (filter->modifier) {
1373             case JDWP_REQUEST_MODIFIER(ThreadOnly):
1374                 tty_message("ThreadOnly: thread(%p)",
1375                             filter->u.ThreadOnly.thread);
1376                 break;
1377             case JDWP_REQUEST_MODIFIER(ClassOnly): {
1378                 char *class_name;
1379                 classSignature(filter->u.ClassOnly.clazz, &class_name, NULL);
1380                 tty_message("ClassOnly: clazz(%s)",
1381                             class_name);
1382                 break;
1383             }
1384             case JDWP_REQUEST_MODIFIER(LocationOnly): {
1385                 char *method_name;
1386                 char *class_name;
1387                 methodSignature(filter->u.LocationOnly.method, &method_name, NULL, NULL);
1388                 classSignature(filter->u.LocationOnly.clazz, &class_name, NULL);
1389                 tty_message("LocationOnly: clazz(%s), method(%s) location(%d)",
1390                             class_name,
1391                             method_name,
1392                             filter->u.LocationOnly.location);
1393                 break;
1394             }
1395             case JDWP_REQUEST_MODIFIER(FieldOnly): {
1396                 char *class_name;
1397                 classSignature(filter->u.FieldOnly.clazz, &class_name, NULL);
1398                 tty_message("FieldOnly: clazz(%p), field(%d)",
1399                             class_name,
1400                             filter->u.FieldOnly.field);
1401                 break;
1402             }
1403             case JDWP_REQUEST_MODIFIER(ExceptionOnly):
1404                 tty_message("ExceptionOnly: clazz(%p), caught(%d) uncaught(%d)",
1405                             filter->u.ExceptionOnly.exception,
1406                             filter->u.ExceptionOnly.caught,
1407                             filter->u.ExceptionOnly.uncaught);
1408                 break;
1409             case JDWP_REQUEST_MODIFIER(InstanceOnly):
1410                 tty_message("InstanceOnly: instance(%p)",
1411                             filter->u.InstanceOnly.instance);
1412                 break;
1413             case JDWP_REQUEST_MODIFIER(Count):
1414                 tty_message("Count: count(%d)",
1415                             filter->u.Count.count);
1416                 break;
1417             case JDWP_REQUEST_MODIFIER(Conditional):
1418                 tty_message("Conditional: exprID(%d)",
1419                             filter->u.Conditional.exprID);
1420                 break;
1421             case JDWP_REQUEST_MODIFIER(ClassMatch):
1422                 tty_message("ClassMatch: classPattern(%s)",
1423                             filter->u.ClassMatch.classPattern);
1424                 break;
1425             case JDWP_REQUEST_MODIFIER(ClassExclude):
1426                 tty_message("ClassExclude: classPattern(%s)",
1427                             filter->u.ClassExclude.classPattern);
1428                 break;
1429             case JDWP_REQUEST_MODIFIER(Step):
1430                 tty_message("Step: size(%d) depth(%d) thread(%p)",
1431                             filter->u.Step.size,
1432                             filter->u.Step.depth,
1433                             filter->u.Step.thread);
1434                 break;
1435             case JDWP_REQUEST_MODIFIER(SourceNameMatch):
1436                 tty_message("SourceNameMatch: sourceNamePattern(%s)",
1437                             filter->u.SourceNameOnly.sourceNamePattern);
1438                 break;
1439             default:
1440                 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT, "Invalid filter modifier");
1441                 return;
1442         }
1443     }
1444 }
1445 
1446 #endif /* DEBUG */