• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
eventFilterRestricted_alloc(jint filterCount)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
clearFilters(HandlerNode * node)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
patternStringMatch(char * classname,const char * pattern)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 
isVersionGte12x()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
eventInstance(EventInfo * evinfo)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
eventFilterRestricted_passesFilter(JNIEnv * env,char * classname,EventInfo * evinfo,HandlerNode * node,jboolean * shouldDelete)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
eventFilterRestricted_passesUnloadFilter(JNIEnv * env,char * classname,HandlerNode * node,jboolean * shouldDelete)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
eventFilter_predictFiltering(HandlerNode * node,jclass clazz,char * classname)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
eventFilterRestricted_isBreakpointInClass(JNIEnv * env,jclass clazz,HandlerNode * node)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
eventFilter_setConditionalFilter(HandlerNode * node,jint index,jint exprID)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
eventFilter_setCountFilter(HandlerNode * node,jint index,jint count)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
eventFilter_setThreadOnlyFilter(HandlerNode * node,jint index,jthread thread)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
eventFilter_setLocationOnlyFilter(HandlerNode * node,jint index,jclass clazz,jmethodID method,jlocation location)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
eventFilter_setFieldOnlyFilter(HandlerNode * node,jint index,jclass clazz,jfieldID field)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
eventFilter_setClassOnlyFilter(HandlerNode * node,jint index,jclass clazz)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
eventFilter_setExceptionOnlyFilter(HandlerNode * node,jint index,jclass exceptionClass,jboolean caught,jboolean uncaught)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
eventFilter_setInstanceOnlyFilter(HandlerNode * node,jint index,jobject instance)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
eventFilter_setClassMatchFilter(HandlerNode * node,jint index,char * classPattern)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
eventFilter_setClassExcludeFilter(HandlerNode * node,jint index,char * classPattern)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
eventFilter_setStepFilter(HandlerNode * node,jint index,jthread thread,jint size,jint depth)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
eventFilter_setSourceNameMatchFilter(HandlerNode * node,jint index,char * sourceNamePattern)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 *
findFilter(HandlerNode * node,jint modifier)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
matchBreakpoint(JNIEnv * env,HandlerNode * node,void * arg)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
setBreakpoint(HandlerNode * node)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
clearBreakpoint(HandlerNode * node)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
isBreakpointSet(jclass clazz,jmethodID method,jlocation location)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
matchWatchpoint(JNIEnv * env,HandlerNode * node,void * arg)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
setWatchpoint(HandlerNode * node)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
clearWatchpoint(HandlerNode * node)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
requestThread(HandlerNode * node)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
matchThread(JNIEnv * env,HandlerNode * node,void * arg)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
enableEvents(HandlerNode * node)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
disableEvents(HandlerNode * node)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
eventFilterRestricted_install(HandlerNode * node)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
eventFilterRestricted_deinstall(HandlerNode * node)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