< prev index next >

src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c

Print this page


   1 /*
   2  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  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;


 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 !=


 459                             filter->u.ExceptionOnly.exception)) {
 460                         return JNI_FALSE;
 461                     }
 462                 }
 463                 break;
 464 
 465             case JDWP_REQUEST_MODIFIER(InstanceOnly): {
 466                 jobject eventInst = eventInstance(evinfo);
 467                 jobject filterInst = filter->u.InstanceOnly.instance;
 468                 /* if no error and doesn't match, don't pass
 469                  * filter
 470                  */
 471                 if (eventInst != NULL &&
 472                       !isSameObject(env, eventInst, filterInst)) {
 473                     return JNI_FALSE;
 474                 }
 475                 break;
 476             }
 477             case JDWP_REQUEST_MODIFIER(Count): {
 478                 JDI_ASSERT(filter->u.Count.count > 0);








 479                 if (--filter->u.Count.count > 0) {
 480                     return JNI_FALSE;
 481                 }
 482                 *shouldDelete = JNI_TRUE;
 483                 break;
 484             }
 485 
 486             case JDWP_REQUEST_MODIFIER(Conditional):
 487 /***
 488                 if (...  filter->u.Conditional.exprID ...) {
 489                     return JNI_FALSE;
 490                 }
 491 ***/
 492                 break;
 493 
 494         case JDWP_REQUEST_MODIFIER(ClassMatch): {
 495             if (!patternStringMatch(classname,
 496                        filter->u.ClassMatch.classPattern)) {
 497                 return JNI_FALSE;
 498             }
 499             break;
 500         }
 501 
 502         case JDWP_REQUEST_MODIFIER(ClassExclude): {
 503             if (patternStringMatch(classname,
 504                       filter->u.ClassExclude.classPattern)) {
 505                 return JNI_FALSE;
 506             }
 507             break;
 508         }
 509 
 510         case JDWP_REQUEST_MODIFIER(Step):
 511                 if (!isSameObject(env, thread, filter->u.Step.thread)) {
 512                     return JNI_FALSE;
 513                 }
 514                 if (!stepControl_handleStep(env, thread, clazz, method)) {










 515                     return JNI_FALSE;
 516                 }
 517                 break;

 518 
 519           case JDWP_REQUEST_MODIFIER(SourceNameMatch): {
 520               char* desiredNamePattern = filter->u.SourceNameOnly.sourceNamePattern;
 521               if (searchAllSourceNames(env, clazz,
 522                            desiredNamePattern) != 1) {
 523                   /* The name isn't in the SDE; try the sourceName in the ref
 524                    * type
 525                    */
 526                   char *sourceName = 0;
 527                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
 528                                             (gdata->jvmti, clazz, &sourceName);
 529                   if (error == JVMTI_ERROR_NONE &&
 530                       sourceName != 0 &&
 531                       patternStringMatch(sourceName, desiredNamePattern)) {
 532                           // got a hit - report the event
 533                           jvmtiDeallocate(sourceName);
 534                           break;
 535                   }
 536                   // We have no match, we have no source file name,
 537                   // or we got a JVM TI error. Don't report the event.
 538                   jvmtiDeallocate(sourceName);
 539                   return JNI_FALSE;
 540               }
 541               break;
 542           }
 543 
 544         default:
 545             EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
 546             return JNI_FALSE;
 547         }
 548     }




 549     return JNI_TRUE;
 550 }
 551 
 552 /* Determine if this event is interesting to this handler.  Do so
 553  * by checking each of the handler's filters.  Return false if any
 554  * of the filters fail, true if the handler wants this event.
 555  * Special version of filter for unloads since they don't have an
 556  * event structure or a jclass.
 557  *
 558  * If shouldDelete is returned true, a count filter has expired
 559  * and the corresponding node should be deleted.
 560  */
 561 jboolean
 562 eventFilterRestricted_passesUnloadFilter(JNIEnv *env,
 563                                          char *classname,
 564                                          HandlerNode *node,
 565                                          jboolean *shouldDelete)
 566 {
 567     Filter *filter = FILTERS_ARRAY(node);
 568     int i;


 724     } else {
 725         FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Count);
 726         filter->count = count;
 727         return JVMTI_ERROR_NONE;
 728     }
 729 }
 730 
 731 jvmtiError
 732 eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index,
 733                                 jthread thread)
 734 {
 735     JNIEnv *env = getEnv();
 736     ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly;
 737     if (index >= FILTER_COUNT(node)) {
 738         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 739     }
 740     if (NODE_EI(node) == EI_GC_FINISH) {
 741         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 742     }
 743 



 744     /* Create a thread ref that will live beyond */
 745     /* the end of this call */
 746     saveGlobalRef(env, thread, &(filter->thread));
 747     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly);
 748     return JVMTI_ERROR_NONE;
 749 }
 750 
 751 jvmtiError
 752 eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index,
 753                                   jclass clazz, jmethodID method,
 754                                   jlocation location)
 755 {
 756     JNIEnv *env = getEnv();
 757     LocationFilter *filter = &FILTER(node, index).u.LocationOnly;
 758     if (index >= FILTER_COUNT(node)) {
 759         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 760     }
 761     if ((NODE_EI(node) != EI_BREAKPOINT) &&
 762         (NODE_EI(node) != EI_FIELD_ACCESS) &&
 763         (NODE_EI(node) != EI_FIELD_MODIFICATION) &&


 912     FILTER(node, index).modifier =
 913                        JDWP_REQUEST_MODIFIER(ClassExclude);
 914     filter->classPattern = classPattern;
 915     return JVMTI_ERROR_NONE;
 916 }
 917 
 918 jvmtiError
 919 eventFilter_setStepFilter(HandlerNode *node, jint index,
 920                           jthread thread, jint size, jint depth)
 921 {
 922     jvmtiError error;
 923     JNIEnv *env = getEnv();
 924     StepFilter *filter = &FILTER(node, index).u.Step;
 925     if (index >= FILTER_COUNT(node)) {
 926         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 927     }
 928     if (NODE_EI(node) != EI_SINGLE_STEP) {
 929         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 930     }
 931 



 932     /* Create a thread ref that will live beyond */
 933     /* the end of this call */
 934     saveGlobalRef(env, thread, &(filter->thread));
 935     error = stepControl_beginStep(env, filter->thread, size, depth, node);
 936     if (error != JVMTI_ERROR_NONE) {
 937         tossGlobalRef(env, &(filter->thread));
 938         return error;
 939     }
 940     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step);
 941     filter->depth = depth;
 942     filter->size = size;
 943     return JVMTI_ERROR_NONE;
 944 }
 945 




















 946 
 947 jvmtiError
 948 eventFilter_setSourceNameMatchFilter(HandlerNode *node,
 949                                     jint index,
 950                                     char *sourceNamePattern) {
 951     SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly;
 952     if (index >= FILTER_COUNT(node)) {
 953         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 954     }
 955     if (NODE_EI(node) != EI_CLASS_PREPARE) {
 956         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 957     }
 958 
 959     FILTER(node, index).modifier =
 960                        JDWP_REQUEST_MODIFIER(SourceNameMatch);
 961     filter->sourceNamePattern = sourceNamePattern;
 962     return JVMTI_ERROR_NONE;
 963 
 964 }
 965 


