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
handleClassPrepare(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)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
handleGarbageCollectionFinish(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)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
handleFrameEvent(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)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
genericHandler(JNIEnv * env,EventInfo * evinfo,HandlerNode * node,struct bag * eventBag)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
standardHandlers_defaultHandler(EventIndex ei)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
standardHandlers_onConnect(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
standardHandlers_onDisconnect(void)182 standardHandlers_onDisconnect(void)
183 {
184 }
185