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