Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 1998, 2005, 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 #include "util.h"
     27 #include "stepControl.h"
     28 #include "eventHandler.h"
     29 #include "eventHelper.h"
     30 #include "threadControl.h"
     31 #include "SDE.h"
     32 
     33 static jrawMonitorID stepLock;
     34 
     35 static jint
     36 getFrameCount(jthread thread)
     37 {
     38     jint count = 0;
     39     jvmtiError error;
     40 
     41     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
     42                     (gdata->jvmti, thread, &count);
     43     if (error != JVMTI_ERROR_NONE) {
     44         EXIT_ERROR(error, "getting frame count");
     45     }
     46     return count;
     47 }
     48 
     49 /*
     50  * Most enabling/disabling of JVMTI events happens implicitly through
     51  * the inserting and freeing of handlers for those events. Stepping is
     52  * different because requested steps are usually not identical to JVMTI steps.
     53  * They usually require multiple events step, and otherwise, before they
     54  * complete. While a step request is pending, we may need to temporarily
     55  * disable and re-enable stepping, but we can't just remove the handlers
     56  * because that would break the application's ability to remove the
     57  * events. So, for step events only, we directly enable and disable stepping.
     58  * This is safe because there can only ever be one pending step request
     59  * per thread.
     60  */
     61 static void
     62 enableStepping(jthread thread)
     63 {
     64     jvmtiError error;
     65 
     66     LOG_STEP(("enableStepping: thread=%p", thread));
     67 
     68     error = threadControl_setEventMode(JVMTI_ENABLE, EI_SINGLE_STEP,
     69                                             thread);
     70     if (error != JVMTI_ERROR_NONE) {
     71         EXIT_ERROR(error, "enabling single step");
     72     }
     73 }
     74 
     75 static void
     76 disableStepping(jthread thread)
     77 {
     78     jvmtiError error;
     79 
     80     LOG_STEP(("disableStepping: thread=%p", thread));
     81 
     82     error = threadControl_setEventMode(JVMTI_DISABLE, EI_SINGLE_STEP,
     83                                             thread);
     84     if (error != JVMTI_ERROR_NONE) {
     85         EXIT_ERROR(error, "disabling single step");
     86     }
     87 }
     88 
     89 static jvmtiError
     90 getFrameLocation(jthread thread,
     91         jclass *pclazz, jmethodID *pmethod, jlocation *plocation)
     92 {
     93     jvmtiError error;
     94 
     95     *pclazz = NULL;
     96     *pmethod = NULL;
     97     *plocation = -1;
     98 
     99     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
    100             (gdata->jvmti, thread, 0, pmethod, plocation);
    101     if (error == JVMTI_ERROR_NONE && *pmethod!=NULL ) {
    102         /* This also serves to verify that the methodID is valid */
    103         error = methodClass(*pmethod, pclazz);
    104     }
    105     return error;
    106 }
    107 
    108 static void
    109 getLineNumberTable(jmethodID method, jint *pcount,
    110                 jvmtiLineNumberEntry **ptable)
    111 {
    112     jvmtiError error;
    113 
    114     *pcount = 0;
    115     *ptable = NULL;
    116 
    117     /* If the method is native or obsolete, don't even ask for the line table */
    118     if ( isMethodObsolete(method) || isMethodNative(method)) {
    119         return;
    120     }
    121 
    122     error = JVMTI_FUNC_PTR(gdata->jvmti,GetLineNumberTable)
    123                 (gdata->jvmti, method, pcount, ptable);
    124     if (error != JVMTI_ERROR_NONE) {
    125         *pcount = 0;
    126     }
    127 }
    128 
    129 static jint
    130 findLineNumber(jthread thread, jlocation location,
    131                jvmtiLineNumberEntry *lines, jint count)
    132 {
    133     jint line = -1;
    134 
    135     if (location != -1) {
    136         if (count > 0) {
    137             jint i;
    138             /* any preface before first line is assigned to first line */
    139             for (i=1; i<count; i++) {
    140                 if (location < lines[i].start_location) {
    141                     break;
    142                 }
    143             }
    144             line = lines[i-1].line_number;
    145         }
    146     }
    147     return line;
    148 }
    149 
    150 static jboolean
    151 hasLineNumbers(jmethodID method)
    152 {
    153     jint count;
    154     jvmtiLineNumberEntry *table;
    155 
    156     getLineNumberTable(method, &count, &table);
    157     if ( count == 0 ) {
    158         return JNI_FALSE;
    159     } else {
    160         jvmtiDeallocate(table);
    161     }
    162     return JNI_TRUE;
    163 }
    164 
    165 static jvmtiError
    166 initState(JNIEnv *env, jthread thread, StepRequest *step)
    167 {
    168     jvmtiError error;
    169 
    170     /*
    171      * Initial values that may be changed below
    172      */
    173     step->fromLine = -1;
    174     step->fromNative = JNI_FALSE;
    175     step->frameExited = JNI_FALSE;
    176     step->fromStackDepth = getFrameCount(thread);
    177 
    178     if (step->fromStackDepth <= 0) {
    179         /*
    180          * If there are no stack frames, treat the step as though
    181          * from a native frame. This is most likely to occur at the
    182          * beginning of a debug session, right after the VM_INIT event,
    183          * so we need to do something intelligent.
    184          */
    185         step->fromNative = JNI_TRUE;
    186         return JVMTI_ERROR_NONE;
    187     }
    188 
    189     /*
    190      * Try to get a notification on frame pop. If we're in an opaque frame
    191      * we won't be able to, but we can use other methods to detect that
    192      * a native frame has exited.
    193      *
    194      * TO DO: explain the need for this notification.
    195      */
    196     error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
    197                 (gdata->jvmti, thread, 0);
    198     if (error == JVMTI_ERROR_OPAQUE_FRAME) {
    199         step->fromNative = JNI_TRUE;
    200         error = JVMTI_ERROR_NONE;
    201         /* continue without error */
    202     } else if (error == JVMTI_ERROR_DUPLICATE) {
    203         error = JVMTI_ERROR_NONE;
    204         /* Already being notified, continue without error */
    205     } else if (error != JVMTI_ERROR_NONE) {
    206         return error;
    207     }
    208 
    209     LOG_STEP(("initState(): frame=%d", step->fromStackDepth));
    210 
    211     /*
    212      * Note: we can't undo the frame pop notify, so
    213      * we'll just have to let the handler ignore it if
    214      * there are any errors below.
    215      */
    216 
    217     if (step->granularity == JDWP_STEP_SIZE(LINE) ) {
    218 
    219         LOG_STEP(("initState(): Begin line step"));
    220 
    221         WITH_LOCAL_REFS(env, 1) {
    222 
    223             jclass clazz;
    224             jmethodID method;
    225             jlocation location;
    226 
    227             error = getFrameLocation(thread, &clazz, &method, &location);
    228             if (error == JVMTI_ERROR_NONE) {
    229                 /* Clear out previous line table only if we changed methods */
    230                 if ( method != step->method ) {
    231                     step->lineEntryCount = 0;
    232                     if (step->lineEntries != NULL) {
    233                         jvmtiDeallocate(step->lineEntries);
    234                         step->lineEntries = NULL;
    235                     }
    236                     step->method = method;
    237                     getLineNumberTable(step->method,
    238                                  &step->lineEntryCount, &step->lineEntries);
    239                     if (step->lineEntryCount > 0) {
    240                         convertLineNumberTable(env, clazz,
    241                                 &step->lineEntryCount, &step->lineEntries);
    242                     }
    243                 }
    244                 step->fromLine = findLineNumber(thread, location,
    245                                      step->lineEntries, step->lineEntryCount);
    246             }
    247 
    248         } END_WITH_LOCAL_REFS(env);
    249 
    250     }
    251 
    252     return error;
    253 }
    254 
    255 /*
    256  * TO DO: The step handlers (handleFrameChange and handleStep can
    257  * be broken down and made simpler now that we can install and de-install event
    258  * handlers.
    259  */
    260 static void
    261 handleFramePopEvent(JNIEnv *env, EventInfo *evinfo,
    262                     HandlerNode *node,
    263                     struct bag *eventBag)
    264 {
    265     StepRequest *step;
    266     jthread thread = evinfo->thread;
    267 
    268     stepControl_lock();
    269 
    270     step = threadControl_getStepRequest(thread);
    271     if (step == NULL) {
    272         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
    273     }
    274 
    275     if (step->pending) {
    276         /*
    277          * Note: current depth is reported as *before* the pending frame
    278          * pop.
    279          */
    280         jint currentDepth;
    281         jint fromDepth;
    282         jint afterPopDepth;
    283 
    284         currentDepth = getFrameCount(thread);
    285         fromDepth = step->fromStackDepth;
    286         afterPopDepth = currentDepth-1;
    287 
    288         LOG_STEP(("handleFramePopEvent: BEGIN fromDepth=%d, currentDepth=%d",
    289                         fromDepth, currentDepth));
    290 
    291         /*
    292          * If we are exiting the original stepping frame, record that
    293          * fact here. Once the next step event comes in, we can safely
    294          * stop stepping there.
    295          */
    296         if (fromDepth > afterPopDepth ) {
    297             step->frameExited = JNI_TRUE;
    298         }
    299 
    300         if (step->depth == JDWP_STEP_DEPTH(OVER)) {
    301             /*
    302              * Either
    303              * 1) the original stepping frame is about to be popped
    304              *    [fromDepth == currentDepth]. Re-enable stepping to
    305              *    reach a point where we can stop.
    306              * 2) a method called from the stepping frame has returned
    307              *    (during which we had stepping disabled)
    308              *    [fromDepth == currentDepth - 1]. Re-enable stepping
    309              *    so that we can continue instructions steps in the
    310              *    original stepping frame.
    311              * 3) a method further down the call chain has notified
    312              *    of a frame pop [fromDepth < currentDepth - 1]. This
    313              *    *might* represent case (2) above if the stepping frame
    314              *    was calling a native method which in turn called a
    315              *    java method. If so, we must enable stepping to
    316              *    ensure that we get control back after the intervening
    317              *    native frame is popped (you can't get frame pop
    318              *    notifications on native frames). If the native caller
    319              *    calls another Java method before returning,
    320              *    stepping will be diabled again and another frame pop
    321              *    will be awaited.
    322              *
    323              *    If it turns out that this is not case (2) with native
    324              *    methods, then the enabled stepping is benign and
    325              *    will be disabled again on the next step event.
    326              *
    327              * Note that the condition not covered above,
    328              * [fromDepth > currentDepth] shouldn't happen since it means
    329              * that too many frames have been popped. For robustness,
    330              * we enable stepping in that case too, so that the errant
    331              * step-over can be stopped.
    332              *
    333              */
    334             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OVER"));
    335             enableStepping(thread);
    336         } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
    337                    fromDepth > afterPopDepth) {
    338             /*
    339              * The original stepping frame is about to be popped. Step
    340              * until we reach the next safe place to stop.
    341              */
    342             LOG_STEP(("handleFramePopEvent: starting singlestep, depth==OUT && fromDepth > afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
    343             enableStepping(thread);
    344         } else if (step->methodEnterHandlerNode != NULL &&
    345                    fromDepth >= afterPopDepth) {
    346             /*
    347              * We installed a method entry event handler as part of a
    348              * step into operation. We've popped back to the original
    349              * stepping frame without finding a place to stop.
    350              * Resume stepping in the original frame.
    351              */
    352             LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==OUT && fromDepth >= afterPopDepth (%d>%d)",fromDepth, afterPopDepth));
    353             enableStepping(thread);
    354             (void)eventHandler_free(step->methodEnterHandlerNode);
    355             step->methodEnterHandlerNode = NULL;
    356         }
    357         LOG_STEP(("handleFramePopEvent: finished"));
    358     }
    359 
    360     stepControl_unlock();
    361 }
    362 
    363 static void
    364 handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo,
    365                           HandlerNode *node,
    366                           struct bag *eventBag)
    367 {
    368     StepRequest *step;
    369     jthread thread = evinfo->thread;
    370 
    371     stepControl_lock();
    372 
    373     step = threadControl_getStepRequest(thread);
    374     if (step == NULL) {
    375         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
    376     }
    377 
    378     if (step->pending) {
    379         /*
    380          *  Determine where we are on the call stack relative to where
    381          *  we started.
    382          */
    383         jint currentDepth = getFrameCount(thread);
    384         jint fromDepth = step->fromStackDepth;
    385 
    386         LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d",
    387                         fromDepth, currentDepth));
    388 
    389         /*
    390          * If we are exiting the original stepping frame, record that
    391          * fact here. Once the next step event comes in, we can safely
    392          * stop stepping there.
    393          */
    394         if (fromDepth > currentDepth) {
    395             step->frameExited = JNI_TRUE;
    396         }
    397 
    398         if (step->depth == JDWP_STEP_DEPTH(OVER) &&
    399             fromDepth >= currentDepth) {
    400             /*
    401              * Either the original stepping frame is done,
    402              * or a called method has returned (during which we had stepping
    403              * disabled). In either case we must resume stepping.
    404              */
    405             enableStepping(thread);
    406         } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
    407                    fromDepth > currentDepth) {
    408             /*
    409              * The original stepping frame is done. Step
    410              * until we reach the next safe place to stop.
    411              */
    412             enableStepping(thread);
    413         } else if (step->methodEnterHandlerNode != NULL &&
    414                    fromDepth >= currentDepth) {
    415             /*
    416              * We installed a method entry event handler as part of a
    417              * step into operation. We've popped back to the original
    418              * stepping frame or higher without finding a place to stop.
    419              * Resume stepping in the original frame.
    420              */
    421             enableStepping(thread);
    422             (void)eventHandler_free(step->methodEnterHandlerNode);
    423             step->methodEnterHandlerNode = NULL;
    424         }
    425     }
    426 
    427     stepControl_unlock();
    428 }
    429 
    430 static void
    431 handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo,
    432                        HandlerNode *node,
    433                        struct bag *eventBag)
    434 {
    435     StepRequest *step;
    436     jthread thread;
    437 
    438     thread = evinfo->thread;
    439 
    440     stepControl_lock();
    441 
    442     step = threadControl_getStepRequest(thread);
    443     if (step == NULL) {
    444         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
    445     }
    446 
    447     if (step->pending) {
    448         jclass    clazz;
    449         jmethodID method;
    450         char     *classname;
    451 
    452         LOG_STEP(("handleMethodEnterEvent: thread=%p", thread));
    453 
    454         clazz     = evinfo->clazz;
    455         method    = evinfo->method;
    456         classname = getClassname(clazz);
    457 
    458         /*
    459          * This handler is relevant only to step into
    460          */
    461         JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
    462 
    463         if (    (!eventFilter_predictFiltering(step->stepHandlerNode,
    464                                                clazz, classname))
    465              && (   step->granularity != JDWP_STEP_SIZE(LINE)
    466                  || hasLineNumbers(method) ) ) {
    467             /*
    468              * We've found a suitable method in which to stop. Step
    469              * until we reach the next safe location to complete the step->,
    470              * and we can get rid of the method entry handler.
    471              */
    472             enableStepping(thread);
    473             if ( step->methodEnterHandlerNode != NULL ) {
    474                 (void)eventHandler_free(step->methodEnterHandlerNode);
    475                 step->methodEnterHandlerNode = NULL;
    476             }
    477         }
    478         jvmtiDeallocate(classname);
    479         classname = NULL;
    480     }
    481 
    482     stepControl_unlock();
    483 }
    484 
    485 static void
    486 completeStep(JNIEnv *env, jthread thread, StepRequest *step)
    487 {
    488     jvmtiError error;
    489 
    490     /*
    491      * We've completed a step; reset state for the next one, if any
    492      */
    493 
    494     LOG_STEP(("completeStep: thread=%p", thread));
    495 
    496     if (step->methodEnterHandlerNode != NULL) {
    497         (void)eventHandler_free(step->methodEnterHandlerNode);
    498         step->methodEnterHandlerNode = NULL;
    499     }
    500 
    501     error = initState(env, thread, step);
    502     if (error != JVMTI_ERROR_NONE) {
    503         /*
    504          * None of the initState errors should happen after one step
    505          * has successfully completed.
    506          */
    507         EXIT_ERROR(error, "initializing step state");
    508     }
    509 }
    510 
    511 jboolean
    512 stepControl_handleStep(JNIEnv *env, jthread thread,
    513                        jclass clazz, jmethodID method)
    514 {
    515     jboolean completed = JNI_FALSE;
    516     StepRequest *step;
    517     jint currentDepth;
    518     jint fromDepth;
    519     jvmtiError error;
    520     char *classname;
    521 
    522     classname = NULL;
    523     stepControl_lock();
    524 
    525     step = threadControl_getStepRequest(thread);
    526     if (step == NULL) {
    527         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
    528     }
    529 
    530     /*
    531      * If no step is currently pending, ignore the event
    532      */
    533     if (!step->pending) {
    534         goto done;
    535     }
    536 
    537     LOG_STEP(("stepControl_handleStep: thread=%p", thread));
    538 
    539     /*
    540      * We never filter step into instruction. It's always over on the
    541      * first step event.
    542      */
    543     if (step->depth == JDWP_STEP_DEPTH(INTO) &&
    544         step->granularity == JDWP_STEP_SIZE(MIN)) {
    545         completed = JNI_TRUE;
    546         LOG_STEP(("stepControl_handleStep: completed, into min"));
    547         goto done;
    548     }
    549 
    550     /*
    551      * If we have left the method in which
    552      * stepping started, the step is always complete.
    553      */
    554     if (step->frameExited) {
    555         completed = JNI_TRUE;
    556         LOG_STEP(("stepControl_handleStep: completed, frame exited"));
    557         goto done;
    558     }
    559 
    560     /*
    561      *  Determine where we are on the call stack relative to where
    562      *  we started.
    563      */
    564     currentDepth = getFrameCount(thread);
    565     fromDepth = step->fromStackDepth;
    566 
    567     if (fromDepth > currentDepth) {
    568         /*
    569          * We have returned from the caller. There are cases where
    570          * we don't get frame pop notifications
    571          * (e.g. stepping from opaque frames), and that's when
    572          * this code will be reached. Complete the step->
    573          */
    574         completed = JNI_TRUE;
    575         LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth));
    576     } else if (fromDepth < currentDepth) {
    577         /* We have dropped into a called method. */
    578         if (   step->depth == JDWP_STEP_DEPTH(INTO)
    579             && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz,
    580                                           (classname = getClassname(clazz))))
    581             && hasLineNumbers(method) ) {
    582 
    583             /* Stepped into a method with lines, so we're done */
    584             completed = JNI_TRUE;
    585             LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth));
    586         } else {
    587             /*
    588              * We need to continue, but don't want the overhead of step
    589              * events from this method. So, we disable stepping and
    590              * enable a frame pop. If we're stepping into, we also
    591              * enable method enter events because a called frame may be
    592              * where we want to stop.
    593              */
    594             disableStepping(thread);
    595 
    596             if (step->depth == JDWP_STEP_DEPTH(INTO)) {
    597                 step->methodEnterHandlerNode =
    598                     eventHandler_createInternalThreadOnly(
    599                                        EI_METHOD_ENTRY,
    600                                        handleMethodEnterEvent, thread);
    601                 if (step->methodEnterHandlerNode == NULL) {
    602                     EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
    603                                 "installing event method enter handler");
    604                 }
    605             }
    606 
    607             error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
    608                         (gdata->jvmti, thread, 0);
    609             if (error == JVMTI_ERROR_DUPLICATE) {
    610                 error = JVMTI_ERROR_NONE;
    611             } else if (error != JVMTI_ERROR_NONE) {
    612                 EXIT_ERROR(error, "setting up notify frame pop");
    613             }
    614         }
    615         jvmtiDeallocate(classname);
    616         classname = NULL;
    617     } else {
    618         /*
    619          * We are at the same stack depth where stepping started.
    620          * Instruction steps are complete at this point. For line
    621          * steps we must check to see whether we've moved to a
    622          * different line.
    623          */
    624         if (step->granularity == JDWP_STEP_SIZE(MIN)) {
    625             completed = JNI_TRUE;
    626             LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and min", fromDepth));
    627         } else {
    628             if (step->fromLine != -1) {
    629                 jint line = -1;
    630                 jlocation location;
    631                 jmethodID method;
    632                 WITH_LOCAL_REFS(env, 1) {
    633                     jclass clazz;
    634                     error = getFrameLocation(thread,
    635                                         &clazz, &method, &location);
    636                     if ( isMethodObsolete(method)) {
    637                         method = NULL;
    638                         location = -1;
    639                     }
    640                     if (error != JVMTI_ERROR_NONE || location == -1) {
    641                         EXIT_ERROR(error, "getting frame location");
    642                     }
    643                     if ( method == step->method ) {
    644                         LOG_STEP(("stepControl_handleStep: checking line location"));
    645                         log_debugee_location("stepControl_handleStep: checking line loc",
    646                                 thread, method, location);
    647                         line = findLineNumber(thread, location,
    648                                       step->lineEntries, step->lineEntryCount);
    649                     }
    650                     if (line != step->fromLine) {
    651                         completed = JNI_TRUE;
    652                         LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and different line", fromDepth));
    653                     }
    654                 } END_WITH_LOCAL_REFS(env);
    655             } else {
    656                 /*
    657                  * This is a rare case. We have stepped from a location
    658                  * inside a native method to a location within a Java
    659                  * method at the same stack depth. This means that
    660                  * the original native method returned to another
    661                  * native method which, in turn, invoked a Java method.
    662                  *
    663                  * Since the original frame was  native, we were unable
    664                  * to ask for a frame pop event, and, thus, could not
    665                  * set the step->frameExited flag when the original
    666                  * method was done. Instead we end up here
    667                  * and act just as though the frameExited flag was set
    668                  * and complete the step immediately.
    669                  */
    670                 completed = JNI_TRUE;
    671                 LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and no line", fromDepth));
    672             }
    673         }
    674         LOG_STEP(("stepControl_handleStep: finished"));
    675     }
    676 done:
    677     if (completed) {
    678         completeStep(env, thread, step);
    679     }
    680     stepControl_unlock();
    681     return completed;
    682 }
    683 
    684 
    685 void
    686 stepControl_initialize(void)
    687 {
    688     stepLock = debugMonitorCreate("JDWP Step Handler Lock");
    689 }
    690 
    691 void
    692 stepControl_reset(void)
    693 {
    694 }
    695 
    696 /*
    697  * Reset step control request stack depth and line number.
    698  */
    699 void
    700 stepControl_resetRequest(jthread thread)
    701 {
    702 
    703     StepRequest *step;
    704     jvmtiError error;
    705 
    706     LOG_STEP(("stepControl_resetRequest: thread=%p", thread));
    707 
    708     stepControl_lock();
    709 
    710     step = threadControl_getStepRequest(thread);
    711 
    712     if (step != NULL) {
    713         JNIEnv *env;
    714         env = getEnv();
    715         error = initState(env, thread, step);
    716         if (error != JVMTI_ERROR_NONE) {
    717             EXIT_ERROR(error, "initializing step state");
    718         }
    719     } else {
    720         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
    721     }
    722 
    723     stepControl_unlock();
    724 }
    725 
    726 static void
    727 initEvents(jthread thread, StepRequest *step)
    728 {
    729     /* Need to install frame pop handler and exception catch handler when
    730      * single-stepping is enabled (i.e. step-into or step-over/step-out
    731      * when fromStackDepth > 0).
    732      */
    733     if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) {
    734         /*
    735          * TO DO: These might be able to applied more selectively to
    736          * boost performance.
    737          */
    738         step->catchHandlerNode = eventHandler_createInternalThreadOnly(
    739                                      EI_EXCEPTION_CATCH,
    740                                      handleExceptionCatchEvent,
    741                                      thread);
    742         step->framePopHandlerNode = eventHandler_createInternalThreadOnly(
    743                                         EI_FRAME_POP,
    744                                         handleFramePopEvent,
    745                                         thread);
    746 
    747         if (step->catchHandlerNode == NULL ||
    748             step->framePopHandlerNode == NULL) {
    749             EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
    750                         "installing step event handlers");
    751         }
    752 
    753     }
    754     /*
    755      * Initially enable stepping:
    756      * 1) For step into, always
    757      * 2) For step over, unless right after the VM_INIT.
    758      *    Enable stepping for STEP_MIN or STEP_LINE with or without line numbers.
    759      *    If the class is redefined then non EMCP methods may not have line
    760      *    number info. So enable line stepping for non line number so that it
    761      *    behaves like STEP_MIN/STEP_OVER.
    762      * 3) For step out, only if stepping from native, except right after VM_INIT
    763      *
    764      * (right after VM_INIT, a step->over or out is identical to running
    765      * forever)
    766      */
    767     switch (step->depth) {
    768         case JDWP_STEP_DEPTH(INTO):
    769             enableStepping(thread);
    770             break;
    771         case JDWP_STEP_DEPTH(OVER):
    772             if (step->fromStackDepth > 0 && !step->fromNative ) {
    773               enableStepping(thread);
    774             }
    775             break;
    776         case JDWP_STEP_DEPTH(OUT):
    777             if (step->fromNative &&
    778                 (step->fromStackDepth > 0)) {
    779                 enableStepping(thread);
    780             }
    781             break;
    782         default:
    783             JDI_ASSERT(JNI_FALSE);
    784     }
    785 }
    786 
    787 jvmtiError
    788 stepControl_beginStep(JNIEnv *env, jthread thread, jint size, jint depth,
    789                       HandlerNode *node)
    790 {
    791     StepRequest *step;
    792     jvmtiError error;
    793     jvmtiError error2;
    794 
    795     LOG_STEP(("stepControl_beginStep: thread=%p,size=%d,depth=%d",
    796                         thread, size, depth));
    797 
    798     eventHandler_lock(); /* for proper lock order */
    799     stepControl_lock();
    800 
    801     step = threadControl_getStepRequest(thread);
    802     if (step == NULL) {
    803         error = AGENT_ERROR_INVALID_THREAD;
    804         /* Normally not getting a StepRequest struct pointer is a fatal error
    805          *   but on a beginStep, we just return an error code.
    806          */
    807     } else {
    808         /*
    809          * In case the thread isn't already suspended, do it again.
    810          */
    811         error = threadControl_suspendThread(thread, JNI_FALSE);
    812         if (error == JVMTI_ERROR_NONE) {
    813             /*
    814              * Overwrite any currently executing step.
    815              */
    816             step->granularity = size;
    817             step->depth = depth;
    818             step->catchHandlerNode = NULL;
    819             step->framePopHandlerNode = NULL;
    820             step->methodEnterHandlerNode = NULL;
    821             step->stepHandlerNode = node;
    822             error = initState(env, thread, step);
    823             if (error == JVMTI_ERROR_NONE) {
    824                 initEvents(thread, step);
    825             }
    826             /* false means it is not okay to unblock the commandLoop thread */
    827             error2 = threadControl_resumeThread(thread, JNI_FALSE);
    828             if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) {
    829                 error = error2;
    830             }
    831 
    832             /*
    833              * If everything went ok, indicate a step is pending.
    834              */
    835             if (error == JVMTI_ERROR_NONE) {
    836                 step->pending = JNI_TRUE;
    837             }
    838         } else {
    839             EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread");
    840         }
    841     }
    842 
    843     stepControl_unlock();
    844     eventHandler_unlock();
    845 
    846     return error;
    847 }
    848 
    849 
    850 static void
    851 clearStep(jthread thread, StepRequest *step)
    852 {
    853     if (step->pending) {
    854 
    855         disableStepping(thread);
    856         if ( step->catchHandlerNode != NULL ) {
    857             (void)eventHandler_free(step->catchHandlerNode);
    858             step->catchHandlerNode = NULL;
    859         }
    860         if ( step->framePopHandlerNode!= NULL ) {
    861             (void)eventHandler_free(step->framePopHandlerNode);
    862             step->framePopHandlerNode = NULL;
    863         }
    864         if ( step->methodEnterHandlerNode != NULL ) {
    865             (void)eventHandler_free(step->methodEnterHandlerNode);
    866             step->methodEnterHandlerNode = NULL;
    867         }
    868         step->pending = JNI_FALSE;
    869 
    870         /*
    871          * Warning: Do not clear step->method, step->lineEntryCount,
    872          *          or step->lineEntries here, they will likely
    873          *          be needed on the next step.
    874          */
    875 
    876     }
    877 }
    878 
    879 jvmtiError
    880 stepControl_endStep(jthread thread)
    881 {
    882     StepRequest *step;
    883     jvmtiError error;
    884 
    885     LOG_STEP(("stepControl_endStep: thread=%p", thread));
    886 
    887     eventHandler_lock(); /* for proper lock order */
    888     stepControl_lock();
    889 
    890     step = threadControl_getStepRequest(thread);
    891     if (step != NULL) {
    892         clearStep(thread, step);
    893         error = JVMTI_ERROR_NONE;
    894     } else {
    895         /* If the stepRequest can't be gotten, then this thread no longer
    896          *   exists, just return, don't die here, this is normal at
    897          *   termination time. Return JVMTI_ERROR_NONE so the thread Ref
    898          *   can be tossed.
    899          */
    900          error = JVMTI_ERROR_NONE;
    901     }
    902 
    903     stepControl_unlock();
    904     eventHandler_unlock();
    905 
    906     return error;
    907 }
    908 
    909 void
    910 stepControl_clearRequest(jthread thread, StepRequest *step)
    911 {
    912     LOG_STEP(("stepControl_clearRequest: thread=%p", thread));
    913     clearStep(thread, step);
    914 }
    915 
    916 void
    917 stepControl_lock(void)
    918 {
    919     debugMonitorEnter(stepLock);
    920 }
    921 
    922 void
    923 stepControl_unlock(void)
    924 {
    925     debugMonitorExit(stepLock);
    926 }
    927