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