Home | History | Annotate | Download | only in back
      1 /*
      2  * Copyright (c) 2001, 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  * handlers
     27  *
     28  * The default event request handler functions
     29  */
     30 
     31 #include "util.h"
     32 #include "eventHandler.h"
     33 #include "threadControl.h"
     34 #include "eventHelper.h"
     35 #include "classTrack.h"
     36 
     37 #include "standardHandlers.h"
     38 
     39 static void
     40 handleClassPrepare(JNIEnv *env, EventInfo *evinfo,
     41                    HandlerNode *node,
     42                    struct bag *eventBag)
     43 {
     44     jthread thread = evinfo->thread;
     45 
     46     /* We try hard to avoid class loads/prepares in debugger
     47      * threads, but it is still possible for them to happen (most
     48      * likely for exceptions that are thrown within JNI
     49      * methods). If such an event occurs, we must report it, but
     50      * we cannot suspend the debugger thread.
     51      *
     52      * 1) We report the thread as NULL because we don't want the
     53      *    application to get hold of a debugger thread object.
     54      * 2) We try to do the right thing wrt to suspending
     55      *    threads without suspending debugger threads. If the
     56      *    requested suspend policy is NONE, there's no problem. If
     57      *    the requested policy is ALL, we can just suspend all
     58      *    application threads without producing any surprising
     59      *    results by leaving the debugger thread running. However,
     60      *    if the requested policy is EVENT_THREAD, we are forced
     61      *    to do something different than requested. The most
     62      *    useful behavior is to suspend all application threads
     63      *    (just as if the policy was ALL). This allows the
     64      *    application to operate on the class before it gets into
     65      *    circulation and so it is preferable to the other
     66      *    alternative of suspending no threads.
     67      */
     68     if (threadControl_isDebugThread(thread)) {
     69         evinfo->thread = NULL;
     70         if (node->suspendPolicy == JDWP_SUSPEND_POLICY(EVENT_THREAD)) {
     71             node->suspendPolicy = JDWP_SUSPEND_POLICY(ALL);
     72         }
     73     }
     74     eventHelper_recordEvent(evinfo, node->handlerID,
     75                             node->suspendPolicy, eventBag);
     76 }
     77 
     78 static void
     79 handleGarbageCollectionFinish(JNIEnv *env, EventInfo *evinfo,
     80                   HandlerNode *node,
     81                   struct bag *eventBag)
     82 {
     83     JDI_ASSERT_MSG(JNI_FALSE, "Should never call handleGarbageCollectionFinish");
     84 }
     85 
     86 static void
     87 handleFrameEvent(JNIEnv *env, EventInfo *evinfo,
     88                  HandlerNode *node,
     89                  struct bag *eventBag)
     90 {
     91     /*
     92      * The frame id that comes with this event is very transient.
     93      * We can't send the frame to the helper thread because it
     94      * might be useless by the time the helper thread can use it
     95      * (if suspend policy is NONE). So, get the needed info from
     96      * the frame and then use a special command to the helper
     97      * thread.
     98      */
     99 
    100     jmethodID method;
    101     jlocation location;
    102     jvmtiError error;
    103     FrameNumber fnum = 0;
    104     jvalue returnValue;
    105 
    106     error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)
    107             (gdata->jvmti, evinfo->thread, fnum, &method, &location);
    108     if (error != JVMTI_ERROR_NONE) {
    109         location = -1;
    110     }
    111     returnValue = evinfo->u.method_exit.return_value;
    112 
    113     eventHelper_recordFrameEvent(node->handlerID,
    114                                  node->suspendPolicy,
    115                                  evinfo->ei,
    116                                  evinfo->thread,
    117                                  evinfo->clazz,
    118                                  evinfo->method,
    119                                  location,
    120                                  node->needReturnValue,
    121                                  returnValue,
    122                                  eventBag);
    123 }
    124 
    125 static void
    126 genericHandler(JNIEnv *env, EventInfo *evinfo,
    127                HandlerNode *node,
    128                struct bag *eventBag)
    129 {
    130     eventHelper_recordEvent(evinfo, node->handlerID, node->suspendPolicy,
    131                             eventBag);
    132 }
    133 
    134 HandlerFunction
    135 standardHandlers_defaultHandler(EventIndex ei)
    136 {
    137     switch (ei) {
    138         case EI_BREAKPOINT:
    139         case EI_EXCEPTION:
    140         case EI_FIELD_ACCESS:
    141         case EI_FIELD_MODIFICATION:
    142         case EI_SINGLE_STEP:
    143         case EI_THREAD_START:
    144         case EI_THREAD_END:
    145         case EI_VM_DEATH:
    146         case EI_MONITOR_CONTENDED_ENTER:
    147         case EI_MONITOR_CONTENDED_ENTERED:
    148         case EI_MONITOR_WAIT:
    149         case EI_MONITOR_WAITED:
    150             return &genericHandler;
    151 
    152         case EI_CLASS_PREPARE:
    153             return &handleClassPrepare;
    154 
    155         case EI_GC_FINISH:
    156             return &handleGarbageCollectionFinish;
    157 
    158         case EI_METHOD_ENTRY:
    159         case EI_METHOD_EXIT:
    160             return &handleFrameEvent;
    161 
    162         default:
    163             /* This NULL will trigger a AGENT_ERROR_INVALID_EVENT_TYPE */
    164             return NULL;
    165     }
    166 }
    167 
    168 void
    169 standardHandlers_onConnect(void)
    170 {
    171     jboolean installed;
    172 
    173     /* always report VMDeath to a connected debugger */
    174     installed = (eventHandler_createPermanentInternal(
    175                         EI_VM_DEATH, genericHandler) != NULL);
    176     if (!installed) {
    177         EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"Unable to install VM Death event handler");
    178     }
    179 }
    180 
    181 void
    182 standardHandlers_onDisconnect(void)
    183 {
    184 }
    185