1 /* 2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 /* 26 * eventFilter 27 * 28 * This module handles event filteration and the enabling/disabling 29 * of the corresponding events. Used for filters on JDI EventRequests 30 * and also internal requests. Our data is in a private hidden section 31 * of the HandlerNode's data. See comment for enclosing 32 * module eventHandler. 33 */ 34 35 #include "util.h" 36 #include "eventFilter.h" 37 #include "eventFilterRestricted.h" 38 #include "eventHandlerRestricted.h" 39 #include "stepControl.h" 40 #include "threadControl.h" 41 #include "SDE.h" 42 #include "jvmti.h" 43 44 typedef struct ClassFilter { 45 jclass clazz; 46 } ClassFilter; 47 48 typedef struct LocationFilter { 49 jclass clazz; 50 jmethodID method; 51 jlocation location; 52 } LocationFilter; 53 54 typedef struct ThreadFilter { 55 jthread thread; 56 } ThreadFilter; 57 58 typedef struct CountFilter { 59 jint count; 60 } CountFilter; 61 62 typedef struct ConditionalFilter { 63 jint exprID; 64 } ConditionalFilter; 65 66 typedef struct FieldFilter { 67 jclass clazz; 68 jfieldID field; 69 } FieldFilter; 70 71 typedef struct ExceptionFilter { 72 jclass exception; 73 jboolean caught; 74 jboolean uncaught; 75 } ExceptionFilter; 76 77 typedef struct InstanceFilter { 78 jobject instance; 79 } InstanceFilter; 80 81 typedef struct StepFilter { 82 jint size; 83 jint depth; 84 jthread thread; 85 } StepFilter; 86 87 typedef struct MatchFilter { 88 char *classPattern; 89 } MatchFilter; 90 91 typedef struct SourceNameFilter { 92 char *sourceNamePattern; 93 } SourceNameFilter; 94 95 typedef struct Filter_ { 96 jbyte modifier; 97 union { 98 struct ClassFilter ClassOnly; 99 struct LocationFilter LocationOnly; 100 struct ThreadFilter ThreadOnly; 101 struct CountFilter Count; 102 struct ConditionalFilter Conditional; 103 struct FieldFilter FieldOnly; 104 struct ExceptionFilter ExceptionOnly; 105 struct InstanceFilter InstanceOnly; 106 struct StepFilter Step; 107 struct MatchFilter ClassMatch; 108 struct MatchFilter ClassExclude; 109 struct SourceNameFilter SourceNameOnly; 110 } u; 111 } Filter; 112 113 /* The filters array is allocated to the specified filterCount. 114 * Theoretically, some compiler could do range checking on this 115 * array - so, we define it to have a ludicrously large size so 116 * that this range checking won't get upset. 117 * 118 * The actual allocated number of bytes is computed using the 119 * offset of "filters" and so is not effected by this number. 120 */ 121 #define MAX_FILTERS 10000 122 123 typedef struct EventFilters_ { 124 jint filterCount; 125 Filter filters[MAX_FILTERS]; 126 } EventFilters; 127 128 typedef struct EventFilterPrivate_HandlerNode_ { 129 EventHandlerRestricted_HandlerNode not_for_us; 130 EventFilters ef; 131 } EventFilterPrivate_HandlerNode; 132 133 /** 134 * The following macros extract filter info (EventFilters) from private 135 * data at the end of a HandlerNode 136 */ 137 #define EVENT_FILTERS(node) (&(((EventFilterPrivate_HandlerNode*)(void*)node)->ef)) 138 #define FILTER_COUNT(node) (EVENT_FILTERS(node)->filterCount) 139 #define FILTERS_ARRAY(node) (EVENT_FILTERS(node)->filters) 140 #define FILTER(node,index) ((FILTERS_ARRAY(node))[index]) 141 #define NODE_EI(node) (node->ei) 142 143 /***** filter set-up / destruction *****/ 144 145 /** 146 * Allocate a HandlerNode. 147 * We do it because eventHandler doesn't know how big to make it. 148 */ 149 HandlerNode * 150 eventFilterRestricted_alloc(jint filterCount) 151 { 152 /*LINTED*/ 153 size_t size = offsetof(EventFilterPrivate_HandlerNode, ef) + 154 offsetof(EventFilters, filters) + 155 (filterCount * (int)sizeof(Filter)); 156 HandlerNode *node = jvmtiAllocate((jint)size); 157 158 if (node != NULL) { 159 int i; 160 Filter *filter; 161 162 (void)memset(node, 0, size); 163 164 FILTER_COUNT(node) = filterCount; 165 166 /* Initialize all modifiers 167 */ 168 for (i = 0, filter = FILTERS_ARRAY(node); 169 i < filterCount; 170 i++, filter++) { 171 filter->modifier = JDWP_REQUEST_NONE; 172 } 173 } 174 175 return node; 176 } 177 178 /** 179 * Free up global refs held by the filter. 180 * free things up at the JNI level if needed. 181 */ 182 static jvmtiError 183 clearFilters(HandlerNode *node) 184 { 185 JNIEnv *env = getEnv(); 186 jint i; 187 jvmtiError error = JVMTI_ERROR_NONE; 188 Filter *filter = FILTERS_ARRAY(node); 189 190 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 191 switch (filter->modifier) { 192 case JDWP_REQUEST_MODIFIER(ThreadOnly): 193 if ( filter->u.ThreadOnly.thread != NULL ) { 194 tossGlobalRef(env, &(filter->u.ThreadOnly.thread)); 195 } 196 break; 197 case JDWP_REQUEST_MODIFIER(LocationOnly): 198 tossGlobalRef(env, &(filter->u.LocationOnly.clazz)); 199 break; 200 case JDWP_REQUEST_MODIFIER(FieldOnly): 201 tossGlobalRef(env, &(filter->u.FieldOnly.clazz)); 202 break; 203 case JDWP_REQUEST_MODIFIER(ExceptionOnly): 204 if ( filter->u.ExceptionOnly.exception != NULL ) { 205 tossGlobalRef(env, &(filter->u.ExceptionOnly.exception)); 206 } 207 break; 208 case JDWP_REQUEST_MODIFIER(InstanceOnly): 209 if ( filter->u.InstanceOnly.instance != NULL ) { 210 tossGlobalRef(env, &(filter->u.InstanceOnly.instance)); 211 } 212 break; 213 case JDWP_REQUEST_MODIFIER(ClassOnly): 214 tossGlobalRef(env, &(filter->u.ClassOnly.clazz)); 215 break; 216 case JDWP_REQUEST_MODIFIER(ClassMatch): 217 jvmtiDeallocate(filter->u.ClassMatch.classPattern); 218 break; 219 case JDWP_REQUEST_MODIFIER(ClassExclude): 220 jvmtiDeallocate(filter->u.ClassExclude.classPattern); 221 break; 222 case JDWP_REQUEST_MODIFIER(Step): { 223 jthread thread = filter->u.Step.thread; 224 error = stepControl_endStep(thread); 225 if (error == JVMTI_ERROR_NONE) { 226 tossGlobalRef(env, &(filter->u.Step.thread)); 227 } 228 break; 229 } 230 } 231 } 232 if (error == JVMTI_ERROR_NONE) { 233 FILTER_COUNT(node) = 0; /* blast so we don't clear again */ 234 } 235 236 return error; 237 } 238 239 240 /***** filtering *****/ 241 242 /* 243 * Match a string against a wildcard 244 * string pattern. 245 */ 246 static jboolean 247 patternStringMatch(char *classname, const char *pattern) 248 { 249 int pattLen; 250 int compLen; 251 char *start; 252 int offset; 253 254 if ( pattern==NULL || classname==NULL ) { 255 return JNI_FALSE; 256 } 257 pattLen = (int)strlen(pattern); 258 259 if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) { 260 /* An exact match is required when there is no *: bug 4331522 */ 261 return strcmp(pattern, classname) == 0; 262 } else { 263 compLen = pattLen - 1; 264 offset = (int)strlen(classname) - compLen; 265 if (offset < 0) { 266 return JNI_FALSE; 267 } else { 268 if (pattern[0] == '*') { 269 pattern++; 270 start = classname + offset; 271 } else { 272 start = classname; 273 } 274 return strncmp(pattern, start, compLen) == 0; 275 } 276 } 277 } 278 279 static jboolean isVersionGte12x() { 280 jint version; 281 jvmtiError err = 282 JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version); 283 284 if (err == JVMTI_ERROR_NONE) { 285 jint major, minor; 286 287 major = (version & JVMTI_VERSION_MASK_MAJOR) 288 >> JVMTI_VERSION_SHIFT_MAJOR; 289 minor = (version & JVMTI_VERSION_MASK_MINOR) 290 >> JVMTI_VERSION_SHIFT_MINOR; 291 return (major > 1 || major == 1 && minor >= 2); 292 } else { 293 return JNI_FALSE; 294 } 295 } 296 297 /* Return the object instance in which the event occurred */ 298 /* Return NULL if static or if an error occurs */ 299 static jobject 300 eventInstance(EventInfo *evinfo) 301 { 302 jobject object = NULL; 303 jthread thread ; 304 jmethodID method ; 305 jint modifiers = 0; 306 jvmtiError error; 307 308 static jboolean got_version = JNI_FALSE; 309 static jboolean is_version_gte_12x = JNI_FALSE; 310 311 if (!got_version) { 312 is_version_gte_12x = isVersionGte12x(); 313 got_version = JNI_TRUE; 314 } 315 316 switch (evinfo->ei) { 317 case EI_SINGLE_STEP: 318 case EI_BREAKPOINT: 319 case EI_FRAME_POP: 320 case EI_METHOD_ENTRY: 321 case EI_METHOD_EXIT: 322 case EI_EXCEPTION: 323 case EI_EXCEPTION_CATCH: 324 case EI_MONITOR_CONTENDED_ENTER: 325 case EI_MONITOR_CONTENDED_ENTERED: 326 case EI_MONITOR_WAIT: 327 case EI_MONITOR_WAITED: 328 thread = evinfo->thread; 329 method = evinfo->method; 330 break; 331 case EI_FIELD_ACCESS: 332 case EI_FIELD_MODIFICATION: 333 object = evinfo->object; 334 return object; 335 default: 336 return object; /* NULL */ 337 } 338 339 error = methodModifiers(method, &modifiers); 340 341 /* fail if error or static (0x8) */ 342 if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) { 343 FrameNumber fnum = 0; 344 if (is_version_gte_12x) { 345 /* Use new 1.2.x function, GetLocalInstance */ 346 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance) 347 (gdata->jvmti, thread, fnum, &object); 348 } else { 349 /* get slot zero object "this" */ 350 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject) 351 (gdata->jvmti, thread, fnum, 0, &object); 352 } 353 if (error != JVMTI_ERROR_NONE) { 354 object = NULL; 355 } 356 } 357 358 return object; 359 } 360 361 /* 362 * Determine if this event is interesting to this handler. 363 * Do so by checking each of the handler's filters. 364 * Return false if any of the filters fail, 365 * true if the handler wants this event. 366 * Anyone modifying this function should check 367 * eventFilterRestricted_passesUnloadFilter and 368 * eventFilter_predictFiltering as well. 369 * 370 * If shouldDelete is returned true, a count filter has expired 371 * and the corresponding node should be deleted. 372 */ 373 jboolean 374 eventFilterRestricted_passesFilter(JNIEnv *env, 375 char *classname, 376 EventInfo *evinfo, 377 HandlerNode *node, 378 jboolean *shouldDelete) 379 { 380 jthread thread; 381 jclass clazz; 382 jmethodID method; 383 Filter *filter = FILTERS_ARRAY(node); 384 int i; 385 386 *shouldDelete = JNI_FALSE; 387 thread = evinfo->thread; 388 clazz = evinfo->clazz; 389 method = evinfo->method; 390 391 /* 392 * Suppress most events if they happen in debug threads 393 */ 394 if ((evinfo->ei != EI_CLASS_PREPARE) && 395 (evinfo->ei != EI_GC_FINISH) && 396 (evinfo->ei != EI_CLASS_LOAD) && 397 threadControl_isDebugThread(thread)) { 398 return JNI_FALSE; 399 } 400 401 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 402 switch (filter->modifier) { 403 case JDWP_REQUEST_MODIFIER(ThreadOnly): 404 if (!isSameObject(env, thread, filter->u.ThreadOnly.thread)) { 405 return JNI_FALSE; 406 } 407 break; 408 409 case JDWP_REQUEST_MODIFIER(ClassOnly): 410 /* Class filters catch events in the specified 411 * class and any subclass/subinterface. 412 */ 413 if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz, 414 filter->u.ClassOnly.clazz)) { 415 return JNI_FALSE; 416 } 417 break; 418 419 /* This is kinda cheating assumming the event 420 * fields will be in the same locations, but it is 421 * true now. 422 */ 423 case JDWP_REQUEST_MODIFIER(LocationOnly): 424 if (evinfo->method != 425 filter->u.LocationOnly.method || 426 evinfo->location != 427 filter->u.LocationOnly.location || 428 !isSameObject(env, clazz, filter->u.LocationOnly.clazz)) { 429 return JNI_FALSE; 430 } 431 break; 432 433 case JDWP_REQUEST_MODIFIER(FieldOnly): 434 /* Field watchpoints can be triggered from the 435 * declared class or any subclass/subinterface. 436 */ 437 if ((evinfo->u.field_access.field != 438 filter->u.FieldOnly.field) || 439 !isSameObject(env, evinfo->u.field_access.field_clazz, 440 filter->u.FieldOnly.clazz)) { 441 return JNI_FALSE; 442 } 443 break; 444 445 case JDWP_REQUEST_MODIFIER(ExceptionOnly): 446 /* do we want caught/uncaught exceptions */ 447 if (!((evinfo->u.exception.catch_clazz == NULL)? 448 filter->u.ExceptionOnly.uncaught : 449 filter->u.ExceptionOnly.caught)) { 450 return JNI_FALSE; 451 } 452 453 /* do we care about exception class */ 454 if (filter->u.ExceptionOnly.exception != NULL) { 455 jclass exception = evinfo->object; 456 457 /* do we want this exception class */ 458 if (!JNI_FUNC_PTR(env,IsInstanceOf)(env, exception, 459 filter->u.ExceptionOnly.exception)) { 460 return JNI_FALSE; 461 } 462 } 463 break; 464 465 case JDWP_REQUEST_MODIFIER(InstanceOnly): { 466 jobject eventInst = eventInstance(evinfo); 467 jobject filterInst = filter->u.InstanceOnly.instance; 468 /* if no error and doesn't match, don't pass 469 * filter 470 */ 471 if (eventInst != NULL && 472 !isSameObject(env, eventInst, filterInst)) { 473 return JNI_FALSE; 474 } 475 break; 476 } 477 case JDWP_REQUEST_MODIFIER(Count): { 478 JDI_ASSERT(filter->u.Count.count > 0); 479 if (--filter->u.Count.count > 0) { 480 return JNI_FALSE; 481 } 482 *shouldDelete = JNI_TRUE; 483 break; 484 } 485 486 case JDWP_REQUEST_MODIFIER(Conditional): 487 /*** 488 if (... filter->u.Conditional.exprID ...) { 489 return JNI_FALSE; 490 } 491 ***/ 492 break; 493 494 case JDWP_REQUEST_MODIFIER(ClassMatch): { 495 if (!patternStringMatch(classname, 496 filter->u.ClassMatch.classPattern)) { 497 return JNI_FALSE; 498 } 499 break; 500 } 501 502 case JDWP_REQUEST_MODIFIER(ClassExclude): { 503 if (patternStringMatch(classname, 504 filter->u.ClassExclude.classPattern)) { 505 return JNI_FALSE; 506 } 507 break; 508 } 509 510 case JDWP_REQUEST_MODIFIER(Step): 511 if (!isSameObject(env, thread, filter->u.Step.thread)) { 512 return JNI_FALSE; 513 } 514 if (!stepControl_handleStep(env, thread, clazz, method)) { 515 return JNI_FALSE; 516 } 517 break; 518 519 case JDWP_REQUEST_MODIFIER(SourceNameMatch): { 520 char* desiredNamePattern = filter->u.SourceNameOnly.sourceNamePattern; 521 if (!searchAllSourceNames(env, clazz, 522 desiredNamePattern) == 1) { 523 /* The name isn't in the SDE; try the sourceName in the ref 524 * type 525 */ 526 char *sourceName = 0; 527 jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName) 528 (gdata->jvmti, clazz, &sourceName); 529 if (error == JVMTI_ERROR_NONE && 530 sourceName != 0 && 531 patternStringMatch(sourceName, desiredNamePattern)) { 532 // got a hit - report the event 533 jvmtiDeallocate(sourceName); 534 break; 535 } 536 // We have no match, we have no source file name, 537 // or we got a JVM TI error. Don't report the event. 538 jvmtiDeallocate(sourceName); 539 return JNI_FALSE; 540 } 541 break; 542 } 543 544 default: 545 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier"); 546 return JNI_FALSE; 547 } 548 } 549 return JNI_TRUE; 550 } 551 552 /* Determine if this event is interesting to this handler. Do so 553 * by checking each of the handler's filters. Return false if any 554 * of the filters fail, true if the handler wants this event. 555 * Special version of filter for unloads since they don't have an 556 * event structure or a jclass. 557 * 558 * If shouldDelete is returned true, a count filter has expired 559 * and the corresponding node should be deleted. 560 */ 561 jboolean 562 eventFilterRestricted_passesUnloadFilter(JNIEnv *env, 563 char *classname, 564 HandlerNode *node, 565 jboolean *shouldDelete) 566 { 567 Filter *filter = FILTERS_ARRAY(node); 568 int i; 569 570 *shouldDelete = JNI_FALSE; 571 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 572 switch (filter->modifier) { 573 574 case JDWP_REQUEST_MODIFIER(Count): { 575 JDI_ASSERT(filter->u.Count.count > 0); 576 if (--filter->u.Count.count > 0) { 577 return JNI_FALSE; 578 } 579 *shouldDelete = JNI_TRUE; 580 break; 581 } 582 583 case JDWP_REQUEST_MODIFIER(ClassMatch): { 584 if (!patternStringMatch(classname, 585 filter->u.ClassMatch.classPattern)) { 586 return JNI_FALSE; 587 } 588 break; 589 } 590 591 case JDWP_REQUEST_MODIFIER(ClassExclude): { 592 if (patternStringMatch(classname, 593 filter->u.ClassExclude.classPattern)) { 594 return JNI_FALSE; 595 } 596 break; 597 } 598 599 default: 600 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"Invalid filter modifier"); 601 return JNI_FALSE; 602 } 603 } 604 return JNI_TRUE; 605 } 606 607 /** 608 * This function returns true only if it is certain that 609 * all events for the given node in the given stack frame will 610 * be filtered. It is used to optimize stepping. (If this 611 * function returns true the stepping algorithm does not 612 * have to step through every instruction in this stack frame; 613 * instead, it can use more efficient method entry/exit 614 * events. 615 */ 616 jboolean 617 eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname) 618 { 619 JNIEnv *env; 620 jboolean willBeFiltered; 621 Filter *filter; 622 jboolean done; 623 int count; 624 int i; 625 626 willBeFiltered = JNI_FALSE; 627 env = NULL; 628 filter = FILTERS_ARRAY(node); 629 count = FILTER_COUNT(node); 630 done = JNI_FALSE; 631 632 for (i = 0; (i < count) && (!done); ++i, ++filter) { 633 switch (filter->modifier) { 634 case JDWP_REQUEST_MODIFIER(ClassOnly): 635 if ( env==NULL ) { 636 env = getEnv(); 637 } 638 if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz, 639 filter->u.ClassOnly.clazz)) { 640 willBeFiltered = JNI_TRUE; 641 done = JNI_TRUE; 642 } 643 break; 644 645 case JDWP_REQUEST_MODIFIER(Count): { 646 /* 647 * If preceding filters have determined that events will 648 * be filtered out, that is fine and we won't get here. 649 * However, the count must be decremented - even if 650 * subsequent filters will filter these events. We 651 * thus must end now unable to predict 652 */ 653 done = JNI_TRUE; 654 break; 655 } 656 657 case JDWP_REQUEST_MODIFIER(ClassMatch): { 658 if (!patternStringMatch(classname, 659 filter->u.ClassMatch.classPattern)) { 660 willBeFiltered = JNI_TRUE; 661 done = JNI_TRUE; 662 } 663 break; 664 } 665 666 case JDWP_REQUEST_MODIFIER(ClassExclude): { 667 if (patternStringMatch(classname, 668 filter->u.ClassExclude.classPattern)) { 669 willBeFiltered = JNI_TRUE; 670 done = JNI_TRUE; 671 } 672 break; 673 } 674 } 675 } 676 677 return willBeFiltered; 678 } 679 680 /** 681 * Determine if the given breakpoint node is in the specified class. 682 */ 683 jboolean 684 eventFilterRestricted_isBreakpointInClass(JNIEnv *env, jclass clazz, 685 HandlerNode *node) 686 { 687 Filter *filter = FILTERS_ARRAY(node); 688 int i; 689 690 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 691 switch (filter->modifier) { 692 case JDWP_REQUEST_MODIFIER(LocationOnly): 693 return isSameObject(env, clazz, filter->u.LocationOnly.clazz); 694 } 695 } 696 return JNI_TRUE; /* should never come here */ 697 } 698 699 /***** filter set-up *****/ 700 701 jvmtiError 702 eventFilter_setConditionalFilter(HandlerNode *node, jint index, 703 jint exprID) 704 { 705 ConditionalFilter *filter = &FILTER(node, index).u.Conditional; 706 if (index >= FILTER_COUNT(node)) { 707 return AGENT_ERROR_ILLEGAL_ARGUMENT; 708 } 709 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Conditional); 710 filter->exprID = exprID; 711 return JVMTI_ERROR_NONE; 712 } 713 714 jvmtiError 715 eventFilter_setCountFilter(HandlerNode *node, jint index, 716 jint count) 717 { 718 CountFilter *filter = &FILTER(node, index).u.Count; 719 if (index >= FILTER_COUNT(node)) { 720 return AGENT_ERROR_ILLEGAL_ARGUMENT; 721 } 722 if (count <= 0) { 723 return JDWP_ERROR(INVALID_COUNT); 724 } else { 725 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Count); 726 filter->count = count; 727 return JVMTI_ERROR_NONE; 728 } 729 } 730 731 jvmtiError 732 eventFilter_setThreadOnlyFilter(HandlerNode *node, jint index, 733 jthread thread) 734 { 735 JNIEnv *env = getEnv(); 736 ThreadFilter *filter = &FILTER(node, index).u.ThreadOnly; 737 if (index >= FILTER_COUNT(node)) { 738 return AGENT_ERROR_ILLEGAL_ARGUMENT; 739 } 740 if (NODE_EI(node) == EI_GC_FINISH) { 741 return AGENT_ERROR_ILLEGAL_ARGUMENT; 742 } 743 744 /* Create a thread ref that will live beyond */ 745 /* the end of this call */ 746 saveGlobalRef(env, thread, &(filter->thread)); 747 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ThreadOnly); 748 return JVMTI_ERROR_NONE; 749 } 750 751 jvmtiError 752 eventFilter_setLocationOnlyFilter(HandlerNode *node, jint index, 753 jclass clazz, jmethodID method, 754 jlocation location) 755 { 756 JNIEnv *env = getEnv(); 757 LocationFilter *filter = &FILTER(node, index).u.LocationOnly; 758 if (index >= FILTER_COUNT(node)) { 759 return AGENT_ERROR_ILLEGAL_ARGUMENT; 760 } 761 if ((NODE_EI(node) != EI_BREAKPOINT) && 762 (NODE_EI(node) != EI_FIELD_ACCESS) && 763 (NODE_EI(node) != EI_FIELD_MODIFICATION) && 764 (NODE_EI(node) != EI_SINGLE_STEP) && 765 (NODE_EI(node) != EI_EXCEPTION)) { 766 767 return AGENT_ERROR_ILLEGAL_ARGUMENT; 768 } 769 770 /* Create a class ref that will live beyond */ 771 /* the end of this call */ 772 saveGlobalRef(env, clazz, &(filter->clazz)); 773 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(LocationOnly); 774 filter->method = method; 775 filter->location = location; 776 return JVMTI_ERROR_NONE; 777 } 778 779 jvmtiError 780 eventFilter_setFieldOnlyFilter(HandlerNode *node, jint index, 781 jclass clazz, jfieldID field) 782 { 783 JNIEnv *env = getEnv(); 784 FieldFilter *filter = &FILTER(node, index).u.FieldOnly; 785 if (index >= FILTER_COUNT(node)) { 786 return AGENT_ERROR_ILLEGAL_ARGUMENT; 787 } 788 if ((NODE_EI(node) != EI_FIELD_ACCESS) && 789 (NODE_EI(node) != EI_FIELD_MODIFICATION)) { 790 791 return AGENT_ERROR_ILLEGAL_ARGUMENT; 792 } 793 794 /* Create a class ref that will live beyond */ 795 /* the end of this call */ 796 saveGlobalRef(env, clazz, &(filter->clazz)); 797 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(FieldOnly); 798 filter->field = field; 799 return JVMTI_ERROR_NONE; 800 } 801 802 jvmtiError 803 eventFilter_setClassOnlyFilter(HandlerNode *node, jint index, 804 jclass clazz) 805 { 806 JNIEnv *env = getEnv(); 807 ClassFilter *filter = &FILTER(node, index).u.ClassOnly; 808 if (index >= FILTER_COUNT(node)) { 809 return AGENT_ERROR_ILLEGAL_ARGUMENT; 810 } 811 if ( 812 (NODE_EI(node) == EI_GC_FINISH) || 813 (NODE_EI(node) == EI_THREAD_START) || 814 (NODE_EI(node) == EI_THREAD_END)) { 815 816 return AGENT_ERROR_ILLEGAL_ARGUMENT; 817 } 818 819 /* Create a class ref that will live beyond */ 820 /* the end of this call */ 821 saveGlobalRef(env, clazz, &(filter->clazz)); 822 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(ClassOnly); 823 return JVMTI_ERROR_NONE; 824 } 825 826 jvmtiError 827 eventFilter_setExceptionOnlyFilter(HandlerNode *node, jint index, 828 jclass exceptionClass, 829 jboolean caught, 830 jboolean uncaught) 831 { 832 JNIEnv *env = getEnv(); 833 ExceptionFilter *filter = &FILTER(node, index).u.ExceptionOnly; 834 if (index >= FILTER_COUNT(node)) { 835 return AGENT_ERROR_ILLEGAL_ARGUMENT; 836 } 837 if (NODE_EI(node) != EI_EXCEPTION) { 838 return AGENT_ERROR_ILLEGAL_ARGUMENT; 839 } 840 841 filter->exception = NULL; 842 if (exceptionClass != NULL) { 843 /* Create a class ref that will live beyond */ 844 /* the end of this call */ 845 saveGlobalRef(env, exceptionClass, &(filter->exception)); 846 } 847 FILTER(node, index).modifier = 848 JDWP_REQUEST_MODIFIER(ExceptionOnly); 849 filter->caught = caught; 850 filter->uncaught = uncaught; 851 return JVMTI_ERROR_NONE; 852 } 853 854 jvmtiError 855 eventFilter_setInstanceOnlyFilter(HandlerNode *node, jint index, 856 jobject instance) 857 { 858 JNIEnv *env = getEnv(); 859 InstanceFilter *filter = &FILTER(node, index).u.InstanceOnly; 860 if (index >= FILTER_COUNT(node)) { 861 return AGENT_ERROR_ILLEGAL_ARGUMENT; 862 } 863 864 filter->instance = NULL; 865 if (instance != NULL) { 866 /* Create an object ref that will live beyond 867 * the end of this call 868 */ 869 saveGlobalRef(env, instance, &(filter->instance)); 870 } 871 FILTER(node, index).modifier = 872 JDWP_REQUEST_MODIFIER(InstanceOnly); 873 return JVMTI_ERROR_NONE; 874 } 875 876 jvmtiError 877 eventFilter_setClassMatchFilter(HandlerNode *node, jint index, 878 char *classPattern) 879 { 880 MatchFilter *filter = &FILTER(node, index).u.ClassMatch; 881 if (index >= FILTER_COUNT(node)) { 882 return AGENT_ERROR_ILLEGAL_ARGUMENT; 883 } 884 if ( 885 (NODE_EI(node) == EI_THREAD_START) || 886 (NODE_EI(node) == EI_THREAD_END)) { 887 888 return AGENT_ERROR_ILLEGAL_ARGUMENT; 889 } 890 891 FILTER(node, index).modifier = 892 JDWP_REQUEST_MODIFIER(ClassMatch); 893 filter->classPattern = classPattern; 894 return JVMTI_ERROR_NONE; 895 } 896 897 jvmtiError 898 eventFilter_setClassExcludeFilter(HandlerNode *node, jint index, 899 char *classPattern) 900 { 901 MatchFilter *filter = &FILTER(node, index).u.ClassExclude; 902 if (index >= FILTER_COUNT(node)) { 903 return AGENT_ERROR_ILLEGAL_ARGUMENT; 904 } 905 if ( 906 (NODE_EI(node) == EI_THREAD_START) || 907 (NODE_EI(node) == EI_THREAD_END)) { 908 909 return AGENT_ERROR_ILLEGAL_ARGUMENT; 910 } 911 912 FILTER(node, index).modifier = 913 JDWP_REQUEST_MODIFIER(ClassExclude); 914 filter->classPattern = classPattern; 915 return JVMTI_ERROR_NONE; 916 } 917 918 jvmtiError 919 eventFilter_setStepFilter(HandlerNode *node, jint index, 920 jthread thread, jint size, jint depth) 921 { 922 jvmtiError error; 923 JNIEnv *env = getEnv(); 924 StepFilter *filter = &FILTER(node, index).u.Step; 925 if (index >= FILTER_COUNT(node)) { 926 return AGENT_ERROR_ILLEGAL_ARGUMENT; 927 } 928 if (NODE_EI(node) != EI_SINGLE_STEP) { 929 return AGENT_ERROR_ILLEGAL_ARGUMENT; 930 } 931 932 /* Create a thread ref that will live beyond */ 933 /* the end of this call */ 934 saveGlobalRef(env, thread, &(filter->thread)); 935 error = stepControl_beginStep(env, filter->thread, size, depth, node); 936 if (error != JVMTI_ERROR_NONE) { 937 tossGlobalRef(env, &(filter->thread)); 938 return error; 939 } 940 FILTER(node, index).modifier = JDWP_REQUEST_MODIFIER(Step); 941 filter->depth = depth; 942 filter->size = size; 943 return JVMTI_ERROR_NONE; 944 } 945 946 947 jvmtiError 948 eventFilter_setSourceNameMatchFilter(HandlerNode *node, 949 jint index, 950 char *sourceNamePattern) { 951 SourceNameFilter *filter = &FILTER(node, index).u.SourceNameOnly; 952 if (index >= FILTER_COUNT(node)) { 953 return AGENT_ERROR_ILLEGAL_ARGUMENT; 954 } 955 if (NODE_EI(node) != EI_CLASS_PREPARE) { 956 return AGENT_ERROR_ILLEGAL_ARGUMENT; 957 } 958 959 FILTER(node, index).modifier = 960 JDWP_REQUEST_MODIFIER(SourceNameMatch); 961 filter->sourceNamePattern = sourceNamePattern; 962 return JVMTI_ERROR_NONE; 963 964 } 965 966 /***** JVMTI event enabling / disabling *****/ 967 968 /** 969 * Return the Filter that is of the specified type (modifier). 970 * Return NULL if not found. 971 */ 972 static Filter * 973 findFilter(HandlerNode *node, jint modifier) 974 { 975 int i; 976 Filter *filter; 977 for (i = 0, filter = FILTERS_ARRAY(node); 978 i <FILTER_COUNT(node); 979 i++, filter++) { 980 if (filter->modifier == modifier) { 981 return filter; 982 } 983 } 984 return NULL; 985 } 986 987 /** 988 * Determine if the specified breakpoint node is in the 989 * same location as the LocationFilter passed in arg. 990 * 991 * This is a match function called by a 992 * eventHandlerRestricted_iterator invokation. 993 */ 994 static jboolean 995 matchBreakpoint(JNIEnv *env, HandlerNode *node, void *arg) 996 { 997 LocationFilter *goal = (LocationFilter *)arg; 998 Filter *filter = FILTERS_ARRAY(node); 999 int i; 1000 1001 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 1002 switch (filter->modifier) { 1003 case JDWP_REQUEST_MODIFIER(LocationOnly): { 1004 LocationFilter *trial = &(filter->u.LocationOnly); 1005 if (trial->method == goal->method && 1006 trial->location == goal->location && 1007 isSameObject(env, trial->clazz, goal->clazz)) { 1008 return JNI_TRUE; 1009 } 1010 } 1011 } 1012 } 1013 return JNI_FALSE; 1014 } 1015 1016 /** 1017 * Set a breakpoint if this is the first one at this location. 1018 */ 1019 static jvmtiError 1020 setBreakpoint(HandlerNode *node) 1021 { 1022 jvmtiError error = JVMTI_ERROR_NONE; 1023 Filter *filter; 1024 1025 filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly)); 1026 if (filter == NULL) { 1027 /* bp event with no location filter */ 1028 error = AGENT_ERROR_INTERNAL; 1029 } else { 1030 LocationFilter *lf = &(filter->u.LocationOnly); 1031 1032 /* if this is the first handler for this 1033 * location, set bp at JVMTI level 1034 */ 1035 if (!eventHandlerRestricted_iterator( 1036 EI_BREAKPOINT, matchBreakpoint, lf)) { 1037 LOG_LOC(("SetBreakpoint at location: method=%p,location=%d", 1038 lf->method, (int)lf->location)); 1039 error = JVMTI_FUNC_PTR(gdata->jvmti,SetBreakpoint) 1040 (gdata->jvmti, lf->method, lf->location); 1041 } 1042 } 1043 return error; 1044 } 1045 1046 /** 1047 * Clear a breakpoint if this is the last one at this location. 1048 */ 1049 static jvmtiError 1050 clearBreakpoint(HandlerNode *node) 1051 { 1052 jvmtiError error = JVMTI_ERROR_NONE; 1053 Filter *filter; 1054 1055 filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly)); 1056 if (filter == NULL) { 1057 /* bp event with no location filter */ 1058 error = AGENT_ERROR_INTERNAL; 1059 } else { 1060 LocationFilter *lf = &(filter->u.LocationOnly); 1061 1062 /* if this is the last handler for this 1063 * location, clear bp at JVMTI level 1064 */ 1065 if (!eventHandlerRestricted_iterator( 1066 EI_BREAKPOINT, matchBreakpoint, lf)) { 1067 LOG_LOC(("ClearBreakpoint at location: method=%p,location=%d", 1068 lf->method, (int)lf->location)); 1069 error = JVMTI_FUNC_PTR(gdata->jvmti,ClearBreakpoint) 1070 (gdata->jvmti, lf->method, lf->location); 1071 } 1072 } 1073 return error; 1074 } 1075 1076 /** 1077 * Return true if a breakpoint is set at the specified location. 1078 */ 1079 jboolean 1080 isBreakpointSet(jclass clazz, jmethodID method, jlocation location) 1081 { 1082 LocationFilter lf; 1083 1084 lf.clazz = clazz; 1085 lf.method = method; 1086 lf.location = location; 1087 1088 return eventHandlerRestricted_iterator(EI_BREAKPOINT, 1089 matchBreakpoint, &lf); 1090 } 1091 1092 /** 1093 * Determine if the specified watchpoint node has the 1094 * same field as the FieldFilter passed in arg. 1095 * 1096 * This is a match function called by a 1097 * eventHandlerRestricted_iterator invokation. 1098 */ 1099 static jboolean 1100 matchWatchpoint(JNIEnv *env, HandlerNode *node, void *arg) 1101 { 1102 FieldFilter *goal = (FieldFilter *)arg; 1103 Filter *filter = FILTERS_ARRAY(node); 1104 int i; 1105 1106 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 1107 switch (filter->modifier) { 1108 case JDWP_REQUEST_MODIFIER(FieldOnly): { 1109 FieldFilter *trial = &(filter->u.FieldOnly); 1110 if (trial->field == goal->field && 1111 isSameObject(env, trial->clazz, goal->clazz)) { 1112 return JNI_TRUE; 1113 } 1114 } 1115 } 1116 } 1117 return JNI_FALSE; 1118 } 1119 1120 /** 1121 * Set a watchpoint if this is the first one on this field. 1122 */ 1123 static jvmtiError 1124 setWatchpoint(HandlerNode *node) 1125 { 1126 jvmtiError error = JVMTI_ERROR_NONE; 1127 Filter *filter; 1128 1129 filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly)); 1130 if (filter == NULL) { 1131 /* event with no field filter */ 1132 error = AGENT_ERROR_INTERNAL; 1133 } else { 1134 FieldFilter *ff = &(filter->u.FieldOnly); 1135 1136 /* if this is the first handler for this 1137 * field, set wp at JVMTI level 1138 */ 1139 if (!eventHandlerRestricted_iterator( 1140 NODE_EI(node), matchWatchpoint, ff)) { 1141 error = (NODE_EI(node) == EI_FIELD_ACCESS) ? 1142 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldAccessWatch) 1143 (gdata->jvmti, ff->clazz, ff->field) : 1144 JVMTI_FUNC_PTR(gdata->jvmti,SetFieldModificationWatch) 1145 (gdata->jvmti, ff->clazz, ff->field); 1146 } 1147 } 1148 return error; 1149 } 1150 1151 /** 1152 * Clear a watchpoint if this is the last one on this field. 1153 */ 1154 static jvmtiError 1155 clearWatchpoint(HandlerNode *node) 1156 { 1157 jvmtiError error = JVMTI_ERROR_NONE; 1158 Filter *filter; 1159 1160 filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly)); 1161 if (filter == NULL) { 1162 /* event with no field filter */ 1163 error = AGENT_ERROR_INTERNAL; 1164 } else { 1165 FieldFilter *ff = &(filter->u.FieldOnly); 1166 1167 /* if this is the last handler for this 1168 * field, clear wp at JVMTI level 1169 */ 1170 if (!eventHandlerRestricted_iterator( 1171 NODE_EI(node), matchWatchpoint, ff)) { 1172 error = (NODE_EI(node) == EI_FIELD_ACCESS) ? 1173 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldAccessWatch) 1174 (gdata->jvmti, ff->clazz, ff->field) : 1175 JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldModificationWatch) 1176 (gdata->jvmti, ff->clazz, ff->field); 1177 } 1178 } 1179 return error; 1180 } 1181 1182 /** 1183 * Determine the thread this node is filtered on. 1184 * NULL if not thread filtered. 1185 */ 1186 static jthread 1187 requestThread(HandlerNode *node) 1188 { 1189 int i; 1190 Filter *filter = FILTERS_ARRAY(node); 1191 1192 for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) { 1193 switch (filter->modifier) { 1194 case JDWP_REQUEST_MODIFIER(ThreadOnly): 1195 return filter->u.ThreadOnly.thread; 1196 } 1197 } 1198 1199 return NULL; 1200 } 1201 1202 /** 1203 * Determine if the specified node has a 1204 * thread filter with the thread passed in arg. 1205 * 1206 * This is a match function called by a 1207 * eventHandlerRestricted_iterator invokation. 1208 */ 1209 static jboolean 1210 matchThread(JNIEnv *env, HandlerNode *node, void *arg) 1211 { 1212 jthread goalThread = (jthread)arg; 1213 jthread reqThread = requestThread(node); 1214 1215 /* If the event's thread and the passed thread are the same 1216 * (or both are NULL), we have a match. 1217 */ 1218 return isSameObject(env, reqThread, goalThread); 1219 } 1220 1221 /** 1222 * Do any enabling of events (including setting breakpoints etc) 1223 * needed to get the events requested by this handler node. 1224 */ 1225 static jvmtiError 1226 enableEvents(HandlerNode *node) 1227 { 1228 jvmtiError error = JVMTI_ERROR_NONE; 1229 1230 switch (NODE_EI(node)) { 1231 /* The stepping code directly enables/disables stepping as 1232 * necessary 1233 */ 1234 case EI_SINGLE_STEP: 1235 /* Internal thread event handlers are always present 1236 * (hardwired in the event hook), so we don't change the 1237 * notification mode here. 1238 */ 1239 case EI_THREAD_START: 1240 case EI_THREAD_END: 1241 case EI_VM_INIT: 1242 case EI_VM_DEATH: 1243 case EI_CLASS_PREPARE: 1244 case EI_GC_FINISH: 1245 return error; 1246 1247 case EI_FIELD_ACCESS: 1248 case EI_FIELD_MODIFICATION: 1249 error = setWatchpoint(node); 1250 break; 1251 1252 case EI_BREAKPOINT: 1253 error = setBreakpoint(node); 1254 break; 1255 1256 default: 1257 break; 1258 } 1259 1260 /* Don't globally enable if the above failed */ 1261 if (error == JVMTI_ERROR_NONE) { 1262 jthread thread = requestThread(node); 1263 1264 /* If this is the first request of it's kind on this 1265 * thread (or all threads (thread == NULL)) then enable 1266 * these events on this thread. 1267 */ 1268 if (!eventHandlerRestricted_iterator( 1269 NODE_EI(node), matchThread, thread)) { 1270 error = threadControl_setEventMode(JVMTI_ENABLE, 1271 NODE_EI(node), thread); 1272 } 1273 } 1274 return error; 1275 } 1276 1277 /** 1278 * Do any disabling of events (including clearing breakpoints etc) 1279 * needed to no longer get the events requested by this handler node. 1280 */ 1281 static jvmtiError 1282 disableEvents(HandlerNode *node) 1283 { 1284 jvmtiError error = JVMTI_ERROR_NONE; 1285 jvmtiError error2 = JVMTI_ERROR_NONE; 1286 jthread thread; 1287 1288 1289 switch (NODE_EI(node)) { 1290 /* The stepping code directly enables/disables stepping as 1291 * necessary 1292 */ 1293 case EI_SINGLE_STEP: 1294 /* Internal thread event handlers are always present 1295 * (hardwired in the event hook), so we don't change the 1296 * notification mode here. 1297 */ 1298 case EI_THREAD_START: 1299 case EI_THREAD_END: 1300 case EI_VM_INIT: 1301 case EI_VM_DEATH: 1302 case EI_CLASS_PREPARE: 1303 case EI_GC_FINISH: 1304 return error; 1305 1306 case EI_FIELD_ACCESS: 1307 case EI_FIELD_MODIFICATION: 1308 error = clearWatchpoint(node); 1309 break; 1310 1311 case EI_BREAKPOINT: 1312 error = clearBreakpoint(node); 1313 break; 1314 1315 default: 1316 break; 1317 } 1318 1319 thread = requestThread(node); 1320 1321 /* If this is the last request of it's kind on this thread 1322 * (or all threads (thread == NULL)) then disable these 1323 * events on this thread. 1324 * 1325 * Disable even if the above caused an error 1326 */ 1327 if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) { 1328 error2 = threadControl_setEventMode(JVMTI_DISABLE, 1329 NODE_EI(node), thread); 1330 } 1331 return error != JVMTI_ERROR_NONE? error : error2; 1332 } 1333 1334 1335 /***** filter (and event) installation and deinstallation *****/ 1336 1337 /** 1338 * Make the set of event filters that correspond with this 1339 * node active (including enabling the corresponding events). 1340 */ 1341 jvmtiError 1342 eventFilterRestricted_install(HandlerNode *node) 1343 { 1344 return enableEvents(node); 1345 } 1346 1347 /** 1348 * Make the set of event filters that correspond with this 1349 * node inactive (including disabling the corresponding events 1350 * and freeing resources). 1351 */ 1352 jvmtiError 1353 eventFilterRestricted_deinstall(HandlerNode *node) 1354 { 1355 jvmtiError error1, error2; 1356 1357 error1 = disableEvents(node); 1358 error2 = clearFilters(node); 1359 1360 return error1 != JVMTI_ERROR_NONE? error1 : error2; 1361 } 1362