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
33static jrawMonitorID stepLock;
34
35static jint
36getFrameCount(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 */
61static void
62enableStepping(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
75static void
76disableStepping(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
89static jvmtiError
90getFrameLocation(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
108static void
109getLineNumberTable(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
129static jint
130findLineNumber(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
150static jboolean
151hasLineNumbers(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
165static jvmtiError
166initState(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 */
260static void
261handleFramePopEvent(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
363static void
364handleExceptionCatchEvent(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
430static void
431handleMethodEnterEvent(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
485static void
486completeStep(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
511jboolean
512stepControl_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    }
676done:
677    if (completed) {
678        completeStep(env, thread, step);
679    }
680    stepControl_unlock();
681    return completed;
682}
683
684
685void
686stepControl_initialize(void)
687{
688    stepLock = debugMonitorCreate("JDWP Step Handler Lock");
689}
690
691void
692stepControl_reset(void)
693{
694}
695
696/*
697 * Reset step control request stack depth and line number.
698 */
699void
700stepControl_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
726static void
727initEvents(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
787jvmtiError
788stepControl_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
850static void
851clearStep(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
879jvmtiError
880stepControl_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
909void
910stepControl_clearRequest(jthread thread, StepRequest *step)
911{
912    LOG_STEP(("stepControl_clearRequest: thread=%p", thread));
913    clearStep(thread, step);
914}
915
916void
917stepControl_lock(void)
918{
919    debugMonitorEnter(stepLock);
920}
921
922void
923stepControl_unlock(void)
924{
925    debugMonitorExit(stepLock);
926}
927