stepcontrol.c

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

C
929
字号
/* * @(#)stepControl.c	1.55 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.  */#include "util.h"#include "stepControl.h"#include "eventHandler.h"#include "eventHelper.h"#include "threadControl.h"#include "SDE.h"static jrawMonitorID stepLock;static jintgetFrameCount(jthread thread){    jint count = 0;    jvmtiError error;        error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)                    (gdata->jvmti, thread, &count);    if (error != JVMTI_ERROR_NONE) {        EXIT_ERROR(error, "getting frame count");    }    return count;}/*                                                               * Most enabling/disabling of JVMTI events happens implicitly through  * the inserting and freeing of handlers for those events. Stepping is * different because requested steps are usually not identical to JVMTI steps.  * They usually require multiple events step, and otherwise, before they  * complete. While a step request is pending, we may need to temporarily * disable and re-enable stepping, but we can't just remove the handlers * because that would break the application's ability to remove the  * events. So, for step events only, we directly enable and disable stepping. * This is safe because there can only ever be one pending step request  * per thread.  */static void enableStepping(jthread thread){    jvmtiError error;        LOG_STEP(("enableStepping: thread=%p", thread));        error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP,                                            thread);    if (error != JVMTI_ERROR_NONE) {        EXIT_ERROR(error, "enabling single step");    }}static void disableStepping(jthread thread){    jvmtiError error;        LOG_STEP(("disableStepping: thread=%p", thread));        error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP,                                            thread);    if (error != JVMTI_ERROR_NONE) {        EXIT_ERROR(error, "disabling single step");    }}static jvmtiErrorgetFrameLocation(jthread thread,        jclass *pclazz, jmethodID *pmethod, jlocation *plocation){    jvmtiError error;        *pclazz = NULL;    *pmethod = NULL;    *plocation = -1;        error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)            (gdata->jvmti, thread, 0, pmethod, plocation);    if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) {        /* This also serves to verify that the methodID is valid */        error = methodClass(*pmethod, pclazz);    }    return error;}       static voidgetLineNumberTable(jmethodID method, jint *pcount,                 jvmtiLineNumberEntry **ptable){    jvmtiError error;        *pcount = 0;    *ptable = NULL;    /* If the method is native or obsolete, don't even ask for the line table */    if ( isMethodObsolete(method) || isMethodNative(method)) {        return;    }        error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)                (gdata->jvmti, method, pcount, ptable);    if (error != JVMTI_ERROR_NONE) {        *pcount = 0;    }}static jint findLineNumber(jthread thread, jlocation location,               jvmtiLineNumberEntry *lines, jint count) {    jint line = -1;    if (location != -1) {        if (count > 0) {            jint i;            /* any preface before first line is assigned to first line */            for (i=1; i<count; i++) {                if (location < lines[i].start_location) {                    break;                }            }            line = lines[i-1].line_number;        }    }    return line;}static jbooleanhasLineNumbers(jmethodID method){    jint count;    jvmtiLineNumberEntry *table;        getLineNumberTable(method, &count, &table);    if ( count == 0 ) {        return JNI_FALSE;    } else {        jvmtiDeallocate(table);    }    return JNI_TRUE;}static jvmtiErrorinitState(JNIEnv *env, jthread thread, StepRequest *step){    jvmtiError error;    /*     * Initial values that may be changed below     */    step->fromLine = -1;    step->fromNative = JNI_FALSE;     step->frameExited = JNI_FALSE;    step->fromStackDepth = getFrameCount(thread);    if (step->fromStackDepth <= 0) {        /*         * If there are no stack frames, treat the step as though         * from a native frame. This is most likely to occur at the          * beginning of a debug session, right after the VM_INIT event,         * so we need to do something intelligent.         */        step->fromNative = JNI_TRUE;        return JVMTI_ERROR_NONE;    }    /*     * Try to get a notification on frame pop. If we're in an opaque frame     * we won't be able to, but we can use other methods to detect that     * a native frame has exited.     *     * TO DO: explain the need for this notification.     */    error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)                (gdata->jvmti, thread, 0);    if (error == JVMTI_ERROR_OPAQUE_FRAME) {        step->fromNative = JNI_TRUE;        error = JVMTI_ERROR_NONE;        /* continue without error */    } else if (error == JVMTI_ERROR_DUPLICATE) {        error = JVMTI_ERROR_NONE;        /* Already being notified, continue without error */    } else if (error != JVMTI_ERROR_NONE) {        return error;    }    LOG_STEP(("initState(): frame=%d", step->fromStackDepth));        /*     * Note: we can't undo the frame pop notify, so     * we'll just have to let the handler ignore it if      * there are any errors below.     */    if (step->granularity == JDWP_STEP_SIZE(LINE) ) {                LOG_STEP(("initState(): Begin line step"));                WITH_LOCAL_REFS(env, 1) {                        jclass clazz;            jmethodID method;            jlocation location;                        error = getFrameLocation(thread, &clazz, &method, &location);            if (error == JVMTI_ERROR_NONE) {                /* Clear out previous line table only if we changed methods */                if ( method != step->method ) {                    step->lineEntryCount = 0;                    if (step->lineEntries != NULL) {                        jvmtiDeallocate(step->lineEntries);                        step->lineEntries = NULL;                    }                    step->method = method;                    getLineNumberTable(step->method,                                  &step->lineEntryCount, &step->lineEntries);                    if (step->lineEntryCount > 0) {                        convertLineNumberTable(env, clazz,                                 &step->lineEntryCount, &step->lineEntries);                    }                }                step->fromLine = findLineNumber(thread, location,                                     step->lineEntries, step->lineEntryCount);            }                } END_WITH_LOCAL_REFS(env);        }       return error;}/* * TO DO: The step handlers (handleFrameChange and handleStep can  * be broken down and made simpler now that we can install and de-install event * handlers.  */static void handleFramePopEvent(JNIEnv *env, EventInfo *evinfo,                     HandlerNode *node,                     struct bag *eventBag){    StepRequest *step;    jthread thread = evinfo->thread;    stepControl_lock();    step = threadControl_getStepRequest(thread);    if (step == NULL) {        EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");    }    if (step->pending) {        /*                                         * Note: current depth is reported as *before* the pending frame         * pop.          */        jint currentDepth;        jint fromDepth;        jint afterPopDepth;                currentDepth = getFrameCount(thread);        fromDepth = step->fromStackDepth;        afterPopDepth = currentDepth-1;                    LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d",                        fromDepth, currentDepth));        /*         * If we are exiting the original stepping frame, record that          * fact here. Once the next step event comes in, we can safely         * stop stepping there.          */        if (fromDepth > afterPopDepth ) {            step->frameExited = JNI_TRUE;        }        if (step->depth == JDWP_STEP_DEPTH(OVER)) {            /*             * Either              * 1) the original stepping frame is about to be popped             *    [fromDepth == currentDepth]. Re-enable stepping to             *    reach a point where we can stop.             * 2) a method called from the stepping frame has returned              *    (during which we had stepping disabled)             *    [fromDepth == currentDepth - 1]. Re-enable stepping              *    so that we can continue instructions steps in the 

⌨️ 快捷键说明

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