1225 static jvmtiError
1226 enableEvents(HandlerNode *node)
1227 {
1228     jvmtiError error = JVMTI_ERROR_NONE;
1229 
1230     switch (NODE_EI(node)) {
1231         /* The stepping code directly enables/disables stepping as
1232          * necessary
1233          */
1234         case EI_SINGLE_STEP:
1235         /* Internal thread event handlers are always present
1236          * (hardwired in the event hook), so we don't change the
1237          * notification mode here.
1238          */
1239         case EI_THREAD_START:
1240         case EI_THREAD_END:
1241         case EI_VM_INIT:
1242         case EI_VM_DEATH:
1243         case EI_CLASS_PREPARE:
1244         case EI_GC_FINISH:






1245             return error;
1246 
1247         case EI_FIELD_ACCESS:
1248         case EI_FIELD_MODIFICATION:
1249             error = setWatchpoint(node);
1250             break;
1251 
1252         case EI_BREAKPOINT:
1253             error = setBreakpoint(node);
1254             break;
1255 
1256         default:
1257             break;
1258     }
1259 
1260     /* Don't globally enable if the above failed */
1261     if (error == JVMTI_ERROR_NONE) {
1262         jthread thread = requestThread(node);
1263 
1264         /* If this is the first request of it's kind on this


1284     jvmtiError error = JVMTI_ERROR_NONE;
1285     jvmtiError error2 = JVMTI_ERROR_NONE;
1286     jthread thread;
1287 
1288 
1289     switch (NODE_EI(node)) {
1290         /* The stepping code directly enables/disables stepping as
1291          * necessary
1292          */
1293         case EI_SINGLE_STEP:
1294         /* Internal thread event handlers are always present
1295          * (hardwired in the event hook), so we don't change the
1296          * notification mode here.
1297          */
1298         case EI_THREAD_START:
1299         case EI_THREAD_END:
1300         case EI_VM_INIT:
1301         case EI_VM_DEATH:
1302         case EI_CLASS_PREPARE:
1303         case EI_GC_FINISH:






1304             return error;
1305 
1306         case EI_FIELD_ACCESS:
1307         case EI_FIELD_MODIFICATION:
1308             error = clearWatchpoint(node);
1309             break;
1310 
1311         case EI_BREAKPOINT:
1312             error = clearBreakpoint(node);
1313             break;
1314 
1315         default:
1316             break;
1317     }
1318 
1319     thread = requestThread(node);
1320 
1321     /* If this is the last request of it's kind on this thread
1322      * (or all threads (thread == NULL)) then disable these
1323      * events on this thread.
1324      *
1325      * Disable even if the above caused an error
1326      */
1327     if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) {
1328         error2 = threadControl_setEventMode(JVMTI_DISABLE,
1329                                             NODE_EI(node), thread);
1330     }
1331     return error != JVMTI_ERROR_NONE? error : error2;





















































































1332 }
1333 
1334 
1335 /***** filter (and event) installation and deinstallation *****/
1336 
1337 /**
1338  * Make the set of event filters that correspond with this
1339  * node active (including enabling the corresponding events).
1340  */
1341 jvmtiError
1342 eventFilterRestricted_install(HandlerNode *node)
1343 {
1344     return enableEvents(node);
1345 }
1346 
1347 /**
1348  * Make the set of event filters that correspond with this
1349  * node inactive (including disabling the corresponding events
1350  * and freeing resources).
1351  */
   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


  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;


 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 !=


 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;


 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) &&


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 


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


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  */
< prev index next >