Bug Summary

File:jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c
Warning:line 664, column 17
Called function pointer is null (null dereference)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name eventHandler.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D JDWP_LOGGING -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/unix/native/libjdwp -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/jdk.jdwp.agent -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/include -I /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/export -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused -Wno-unused-function -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c
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 * eventHandler
27 *
28 * This module handles events as they come in directly from JVMTI
29 * and also maps them to JDI events. JDI events are those requested
30 * at the JDI or JDWP level and seen on those levels. Mapping is
31 * one-to-many, a JVMTI event may map to several JDI events, or
32 * to none. Part of that mapping process is filteration, which
33 * eventFilter sub-module handles. A JDI EventRequest corresponds
34 * to a HandlerNode and a JDI filter to the hidden HandlerNode data
35 * used by eventFilter. For example, if at the JDI level the user
36 * executed:
37 *
38 * EventRequestManager erm = vm.eventRequestManager();
39 * BreakpointRequest bp = erm.createBreakpointRequest();
40 * bp.enable();
41 * ClassPrepareRequest req = erm.createClassPrepareRequest();
42 * req.enable();
43 * req = erm.createClassPrepareRequest();
44 * req.addClassFilter("Foo*");
45 * req.enable();
46 *
47 * Three handlers would be created, the first with a LocationOnly
48 * filter and the last with a ClassMatch filter.
49 * When a JVMTI class prepare event for "Foobar"
50 * comes in, the second handler will create one JDI event, the
51 * third handler will compare the class signature, and since
52 * it matchs create a second event. There may also be internal
53 * events as there are in this case, one created by the front-end
54 * and one by the back-end.
55 *
56 * Each event kind has a handler chain, which is a doublely linked
57 * list of handlers for that kind of event.
58 */
59#include "util.h"
60#include "eventHandler.h"
61#include "eventHandlerRestricted.h"
62#include "eventFilter.h"
63#include "eventFilterRestricted.h"
64#include "standardHandlers.h"
65#include "threadControl.h"
66#include "eventHelper.h"
67#include "classTrack.h"
68#include "commonRef.h"
69#include "debugLoop.h"
70#include "signature.h"
71
72static HandlerID requestIdCounter;
73static jbyte currentSessionID;
74
75/* Counter of active callbacks and flag for vm_death */
76static int active_callbacks = 0;
77static jboolean vm_death_callback_active = JNI_FALSE0;
78static jrawMonitorID callbackLock;
79static jrawMonitorID callbackBlock;
80
81/* Macros to surround callback code (non-VM_DEATH callbacks).
82 * Note that this just keeps a count of the non-VM_DEATH callbacks that
83 * are currently active, it does not prevent these callbacks from
84 * operating in parallel. It's the VM_DEATH callback that will wait
85 * for all these callbacks to finish up, so that it can report the
86 * VM_DEATH in a clean state.
87 * If the VM_DEATH callback is active in the BEGIN macro then this
88 * callback just blocks until released by the VM_DEATH callback.
89 * If the VM_DEATH callback is active in the END macro, then this
90 * callback will notify the VM_DEATH callback if it's the last one,
91 * and then block until released by the VM_DEATH callback.
92 * Why block? These threads are often the threads of the Java program,
93 * not blocking might mean that a return would continue execution of
94 * some java thread in the middle of VM_DEATH, this seems troubled.
95 *
96 * WARNING: No not 'return' or 'goto' out of the BEGIN_CALLBACK/END_CALLBACK
97 * block, this will mess up the count.
98 */
99
100#define BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
\
101{ /* BEGIN OF CALLBACK */ \
102 jboolean bypass = JNI_TRUE1; \
103 debugMonitorEnter(callbackLock); { \
104 if (vm_death_callback_active) { \
105 /* allow VM_DEATH callback to finish */ \
106 debugMonitorExit(callbackLock); \
107 /* Now block because VM is about to die */ \
108 debugMonitorEnter(callbackBlock); \
109 debugMonitorExit(callbackBlock); \
110 } else { \
111 active_callbacks++; \
112 bypass = JNI_FALSE0; \
113 debugMonitorExit(callbackLock); \
114 } \
115 } \
116 if ( !bypass ) { \
117 /* BODY OF CALLBACK CODE */
118
119#define END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 119); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
/* Part of bypass if body */ \
120 debugMonitorEnter(callbackLock); { \
121 active_callbacks--; \
122 if (active_callbacks < 0) { \
123 EXIT_ERROR(0, "Problems tracking active callbacks"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 123); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }
; \
124 } \
125 if (vm_death_callback_active) { \
126 if (active_callbacks == 0) { \
127 debugMonitorNotifyAll(callbackLock); \
128 } \
129 /* allow VM_DEATH callback to finish */ \
130 debugMonitorExit(callbackLock); \
131 /* Now block because VM is about to die */ \
132 debugMonitorEnter(callbackBlock); \
133 debugMonitorExit(callbackBlock); \
134 } else { \
135 debugMonitorExit(callbackLock); \
136 } \
137 } \
138 } \
139} /* END OF CALLBACK */
140
141/*
142 * We are starting with a very simple locking scheme
143 * for event handling. All readers and writers of data in
144 * the handlers[] chain must own this lock for the duration
145 * of its use. If contention becomes a problem, we can:
146 *
147 * 1) create a lock per event type.
148 * 2) move to a readers/writers approach where multiple threads
149 * can access the chains simultaneously while reading (the
150 * normal activity of an event callback).
151 */
152static jrawMonitorID handlerLock;
153
154typedef struct HandlerChain_ {
155 HandlerNode *first;
156 /* add lock here */
157} HandlerChain;
158
159/*
160 * This array maps event kinds to handler chains.
161 * Protected by handlerLock.
162 */
163
164static HandlerChain __handlers[EI_max-EI_min+1];
165
166/* Given a HandlerNode, these access our private data.
167 */
168#define PRIVATE_DATA(node)(&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))
\
169 (&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->private_ehpd))
170
171#define NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
(PRIVATE_DATA(node)(&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))
->private_next)
172#define PREV(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_prev)
(PRIVATE_DATA(node)(&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))
->private_prev)
173#define CHAIN(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_chain)
(PRIVATE_DATA(node)(&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))
->private_chain)
174#define HANDLER_FUNCTION(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_handlerFunction)
(PRIVATE_DATA(node)(&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))
->private_handlerFunction)
175
176static jclass getObjectClass(jobject object);
177static jvmtiError freeHandler(HandlerNode *node);
178
179static jvmtiError freeHandlerChain(HandlerChain *chain);
180
181static HandlerChain *
182getHandlerChain(EventIndex i)
183{
184 if ( i < EI_min || i > EI_max ) {
185 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"bad index for handler"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+24))), ((jvmtiError)(JVMTI_ERROR_MAX+64+24)), ("bad index for handler"
==((void*)0)?"":"bad index for handler"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 185); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+24)), "bad index for handler"); }
;
186 }
187 return &(__handlers[i-EI_min]);
188}
189
190static void
191insert(HandlerChain *chain, HandlerNode *node)
192{
193 HandlerNode *oldHead = chain->first;
194 NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
= oldHead;
195 PREV(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_prev)
= NULL((void*)0);
196 CHAIN(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_chain)
= chain;
197 if (oldHead != NULL((void*)0)) {
198 PREV(oldHead)((&(((EventHandlerRestricted_HandlerNode*)(void*)(oldHead
))->private_ehpd))->private_prev)
= node;
199 }
200 chain->first = node;
201}
202
203static HandlerNode *
204findInChain(HandlerChain *chain, HandlerID handlerID)
205{
206 HandlerNode *node = chain->first;
207 while (node != NULL((void*)0)) {
208 if (node->handlerID == handlerID) {
209 return node;
210 }
211 node = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
212 }
213 return NULL((void*)0);
214}
215
216static HandlerNode *
217find(EventIndex ei, HandlerID handlerID)
218{
219 return findInChain(getHandlerChain(ei), handlerID);
220}
221
222/**
223 * Deinsert. Safe for non-inserted nodes.
224 */
225static void
226deinsert(HandlerNode *node)
227{
228 HandlerChain *chain = CHAIN(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_chain)
;
229
230 if (chain == NULL((void*)0)) {
231 return;
232 }
233 if (chain->first == node) {
234 chain->first = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
235 }
236 if (NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
!= NULL((void*)0)) {
237 PREV(NEXT(node))((&(((EventHandlerRestricted_HandlerNode*)(void*)(((&
(((EventHandlerRestricted_HandlerNode*)(void*)(node))->private_ehpd
))->private_next)))->private_ehpd))->private_prev)
= PREV(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_prev)
;
238 }
239 if (PREV(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_prev)
!= NULL((void*)0)) {
240 NEXT(PREV(node))((&(((EventHandlerRestricted_HandlerNode*)(void*)(((&
(((EventHandlerRestricted_HandlerNode*)(void*)(node))->private_ehpd
))->private_prev)))->private_ehpd))->private_next)
= NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
241 }
242 CHAIN(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_chain)
= NULL((void*)0);
243}
244
245jboolean
246eventHandlerRestricted_iterator(EventIndex ei,
247 IteratorFunction func, void *arg)
248{
249 HandlerChain *chain;
250 HandlerNode *node;
251 JNIEnv *env;
252
253 chain = getHandlerChain(ei);
254 node = chain->first;
255 env = getEnv();
256
257 if ( func == NULL((void*)0) ) {
258 EXIT_ERROR(AGENT_ERROR_INTERNAL,"iterator function NULL"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+1))), ((jvmtiError)(JVMTI_ERROR_MAX+64+1)), ("iterator function NULL"
==((void*)0)?"":"iterator function NULL"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 258); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+1)), "iterator function NULL"); }
;
259 }
260
261 while (node != NULL((void*)0)) {
262 if (((func)(env, node, arg))) {
263 return JNI_TRUE1;
264 }
265 node = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
266 }
267 return JNI_FALSE0;
268}
269
270/* BREAKPOINT, METHOD_ENTRY and SINGLE_STEP events are covered by
271 * the co-location of events policy. Of these three co-located
272 * events, METHOD_ENTRY is always reported first and BREAKPOINT
273 * is always reported last. Here are the possible combinations and
274 * their order:
275 *
276 * (p1) METHOD_ENTRY, BREAKPOINT (existing)
277 * (p2) METHOD_ENTRY, BREAKPOINT (new)
278 * (p1) METHOD_ENTRY, SINGLE_STEP
279 * (p1) METHOD_ENTRY, SINGLE_STEP, BREAKPOINT (existing)
280 * (p1/p2) METHOD_ENTRY, SINGLE_STEP, BREAKPOINT (new)
281 * (p1) SINGLE_STEP, BREAKPOINT (existing)
282 * (p2) SINGLE_STEP, BREAKPOINT (new)
283 *
284 * BREAKPOINT (existing) indicates a BREAKPOINT that is set before
285 * the other co-located event is posted. BREAKPOINT (new) indicates
286 * a BREAKPOINT that is set after the other co-located event is
287 * posted and before the thread has resumed execution.
288 *
289 * Co-location of events policy used to be implemented via
290 * temporary BREAKPOINTs along with deferring the reporting of
291 * non-BREAKPOINT co-located events, but the temporary BREAKPOINTs
292 * caused performance problems on VMs where setting or clearing
293 * BREAKPOINTs is expensive, e.g., HotSpot.
294 *
295 * The policy is now implemented in two phases. Phase 1: when a
296 * METHOD_ENTRY or SINGLE_STEP event is received, if there is an
297 * existing co-located BREAKPOINT, then the current event is
298 * deferred. When the BREAKPOINT event is processed, the event
299 * bag will contain the deferred METHOD_ENTRY and/or SINGLE_STEP
300 * events along with the BREAKPOINT event. For a METHOD_ENTRY
301 * event where there is not an existing co-located BREAKPOINT,
302 * if SINGLE_STEP events are also enabled for the thread, then
303 * the METHOD_ENTRY event is deferred. When the SINGLE_STEP event
304 * is processed, the event bag will also contain the deferred
305 * METHOD_ENTRY event. This covers each of the combinations
306 * marked with 'p1' above.
307 *
308 * Phase 2: if there is no existing co-located BREAKPOINT, then the
309 * location information for the METHOD_ENTRY or SINGLE_STEP event
310 * is recorded in the ThreadNode. If the next event for the thread
311 * is a co-located BREAKPOINT, then the first BREAKPOINT event will
312 * be skipped since it cannot be delivered in the same event set.
313 * This covers each of the combinations marked with 'p2' above.
314 *
315 * For the combination marked p1/p2, part of the case is handled
316 * during phase 1 and the rest is handled during phase 2.
317 *
318 * The recording of information in the ThreadNode is handled in
319 * this routine. The special handling of the next event for the
320 * thread is handled in skipEventReport().
321 */
322
323static jboolean
324deferEventReport(JNIEnv *env, jthread thread,
325 EventIndex ei, jclass clazz, jmethodID method, jlocation location)
326{
327 jboolean deferring = JNI_FALSE0;
328
329 switch (ei) {
330 case EI_METHOD_ENTRY:
331 if (!isMethodNative(method)) {
332 jvmtiError error;
333 jlocation start;
334 jlocation end;
335 error = methodLocation(method, &start, &end);
336 if (error == JVMTI_ERROR_NONE) {
337 deferring = isBreakpointSet(clazz, method, start) ||
338 threadControl_getInstructionStepMode(thread)
339 == JVMTI_ENABLE;
340 if (!deferring) {
341 threadControl_saveCLEInfo(env, thread, ei,
342 clazz, method, start);
343 }
344 }
345 }
346 break;
347 case EI_SINGLE_STEP:
348 deferring = isBreakpointSet(clazz, method, location);
349 if (!deferring) {
350 threadControl_saveCLEInfo(env, thread, ei,
351 clazz, method, location);
352 }
353 break;
354 default:
355 break;
356 }
357 /* TO DO: Once JVMTI supports a way to know if we're
358 * at the end of a method, we should check here for
359 * break and step events which precede a method exit
360 * event.
361 */
362 return deferring;
363}
364
365/* Handle phase 2 of the co-located events policy. See detailed
366 * comments in deferEventReport() above.
367 */
368static jboolean
369skipEventReport(JNIEnv *env, jthread thread, EventIndex ei,
370 jclass clazz, jmethodID method, jlocation location)
371{
372 jboolean skipping = JNI_FALSE0;
373
374 if (ei == EI_BREAKPOINT) {
375 if (threadControl_cmpCLEInfo(env, thread, clazz, method, location)) {
376 LOG_MISC(("Co-located breakpoint event found: "((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,378), log_message_end ("Co-located breakpoint event found: "
"%s,thread=%p,clazz=%p,method=%p,location=%d", eventText(ei)
, thread, clazz, method, location)):((void)0))
377 "%s,thread=%p,clazz=%p,method=%p,location=%d",((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,378), log_message_end ("Co-located breakpoint event found: "
"%s,thread=%p,clazz=%p,method=%p,location=%d", eventText(ei)
, thread, clazz, method, location)):((void)0))
378 eventText(ei), thread, clazz, method, location))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,378), log_message_end ("Co-located breakpoint event found: "
"%s,thread=%p,clazz=%p,method=%p,location=%d", eventText(ei)
, thread, clazz, method, location)):((void)0))
;
379 skipping = JNI_TRUE1;
380 }
381 }
382
383 threadControl_clearCLEInfo(env, thread);
384
385 return skipping;
386}
387
388static void
389reportEvents(JNIEnv *env, jbyte sessionID, jthread thread, EventIndex ei,
390 jclass clazz, jmethodID method, jlocation location,
391 struct bag *eventBag)
392{
393 jbyte suspendPolicy;
394 jboolean invoking;
395
396 if (bagSize(eventBag) < 1) {
397 return;
398 }
399
400 /*
401 * Never report events before initialization completes
402 */
403 if (!debugInit_isInitComplete()) {
404 return;
405 }
406
407 /*
408 * Check to see if we should skip reporting this event due to
409 * co-location of events policy.
410 */
411 if (thread != NULL((void*)0) &&
412 skipEventReport(env, thread, ei, clazz, method, location)) {
413 LOG_MISC(("event report being skipped: "((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,415), log_message_end ("event report being skipped: " "ei=%s,thread=%p,clazz=%p,method=%p,location=%d"
, eventText(ei), thread, clazz, method, location)):((void)0))
414 "ei=%s,thread=%p,clazz=%p,method=%p,location=%d",((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,415), log_message_end ("event report being skipped: " "ei=%s,thread=%p,clazz=%p,method=%p,location=%d"
, eventText(ei), thread, clazz, method, location)):((void)0))
415 eventText(ei), thread, clazz, method, location))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,415), log_message_end ("event report being skipped: " "ei=%s,thread=%p,clazz=%p,method=%p,location=%d"
, eventText(ei), thread, clazz, method, location)):((void)0))
;
416 bagDeleteAll(eventBag);
417 return;
418 }
419
420 /* We delay the reporting of some events so that they can be
421 * properly grouped into event sets with upcoming events. If
422 * the reporting is to be deferred, the event commands remain
423 * in the event bag until a subsequent event occurs. Event is
424 * NULL for synthetic events (e.g. unload).
425 */
426 if (thread == NULL((void*)0)
427 || !deferEventReport(env, thread, ei,
428 clazz, method, location)) {
429 struct bag *completedBag = bagDup(eventBag);
430 bagDeleteAll(eventBag);
431 if (completedBag == NULL((void*)0)) {
432 /*
433 * TO DO: Report, but don't terminate?
434 */
435 return;
436 } else {
437 suspendPolicy = eventHelper_reportEvents(sessionID, completedBag);
438 if (thread != NULL((void*)0) && suspendPolicy != JDWP_SUSPEND_POLICY(NONE)0) {
439 do {
440 /* The events have been reported and this
441 * thread is about to continue, but it may
442 * have been started up just to perform a
443 * requested method invocation. If so, we do
444 * the invoke now and then stop again waiting
445 * for another continue. By then another
446 * invoke request can be in place, so there is
447 * a loop around this code.
448 */
449 invoking = invoker_doInvoke(thread);
450 if (invoking) {
451 eventHelper_reportInvokeDone(sessionID, thread);
452 }
453 } while (invoking);
454 }
455 bagDestroyBag(completedBag);
456 }
457 }
458}
459
460/* A bagEnumerateFunction. Create a synthetic class unload event
461 * for every class no longer present. Analogous to event_callback
462 * combined with a handler in a unload specific (no event
463 * structure) kind of way.
464 */
465static jboolean
466synthesizeUnloadEvent(void *signatureVoid, void *envVoid)
467{
468 JNIEnv *env = (JNIEnv *)envVoid;
469 char *signature = *(char **)signatureVoid;
470 char *classname;
471 HandlerNode *node;
472 jbyte eventSessionID = currentSessionID;
473 struct bag *eventBag = eventHelper_createEventBag();
474
475 /* TO DO: Report null error, but don't die */
476 JDI_ASSERT(eventBag != NULL)do { if (gdata && gdata->assertOn && !(eventBag
!= ((void*)0))) { jdiAssertionFailed("/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 476, "eventBag != NULL"); } } while (0)
;
477
478 /* Signature needs to last, so convert extra copy to
479 * classname
480 */
481 classname = jvmtiAllocate((int)strlen(signature)+1);
482 (void)strcpy(classname, signature);
483 convertSignatureToClassname(classname);
484
485 debugMonitorEnter(handlerLock);
486
487 node = getHandlerChain(EI_GC_FINISH)->first;
488 while (node != NULL((void*)0)) {
489 /* save next so handlers can remove themselves */
490 HandlerNode *next = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
491 jboolean shouldDelete;
492
493 if (eventFilterRestricted_passesUnloadFilter(env, classname,
494 node,
495 &shouldDelete)) {
496 /* There may be multiple handlers, the signature will
497 * be freed when the event helper thread has written
498 * it. So each event needs a separate allocation.
499 */
500 char *durableSignature = jvmtiAllocate((int)strlen(signature)+1);
501 (void)strcpy(durableSignature, signature);
502
503 eventHelper_recordClassUnload(node->handlerID,
504 durableSignature,
505 eventBag);
506 }
507 if (shouldDelete) {
508 /* We can safely free the node now that we are done
509 * using it.
510 */
511 (void)freeHandler(node);
512 }
513 node = next;
514 }
515
516 debugMonitorExit(handlerLock);
517
518 if (eventBag != NULL((void*)0)) {
519 reportEvents(env, eventSessionID, (jthread)NULL((void*)0), 0,
520 (jclass)NULL((void*)0), (jmethodID)NULL((void*)0), 0, eventBag);
521
522 /*
523 * bag was created locally, destroy it here.
524 */
525 bagDestroyBag(eventBag);
526 }
527
528 jvmtiDeallocate(signature);
529 jvmtiDeallocate(classname);
530
531 return JNI_TRUE1;
532}
533
534/* Garbage Collection Happened */
535static unsigned int garbageCollected = 0;
536
537/*
538 * The JVMTI generic event callback. Each event is passed to a sequence of
539 * handlers in a chain until the chain ends or one handler
540 * consumes the event.
541 */
542static void
543event_callback(JNIEnv *env, EventInfo *evinfo)
544{
545 struct bag *eventBag;
546 jbyte eventSessionID = currentSessionID; /* session could change */
547 jthrowable currentException;
548 jthread thread;
549 EventIndex ei = evinfo->ei;
550
551 LOG_MISC(("event_callback(): ei=%s", eventText(ei)))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,551), log_message_end ("event_callback(): ei=%s", eventText(
ei))):((void)0))
;
10
Assuming the condition is false
11
'?' condition is false
552 log_debugee_location("event_callback()", evinfo->thread, evinfo->method, evinfo->location);
553
554 /* We want to preserve any current exception that might get
555 * wiped out during event handling (e.g. JNI calls). We have
556 * to rely on space for the local reference on the current
557 * frame because doing a PushLocalFrame here might itself
558 * generate an exception.
559 */
560 currentException = JNI_FUNC_PTR(env,ExceptionOccurred)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,560), log_message_end ("%s()","ExceptionOccurred")):((void)0
)), (env))))->ExceptionOccurred))
(env);
12
Assuming the condition is false
13
'?' condition is false
561 JNI_FUNC_PTR(env,ExceptionClear)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,561), log_message_end ("%s()","ExceptionClear")):((void)0)),
(env))))->ExceptionClear))
(env);
14
Assuming the condition is false
15
'?' condition is false
562
563 /* See if a garbage collection finish event happened earlier.
564 *
565 * Note: The "if" is an optimization to avoid entering the lock on every
566 * event; garbageCollected may be zapped before we enter
567 * the lock but then this just becomes one big no-op.
568 */
569 if ( garbageCollected > 0 ) {
16
Assuming 'garbageCollected' is <= 0
17
Taking false branch
570 struct bag *unloadedSignatures = NULL((void*)0);
571
572 /* We want to compact the hash table of all
573 * objects sent to the front end by removing objects that have
574 * been collected.
575 */
576 commonRef_compact();
577
578 /* We also need to simulate the class unload events. */
579
580 debugMonitorEnter(handlerLock);
581
582 /* Clear garbage collection counter */
583 garbageCollected = 0;
584
585 /* Analyze which class unloads occurred */
586 unloadedSignatures = classTrack_processUnloads(env);
587
588 debugMonitorExit(handlerLock);
589
590 /* Generate the synthetic class unload events and/or just cleanup. */
591 if ( unloadedSignatures != NULL((void*)0) ) {
592 (void)bagEnumerateOver(unloadedSignatures, synthesizeUnloadEvent,
593 (void *)env);
594 bagDestroyBag(unloadedSignatures);
595 }
596 }
597
598 thread = evinfo->thread;
599 if (thread
17.1
'thread' is equal to NULL
!= NULL((void*)0)) {
18
Taking false branch
600 /*
601 * Record the fact that we're entering an event
602 * handler so that thread operations (status, interrupt,
603 * stop) can be done correctly and so that thread
604 * resources can be allocated. This must be done before
605 * grabbing any locks.
606 */
607 eventBag = threadControl_onEventHandlerEntry(eventSessionID, evinfo, currentException);
608 if ( eventBag == NULL((void*)0) ) {
609 jboolean invoking;
610 do {
611 /* The event has been 'handled' and this
612 * thread is about to continue, but it may
613 * have been started up just to perform a
614 * requested method invocation. If so, we do
615 * the invoke now and then stop again waiting
616 * for another continue. By then another
617 * invoke request can be in place, so there is
618 * a loop around this code.
619 */
620 invoking = invoker_doInvoke(thread);
621 if (invoking) {
622 eventHelper_reportInvokeDone(eventSessionID, thread);
623 }
624 } while (invoking);
625 return; /* Do nothing, event was consumed */
626 }
627 } else {
628 eventBag = eventHelper_createEventBag();
629 if (eventBag == NULL((void*)0)) {
19
Assuming 'eventBag' is not equal to NULL
20
Taking false branch
630 /*
631 * TO DO: Report, but don't die
632 */
633 eventBag = NULL((void*)0); /* to shut up lint */
634 }
635 }
636
637 debugMonitorEnter(handlerLock);
638 {
639 HandlerNode *node;
640 char *classname;
641
642 /* We must keep track of all classes prepared to know what's unloaded */
643 if (evinfo->ei
20.1
Field 'ei' is not equal to EI_CLASS_PREPARE
== EI_CLASS_PREPARE) {
21
Taking false branch
644 classTrack_addPreparedClass(env, evinfo->clazz);
645 }
646
647 node = getHandlerChain(evinfo->ei)->first;
648 classname = getClassname(evinfo->clazz);
649
650 while (node != NULL((void*)0)) {
22
Assuming 'node' is not equal to NULL
23
Loop condition is true. Entering loop body
651 /* save next so handlers can remove themselves */
652 HandlerNode *next = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
653 jboolean shouldDelete;
654
655 if (eventFilterRestricted_passesFilter(env, classname,
24
Assuming the condition is true
25
Taking true branch
656 evinfo, node,
657 &shouldDelete)) {
658 HandlerFunction func;
659
660 func = HANDLER_FUNCTION(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_handlerFunction)
;
661 if ( func == NULL((void*)0) ) {
26
Assuming 'func' is equal to NULL
27
Taking true branch
662 EXIT_ERROR(AGENT_ERROR_INTERNAL,"handler function NULL"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+1))), ((jvmtiError)(JVMTI_ERROR_MAX+64+1)), ("handler function NULL"
==((void*)0)?"":"handler function NULL"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 662); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+1)), "handler function NULL"); }
;
28
'?' condition is false
663 }
664 (*func)(env, evinfo, node, eventBag);
29
Called function pointer is null (null dereference)
665 }
666 if (shouldDelete) {
667 /* We can safely free the node now that we are done
668 * using it.
669 */
670 (void)freeHandler(node);
671 }
672 node = next;
673 }
674 jvmtiDeallocate(classname);
675 }
676 debugMonitorExit(handlerLock);
677
678 if (eventBag != NULL((void*)0)) {
679 reportEvents(env, eventSessionID, thread, evinfo->ei,
680 evinfo->clazz, evinfo->method, evinfo->location, eventBag);
681 }
682
683 /* we are continuing after VMDeathEvent - now we are dead */
684 if (evinfo->ei == EI_VM_DEATH) {
685 gdata->vmDead = JNI_TRUE1;
686 }
687
688 /*
689 * If the bag was created locally, destroy it here.
690 */
691 if (thread == NULL((void*)0)) {
692 bagDestroyBag(eventBag);
693 }
694
695 /* Always restore any exception that was set beforehand. If
696 * there is a pending async exception, StopThread will be
697 * called from threadControl_onEventHandlerExit immediately
698 * below. Depending on VM implementation and state, the async
699 * exception might immediately overwrite the currentException,
700 * or it might be delayed until later. */
701 if (currentException != NULL((void*)0)) {
702 JNI_FUNC_PTR(env,Throw)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,702), log_message_end ("%s()","Throw")):((void)0)), (env))))
->Throw))
(env, currentException);
703 } else {
704 JNI_FUNC_PTR(env,ExceptionClear)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,704), log_message_end ("%s()","ExceptionClear")):((void)0)),
(env))))->ExceptionClear))
(env);
705 }
706
707 /*
708 * Release thread resources and perform any delayed operations.
709 */
710 if (thread != NULL((void*)0)) {
711 threadControl_onEventHandlerExit(evinfo->ei, thread, eventBag);
712 }
713}
714
715/* Returns a local ref to the declaring class for an object. */
716static jclass
717getObjectClass(jobject object)
718{
719 jclass clazz;
720 JNIEnv *env = getEnv();
721
722 clazz = JNI_FUNC_PTR(env,GetObjectClass)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,722), log_message_end ("%s()","GetObjectClass")):((void)0)),
(env))))->GetObjectClass))
(env, object);
723
724 return clazz;
725}
726
727/* Returns a local ref to the declaring class for a method, or NULL. */
728jclass
729getMethodClass(jvmtiEnv *jvmti_env, jmethodID method)
730{
731 jclass clazz = NULL((void*)0);
732 jvmtiError error;
733
734 if ( method == NULL((void*)0) ) {
735 return NULL((void*)0);
736 }
737 error = methodClass(method, &clazz);
738 if ( error != JVMTI_ERROR_NONE ) {
739 EXIT_ERROR(error,"Can't get jclass for a methodID, invalid?"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't get jclass for a methodID, invalid?"
==((void*)0)?"":"Can't get jclass for a methodID, invalid?"),
"/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 739); debugInit_exit((jvmtiError)error, "Can't get jclass for a methodID, invalid?"
); }
;
740 return NULL((void*)0);
741 }
742 return clazz;
743}
744
745/* Event callback for JVMTI_EVENT_SINGLE_STEP */
746static void JNICALL
747cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv *env,
748 jthread thread, jmethodID method, jlocation location)
749{
750 EventInfo info;
751
752 LOG_CB(("cbSingleStep: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,752), log_message_end ("cbSingleStep: thread=%p", thread)):(
(void)0))
;
753
754 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
755 (void)memset(&info,0,sizeof(info));
756 info.ei = EI_SINGLE_STEP;
757 info.thread = thread;
758 info.clazz = getMethodClass(jvmti_env, method);
759 info.method = method;
760 info.location = location;
761 event_callback(env, &info);
762 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 762); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
763
764 LOG_MISC(("END cbSingleStep"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,764), log_message_end ("END cbSingleStep")):((void)0))
;
765}
766
767/* Event callback for JVMTI_EVENT_BREAKPOINT */
768static void JNICALL
769cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv *env,
770 jthread thread, jmethodID method, jlocation location)
771{
772 EventInfo info;
773
774 LOG_CB(("cbBreakpoint: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,774), log_message_end ("cbBreakpoint: thread=%p", thread)):(
(void)0))
;
775
776 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
777 (void)memset(&info,0,sizeof(info));
778 info.ei = EI_BREAKPOINT;
779 info.thread = thread;
780 info.clazz = getMethodClass(jvmti_env, method);
781 info.method = method;
782 info.location = location;
783 event_callback(env, &info);
784 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 784); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
785
786 LOG_MISC(("END cbBreakpoint"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,786), log_message_end ("END cbBreakpoint")):((void)0))
;
787}
788
789/* Event callback for JVMTI_EVENT_FRAME_POP */
790static void JNICALL
791cbFramePop(jvmtiEnv *jvmti_env, JNIEnv *env,
792 jthread thread, jmethodID method,
793 jboolean wasPoppedByException)
794{
795 EventInfo info;
796
797 /* JDWP does not return these events when popped due to an exception. */
798 if ( wasPoppedByException ) {
799 return;
800 }
801
802 LOG_CB(("cbFramePop: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,802), log_message_end ("cbFramePop: thread=%p", thread)):((void
)0))
;
803
804 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
805 (void)memset(&info,0,sizeof(info));
806 info.ei = EI_FRAME_POP;
807 info.thread = thread;
808 info.clazz = getMethodClass(jvmti_env, method);
809 info.method = method;
810 event_callback(env, &info);
811 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 811); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
812
813 LOG_MISC(("END cbFramePop"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,813), log_message_end ("END cbFramePop")):((void)0))
;
814}
815
816/* Event callback for JVMTI_EVENT_EXCEPTION */
817static void JNICALL
818cbException(jvmtiEnv *jvmti_env, JNIEnv *env,
819 jthread thread, jmethodID method,
820 jlocation location, jobject exception,
821 jmethodID catch_method, jlocation catch_location)
822{
823 EventInfo info;
824
825 LOG_CB(("cbException: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,825), log_message_end ("cbException: thread=%p", thread)):((
void)0))
;
826
827 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
828 (void)memset(&info,0,sizeof(info));
829 info.ei = EI_EXCEPTION;
830 info.thread = thread;
831 info.clazz = getMethodClass(jvmti_env, method);
832 info.method = method;
833 info.location = location;
834 info.object = exception;
835 info.u.exception.catch_clazz = getMethodClass(jvmti_env, catch_method);
836 info.u.exception.catch_method = catch_method;
837 info.u.exception.catch_location = catch_location;
838 event_callback(env, &info);
839 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 839); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
840
841 LOG_MISC(("END cbException"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,841), log_message_end ("END cbException")):((void)0))
;
842}
843
844/* Event callback for JVMTI_EVENT_THREAD_START */
845static void JNICALL
846cbThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread)
847{
848 EventInfo info;
849
850 LOG_CB(("cbThreadStart: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,850), log_message_end ("cbThreadStart: thread=%p", thread)):
((void)0))
;
851
852 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
853 (void)memset(&info,0,sizeof(info));
854 info.ei = EI_THREAD_START;
855 info.thread = thread;
856 event_callback(env, &info);
857 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 857); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
858
859 LOG_MISC(("END cbThreadStart"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,859), log_message_end ("END cbThreadStart")):((void)0))
;
860}
861
862/* Event callback for JVMTI_EVENT_THREAD_END */
863static void JNICALL
864cbThreadEnd(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread)
865{
866 EventInfo info;
867
868 LOG_CB(("cbThreadEnd: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,868), log_message_end ("cbThreadEnd: thread=%p", thread)):((
void)0))
;
869
870 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
871 (void)memset(&info,0,sizeof(info));
872 info.ei = EI_THREAD_END;
873 info.thread = thread;
874 event_callback(env, &info);
875 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 875); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
876
877 LOG_MISC(("END cbThreadEnd"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,877), log_message_end ("END cbThreadEnd")):((void)0))
;
878}
879
880/* Event callback for JVMTI_EVENT_CLASS_PREPARE */
881static void JNICALL
882cbClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *env,
883 jthread thread, jclass klass)
884{
885 EventInfo info;
886
887 LOG_CB(("cbClassPrepare: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,887), log_message_end ("cbClassPrepare: thread=%p", thread))
:((void)0))
;
888
889 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
890 (void)memset(&info,0,sizeof(info));
891 info.ei = EI_CLASS_PREPARE;
892 info.thread = thread;
893 info.clazz = klass;
894 event_callback(env, &info);
895 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 895); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
896
897 LOG_MISC(("END cbClassPrepare"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,897), log_message_end ("END cbClassPrepare")):((void)0))
;
898}
899
900/* Event callback for JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
901static void JNICALL
902cbGarbageCollectionFinish(jvmtiEnv *jvmti_env)
903{
904 LOG_CB(("cbGarbageCollectionFinish"))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,904), log_message_end ("cbGarbageCollectionFinish")):((void)
0))
;
905 ++garbageCollected;
906 LOG_MISC(("END cbGarbageCollectionFinish"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,906), log_message_end ("END cbGarbageCollectionFinish")):((void
)0))
;
907}
908
909/* Event callback for JVMTI_EVENT_CLASS_LOAD */
910static void JNICALL
911cbClassLoad(jvmtiEnv *jvmti_env, JNIEnv *env,
912 jthread thread, jclass klass)
913{
914 EventInfo info;
915
916 LOG_CB(("cbClassLoad: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,916), log_message_end ("cbClassLoad: thread=%p", thread)):((
void)0))
;
917
918 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
919 (void)memset(&info,0,sizeof(info));
920 info.ei = EI_CLASS_LOAD;
921 info.thread = thread;
922 info.clazz = klass;
923 event_callback(env, &info);
924 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 924); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
925
926 LOG_MISC(("END cbClassLoad"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,926), log_message_end ("END cbClassLoad")):((void)0))
;
927}
928
929/* Event callback for JVMTI_EVENT_FIELD_ACCESS */
930static void JNICALL
931cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv *env,
932 jthread thread, jmethodID method,
933 jlocation location, jclass field_klass,
934 jobject object, jfieldID field)
935{
936 EventInfo info;
937
938 LOG_CB(("cbFieldAccess: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,938), log_message_end ("cbFieldAccess: thread=%p", thread)):
((void)0))
;
939
940 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
941 (void)memset(&info,0,sizeof(info));
942 info.ei = EI_FIELD_ACCESS;
943 info.thread = thread;
944 info.clazz = getMethodClass(jvmti_env, method);
945 info.method = method;
946 info.location = location;
947 info.u.field_access.field_clazz = field_klass;
948 info.object = object;
949 info.u.field_access.field = field;
950 event_callback(env, &info);
951 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 951); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
952
953 LOG_MISC(("END cbFieldAccess"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,953), log_message_end ("END cbFieldAccess")):((void)0))
;
954}
955
956/* Event callback for JVMTI_EVENT_FIELD_MODIFICATION */
957static void JNICALL
958cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv *env,
959 jthread thread, jmethodID method,
960 jlocation location, jclass field_klass, jobject object, jfieldID field,
961 char signature_type, jvalue new_value)
962{
963 EventInfo info;
964
965 LOG_CB(("cbFieldModification: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,965), log_message_end ("cbFieldModification: thread=%p", thread
)):((void)0))
;
966
967 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
968 (void)memset(&info,0,sizeof(info));
969 info.ei = EI_FIELD_MODIFICATION;
970 info.thread = thread;
971 info.clazz = getMethodClass(jvmti_env, method);
972 info.method = method;
973 info.location = location;
974 info.u.field_modification.field = field;
975 info.u.field_modification.field_clazz = field_klass;
976 info.object = object;
977 info.u.field_modification.signature_type= signature_type;
978 info.u.field_modification.new_value = new_value;
979 event_callback(env, &info);
980 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 980); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
981
982 LOG_MISC(("END cbFieldModification"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,982), log_message_end ("END cbFieldModification")):((void)0)
)
;
983}
984
985/* Event callback for JVMTI_EVENT_EXCEPTION_CATCH */
986static void JNICALL
987cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread,
988 jmethodID method, jlocation location, jobject exception)
989{
990 EventInfo info;
991
992 LOG_CB(("cbExceptionCatch: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,992), log_message_end ("cbExceptionCatch: thread=%p", thread
)):((void)0))
;
993
994 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
995 (void)memset(&info,0,sizeof(info));
996 info.ei = EI_EXCEPTION_CATCH;
997 info.thread = thread;
998 info.clazz = getMethodClass(jvmti_env, method);
999 info.method = method;
1000 info.location = location;
1001 info.object = exception;
1002 event_callback(env, &info);
1003 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1003); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1004
1005 LOG_MISC(("END cbExceptionCatch"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1005), log_message_end ("END cbExceptionCatch")):((void)0))
;
1006}
1007
1008/* Event callback for JVMTI_EVENT_METHOD_ENTRY */
1009static void JNICALL
1010cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv *env,
1011 jthread thread, jmethodID method)
1012{
1013 EventInfo info;
1014
1015 LOG_CB(("cbMethodEntry: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1015), log_message_end ("cbMethodEntry: thread=%p", thread))
:((void)0))
;
1016
1017 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1018 (void)memset(&info,0,sizeof(info));
1019 info.ei = EI_METHOD_ENTRY;
1020 info.thread = thread;
1021 info.clazz = getMethodClass(jvmti_env, method);
1022 info.method = method;
1023 event_callback(env, &info);
1024 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1024); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1025
1026 LOG_MISC(("END cbMethodEntry"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1026), log_message_end ("END cbMethodEntry")):((void)0))
;
1027}
1028
1029/* Event callback for JVMTI_EVENT_METHOD_EXIT */
1030static void JNICALL
1031cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv *env,
1032 jthread thread, jmethodID method,
1033 jboolean wasPoppedByException, jvalue return_value)
1034{
1035 EventInfo info;
1036
1037 /* JDWP does not return these events when popped due to an exception. */
1038 if ( wasPoppedByException ) {
1039 return;
1040 }
1041
1042 LOG_CB(("cbMethodExit: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1042), log_message_end ("cbMethodExit: thread=%p", thread)):
((void)0))
;
1043
1044 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1045 (void)memset(&info,0,sizeof(info));
1046 info.ei = EI_METHOD_EXIT;
1047 info.thread = thread;
1048 info.clazz = getMethodClass(jvmti_env, method);
1049 info.method = method;
1050 info.u.method_exit.return_value = return_value;
1051 event_callback(env, &info);
1052 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1052); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1053
1054 LOG_MISC(("END cbMethodExit"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1054), log_message_end ("END cbMethodExit")):((void)0))
;
1055}
1056
1057/* Event callback for JVMTI_EVENT_MONITOR_CONTENDED_ENTER */
1058static void JNICALL
1059cbMonitorContendedEnter(jvmtiEnv *jvmti_env, JNIEnv *env,
1060 jthread thread, jobject object)
1061{
1062 EventInfo info;
1063 jvmtiError error;
1064 jmethodID method;
1065 jlocation location;
1066
1067 LOG_CB(("cbMonitorContendedEnter: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1067), log_message_end ("cbMonitorContendedEnter: thread=%p"
, thread)):((void)0))
;
1068
1069 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1070 (void)memset(&info,0,sizeof(info));
1071 info.ei = EI_MONITOR_CONTENDED_ENTER;
1072 info.thread = thread;
1073 info.object = object;
1074 /* get current location of contended monitor enter */
1075 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1075), log_message_end ("%s()","GetFrameLocation")):((void)0
)),(gdata->jvmti))))->GetFrameLocation))
1076 (gdata->jvmti, thread, 0, &method, &location);
1077 if (error == JVMTI_ERROR_NONE) {
1078 info.location = location;
1079 info.method = method;
1080 info.clazz = getMethodClass(jvmti_env, method);
1081 } else {
1082 info.location = -1;
1083 }
1084 event_callback(env, &info);
1085 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1085); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1086
1087 LOG_MISC(("END cbMonitorContendedEnter"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1087), log_message_end ("END cbMonitorContendedEnter")):((void
)0))
;
1088}
1089
1090/* Event callback for JVMTI_EVENT_MONITOR_CONTENDED_ENTERED */
1091static void JNICALL
1092cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv *env,
1093 jthread thread, jobject object)
1094{
1095 EventInfo info;
1096 jvmtiError error;
1097 jmethodID method;
1098 jlocation location;
1099
1100 LOG_CB(("cbMonitorContendedEntered: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1100), log_message_end ("cbMonitorContendedEntered: thread=%p"
, thread)):((void)0))
;
1101
1102 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1103 (void)memset(&info,0,sizeof(info));
1104 info.ei = EI_MONITOR_CONTENDED_ENTERED;
1105 info.thread = thread;
1106 info.object = object;
1107 /* get current location of contended monitor enter */
1108 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1108), log_message_end ("%s()","GetFrameLocation")):((void)0
)),(gdata->jvmti))))->GetFrameLocation))
1109 (gdata->jvmti, thread, 0, &method, &location);
1110 if (error == JVMTI_ERROR_NONE) {
1111 info.location = location;
1112 info.method = method;
1113 info.clazz = getMethodClass(jvmti_env, method);
1114 } else {
1115 info.location = -1;
1116 }
1117 event_callback(env, &info);
1118 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1118); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1119
1120 LOG_MISC(("END cbMonitorContendedEntered"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1120), log_message_end ("END cbMonitorContendedEntered")):((
void)0))
;
1121}
1122
1123/* Event callback for JVMTI_EVENT_MONITOR_WAIT */
1124static void JNICALL
1125cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv *env,
1126 jthread thread, jobject object,
1127 jlong timeout)
1128{
1129 EventInfo info;
1130 jvmtiError error;
1131 jmethodID method;
1132 jlocation location;
1133
1134 LOG_CB(("cbMonitorWait: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1134), log_message_end ("cbMonitorWait: thread=%p", thread))
:((void)0))
;
1135
1136 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1137 (void)memset(&info,0,sizeof(info));
1138 info.ei = EI_MONITOR_WAIT;
1139 info.thread = thread;
1140 info.object = object;
1141 /* The info.clazz is used for both class filtering and for location info.
1142 * For monitor wait event the class filtering is done for class of monitor
1143 * object. So here info.clazz is set to class of monitor object here and it
1144 * is reset to class of method before writing location info.
1145 * See writeMonitorEvent in eventHelper.c
1146 */
1147 info.clazz = getObjectClass(object);
1148 info.u.monitor.timeout = timeout;
1149
1150 /* get location of monitor wait() method. */
1151 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1151), log_message_end ("%s()","GetFrameLocation")):((void)0
)),(gdata->jvmti))))->GetFrameLocation))
1152 (gdata->jvmti, thread, 0, &method, &location);
1153 if (error == JVMTI_ERROR_NONE) {
1154 info.location = location;
1155 info.method = method;
1156 } else {
1157 info.location = -1;
1158 }
1159 event_callback(env, &info);
1160 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1160); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1161
1162 LOG_MISC(("END cbMonitorWait"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1162), log_message_end ("END cbMonitorWait")):((void)0))
;
1163}
1164
1165/* Event callback for JVMTI_EVENT_MONITOR_WAIT */
1166static void JNICALL
1167cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv *env,
1168 jthread thread, jobject object,
1169 jboolean timed_out)
1170{
1171 EventInfo info;
1172 jvmtiError error;
1173 jmethodID method;
1174 jlocation location;
1175
1176 LOG_CB(("cbMonitorWaited: thread=%p", thread))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1176), log_message_end ("cbMonitorWaited: thread=%p", thread
)):((void)0))
;
1177
1178 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1179 (void)memset(&info,0,sizeof(info));
1180 info.ei = EI_MONITOR_WAITED;
1181 info.thread = thread;
1182 info.object = object;
1183 /* The info.clazz is used for both class filtering and for location info.
1184 * For monitor waited event the class filtering is done for class of monitor
1185 * object. So here info.clazz is set to class of monitor object here and it
1186 * is reset to class of method before writing location info.
1187 * See writeMonitorEvent in eventHelper.c
1188 */
1189 info.clazz = getObjectClass(object);
1190 info.u.monitor.timed_out = timed_out;
1191
1192 /* get location of monitor wait() method */
1193 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1193), log_message_end ("%s()","GetFrameLocation")):((void)0
)),(gdata->jvmti))))->GetFrameLocation))
1194 (gdata->jvmti, thread, 0, &method, &location);
1195 if (error == JVMTI_ERROR_NONE) {
1196 info.location = location;
1197 info.method = method;
1198 } else {
1199 info.location = -1;
1200 }
1201 event_callback(env, &info);
1202 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1202); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1203
1204 LOG_MISC(("END cbMonitorWaited"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1204), log_message_end ("END cbMonitorWaited")):((void)0))
;
1205}
1206
1207/* Event callback for JVMTI_EVENT_VM_INIT */
1208static void JNICALL
1209cbVMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread)
1210{
1211 EventInfo info;
1212
1213 LOG_CB(("cbVMInit"))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1213), log_message_end ("cbVMInit")):((void)0))
;
1214
1215 BEGIN_CALLBACK(){ jboolean bypass = 1; debugMonitorEnter(callbackLock); { if (
vm_death_callback_active) { debugMonitorExit(callbackLock); debugMonitorEnter
(callbackBlock); debugMonitorExit(callbackBlock); } else { active_callbacks
++; bypass = 0; debugMonitorExit(callbackLock); } } if ( !bypass
) {
{
1216 (void)memset(&info,0,sizeof(info));
1217 info.ei = EI_VM_INIT;
1218 info.thread = thread;
1219 event_callback(env, &info);
1220 } END_CALLBACK()debugMonitorEnter(callbackLock); { active_callbacks--; if (active_callbacks
< 0) { { print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)0), 0, ("Problems tracking active callbacks"
==((void*)0)?"":"Problems tracking active callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1220); debugInit_exit((jvmtiError)0, "Problems tracking active callbacks"
); }; } if (vm_death_callback_active) { if (active_callbacks ==
0) { debugMonitorNotifyAll(callbackLock); } debugMonitorExit
(callbackLock); debugMonitorEnter(callbackBlock); debugMonitorExit
(callbackBlock); } else { debugMonitorExit(callbackLock); } }
} }
;
1221
1222 LOG_MISC(("END cbVMInit"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1222), log_message_end ("END cbVMInit")):((void)0))
;
1223}
1224
1225/* Event callback for JVMTI_EVENT_VM_DEATH */
1226static void JNICALL
1227cbVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env)
1228{
1229 jvmtiError error;
1230 EventInfo info;
1231 LOG_CB(("cbVMDeath"))((gdata->log_flags & (0x00000040))?(log_message_begin(
"CB","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1231), log_message_end ("cbVMDeath")):((void)0))
;
1
Assuming the condition is false
2
'?' condition is false
1232
1233 /* Setting this flag is needed by findThread(). It's ok to set it before
1234 the callbacks are cleared.*/
1235 gdata->jvmtiCallBacksCleared = JNI_TRUE1;
1236
1237 /* Clear out ALL callbacks at this time, we don't want any more. */
1238 /* This should prevent any new BEGIN_CALLBACK() calls. */
1239 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
1240 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1240), log_message_end ("%s()","SetEventCallbacks")):((void)
0)),(gdata->jvmti))))->SetEventCallbacks))
3
Assuming the condition is false
4
'?' condition is false
1241 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
1242 if (error != JVMTI_ERROR_NONE) {
5
Assuming 'error' is equal to JVMTI_ERROR_NONE
6
Taking false branch
1243 EXIT_ERROR(error,"Can't clear event callbacks on vm death"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't clear event callbacks on vm death"
==((void*)0)?"":"Can't clear event callbacks on vm death"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1243); debugInit_exit((jvmtiError)error, "Can't clear event callbacks on vm death"
); }
;
1244 }
1245
1246 /* Now that no new callbacks will be made, we need to wait for the ones
1247 * that are still active to complete.
1248 * The BEGIN_CALLBACK/END_CALLBACK macros implement the VM_DEATH
1249 * callback protocol. Once the callback table is cleared (above),
1250 * we can have callback threads in different stages:
1251 * 1) after callback function entry and before BEGIN_CALLBACK
1252 * macro; we catch these threads with callbackBlock in the
1253 * BEGIN_CALLBACK macro
1254 * 2) after BEGIN_CALLBACK macro and before END_CALLBACK macro; we
1255 * catch these threads with callbackBlock in the END_CALLBACK
1256 * macro
1257 * 3) after END_CALLBACK macro; these threads have made it past
1258 * callbackBlock and callbackLock and don't count as active
1259 *
1260 * Since some of the callback threads could be blocked or suspended
1261 * we will resume all threads suspended by the debugger for a short
1262 * time to flush out all callbacks. Note that the callback threads
1263 * will block from returning to the VM in both macros. Some threads
1264 * not associated with callbacks, but suspended by the debugger may
1265 * continue on, but not for long.
1266 * Once the last callback finishes, it will notify this thread and
1267 * we fall out of the loop below and actually process the VM_DEATH
1268 * event.
1269 */
1270 debugMonitorEnter(callbackBlock); {
1271 debugMonitorEnter(callbackLock); {
1272 vm_death_callback_active = JNI_TRUE1;
1273 (void)threadControl_resumeAll();
1274 while (active_callbacks > 0) {
7
Assuming 'active_callbacks' is <= 0
8
Loop condition is false. Execution continues on line 1278
1275 /* wait for active CALLBACKs to check in (and block) */
1276 debugMonitorWait(callbackLock);
1277 }
1278 } debugMonitorExit(callbackLock);
1279
1280 /* Only now should we actually process the VM death event */
1281 (void)memset(&info,0,sizeof(info));
1282 info.ei = EI_VM_DEATH;
1283 event_callback(env, &info);
9
Calling 'event_callback'
1284
1285 /* Here we unblock all the callbacks and let them return to the
1286 * VM. It's not clear this is necessary, but leaving threads
1287 * blocked doesn't seem like a good idea. They don't have much
1288 * life left anyway.
1289 */
1290 } debugMonitorExit(callbackBlock);
1291
1292 /*
1293 * The VM will die soon after the completion of this callback -
1294 * we synchronize with both the command loop and the debug loop
1295 * for a more orderly shutdown.
1296 */
1297 commandLoop_sync();
1298 debugLoop_sync();
1299
1300 LOG_MISC(("END cbVMDeath"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1300), log_message_end ("END cbVMDeath")):((void)0))
;
1301}
1302
1303/**
1304 * Delete this handler (do not delete permanent handlers):
1305 * Deinsert handler from active list,
1306 * make it inactive, and free it's memory
1307 * Assumes handlerLock held.
1308 */
1309static jvmtiError
1310freeHandler(HandlerNode *node) {
1311 jvmtiError error = JVMTI_ERROR_NONE;
1312
1313 /* deinsert the handler node before disableEvents() to make
1314 * sure the event will be disabled when no other event
1315 * handlers are installed.
1316 */
1317 if (node != NULL((void*)0) && (!node->permanent)) {
1318 deinsert(node);
1319 error = eventFilterRestricted_deinstall(node);
1320 jvmtiDeallocate(node);
1321 }
1322
1323 return error;
1324}
1325
1326/**
1327 * Delete all the handlers on this chain (do not delete permanent handlers).
1328 * Assumes handlerLock held.
1329 */
1330static jvmtiError
1331freeHandlerChain(HandlerChain *chain)
1332{
1333 HandlerNode *node;
1334 jvmtiError error;
1335
1336 error = JVMTI_ERROR_NONE;
1337 node = chain->first;
1338 while ( node != NULL((void*)0) ) {
1339 HandlerNode *next;
1340 jvmtiError singleError;
1341
1342 next = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
1343 singleError = freeHandler(node);
1344 if ( singleError != JVMTI_ERROR_NONE ) {
1345 error = singleError;
1346 }
1347 node = next;
1348 }
1349 return error;
1350}
1351
1352/**
1353 * Deinsert and free all memory. Safe for non-inserted nodes.
1354 */
1355jvmtiError
1356eventHandler_free(HandlerNode *node)
1357{
1358 jvmtiError error;
1359
1360 debugMonitorEnter(handlerLock);
1361
1362 error = freeHandler(node);
1363
1364 debugMonitorExit(handlerLock);
1365
1366 return error;
1367}
1368
1369/**
1370 * Free all handlers of this kind created by the JDWP client,
1371 * that is, doesn't free handlers internally created by back-end.
1372 */
1373jvmtiError
1374eventHandler_freeAll(EventIndex ei)
1375{
1376 jvmtiError error = JVMTI_ERROR_NONE;
1377 HandlerNode *node;
1378
1379 debugMonitorEnter(handlerLock);
1380 node = getHandlerChain(ei)->first;
1381 while (node != NULL((void*)0)) {
1382 HandlerNode *next = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
; /* allows node removal */
1383 if (node->handlerID != 0) { /* don't free internal handlers */
1384 error = freeHandler(node);
1385 if (error != JVMTI_ERROR_NONE) {
1386 break;
1387 }
1388 }
1389 node = next;
1390 }
1391 debugMonitorExit(handlerLock);
1392 return error;
1393}
1394
1395/***
1396 * Delete all breakpoints on "clazz".
1397 */
1398void
1399eventHandler_freeClassBreakpoints(jclass clazz)
1400{
1401 HandlerNode *node;
1402 JNIEnv *env = getEnv();
1403
1404 debugMonitorEnter(handlerLock);
1405 node = getHandlerChain(EI_BREAKPOINT)->first;
1406 while (node != NULL((void*)0)) {
1407 HandlerNode *next = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
; /* allows node removal */
1408 if (eventFilterRestricted_isBreakpointInClass(env, clazz,
1409 node)) {
1410 (void)freeHandler(node);
1411 }
1412 node = next;
1413 }
1414 debugMonitorExit(handlerLock);
1415}
1416
1417jvmtiError
1418eventHandler_freeByID(EventIndex ei, HandlerID handlerID)
1419{
1420 jvmtiError error;
1421 HandlerNode *node;
1422
1423 debugMonitorEnter(handlerLock);
1424 node = find(ei, handlerID);
1425 if (node != NULL((void*)0)) {
1426 error = freeHandler(node);
1427 } else {
1428 /* already freed */
1429 error = JVMTI_ERROR_NONE;
1430 }
1431 debugMonitorExit(handlerLock);
1432 return error;
1433}
1434
1435void
1436eventHandler_initialize(jbyte sessionID)
1437{
1438 jvmtiError error;
1439 jint i;
1440
1441 requestIdCounter = 1;
1442 currentSessionID = sessionID;
1443
1444 /* This is for BEGIN_CALLBACK/END_CALLBACK handling, make sure this
1445 * is done while none of these callbacks are active.
1446 */
1447 active_callbacks = 0;
1448 vm_death_callback_active = JNI_FALSE0;
1449 callbackLock = debugMonitorCreate("JDWP Callback Lock");
1450 callbackBlock = debugMonitorCreate("JDWP Callback Block");
1451
1452 handlerLock = debugMonitorCreate("JDWP Event Handler Lock");
1453
1454 for (i = EI_min; i <= EI_max; ++i) {
1455 getHandlerChain(i)->first = NULL((void*)0);
1456 }
1457
1458 /*
1459 * Permanently enabled some events.
1460 */
1461 error = threadControl_setEventMode(JVMTI_ENABLE,
1462 EI_VM_INIT, NULL((void*)0));
1463 if (error != JVMTI_ERROR_NONE) {
1464 EXIT_ERROR(error,"Can't enable vm init events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable vm init events"
==((void*)0)?"":"Can't enable vm init events"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1464); debugInit_exit((jvmtiError)error, "Can't enable vm init events"
); }
;
1465 }
1466 error = threadControl_setEventMode(JVMTI_ENABLE,
1467 EI_VM_DEATH, NULL((void*)0));
1468 if (error != JVMTI_ERROR_NONE) {
1469 EXIT_ERROR(error,"Can't enable vm death events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable vm death events"
==((void*)0)?"":"Can't enable vm death events"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1469); debugInit_exit((jvmtiError)error, "Can't enable vm death events"
); }
;
1470 }
1471 error = threadControl_setEventMode(JVMTI_ENABLE,
1472 EI_THREAD_START, NULL((void*)0));
1473 if (error != JVMTI_ERROR_NONE) {
1474 EXIT_ERROR(error,"Can't enable thread start events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable thread start events"
==((void*)0)?"":"Can't enable thread start events"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1474); debugInit_exit((jvmtiError)error, "Can't enable thread start events"
); }
;
1475 }
1476 error = threadControl_setEventMode(JVMTI_ENABLE,
1477 EI_THREAD_END, NULL((void*)0));
1478 if (error != JVMTI_ERROR_NONE) {
1479 EXIT_ERROR(error,"Can't enable thread end events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable thread end events"
==((void*)0)?"":"Can't enable thread end events"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1479); debugInit_exit((jvmtiError)error, "Can't enable thread end events"
); }
;
1480 }
1481 error = threadControl_setEventMode(JVMTI_ENABLE,
1482 EI_CLASS_PREPARE, NULL((void*)0));
1483 if (error != JVMTI_ERROR_NONE) {
1484 EXIT_ERROR(error,"Can't enable class prepare events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable class prepare events"
==((void*)0)?"":"Can't enable class prepare events"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1484); debugInit_exit((jvmtiError)error, "Can't enable class prepare events"
); }
;
1485 }
1486 error = threadControl_setEventMode(JVMTI_ENABLE,
1487 EI_GC_FINISH, NULL((void*)0));
1488 if (error != JVMTI_ERROR_NONE) {
1489 EXIT_ERROR(error,"Can't enable garbage collection finish events"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't enable garbage collection finish events"
==((void*)0)?"":"Can't enable garbage collection finish events"
), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1489); debugInit_exit((jvmtiError)error, "Can't enable garbage collection finish events"
); }
;
1490 }
1491
1492 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
1493 /* Event callback for JVMTI_EVENT_SINGLE_STEP */
1494 gdata->callbacks.SingleStep = &cbSingleStep;
1495 /* Event callback for JVMTI_EVENT_BREAKPOINT */
1496 gdata->callbacks.Breakpoint = &cbBreakpoint;
1497 /* Event callback for JVMTI_EVENT_FRAME_POP */
1498 gdata->callbacks.FramePop = &cbFramePop;
1499 /* Event callback for JVMTI_EVENT_EXCEPTION */
1500 gdata->callbacks.Exception = &cbException;
1501 /* Event callback for JVMTI_EVENT_THREAD_START */
1502 gdata->callbacks.ThreadStart = &cbThreadStart;
1503 /* Event callback for JVMTI_EVENT_THREAD_END */
1504 gdata->callbacks.ThreadEnd = &cbThreadEnd;
1505 /* Event callback for JVMTI_EVENT_CLASS_PREPARE */
1506 gdata->callbacks.ClassPrepare = &cbClassPrepare;
1507 /* Event callback for JVMTI_EVENT_CLASS_LOAD */
1508 gdata->callbacks.ClassLoad = &cbClassLoad;
1509 /* Event callback for JVMTI_EVENT_FIELD_ACCESS */
1510 gdata->callbacks.FieldAccess = &cbFieldAccess;
1511 /* Event callback for JVMTI_EVENT_FIELD_MODIFICATION */
1512 gdata->callbacks.FieldModification = &cbFieldModification;
1513 /* Event callback for JVMTI_EVENT_EXCEPTION_CATCH */
1514 gdata->callbacks.ExceptionCatch = &cbExceptionCatch;
1515 /* Event callback for JVMTI_EVENT_METHOD_ENTRY */
1516 gdata->callbacks.MethodEntry = &cbMethodEntry;
1517 /* Event callback for JVMTI_EVENT_METHOD_EXIT */
1518 gdata->callbacks.MethodExit = &cbMethodExit;
1519 /* Event callback for JVMTI_EVENT_MONITOR_CONTENDED_ENTER */
1520 gdata->callbacks.MonitorContendedEnter = &cbMonitorContendedEnter;
1521 /* Event callback for JVMTI_EVENT_MONITOR_CONTENDED_ENTERED */
1522 gdata->callbacks.MonitorContendedEntered = &cbMonitorContendedEntered;
1523 /* Event callback for JVMTI_EVENT_MONITOR_WAIT */
1524 gdata->callbacks.MonitorWait = &cbMonitorWait;
1525 /* Event callback for JVMTI_EVENT_MONITOR_WAITED */
1526 gdata->callbacks.MonitorWaited = &cbMonitorWaited;
1527 /* Event callback for JVMTI_EVENT_VM_INIT */
1528 gdata->callbacks.VMInit = &cbVMInit;
1529 /* Event callback for JVMTI_EVENT_VM_DEATH */
1530 gdata->callbacks.VMDeath = &cbVMDeath;
1531 /* Event callback for JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
1532 gdata->callbacks.GarbageCollectionFinish = &cbGarbageCollectionFinish;
1533
1534 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
,1534), log_message_end ("%s()","SetEventCallbacks")):((void)
0)),(gdata->jvmti))))->SetEventCallbacks))
1535 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
1536 if (error != JVMTI_ERROR_NONE) {
1537 EXIT_ERROR(error,"Can't set event callbacks"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("Can't set event callbacks"
==((void*)0)?"":"Can't set event callbacks"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c"
, 1537); debugInit_exit((jvmtiError)error, "Can't set event callbacks"
); }
;
1538 }
1539
1540 /* Notify other modules that the event callbacks are in place */
1541 threadControl_onHook();
1542
1543 /* Get the event helper thread initialized */
1544 eventHelper_initialize(sessionID);
1545}
1546
1547void
1548eventHandler_reset(jbyte sessionID)
1549{
1550 int i;
1551
1552 debugMonitorEnter(handlerLock);
1553
1554 /* We must do this first so that if any invokes complete,
1555 * there will be no attempt to send them to the front
1556 * end. Waiting for threadControl_reset leaves a window where
1557 * the invoke completions can sneak through.
1558 */
1559 threadControl_detachInvokes();
1560
1561 /* Reset the event helper thread, purging all queued and
1562 * in-process commands.
1563 */
1564 eventHelper_reset(sessionID);
1565
1566 /* delete all handlers */
1567 for (i = EI_min; i <= EI_max; i++) {
1568 (void)freeHandlerChain(getHandlerChain(i));
1569 }
1570
1571 requestIdCounter = 1;
1572 currentSessionID = sessionID;
1573
1574 debugMonitorExit(handlerLock);
1575}
1576
1577void
1578eventHandler_lock(void)
1579{
1580 debugMonitorEnter(handlerLock);
1581}
1582
1583void
1584eventHandler_unlock(void)
1585{
1586 debugMonitorExit(handlerLock);
1587}
1588
1589/***** handler creation *****/
1590
1591HandlerNode *
1592eventHandler_alloc(jint filterCount, EventIndex ei, jbyte suspendPolicy)
1593{
1594 HandlerNode *node = eventFilterRestricted_alloc(filterCount);
1595
1596 if (node != NULL((void*)0)) {
1597 node->ei = ei;
1598 node->suspendPolicy = suspendPolicy;
1599 node->permanent = JNI_FALSE0;
1600 }
1601
1602 return node;
1603}
1604
1605
1606HandlerID
1607eventHandler_allocHandlerID(void)
1608{
1609 jint handlerID;
1610 debugMonitorEnter(handlerLock);
1611 handlerID = ++requestIdCounter;
1612 debugMonitorExit(handlerLock);
1613 return handlerID;
1614}
1615
1616
1617static jvmtiError
1618installHandler(HandlerNode *node,
1619 HandlerFunction func,
1620 jboolean external)
1621{
1622 jvmtiError error;
1623
1624 if ( func == NULL((void*)0) ) {
1625 return AGENT_ERROR_INVALID_EVENT_TYPE((jvmtiError)(JVMTI_ERROR_MAX+64+24));
1626 }
1627
1628 debugMonitorEnter(handlerLock);
1629
1630 HANDLER_FUNCTION(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_handlerFunction)
= func;
1631
1632 node->handlerID = external? ++requestIdCounter : 0;
1633 error = eventFilterRestricted_install(node);
1634 if (node->ei == EI_GC_FINISH) {
1635 classTrack_activate(getEnv());
1636 }
1637 if (error == JVMTI_ERROR_NONE) {
1638 insert(getHandlerChain(node->ei), node);
1639 }
1640
1641 debugMonitorExit(handlerLock);
1642
1643 return error;
1644}
1645
1646static HandlerNode *
1647createInternal(EventIndex ei, HandlerFunction func,
1648 jthread thread, jclass clazz, jmethodID method,
1649 jlocation location, jboolean permanent)
1650{
1651 jint index = 0;
1652 jvmtiError error = JVMTI_ERROR_NONE;
1653 HandlerNode *node;
1654
1655 /*
1656 * Start with necessary allocations
1657 */
1658 node = eventHandler_alloc(
1659 ((thread == NULL((void*)0))? 0 : 1) + ((clazz == NULL((void*)0))? 0 : 1),
1660 ei, JDWP_SUSPEND_POLICY(NONE)0);
1661 if (node == NULL((void*)0)) {
1662 return NULL((void*)0);
1663 }
1664
1665 node->permanent = permanent;
1666
1667 if (thread != NULL((void*)0)) {
1668 error = eventFilter_setThreadOnlyFilter(node, index++, thread);
1669 }
1670
1671 if ((error == JVMTI_ERROR_NONE) && (clazz != NULL((void*)0))) {
1672 error = eventFilter_setLocationOnlyFilter(node, index++, clazz,
1673 method, location);
1674 }
1675 /*
1676 * Create the new handler node
1677 */
1678 error = installHandler(node, func, JNI_FALSE0);
1679
1680 if (error != JVMTI_ERROR_NONE) {
1681 (void)eventHandler_free(node);
1682 node = NULL((void*)0);
1683 }
1684 return node;
1685}
1686
1687HandlerNode *
1688eventHandler_createPermanentInternal(EventIndex ei, HandlerFunction func)
1689{
1690 return createInternal(ei, func, NULL((void*)0),
1691 NULL((void*)0), NULL((void*)0), 0, JNI_TRUE1);
1692}
1693
1694HandlerNode *
1695eventHandler_createInternalThreadOnly(EventIndex ei,
1696 HandlerFunction func,
1697 jthread thread)
1698{
1699 return createInternal(ei, func, thread,
1700 NULL((void*)0), NULL((void*)0), 0, JNI_FALSE0);
1701}
1702
1703HandlerNode *
1704eventHandler_createInternalBreakpoint(HandlerFunction func,
1705 jthread thread,
1706 jclass clazz,
1707 jmethodID method,
1708 jlocation location)
1709{
1710 return createInternal(EI_BREAKPOINT, func, thread,
1711 clazz, method, location, JNI_FALSE0);
1712}
1713
1714jvmtiError
1715eventHandler_installExternal(HandlerNode *node)
1716{
1717 return installHandler(node,
1718 standardHandlers_defaultHandler(node->ei),
1719 JNI_TRUE1);
1720}
1721
1722/***** debugging *****/
1723
1724#ifdef DEBUG1
1725
1726void
1727eventHandler_dumpAllHandlers(jboolean dumpPermanent)
1728{
1729 int ei;
1730 for (ei = EI_min; ei <= EI_max; ++ei) {
1731 eventHandler_dumpHandlers(ei, dumpPermanent);
1732 }
1733}
1734
1735void
1736eventHandler_dumpHandlers(EventIndex ei, jboolean dumpPermanent)
1737{
1738 HandlerNode *nextNode;
1739 nextNode = getHandlerChain(ei)->first;
1740 if (nextNode != NULL((void*)0)) {
1741 tty_message("\nHandlers for %s(%d)", eventIndex2EventName(ei), ei);
1742 while (nextNode != NULL((void*)0)) {
1743 HandlerNode *node = nextNode;
1744 nextNode = NEXT(node)((&(((EventHandlerRestricted_HandlerNode*)(void*)(node))->
private_ehpd))->private_next)
;
1745
1746 if (node->permanent && !dumpPermanent) {
1747 continue; // ignore permanent handlers
1748 }
1749
1750 tty_message("node(%p) handlerID(%d) suspendPolicy(%d) permanent(%d)",
1751 node, node->handlerID, node->suspendPolicy, node->permanent);
1752 eventFilter_dumpHandlerFilters(node);
1753 }
1754 }
1755}
1756
1757void
1758eventHandler_dumpHandler(HandlerNode *node)
1759{
1760 tty_message("Handler for %s(%d)\n", eventIndex2EventName(node->ei), node->ei);
1761 eventFilter_dumpHandlerFilters(node);
1762}
1763
1764#endif /* DEBUG */