/**
 * This is the back-end implementation for disabling
 * (what are at the JDI level) EventRequests.
 */
static jboolean
clearCommand(PacketInputStream *in, PacketOutputStream *out)
{
    jvmtiError error;
    jdwpEvent eventType;
    HandlerID handlerID;
    EventIndex ei;

    eventType = inStream_readByte(in);
    if (inStream_error(in)) {
        return JNI_TRUE;
    }
    handlerID = inStream_readInt(in);
    if (inStream_error(in)) {
        return JNI_TRUE;
    }

    ei = jdwp2EventIndex(eventType);
    if (ei == 0) {
        /* NOTE: Clear command not yet spec'ed to return INVALID_EVENT_TYPE */
        outStream_setError(out, JDWP_ERROR(INVALID_EVENT_TYPE));
        return JNI_TRUE;
    }

    error = eventHandler_freeByID(ei, handlerID);
    if (error != JVMTI_ERROR_NONE) {
        outStream_setError(out, map2jdwpError(error));
    }

    return JNI_TRUE;
}
static jboolean
clearAllBreakpoints(PacketInputStream *in, PacketOutputStream *out)
{
    jvmtiError error;

    error = eventHandler_freeAll(EI_BREAKPOINT);
    if (error != JVMTI_ERROR_NONE) {
        outStream_setError(out, map2jdwpError(error));
    }
    return JNI_TRUE;
}
/**
 * Take JDWP "modifiers" (which are JDI explicit filters, like
 * addCountFilter(), and implicit filters, like the LocationOnly
 * filter that goes with breakpoints) and add them as filters
 * (eventFilter) to the HandlerNode (eventHandler).
 */
static jdwpError
readAndSetFilters(JNIEnv *env, PacketInputStream *in, HandlerNode *node,
                  jint filterCount)
{
    int i;
    jdwpError serror = JDWP_ERROR(NONE);

    for (i = 0; i < filterCount; ++i) {

        jbyte modifier;

        modifier = inStream_readByte(in);
        if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
            break;

        switch (modifier) {

            case JDWP_REQUEST_MODIFIER(Conditional): {
                jint exprID;
                exprID = inStream_readInt(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setConditionalFilter(node, i, exprID));
                break;
            }

            case JDWP_REQUEST_MODIFIER(Count): {
                jint count;
                count = inStream_readInt(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setCountFilter(node, i, count));
                break;
            }

            case JDWP_REQUEST_MODIFIER(ThreadOnly): {
                jthread thread;
                thread = inStream_readThreadRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setThreadOnlyFilter(node, i, thread));
                break;
            }

            case JDWP_REQUEST_MODIFIER(LocationOnly): {
                jbyte tag;
                jclass clazz;
                jmethodID method;
                jlocation location;
                tag = inStream_readByte(in); /* not currently used */
                tag = tag; /* To shut up lint */
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                clazz = inStream_readClassRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                method = inStream_readMethodID(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                location = inStream_readLocation(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setLocationOnlyFilter(node, i, clazz, method, location));
                break;
            }

            case JDWP_REQUEST_MODIFIER(FieldOnly): {
                jclass clazz;
                jfieldID field;
                clazz = inStream_readClassRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                field = inStream_readFieldID(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setFieldOnlyFilter(node, i, clazz, field));
                break;
            }

            case JDWP_REQUEST_MODIFIER(ClassOnly): {
                jclass clazz;
                clazz = inStream_readClassRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setClassOnlyFilter(node, i, clazz));
                break;
            }

            case JDWP_REQUEST_MODIFIER(ExceptionOnly): {
                jclass exception;
                jboolean caught;
                jboolean uncaught;
                exception = inStream_readClassRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                caught = inStream_readBoolean(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                uncaught = inStream_readBoolean(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setExceptionOnlyFilter(node, i,
                                             exception, caught, uncaught));
                break;
            }

            case JDWP_REQUEST_MODIFIER(InstanceOnly): {
                jobject instance;
                instance = inStream_readObjectRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setInstanceOnlyFilter(node, i, instance));
                break;
            }

            case JDWP_REQUEST_MODIFIER(ClassMatch): {
                char *pattern;
                pattern = inStream_readString(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setClassMatchFilter(node, i,
                                                                pattern));
                break;
            }

            case JDWP_REQUEST_MODIFIER(ClassExclude): {
                char *pattern;
                pattern = inStream_readString(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                        eventFilter_setClassExcludeFilter(node, i, pattern));
                break;
            }
            case JDWP_REQUEST_MODIFIER(Step): {
                jthread thread;
                jint size;
                jint depth;
                thread = inStream_readThreadRef(env, in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                size = inStream_readInt(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                depth = inStream_readInt(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) )
                    break;
                serror = map2jdwpError(
                      eventFilter_setStepFilter(node, i, thread, size, depth));
                break;
            }
            case JDWP_REQUEST_MODIFIER(SourceNameMatch): {
                char *sourceNamePattern;
                sourceNamePattern = inStream_readString(in);
                if ( (serror = inStream_error(in)) != JDWP_ERROR(NONE) ) {
                    break;
                }
                serror = map2jdwpError(
                        eventFilter_setSourceNameMatchFilter(node, i, sourceNamePattern));
                break;
            }

            default:
                serror = JDWP_ERROR(ILLEGAL_ARGUMENT);
                break;
        }
        if ( serror != JDWP_ERROR(NONE) )
            break;
    }
    return serror;
}
/**
 * This is the back-end implementation for enabling
 * (what are at the JDI level) EventRequests.
 *
 * Allocate the event request handler (eventHandler).
 * Add any filters (explicit or implicit).
 * Install the handler.
 * Return the handlerID which is used to map subsequent
 * events to the EventRequest that created it.
 */
