< prev index next >

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

Print this page

  75 } ExceptionFilter;
  76 
  77 typedef struct InstanceFilter {
  78     jobject instance;
  79 } InstanceFilter;
  80 
  81 typedef struct StepFilter {
  82     jint size;
  83     jint depth;
  84     jthread thread;
  85 } StepFilter;
  86 
  87 typedef struct MatchFilter {
  88     char *classPattern;
  89 } MatchFilter;
  90 
  91 typedef struct SourceNameFilter {
  92     char *sourceNamePattern;
  93 } SourceNameFilter;
  94 




  95 typedef struct Filter_ {
  96     jbyte modifier;
  97     union {
  98         struct ClassFilter ClassOnly;
  99         struct LocationFilter LocationOnly;
 100         struct ThreadFilter ThreadOnly;
 101         struct CountFilter Count;
 102         struct ConditionalFilter Conditional;
 103         struct FieldFilter FieldOnly;
 104         struct ExceptionFilter ExceptionOnly;
 105         struct InstanceFilter InstanceOnly;
 106         struct StepFilter Step;
 107         struct MatchFilter ClassMatch;
 108         struct MatchFilter ClassExclude;
 109         struct SourceNameFilter SourceNameOnly;

 110     } u;
 111 } Filter;
 112 
 113 /* The filters array is allocated to the specified filterCount.
 114  * Theoretically, some compiler could do range checking on this
 115  * array - so, we define it to have a ludicrously large size so
 116  * that this range checking won't get upset.
 117  *
 118  * The actual allocated number of bytes is computed using the
 119  * offset of "filters" and so is not effected by this number.
 120  */
 121 #define MAX_FILTERS 10000
 122 
 123 typedef struct EventFilters_ {
 124     jint filterCount;
 125     Filter filters[MAX_FILTERS];
 126 } EventFilters;
 127 
 128 typedef struct EventFilterPrivate_HandlerNode_ {
 129     EventHandlerRestricted_HandlerNode   not_for_us;

 523                    * type
 524                    */
 525                   char *sourceName = 0;
 526                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
 527                                             (gdata->jvmti, clazz, &sourceName);
 528                   if (error == JVMTI_ERROR_NONE &&
 529                       sourceName != 0 &&
 530                       patternStringMatch(sourceName, desiredNamePattern)) {
 531                           // got a hit - report the event
 532                           jvmtiDeallocate(sourceName);
 533                           break;
 534                   }
 535                   // We have no match, we have no source file name,
 536                   // or we got a JVM TI error. Don't report the event.
 537                   jvmtiDeallocate(sourceName);
 538                   return JNI_FALSE;
 539               }
 540               break;
 541           }
 542 








 543         default:
 544             EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
 545             return JNI_FALSE;
 546         }
 547     }
 548     return JNI_TRUE;
 549 }
 550 
 551 /* Determine if this event is interesting to this handler.  Do so
 552  * by checking each of the handler's filters.  Return false if any
 553  * of the filters fail, true if the handler wants this event.
 554  * Special version of filter for unloads since they don't have an
 555  * event structure or a jclass.
 556  *
 557  * If shouldDelete is returned true, a count filter has expired
 558  * and the corresponding node should be deleted.
 559  */
 560 jboolean
 561 eventFilterRestricted_passesUnloadFilter(JNIEnv *env,
 562                                          char *classname,

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














 964 /***** JVMTI event enabling / disabling *****/
 965 
 966 /**
 967  * Return the Filter that is of the specified type (modifier).
 968  * Return NULL if not found.
 969  */
 970 static Filter *
 971 findFilter(HandlerNode *node, jint modifier)
 972 {
 973     int i;
 974     Filter *filter;
 975     for (i = 0, filter = FILTERS_ARRAY(node);
 976                       i <FILTER_COUNT(node);
 977                       i++, filter++) {
 978         if (filter->modifier == modifier) {
 979             return filter;
 980         }
 981     }
 982     return NULL;
 983 }

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


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

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


1302             return error;
1303 
1304         case EI_FIELD_ACCESS:
1305         case EI_FIELD_MODIFICATION:
1306             error = clearWatchpoint(node);
1307             break;
1308 
1309         case EI_BREAKPOINT:
1310             error = clearBreakpoint(node);
1311             break;
1312 
1313         default:
1314             break;
1315     }
1316 
1317     thread = requestThread(node);
1318 
1319     /* If this is the last request of it's kind on this thread
1320      * (or all threads (thread == NULL)) then disable these
1321      * events on this thread.

1354 
1355     error1 = disableEvents(node);
1356     error2 = clearFilters(node);
1357 
1358     return error1 != JVMTI_ERROR_NONE? error1 : error2;
1359 }
1360 
1361 /***** debugging *****/
1362 
1363 #ifdef DEBUG
1364 
1365 void
1366 eventFilter_dumpHandlerFilters(HandlerNode *node)
1367 {
1368     int i;
1369     Filter *filter = FILTERS_ARRAY(node);
1370 
1371     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1372         switch (filter->modifier) {
1373             case JDWP_REQUEST_MODIFIER(ThreadOnly):
1374                 tty_message("ThreadOnly: thread(%p)",
1375                             filter->u.ThreadOnly.thread);

1376                 break;
1377             case JDWP_REQUEST_MODIFIER(ClassOnly): {
1378                 char *class_name;
1379                 classSignature(filter->u.ClassOnly.clazz, &class_name, NULL);
1380                 tty_message("ClassOnly: clazz(%s)",
1381                             class_name);
1382                 break;
1383             }
1384             case JDWP_REQUEST_MODIFIER(LocationOnly): {
1385                 char *method_name;
1386                 char *class_name;
1387                 methodSignature(filter->u.LocationOnly.method, &method_name, NULL, NULL);
1388                 classSignature(filter->u.LocationOnly.clazz, &class_name, NULL);
1389                 tty_message("LocationOnly: clazz(%s), method(%s) location(%d)",
1390                             class_name,
1391                             method_name,
1392                             filter->u.LocationOnly.location);
1393                 break;
1394             }
1395             case JDWP_REQUEST_MODIFIER(FieldOnly): {

1410                 tty_message("InstanceOnly: instance(%p)",
1411                             filter->u.InstanceOnly.instance);
1412                 break;
1413             case JDWP_REQUEST_MODIFIER(Count):
1414                 tty_message("Count: count(%d)",
1415                             filter->u.Count.count);
1416                 break;
1417             case JDWP_REQUEST_MODIFIER(Conditional):
1418                 tty_message("Conditional: exprID(%d)",
1419                             filter->u.Conditional.exprID);
1420                 break;
1421             case JDWP_REQUEST_MODIFIER(ClassMatch):
1422                 tty_message("ClassMatch: classPattern(%s)",
1423                             filter->u.ClassMatch.classPattern);
1424                 break;
1425             case JDWP_REQUEST_MODIFIER(ClassExclude):
1426                 tty_message("ClassExclude: classPattern(%s)",
1427                             filter->u.ClassExclude.classPattern);
1428                 break;
1429             case JDWP_REQUEST_MODIFIER(Step):
1430                 tty_message("Step: size(%d) depth(%d) thread(%p)",
1431                             filter->u.Step.size,
1432                             filter->u.Step.depth,
1433                             filter->u.Step.thread);

1434                 break;
1435             case JDWP_REQUEST_MODIFIER(SourceNameMatch):
1436                 tty_message("SourceNameMatch: sourceNamePattern(%s)",
1437                             filter->u.SourceNameOnly.sourceNamePattern);
1438                 break;



1439             default:
1440                 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT, "Invalid filter modifier");
1441                 return;
1442         }
1443     }
1444 }
1445 
1446 #endif /* DEBUG */

  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 PlatformThreadsFilter {
  96     char unused;  // to avoid an empty struct
  97 } PlatformThreadsFilter;
  98 
  99 typedef struct Filter_ {
 100     jbyte modifier;
 101     union {
 102         struct ClassFilter ClassOnly;
 103         struct LocationFilter LocationOnly;
 104         struct ThreadFilter ThreadOnly;
 105         struct CountFilter Count;
 106         struct ConditionalFilter Conditional;
 107         struct FieldFilter FieldOnly;
 108         struct ExceptionFilter ExceptionOnly;
 109         struct InstanceFilter InstanceOnly;
 110         struct StepFilter Step;
 111         struct MatchFilter ClassMatch;
 112         struct MatchFilter ClassExclude;
 113         struct SourceNameFilter SourceNameOnly;
 114         struct PlatformThreadsFilter PlatformThreadsOnly;
 115     } u;
 116 } Filter;
 117 
 118 /* The filters array is allocated to the specified filterCount.
 119  * Theoretically, some compiler could do range checking on this
 120  * array - so, we define it to have a ludicrously large size so
 121  * that this range checking won't get upset.
 122  *
 123  * The actual allocated number of bytes is computed using the
 124  * offset of "filters" and so is not effected by this number.
 125  */
 126 #define MAX_FILTERS 10000
 127 
 128 typedef struct EventFilters_ {
 129     jint filterCount;
 130     Filter filters[MAX_FILTERS];
 131 } EventFilters;
 132 
 133 typedef struct EventFilterPrivate_HandlerNode_ {
 134     EventHandlerRestricted_HandlerNode   not_for_us;

 528                    * type
 529                    */
 530                   char *sourceName = 0;
 531                   jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
 532                                             (gdata->jvmti, clazz, &sourceName);
 533                   if (error == JVMTI_ERROR_NONE &&
 534                       sourceName != 0 &&
 535                       patternStringMatch(sourceName, desiredNamePattern)) {
 536                           // got a hit - report the event
 537                           jvmtiDeallocate(sourceName);
 538                           break;
 539                   }
 540                   // We have no match, we have no source file name,
 541                   // or we got a JVM TI error. Don't report the event.
 542                   jvmtiDeallocate(sourceName);
 543                   return JNI_FALSE;
 544               }
 545               break;
 546           }
 547 
 548         case JDWP_REQUEST_MODIFIER(PlatformThreadsOnly): {
 549             jboolean isVirtual = JNI_FUNC_PTR(env, IsVirtualThread)(env, thread);
 550             if (isVirtual) {
 551                 return JNI_FALSE;
 552             }
 553             break;
 554         }
 555 
 556         default:
 557             EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier");
 558             return JNI_FALSE;
 559         }
 560     }
 561     return JNI_TRUE;
 562 }
 563 
 564 /* Determine if this event is interesting to this handler.  Do so
 565  * by checking each of the handler's filters.  Return false if any
 566  * of the filters fail, true if the handler wants this event.
 567  * Special version of filter for unloads since they don't have an
 568  * event structure or a jclass.
 569  *
 570  * If shouldDelete is returned true, a count filter has expired
 571  * and the corresponding node should be deleted.
 572  */
 573 jboolean
 574 eventFilterRestricted_passesUnloadFilter(JNIEnv *env,
 575                                          char *classname,

 957 
 958 jvmtiError
 959 eventFilter_setSourceNameMatchFilter(HandlerNode *node,
 960                                     jint index,
 961                                     char *sourceNamePattern) {
 962     SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly;
 963     if (index >= FILTER_COUNT(node)) {
 964         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 965     }
 966     if (NODE_EI(node) != EI_CLASS_PREPARE) {
 967         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 968     }
 969 
 970     FILTER(node, index).modifier =
 971                        JDWP_REQUEST_MODIFIER(SourceNameMatch);
 972     filter->sourceNamePattern = sourceNamePattern;
 973     return JVMTI_ERROR_NONE;
 974 
 975 }
 976 
 977 jvmtiError eventFilter_setPlatformThreadsOnlyFilter(HandlerNode *node, jint index)
 978 {
 979     PlatformThreadsFilter *filter = &FILTER(node, index).u.PlatformThreadsOnly;
 980     if (index >= FILTER_COUNT(node)) {
 981         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 982     }
 983     if (NODE_EI(node) != EI_THREAD_START && NODE_EI(node) != EI_THREAD_END) {
 984         return AGENT_ERROR_ILLEGAL_ARGUMENT;
 985     }
 986     FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(PlatformThreadsOnly);
 987     return JVMTI_ERROR_NONE;
 988 
 989 }
 990 
 991 /***** JVMTI event enabling / disabling *****/
 992 
 993 /**
 994  * Return the Filter that is of the specified type (modifier).
 995  * Return NULL if not found.
 996  */
 997 static Filter *
 998 findFilter(HandlerNode *node, jint modifier)
 999 {
1000     int i;
1001     Filter *filter;
1002     for (i = 0, filter = FILTERS_ARRAY(node);
1003                       i <FILTER_COUNT(node);
1004                       i++, filter++) {
1005         if (filter->modifier == modifier) {
1006             return filter;
1007         }
1008     }
1009     return NULL;
1010 }

1250 static jvmtiError
1251 enableEvents(HandlerNode *node)
1252 {
1253     jvmtiError error = JVMTI_ERROR_NONE;
1254 
1255     switch (NODE_EI(node)) {
1256         /* The stepping code directly enables/disables stepping as
1257          * necessary
1258          */
1259         case EI_SINGLE_STEP:
1260         /* Internal thread event handlers are always present
1261          * (hardwired in the event hook), so we don't change the
1262          * notification mode here.
1263          */
1264         case EI_THREAD_START:
1265         case EI_THREAD_END:
1266         case EI_VM_INIT:
1267         case EI_VM_DEATH:
1268         case EI_CLASS_PREPARE:
1269         case EI_GC_FINISH:
1270         case EI_VIRTUAL_THREAD_START:
1271         case EI_VIRTUAL_THREAD_END:
1272             return error;
1273 
1274         case EI_FIELD_ACCESS:
1275         case EI_FIELD_MODIFICATION:
1276             error = setWatchpoint(node);
1277             break;
1278 
1279         case EI_BREAKPOINT:
1280             error = setBreakpoint(node);
1281             break;
1282 
1283         default:
1284             break;
1285     }
1286 
1287     /* Don't globally enable if the above failed */
1288     if (error == JVMTI_ERROR_NONE) {
1289         jthread thread = requestThread(node);
1290 
1291         /* If this is the first request of it's kind on this

1311     jvmtiError error = JVMTI_ERROR_NONE;
1312     jvmtiError error2 = JVMTI_ERROR_NONE;
1313     jthread thread;
1314 
1315 
1316     switch (NODE_EI(node)) {
1317         /* The stepping code directly enables/disables stepping as
1318          * necessary
1319          */
1320         case EI_SINGLE_STEP:
1321         /* Internal thread event handlers are always present
1322          * (hardwired in the event hook), so we don't change the
1323          * notification mode here.
1324          */
1325         case EI_THREAD_START:
1326         case EI_THREAD_END:
1327         case EI_VM_INIT:
1328         case EI_VM_DEATH:
1329         case EI_CLASS_PREPARE:
1330         case EI_GC_FINISH:
1331         case EI_VIRTUAL_THREAD_START:
1332         case EI_VIRTUAL_THREAD_END:
1333             return error;
1334 
1335         case EI_FIELD_ACCESS:
1336         case EI_FIELD_MODIFICATION:
1337             error = clearWatchpoint(node);
1338             break;
1339 
1340         case EI_BREAKPOINT:
1341             error = clearBreakpoint(node);
1342             break;
1343 
1344         default:
1345             break;
1346     }
1347 
1348     thread = requestThread(node);
1349 
1350     /* If this is the last request of it's kind on this thread
1351      * (or all threads (thread == NULL)) then disable these
1352      * events on this thread.

1385 
1386     error1 = disableEvents(node);
1387     error2 = clearFilters(node);
1388 
1389     return error1 != JVMTI_ERROR_NONE? error1 : error2;
1390 }
1391 
1392 /***** debugging *****/
1393 
1394 #ifdef DEBUG
1395 
1396 void
1397 eventFilter_dumpHandlerFilters(HandlerNode *node)
1398 {
1399     int i;
1400     Filter *filter = FILTERS_ARRAY(node);
1401 
1402     for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {
1403         switch (filter->modifier) {
1404             case JDWP_REQUEST_MODIFIER(ThreadOnly):
1405                 tty_message("ThreadOnly: thread(%p) isVThread(%d)",
1406                             filter->u.ThreadOnly.thread,
1407                             isVThread(filter->u.ThreadOnly.thread));
1408                 break;
1409             case JDWP_REQUEST_MODIFIER(ClassOnly): {
1410                 char *class_name;
1411                 classSignature(filter->u.ClassOnly.clazz, &class_name, NULL);
1412                 tty_message("ClassOnly: clazz(%s)",
1413                             class_name);
1414                 break;
1415             }
1416             case JDWP_REQUEST_MODIFIER(LocationOnly): {
1417                 char *method_name;
1418                 char *class_name;
1419                 methodSignature(filter->u.LocationOnly.method, &method_name, NULL, NULL);
1420                 classSignature(filter->u.LocationOnly.clazz, &class_name, NULL);
1421                 tty_message("LocationOnly: clazz(%s), method(%s) location(%d)",
1422                             class_name,
1423                             method_name,
1424                             filter->u.LocationOnly.location);
1425                 break;
1426             }
1427             case JDWP_REQUEST_MODIFIER(FieldOnly): {

1442                 tty_message("InstanceOnly: instance(%p)",
1443                             filter->u.InstanceOnly.instance);
1444                 break;
1445             case JDWP_REQUEST_MODIFIER(Count):
1446                 tty_message("Count: count(%d)",
1447                             filter->u.Count.count);
1448                 break;
1449             case JDWP_REQUEST_MODIFIER(Conditional):
1450                 tty_message("Conditional: exprID(%d)",
1451                             filter->u.Conditional.exprID);
1452                 break;
1453             case JDWP_REQUEST_MODIFIER(ClassMatch):
1454                 tty_message("ClassMatch: classPattern(%s)",
1455                             filter->u.ClassMatch.classPattern);
1456                 break;
1457             case JDWP_REQUEST_MODIFIER(ClassExclude):
1458                 tty_message("ClassExclude: classPattern(%s)",
1459                             filter->u.ClassExclude.classPattern);
1460                 break;
1461             case JDWP_REQUEST_MODIFIER(Step):
1462                 tty_message("Step: size(%d) depth(%d) thread(%p) isVThread(%d)",
1463                             filter->u.Step.size,
1464                             filter->u.Step.depth,
1465                             filter->u.Step.thread,
1466                             isVThread(filter->u.Step.thread));
1467                 break;
1468             case JDWP_REQUEST_MODIFIER(SourceNameMatch):
1469                 tty_message("SourceNameMatch: sourceNamePattern(%s)",
1470                             filter->u.SourceNameOnly.sourceNamePattern);
1471                 break;
1472             case JDWP_REQUEST_MODIFIER(PlatformThreadsOnly):
1473                 tty_message("PlatformThreadsOnly: enabled");
1474                 break;
1475             default:
1476                 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT, "Invalid filter modifier");
1477                 return;
1478         }
1479     }
1480 }
1481 
1482 #endif /* DEBUG */
< prev index next >