eventfilter.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,327 行 · 第 1/3 页

C
1,327
字号
/* * @(#)eventFilter.c	1.9 06/10/25 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation.  *  * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt).  *  * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA  *  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions.  *//*  * eventFilter * * This module handles event filteration and the enabling/disabling * of the corresponding events. Used for filters on JDI EventRequests * and also internal requests.  Our data is in a private hidden section * of the HandlerNode's data.  See comment for enclosing * module eventHandler. */#include "util.h"#include "eventFilter.h"#include "eventFilterRestricted.h"#include "eventHandlerRestricted.h"#include "stepControl.h"#include "threadControl.h"#include "SDE.h"typedef struct ClassFilter {    jclass clazz;} ClassFilter;typedef struct LocationFilter {    jclass clazz;    jmethodID method;    jlocation location;} LocationFilter;typedef struct ThreadFilter {    jthread thread;} ThreadFilter;typedef struct CountFilter {    jint count;} CountFilter;typedef struct ConditionalFilter {    jint exprID;} ConditionalFilter;typedef struct FieldFilter {    jclass clazz;    jfieldID field;} FieldFilter;typedef struct ExceptionFilter {    jclass exception;    jboolean caught;    jboolean uncaught;} ExceptionFilter;typedef struct InstanceFilter {    jobject instance;} InstanceFilter;typedef struct StepFilter {    jint size;    jint depth;    jthread thread;} StepFilter;typedef struct MatchFilter {    char *classPattern;} MatchFilter;typedef struct SourceNameFilter {    char *sourceNamePattern;} SourceNameFilter;typedef struct Filter_ {    jbyte modifier;    union {        struct ClassFilter ClassOnly;        struct LocationFilter LocationOnly;        struct ThreadFilter ThreadOnly;        struct CountFilter Count;        struct ConditionalFilter Conditional;        struct FieldFilter FieldOnly;        struct ExceptionFilter ExceptionOnly;        struct InstanceFilter InstanceOnly;        struct StepFilter Step;        struct MatchFilter ClassMatch;        struct MatchFilter ClassExclude;        struct SourceNameFilter SourceNameOnly;    } u;} Filter;/* The filters array is allocated to the specified filterCount. * Theoretically, some compiler could do range checking on this * array - so, we define it to have a ludicrously large size so * that this range checking won't get upset. * * The actual allocated number of bytes is computed using the * offset of "filters" and so is not effected by this number. */#define MAX_FILTERS 10000typedef struct EventFilters_ {    jint filterCount;    Filter filters[MAX_FILTERS];} EventFilters;typedef struct EventFilterPrivate_HandlerNode_ {    EventHandlerRestricted_HandlerNode   not_for_us;    EventFilters                         ef;} EventFilterPrivate_HandlerNode;/** * The following macros extract filter info (EventFilters) from private  * data at the end of a HandlerNode  */#define EVENT_FILTERS(node) (&(((EventFilterPrivate_HandlerNode*)(void*)node)->ef))#define FILTER_COUNT(node)  (EVENT_FILTERS(node)->filterCount)#define FILTERS_ARRAY(node) (EVENT_FILTERS(node)->filters)#define FILTER(node,index)  ((FILTERS_ARRAY(node))[index])#define NODE_EI(node)          (node->ei)/***** filter set-up / destruction *****//** * Allocate a HandlerNode. * We do it because eventHandler doesn't know how big to make it. */HandlerNode *eventFilterRestricted_alloc(jint filterCount){    /*LINTED*/    size_t size = offsetof(EventFilterPrivate_HandlerNode, ef) +                   offsetof(EventFilters, filters) +                   (filterCount * (int)sizeof(Filter));    HandlerNode *node = jvmtiAllocate((jint)size);    if (node != NULL) {        int i;                Filter *filter;        (void)memset(node, 0, size);                FILTER_COUNT(node) = filterCount;                /* Initialize all modifiers         */        for (i = 0, filter = FILTERS_ARRAY(node);                                     i < filterCount;                                     i++, filter++) {            filter->modifier = JDWP_REQUEST_NONE;        }    }    return node;}/**  * Free up global refs held by the filter.  * free things up at the JNI level if needed.  */static jvmtiErrorclearFilters(HandlerNode *node){    JNIEnv *env = getEnv();    jint i;    jvmtiError error = JVMTI_ERROR_NONE;    Filter *filter = FILTERS_ARRAY(node);    for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {        switch (filter->modifier) {            case JDWP_REQUEST_MODIFIER(ThreadOnly):                if ( filter->u.ThreadOnly.thread != NULL ) {                    tossGlobalRef(env, &(filter->u.ThreadOnly.thread));                }                break;            case JDWP_REQUEST_MODIFIER(LocationOnly):                tossGlobalRef(env, &(filter->u.LocationOnly.clazz));                break;            case JDWP_REQUEST_MODIFIER(FieldOnly):                tossGlobalRef(env, &(filter->u.FieldOnly.clazz));                break;            case JDWP_REQUEST_MODIFIER(ExceptionOnly):                if ( filter->u.ExceptionOnly.exception != NULL ) {                    tossGlobalRef(env, &(filter->u.ExceptionOnly.exception));                }                break;            case JDWP_REQUEST_MODIFIER(InstanceOnly):                if ( filter->u.InstanceOnly.instance != NULL ) {                    tossGlobalRef(env, &(filter->u.InstanceOnly.instance));                }                break;            case JDWP_REQUEST_MODIFIER(ClassOnly):                tossGlobalRef(env, &(filter->u.ClassOnly.clazz));                break;            case JDWP_REQUEST_MODIFIER(ClassMatch):                jvmtiDeallocate(filter->u.ClassMatch.classPattern);                break;            case JDWP_REQUEST_MODIFIER(ClassExclude):                jvmtiDeallocate(filter->u.ClassExclude.classPattern);                break;            case JDWP_REQUEST_MODIFIER(Step): {                jthread thread = filter->u.Step.thread;                error = stepControl_endStep(thread);                if (error == JVMTI_ERROR_NONE) {                    tossGlobalRef(env, &(filter->u.Step.thread));                }                break;            }        }    }    if (error == JVMTI_ERROR_NONE) {        FILTER_COUNT(node) = 0; /* blast so we don't clear again */    }    return error;}/***** filtering *****//* * Match a string against a wildcard * string pattern. */static jboolean patternStringMatch(char *classname, const char *pattern){    int pattLen;    int compLen;    char *start;    int offset;    if ( pattern==NULL || classname==NULL ) {        return JNI_FALSE;    }    pattLen = (int)strlen(pattern);    if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) {        /* An exact match is required when there is no *: bug 4331522 */         return strcmp(pattern, classname) == 0;     } else {        compLen = pattLen - 1;        offset = (int)strlen(classname) - compLen;        if (offset < 0) {            return JNI_FALSE;        } else {            if (pattern[0] == '*') {                pattern++;                start = classname + offset;            }  else {                start = classname;            }            return strncmp(pattern, start, compLen) == 0;        }    }}/* Return the object instance in which the event occurred *//* Return NULL if static or if an error occurs */static jobjecteventInstance(EventInfo *evinfo){    jobject     object          = NULL;    jthread     thread          ;    jmethodID   method          ;    jint        modifiers       = 0;    jvmtiError  error;    switch (evinfo->ei) {        case EI_SINGLE_STEP:        case EI_BREAKPOINT:        case EI_FRAME_POP:        case EI_METHOD_ENTRY:        case EI_METHOD_EXIT:        case EI_EXCEPTION:        case EI_EXCEPTION_CATCH:        case EI_MONITOR_CONTENDED_ENTER:         case EI_MONITOR_CONTENDED_ENTERED:        case EI_MONITOR_WAIT:        case EI_MONITOR_WAITED:            thread      = evinfo->thread;            method      = evinfo->method;            break;        case EI_FIELD_ACCESS:        case EI_FIELD_MODIFICATION:            object = evinfo->object;            return object;        default:            return object; /* NULL */    }    error = methodModifiers(method, &modifiers);        /* fail if error or static (0x8) */    if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {        FrameNumber fnum            = 0;        /* get slot zero object "this" */        error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)                    (gdata->jvmti, thread, fnum, 0, &object);        if (error != JVMTI_ERROR_NONE)            object = NULL;    }        return object;}/* * Determine if this event is interesting to this handler. * Do so by checking each of the handler's filters. * Return false if any of the filters fail,  * true if the handler wants this event. * Anyone modifying this function should check  * eventFilterRestricted_passesUnloadFilter and  * eventFilter_predictFiltering as well. * * If shouldDelete is returned true, a count filter has expired * and the corresponding node should be deleted. */jboolean eventFilterRestricted_passesFilter(JNIEnv *env,                                   char *classname,                                   EventInfo *evinfo,                                    HandlerNode *node,                                    jboolean *shouldDelete){    jthread thread;    jclass clazz;    jmethodID method;    Filter *filter = FILTERS_ARRAY(node);    int i;    *shouldDelete = JNI_FALSE;    thread = evinfo->thread;    clazz = evinfo->clazz;    method = evinfo->method;    /*     * Suppress most events if they happen in debug threads     */    if ((evinfo->ei != EI_CLASS_PREPARE) &&        (evinfo->ei != EI_GC_FINISH) &&        (evinfo->ei != EI_CLASS_LOAD) &&        threadControl_isDebugThread(thread)) {        return JNI_FALSE;    }    for (i = 0; i < FILTER_COUNT(node); ++i, ++filter) {        switch (filter->modifier) {            case JDWP_REQUEST_MODIFIER(ThreadOnly):                if (!isSameObject(env, thread, filter->u.ThreadOnly.thread)) {                    return JNI_FALSE;                }                break;                    case JDWP_REQUEST_MODIFIER(ClassOnly):                /* Class filters catch events in the specified                 * class and any subclass/subinterface.                   */                if (!JNI_FUNC_PTR(env,IsAssignableFrom)(env, clazz,                               filter->u.ClassOnly.clazz)) {                    return JNI_FALSE;                }                break;                    /* This is kinda cheating assumming the event             * fields will be in the same locations, but it is             * true now.              */            case JDWP_REQUEST_MODIFIER(LocationOnly):                if  (evinfo->method !=                           filter->u.LocationOnly.method ||                     evinfo->location !=                           filter->u.LocationOnly.location ||                     !isSameObject(env, clazz, filter->u.LocationOnly.clazz)) {                    return JNI_FALSE;                }                break;            case JDWP_REQUEST_MODIFIER(FieldOnly):                 /* Field watchpoints can be triggered from the                 * declared class or any subclass/subinterface.                  */                if ((evinfo->u.field_access.field !=                      filter->u.FieldOnly.field) ||                    !isSameObject(env, evinfo->u.field_access.field_clazz,                               filter->u.FieldOnly.clazz)) {                    return JNI_FALSE;                }                break;                        case JDWP_REQUEST_MODIFIER(ExceptionOnly):                 /* do we want caught/uncaught exceptions */                if (!((evinfo->u.exception.catch_clazz == NULL)?                       filter->u.ExceptionOnly.uncaught :                       filter->u.ExceptionOnly.caught)) {                    return JNI_FALSE;                }                    /* do we care about exception class */                if (filter->u.ExceptionOnly.exception != NULL) {                    jclass exception = evinfo->object;                            /* do we want this exception class */                    if (!JNI_FUNC_PTR(env,IsInstanceOf)(env, exception,                            filter->u.ExceptionOnly.exception)) {                        return JNI_FALSE;                    }                }                break;                        case JDWP_REQUEST_MODIFIER(InstanceOnly): {                jobject eventInst = eventInstance(evinfo);                jobject filterInst = filter->u.InstanceOnly.instance;                /* if no error and doesn't match, don't pass                 * filter                  */                if (eventInst != NULL &&                      !isSameObject(env, eventInst, filterInst)) {                    return JNI_FALSE;                }                break;            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?