static jboolean
setCommand(PacketInputStream *in, PacketOutputStream *out)
{
    jdwpError serror;
    HandlerNode *node;
    HandlerID requestID = -1;
    jdwpEvent eventType;
    jbyte suspendPolicy;
    jint filterCount;
    EventIndex ei;

    node = NULL;
    eventType = inStream_readByte(in);
    if (inStream_error(in)) {
        return JNI_TRUE;
    }
    suspendPolicy = inStream_readByte(in);
    if (inStream_error(in)) {
        return JNI_TRUE;
    }
    filterCount = inStream_readInt(in);
    if (inStream_error(in)) {
        return JNI_TRUE;
    }

    ei = jdwp2EventIndex(eventType);
    if (ei == 0) {
        outStream_setError(out, JDWP_ERROR(INVALID_EVENT_TYPE));
        return JNI_TRUE;
    }

    if (ei == EI_VM_INIT) {
        /*
         * VM is already initialized so there's no need to install a handler
         * for this event. However we need to allocate a requestID to send in
         * the reply to the debugger.
         */
        serror = JDWP_ERROR(NONE);
        requestID = eventHandler_allocHandlerID();
    } else {
        node = eventHandler_alloc(filterCount, ei, suspendPolicy);
        if (node == NULL) {
            outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
            return JNI_TRUE;
        }
        if (eventType == JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)) {
            node->needReturnValue = 1;
        } else {
            node->needReturnValue = 0;
        }
        serror = readAndSetFilters(getEnv(), in, node, filterCount);
        if (serror == JDWP_ERROR(NONE)) {
            jvmtiError error;
            error = eventHandler_installExternal(node);
            serror = map2jdwpError(error);
            if (serror == JDWP_ERROR(NONE)) {
                requestID = node->handlerID;
            }
        }
    }

    if (serror == JDWP_ERROR(NONE)) {
        (void)outStream_writeInt(out, requestID);
    } else {
        (void)eventHandler_free(node);
        outStream_setError(out, serror);
    }

    return JNI_TRUE;
}
Beispiel #5
0
jdwpError
transport_startTransport(jboolean isServer, char *name, char *address,
                         long timeout)
{
    jvmtiStartFunction func;
    jdwpTransportEnv *trans;
    char threadName[MAXPATHLEN + 100];
    jint err;
    jdwpError serror;

    /*
     * If the transport is already loaded then use it
     * Note: We're assuming here that we don't support multiple
     * transports - when we do then we need to handle the case
     * where the transport library only supports a single environment.
     * That probably means we have a bag a transport environments
     * to correspond to the transports bag.
     */
    if (transport != NULL) {
        trans = transport;
    } else {
        serror = loadTransport(name, &trans);
        if (serror != JDWP_ERROR(NONE)) {
            return serror;
        }
    }

    if (isServer) {

        char *retAddress;
        char *launchCommand;
        TransportInfo *info;
        jvmtiError error;
        int len;
        char* prop_value;

        info = jvmtiAllocate(sizeof(*info));
        if (info == NULL) {
            return JDWP_ERROR(OUT_OF_MEMORY);
        }
        info->name = jvmtiAllocate((int)strlen(name)+1);
        (void)strcpy(info->name, name);
        info->address = NULL;
        info->timeout = timeout;
        if (info->name == NULL) {
            serror = JDWP_ERROR(OUT_OF_MEMORY);
            goto handleError;
        }
        if (address != NULL) {
            info->address = jvmtiAllocate((int)strlen(address)+1);
            (void)strcpy(info->address, address);
            if (info->address == NULL) {
                serror = JDWP_ERROR(OUT_OF_MEMORY);
                goto handleError;
            }
        }

        info->transport = trans;

        err = (*trans)->StartListening(trans, address, &retAddress);
        if (err != JDWPTRANSPORT_ERROR_NONE) {
            printLastError(trans, err);
            serror = JDWP_ERROR(TRANSPORT_INIT);
            goto handleError;
        }

        /*
         * Record listener address in a system property
         */
        len = (int)strlen(name) + (int)strlen(retAddress) + 2; /* ':' and '\0' */
        prop_value = (char*)jvmtiAllocate(len);
        strcpy(prop_value, name);
        strcat(prop_value, ":");
        strcat(prop_value, retAddress);
        setTransportProperty(getEnv(), prop_value);
        jvmtiDeallocate(prop_value);


        (void)strcpy(threadName, "JDWP Transport Listener: ");
        (void)strcat(threadName, name);

        func = &acceptThread;
        error = spawnNewThread(func, (void*)info, threadName);
        if (error != JVMTI_ERROR_NONE) {
            serror = map2jdwpError(error);
            goto handleError;
        }

        launchCommand = debugInit_launchOnInit();
        if (launchCommand != NULL) {
            serror = launch(launchCommand, name, retAddress);
            if (serror != JDWP_ERROR(NONE)) {
                goto handleError;
            }
        } else {
            if ( ! gdata->quiet ) {
                TTY_MESSAGE(("Listening for transport %s at address: %s",
                    name, retAddress));
            }
        }
        return JDWP_ERROR(NONE);

handleError:
        jvmtiDeallocate(info->name);
        jvmtiDeallocate(info->address);
        jvmtiDeallocate(info);
    } else {
        /*
         * Note that we don't attempt to do a launch here. Launching
         * is currently supported only in server mode.
         */

        /*
         * If we're connecting to another process, there shouldn't be
         * any concurrent listens, so its ok if we block here in this
         * thread, waiting for the attach to finish.
         */
         err = (*trans)->Attach(trans, address, timeout, 0);
         if (err != JDWPTRANSPORT_ERROR_NONE) {
             printLastError(trans, err);
             serror = JDWP_ERROR(TRANSPORT_INIT);
             return serror;
         }

         /*
          * Start the transport loop in a separate thread
          */
         (void)strcpy(threadName, "JDWP Transport Listener: ");
         (void)strcat(threadName, name);

         func = &attachThread;
         err = spawnNewThread(func, (void*)trans, threadName);
         serror = map2jdwpError(err);
    }
    return serror;
}
Beispiel #6
0
/*
 * Determine the component class by looking thru all classes for
 * one that has the signature of the component and the same class loadeer
 * as the array.  See JVM spec 5.3.3:
 *     If the component type is a reference type, C is marked as having
 *     been defined by the defining class loader of the component type.
 */
