1 /*
  2  * Copyright (c) 1998, 2021, 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             /* We installed a method entry event handler as part of a step into operation. */
346             JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
347             if (fromDepth >= afterPopDepth) {
348                 /*
349                  * We've popped back to the original 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==INTO && fromDepth >= afterPopDepth (%d>=%d)", fromDepth, afterPopDepth));
353                 enableStepping(thread);
354                 (void)eventHandler_free(step->methodEnterHandlerNode);
355                 step->methodEnterHandlerNode = NULL;
356             } else {
357                 LOG_STEP(("handleFramePopEvent: starting singlestep, have methodEnter handler && depth==INTO && fromDepth < afterPopDepth (%d<%d)", fromDepth, afterPopDepth));
358             }
359         }
360         LOG_STEP(("handleFramePopEvent: finished"));
361     }
362 
363     stepControl_unlock();
364 }
365 
366 static void
367 handleExceptionCatchEvent(JNIEnv *env, EventInfo *evinfo,
368                           HandlerNode *node,
369                           struct bag *eventBag)
370 {
371     StepRequest *step;
372     jthread thread = evinfo->thread;
373 
374     stepControl_lock();
375 
376     step = threadControl_getStepRequest(thread);
377     if (step == NULL) {
378         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
379     }
380 
381     if (step->pending) {
382         /*
383          *  Determine where we are on the call stack relative to where
384          *  we started.
385          */
386         jint currentDepth = getFrameCount(thread);
387         jint fromDepth = step->fromStackDepth;
388 
389         LOG_STEP(("handleExceptionCatchEvent: fromDepth=%d, currentDepth=%d",
390                         fromDepth, currentDepth));
391 
392         /*
393          * If we are exiting the original stepping frame, record that
394          * fact here. Once the next step event comes in, we can safely
395          * stop stepping there.
396          */
397         if (fromDepth > currentDepth) {
398             step->frameExited = JNI_TRUE;
399         }
400 
401         if (step->depth == JDWP_STEP_DEPTH(OVER) &&
402             fromDepth >= currentDepth) {
403             /*
404              * Either the original stepping frame is done,
405              * or a called method has returned (during which we had stepping
406              * disabled). In either case we must resume stepping.
407              */
408             enableStepping(thread);
409         } else if (step->depth == JDWP_STEP_DEPTH(OUT) &&
410                    fromDepth > currentDepth) {
411             /*
412              * The original stepping frame is done. Step
413              * until we reach the next safe place to stop.
414              */
415             enableStepping(thread);
416         } else if (step->methodEnterHandlerNode != NULL &&
417                    fromDepth >= currentDepth) {
418             /*
419              * We installed a method entry event handler as part of a
420              * step into operation. We've popped back to the original
421              * stepping frame or higher without finding a place to stop.
422              * Resume stepping in the original frame.
423              */
424             enableStepping(thread);
425             (void)eventHandler_free(step->methodEnterHandlerNode);
426             step->methodEnterHandlerNode = NULL;
427         }
428     }
429 
430     stepControl_unlock();
431 }
432 
433 static void
434 handleMethodEnterEvent(JNIEnv *env, EventInfo *evinfo,
435                        HandlerNode *node,
436                        struct bag *eventBag)
437 {
438     StepRequest *step;
439     jthread thread;
440 
441     thread = evinfo->thread;
442 
443     stepControl_lock();
444 
445     step = threadControl_getStepRequest(thread);
446     if (step == NULL) {
447         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
448     }
449 
450     if (step->pending) {
451         jclass    clazz;
452         jmethodID method;
453         char     *classname;
454 
455         LOG_STEP(("handleMethodEnterEvent: thread=%p", thread));
456 
457         clazz     = evinfo->clazz;
458         method    = evinfo->method;
459         classname = getClassname(clazz);
460 
461         /*
462          * This handler is relevant only to step into
463          */
464         JDI_ASSERT(step->depth == JDWP_STEP_DEPTH(INTO));
465 
466         if (    (!eventFilter_predictFiltering(step->stepHandlerNode, clazz, classname))
467              && (   step->granularity != JDWP_STEP_SIZE(LINE)
468                  || hasLineNumbers(method) ) ) {
469             /*
470              * We've found a suitable method in which to resume stepping.
471              * We can also get rid of the method entry handler now.
472              */
473             enableStepping(thread);
474             if ( step->methodEnterHandlerNode != NULL ) {
475                 (void)eventHandler_free(step->methodEnterHandlerNode);
476                 step->methodEnterHandlerNode = NULL;
477             }
478         }
479         jvmtiDeallocate(classname);
480         classname = NULL;
481     }
482 
483     stepControl_unlock();
484 }
485 
486 static void
487 completeStep(JNIEnv *env, jthread thread, StepRequest *step)
488 {
489     jvmtiError error;
490 
491     /*
492      * We've completed a step; reset state for the next one, if any
493      */
494 
495     LOG_STEP(("completeStep: thread=%p", thread));
496 
497     if (step->methodEnterHandlerNode != NULL) {
498         (void)eventHandler_free(step->methodEnterHandlerNode);
499         step->methodEnterHandlerNode = NULL;
500     }
501 
502     error = initState(env, thread, step);
503     if (error != JVMTI_ERROR_NONE) {
504         /*
505          * None of the initState errors should happen after one step
506          * has successfully completed.
507          */
508         EXIT_ERROR(error, "initializing step state");
509     }
510 }
511 
512 jboolean
513 stepControl_handleStep(JNIEnv *env, jthread thread,
514                        jclass clazz, jmethodID method)
515 {
516     jboolean completed = JNI_FALSE;
517     StepRequest *step;
518     jint currentDepth;
519     jint fromDepth;
520     jvmtiError error;
521     char *classname;
522 
523     classname = NULL;
524     stepControl_lock();
525 
526     step = threadControl_getStepRequest(thread);
527     if (step == NULL) {
528         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
529     }
530 
531     /*
532      * If no step is currently pending, ignore the event
533      */
534     if (!step->pending) {
535         goto done;
536     }
537 
538     LOG_STEP(("stepControl_handleStep: thread=%p", thread));
539 
540     /*
541      * We never filter step into instruction. It's always over on the
542      * first step event.
543      */
544     if (step->depth == JDWP_STEP_DEPTH(INTO) &&
545         step->granularity == JDWP_STEP_SIZE(MIN)) {
546         completed = JNI_TRUE;
547         LOG_STEP(("stepControl_handleStep: completed, into min"));
548         goto done;
549     }
550 
551     /*
552      * If we have left the method in which
553      * stepping started, the step is always complete.
554      */
555     if (step->frameExited) {
556         completed = JNI_TRUE;
557         LOG_STEP(("stepControl_handleStep: completed, frame exited"));
558         goto done;
559     }
560 
561     /*
562      *  Determine where we are on the call stack relative to where
563      *  we started.
564      */
565     currentDepth = getFrameCount(thread);
566     fromDepth = step->fromStackDepth;
567 
568     if (fromDepth > currentDepth) {
569         /*
570          * We have returned from the caller. There are cases where
571          * we don't get frame pop notifications
572          * (e.g. stepping from opaque frames), and that's when
573          * this code will be reached. Complete the step->
574          */
575         completed = JNI_TRUE;
576         LOG_STEP(("stepControl_handleStep: completed, fromDepth>currentDepth(%d>%d)", fromDepth, currentDepth));
577     } else if (fromDepth < currentDepth) {
578         /* We have dropped into a called method. */
579         if (   step->depth == JDWP_STEP_DEPTH(INTO)
580             && (!eventFilter_predictFiltering(step->stepHandlerNode, clazz,
581                                           (classname = getClassname(clazz))))
582             && hasLineNumbers(method) ) {
583 
584             /* Stepped into a method with lines, so we're done */
585             completed = JNI_TRUE;
586             LOG_STEP(("stepControl_handleStep: completed, fromDepth<currentDepth(%d<%d) and into method with lines", fromDepth, currentDepth));
587         } else {
588             /*
589              * We need to continue, but don't want the overhead of step
590              * events from this method. So, we disable stepping and
591              * enable a frame pop. If we're stepping into, we also
592              * enable method enter events because a called frame may be
593              * where we want to stop.
594              */
595             disableStepping(thread);
596 
597             if (step->depth == JDWP_STEP_DEPTH(INTO)) {
598                 step->methodEnterHandlerNode =
599                     eventHandler_createInternalThreadOnly(
600                                        EI_METHOD_ENTRY,
601                                        handleMethodEnterEvent, thread);
602                 if (step->methodEnterHandlerNode == NULL) {
603                     EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
604                                 "installing event method enter handler");
605                 }
606             }
607             LOG_STEP(("stepControl_handleStep: NotifyFramePop (fromDepth=%d currentDepth=%d)",
608                       fromDepth, currentDepth));
609 
610             error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
611                         (gdata->jvmti, thread, 0);
612             if (error == JVMTI_ERROR_DUPLICATE) {
613                 error = JVMTI_ERROR_NONE;
614             } else if (error != JVMTI_ERROR_NONE) {
615                 EXIT_ERROR(error, "setting up notify frame pop");
616             }
617         }
618         jvmtiDeallocate(classname);
619         classname = NULL;
620     } else {
621         /*
622          * We are at the same stack depth where stepping started.
623          * Instruction steps are complete at this point. For line
624          * steps we must check to see whether we've moved to a
625          * different line.
626          */
627         if (step->granularity == JDWP_STEP_SIZE(MIN)) {
628             completed = JNI_TRUE;
629             LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and min", fromDepth));
630         } else {
631             if (step->fromLine != -1) {
632                 jint line = -1;
633                 jlocation location;
634                 jmethodID method;
635                 WITH_LOCAL_REFS(env, 1) {
636                     jclass clazz;
637                     error = getFrameLocation(thread,
638                                         &clazz, &method, &location);
639                     if ( isMethodObsolete(method)) {
640                         method = NULL;
641                         location = -1;
642                     }
643                     if (error != JVMTI_ERROR_NONE || location == -1) {
644                         EXIT_ERROR(error, "getting frame location");
645                     }
646                     if ( method == step->method ) {
647                         LOG_STEP(("stepControl_handleStep: checking line location"));
648                         log_debugee_location("stepControl_handleStep: checking line loc",
649                                 thread, method, location);
650                         line = findLineNumber(thread, location,
651                                       step->lineEntries, step->lineEntryCount);
652                     }
653                     if (line != step->fromLine) {
654                         completed = JNI_TRUE;
655                         LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and different line", fromDepth));
656                     }
657                 } END_WITH_LOCAL_REFS(env);
658             } else {
659                 /*
660                  * This is a rare case. We have stepped from a location
661                  * inside a native method to a location within a Java
662                  * method at the same stack depth. This means that
663                  * the original native method returned to another
664                  * native method which, in turn, invoked a Java method.
665                  *
666                  * Since the original frame was  native, we were unable
667                  * to ask for a frame pop event, and, thus, could not
668                  * set the step->frameExited flag when the original
669                  * method was done. Instead we end up here
670                  * and act just as though the frameExited flag was set
671                  * and complete the step immediately.
672                  */
673                 completed = JNI_TRUE;
674                 LOG_STEP(("stepControl_handleStep: completed, fromDepth==currentDepth(%d) and no line", fromDepth));
675             }
676         }
677         LOG_STEP(("stepControl_handleStep: finished"));
678     }
679 done:
680     if (completed) {
681         completeStep(env, thread, step);
682     }
683     stepControl_unlock();
684     return completed;
685 }
686 
687 
688 void
689 stepControl_initialize(void)
690 {
691     stepLock = debugMonitorCreate("JDWP Step Handler Lock");
692 }
693 
694 void
695 stepControl_reset(void)
696 {
697 }
698 
699 /*
700  * Reset step control request stack depth and line number.
701  */
702 void
703 stepControl_resetRequest(jthread thread)
704 {
705 
706     StepRequest *step;
707     jvmtiError error;
708 
709     LOG_STEP(("stepControl_resetRequest: thread=%p", thread));
710 
711     stepControl_lock();
712 
713     step = threadControl_getStepRequest(thread);
714 
715     if (step != NULL) {
716         JNIEnv *env;
717         env = getEnv();
718         error = initState(env, thread, step);
719         if (error != JVMTI_ERROR_NONE) {
720             EXIT_ERROR(error, "initializing step state");
721         }
722     } else {
723         EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting step request");
724     }
725 
726     stepControl_unlock();
727 }
728 
729 static void
730 initEvents(jthread thread, StepRequest *step)
731 {
732     /* Need to install frame pop handler and exception catch handler when
733      * single-stepping is enabled (i.e. step-into or step-over/step-out
734      * when fromStackDepth > 0).
735      */
736     if (step->depth == JDWP_STEP_DEPTH(INTO) || step->fromStackDepth > 0) {
737         /*
738          * TO DO: These might be able to applied more selectively to
739          * boost performance.
740          */
741         step->catchHandlerNode = eventHandler_createInternalThreadOnly(
742                                      EI_EXCEPTION_CATCH,
743                                      handleExceptionCatchEvent,
744                                      thread);
745         JDI_ASSERT(step->framePopHandlerNode == NULL);
746         step->framePopHandlerNode = eventHandler_createInternalThreadOnly(
747                                         EI_FRAME_POP,
748                                         handleFramePopEvent,
749                                         thread);
750 
751         if (step->catchHandlerNode == NULL ||
752             step->framePopHandlerNode == NULL) {
753             EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,
754                         "installing step event handlers");
755         }
756 
757     }
758     /*
759      * Initially enable stepping:
760      * 1) For step into, always
761      * 2) For step over, unless right after the VM_INIT.
762      *    Enable stepping for STEP_MIN or STEP_LINE with or without line numbers.
763      *    If the class is redefined then non EMCP methods may not have line
764      *    number info. So enable line stepping for non line number so that it
765      *    behaves like STEP_MIN/STEP_OVER.
766      * 3) For step out, only if stepping from native, except right after VM_INIT
767      *
768      * (right after VM_INIT, a step->over or out is identical to running
769      * forever)
770      */
771     switch (step->depth) {
772         case JDWP_STEP_DEPTH(INTO):
773             enableStepping(thread);
774             break;
775         case JDWP_STEP_DEPTH(OVER):
776             if (step->fromStackDepth > 0 && !step->fromNative ) {
777               enableStepping(thread);
778             }
779             break;
780         case JDWP_STEP_DEPTH(OUT):
781             if (step->fromNative &&
782                 (step->fromStackDepth > 0)) {
783                 enableStepping(thread);
784             }
785             break;
786         default:
787             JDI_ASSERT(JNI_FALSE);
788     }
789 }
790 
791 jvmtiError
792 stepControl_beginStep(JNIEnv *env, jthread thread, jint size, jint depth,
793                       HandlerNode *node)
794 {
795     StepRequest *step;
796     jvmtiError error;
797     jvmtiError error2;
798 
799     LOG_STEP(("stepControl_beginStep: thread=%p,size=%d,depth=%d",
800               thread, size, depth));
801 
802     eventHandler_lock(); /* for proper lock order */
803     stepControl_lock();
804 
805     step = threadControl_getStepRequest(thread);
806     if (step == NULL) {
807         error = AGENT_ERROR_INVALID_THREAD;
808         /* Normally not getting a StepRequest struct pointer is a fatal error
809          *   but on a beginStep, we just return an error code.
810          */
811     } else {
812         /*
813          * In case the thread isn't already suspended, do it again.
814          */
815         error = threadControl_suspendThread(thread, JNI_FALSE);
816         if (error == JVMTI_ERROR_NONE) {
817             /*
818              * Overwrite any currently executing step.
819              */
820             step->granularity = size;
821             step->depth = depth;
822             step->catchHandlerNode = NULL;
823             step->framePopHandlerNode = NULL;
824             step->methodEnterHandlerNode = NULL;
825             step->stepHandlerNode = node;
826             error = initState(env, thread, step);
827             if (error == JVMTI_ERROR_NONE) {
828                 initEvents(thread, step);
829             }
830             /* false means it is not okay to unblock the commandLoop thread */
831             error2 = threadControl_resumeThread(thread, JNI_FALSE);
832             if (error2 != JVMTI_ERROR_NONE && error == JVMTI_ERROR_NONE) {
833                 error = error2;
834             }
835 
836             /*
837              * If everything went ok, indicate a step is pending.
838              */
839             if (error == JVMTI_ERROR_NONE) {
840                 step->pending = JNI_TRUE;
841             }
842         } else {
843             EXIT_ERROR(error, "stepControl_beginStep: cannot suspend thread");
844         }
845     }
846 
847     stepControl_unlock();
848     eventHandler_unlock();
849 
850     return error;
851 }
852 
853 
854 static void
855 clearStep(jthread thread, StepRequest *step)
856 {
857     if (step->pending) {
858 
859         disableStepping(thread);
860         if ( step->catchHandlerNode != NULL ) {
861             (void)eventHandler_free(step->catchHandlerNode);
862             step->catchHandlerNode = NULL;
863         }
864         if ( step->framePopHandlerNode!= NULL ) {
865             (void)eventHandler_free(step->framePopHandlerNode);
866             step->framePopHandlerNode = NULL;
867         }
868         if ( step->methodEnterHandlerNode != NULL ) {
869             (void)eventHandler_free(step->methodEnterHandlerNode);
870             step->methodEnterHandlerNode = NULL;
871         }
872         step->pending = JNI_FALSE;
873 
874         /*
875          * Warning: Do not clear step->method, step->lineEntryCount,
876          *          or step->lineEntries here, they will likely
877          *          be needed on the next step.
878          */
879 
880     }
881 }
882 
883 jvmtiError
884 stepControl_endStep(jthread thread)
885 {
886     StepRequest *step;
887     jvmtiError error;
888 
889     LOG_STEP(("stepControl_endStep: thread=%p", thread));
890 
891     eventHandler_lock(); /* for proper lock order */
892     stepControl_lock();
893 
894     step = threadControl_getStepRequest(thread);
895     if (step != NULL) {
896         clearStep(thread, step);
897         error = JVMTI_ERROR_NONE;
898     } else {
899         /* If the stepRequest can't be gotten, then this thread no longer
900          *   exists, just return, don't die here, this is normal at
901          *   termination time. Return JVMTI_ERROR_NONE so the thread Ref
902          *   can be tossed.
903          */
904          error = JVMTI_ERROR_NONE;
905     }
906 
907     stepControl_unlock();
908     eventHandler_unlock();
909 
910     return error;
911 }
912 
913 void
914 stepControl_clearRequest(jthread thread, StepRequest *step)
915 {
916     LOG_STEP(("stepControl_clearRequest: thread=%p", thread));
917     clearStep(thread, step);
918 }
919 
920 void
921 stepControl_lock(void)
922 {
923     debugMonitorEnter(stepLock);
924 }
925 
926 void
927 stepControl_unlock(void)
928 {
929     debugMonitorExit(stepLock);
930 }