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 + -
显示快捷键?