static jdwpError 
getComponentClass(JNIEnv *env, jclass arrayClass, char *componentSignature, 
                jclass *componentClassPtr) 
{
    jobject arrayClassLoader;
    jclass *classes;
    jint count;
    jclass componentClass = NULL;
    jdwpError serror;
    jvmtiError error;

    serror = JDWP_ERROR(NONE);
    
    error = classLoader(arrayClass, &arrayClassLoader);
    if (error != JVMTI_ERROR_NONE) {
        return map2jdwpError(error);
    }
    
    error = allLoadedClasses(&classes, &count);
    if (error != JVMTI_ERROR_NONE) {
        serror = map2jdwpError(error);
    } else {
        int i;
        for (i = 0; (i < count) && (componentClass == NULL); i++) {
            char *signature = NULL;
            jclass clazz = classes[i];
            jboolean match;
            jvmtiError error;

            /* signature must match */
            error = classSignature(clazz, &signature, NULL);
            if (error != JVMTI_ERROR_NONE) {
                serror = map2jdwpError(error);
                break;
            }
            match = strcmp(signature, componentSignature) == 0;
            jvmtiDeallocate(signature);

            /* if signature matches, get class loader to check if
             * it matches 
             */
            if (match) {
                jobject loader;
                error = classLoader(clazz, &loader);
                if (error != JVMTI_ERROR_NONE) {
                    return map2jdwpError(error);
                }
                match = isSameObject(env, loader, arrayClassLoader);
            }

            if (match) {
                componentClass = clazz;
            }
        }
        jvmtiDeallocate(classes);

        *componentClassPtr = componentClass;
    }

    if (serror == JDWP_ERROR(NONE) && componentClass == NULL) {
        /* per JVM spec, component class is always loaded 
         * before array class, so this should never occur.
         */
        serror = JDWP_ERROR(NOT_FOUND);
    }

    return serror;
}