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