Bug Summary

File:jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c
Warning:line 1135, column 11
Null pointer passed to 1st parameter expecting 'nonnull'

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 eventHelper.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/eventHelper.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#include "util.h"
27#include "outStream.h"
28#include "eventHandler.h"
29#include "threadControl.h"
30#include "invoker.h"
31#include "signature.h"
32
33
34#define COMMAND_LOOP_THREAD_NAME"JDWP Event Helper Thread" "JDWP Event Helper Thread"
35
36/*
37 * Event helper thread command commandKinds
38 */
39#define COMMAND_REPORT_EVENT_COMPOSITE1 1
40#define COMMAND_REPORT_INVOKE_DONE2 2
41#define COMMAND_REPORT_VM_INIT3 3
42#define COMMAND_SUSPEND_THREAD4 4
43
44/*
45 * Event helper thread command singleKinds
46 */
47#define COMMAND_SINGLE_EVENT11 11
48#define COMMAND_SINGLE_UNLOAD12 12
49#define COMMAND_SINGLE_FRAME_EVENT13 13
50
51typedef struct EventCommandSingle {
52 jbyte suspendPolicy; /* NOTE: Must be the first field */
53 jint id;
54 EventInfo info;
55} EventCommandSingle;
56
57typedef struct UnloadCommandSingle {
58 char *classSignature;
59 jint id;
60} UnloadCommandSingle;
61
62typedef struct FrameEventCommandSingle {
63 jbyte suspendPolicy; /* NOTE: Must be the first field */
64 jint id;
65 EventIndex ei;
66 jthread thread;
67 jclass clazz;
68 jmethodID method;
69 jlocation location;
70 char typeKey; /* Not used for method entry events */
71 /* If typeKey is 0, then no return value is needed */
72 jvalue returnValue; /* Not used for method entry events */
73} FrameEventCommandSingle;
74
75typedef struct CommandSingle {
76 jint singleKind;
77 union {
78 EventCommandSingle eventCommand;
79 UnloadCommandSingle unloadCommand;
80 FrameEventCommandSingle frameEventCommand;
81 } u;
82} CommandSingle;
83
84typedef struct ReportInvokeDoneCommand {
85 jthread thread;
86} ReportInvokeDoneCommand;
87
88typedef struct ReportVMInitCommand {
89 jbyte suspendPolicy; /* NOTE: Must be the first field */
90 jthread thread;
91} ReportVMInitCommand;
92
93typedef struct SuspendThreadCommand {
94 jthread thread;
95} SuspendThreadCommand;
96
97typedef struct ReportEventCompositeCommand {
98 jbyte suspendPolicy; /* NOTE: Must be the first field */
99 jint eventCount;
100 CommandSingle singleCommand[1]; /* variable length */
101} ReportEventCompositeCommand;
102
103typedef struct HelperCommand {
104 jint commandKind;
105 jboolean done;
106 jboolean waiting;
107 jbyte sessionID;
108 struct HelperCommand *next;
109 union {
110 /* NOTE: Each of the structs below must have the same first field */
111 ReportEventCompositeCommand reportEventComposite;
112 ReportInvokeDoneCommand reportInvokeDone;
113 ReportVMInitCommand reportVMInit;
114 SuspendThreadCommand suspendThread;
115 } u;
116 /* composite array expand out, put nothing after */
117} HelperCommand;
118
119typedef struct {
120 HelperCommand *head;
121 HelperCommand *tail;
122} CommandQueue;
123
124static CommandQueue commandQueue;
125static jrawMonitorID commandQueueLock;
126static jrawMonitorID commandCompleteLock;
127static jrawMonitorID blockCommandLoopLock;
128static jrawMonitorID vmDeathLock;
129static volatile jboolean commandLoopEnteredVmDeathLock = JNI_FALSE0;
130
131static jint maxQueueSize = 50 * 1024; /* TO DO: Make this configurable */
132static jboolean holdEvents;
133static jint currentQueueSize = 0;
134static jint currentSessionID;
135
136static void saveEventInfoRefs(JNIEnv *env, EventInfo *evinfo);
137static void tossEventInfoRefs(JNIEnv *env, EventInfo *evinfo);
138
139static jint
140commandSize(HelperCommand *command)
141{
142 jint size = sizeof(HelperCommand);
143 if (command->commandKind == COMMAND_REPORT_EVENT_COMPOSITE1) {
144 /*
145 * One event is accounted for in the Helper Command. If there are
146 * more, add to size here.
147 */
148 /*LINTED*/
149 size += ((int)sizeof(CommandSingle) *
150 (command->u.reportEventComposite.eventCount - 1));
151 }
152 return size;
153}
154
155static void
156freeCommand(HelperCommand *command)
157{
158 if ( command == NULL((void*)0) )
159 return;
160 jvmtiDeallocate(command);
161}
162
163static void
164enqueueCommand(HelperCommand *command,
165 jboolean wait, jboolean reportingVMDeath)
166{
167 static jboolean vmDeathReported = JNI_FALSE0;
168 CommandQueue *queue = &commandQueue;
169 jint size = commandSize(command);
170
171 command->done = JNI_FALSE0;
172 command->waiting = wait;
173 command->next = NULL((void*)0);
174
175 debugMonitorEnter(commandQueueLock);
176 while (size + currentQueueSize > maxQueueSize) {
177 debugMonitorWait(commandQueueLock);
178 }
179 log_debugee_location("enqueueCommand(): HelperCommand being processed", NULL((void*)0), NULL((void*)0), 0);
180 if (vmDeathReported) {
181 /* send no more events after VMDeath and don't wait */
182 wait = JNI_FALSE0;
183 } else {
184 currentQueueSize += size;
185
186 if (queue->head == NULL((void*)0)) {
187 queue->head = command;
188 } else {
189 queue->tail->next = command;
190 }
191 queue->tail = command;
192
193 if (reportingVMDeath) {
194 vmDeathReported = JNI_TRUE1;
195 }
196 }
197 debugMonitorNotifyAll(commandQueueLock);
198 debugMonitorExit(commandQueueLock);
199
200 if (wait) {
201 debugMonitorEnter(commandCompleteLock);
202 while (!command->done) {
203 log_debugee_location("enqueueCommand(): HelperCommand wait", NULL((void*)0), NULL((void*)0), 0);
204 debugMonitorWait(commandCompleteLock);
205 }
206 freeCommand(command);
207 debugMonitorExit(commandCompleteLock);
208 }
209}
210
211static void
212completeCommand(HelperCommand *command)
213{
214 if (command->waiting) {
215 debugMonitorEnter(commandCompleteLock);
216 command->done = JNI_TRUE1;
217 log_debugee_location("completeCommand(): HelperCommand done waiting", NULL((void*)0), NULL((void*)0), 0);
218 debugMonitorNotifyAll(commandCompleteLock);
219 debugMonitorExit(commandCompleteLock);
220 } else {
221 freeCommand(command);
222 }
223}
224
225static HelperCommand *
226dequeueCommand(void)
227{
228 HelperCommand *command = NULL((void*)0);
229 CommandQueue *queue = &commandQueue;
230 jint size;
231
232 debugMonitorEnter(commandQueueLock);
233
234 while (command == NULL((void*)0)) {
235 while (holdEvents || (queue->head == NULL((void*)0))) {
236 debugMonitorWait(commandQueueLock);
237 }
238
239 JDI_ASSERT(queue->head)do { if (gdata && gdata->assertOn && !(queue
->head)) { jdiAssertionFailed("/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 239, "queue->head"); } } while (0)
;
240 command = queue->head;
241 queue->head = command->next;
242 if (queue->tail == command) {
243 queue->tail = NULL((void*)0);
244 }
245
246 log_debugee_location("dequeueCommand(): command being dequeued", NULL((void*)0), NULL((void*)0), 0);
247
248 size = commandSize(command);
249 /*
250 * Immediately close out any commands enqueued from
251 * a dead VM or a previously attached debugger.
252 */
253 if (gdata->vmDead || command->sessionID != currentSessionID) {
254 log_debugee_location("dequeueCommand(): command session removal", NULL((void*)0), NULL((void*)0), 0);
255 completeCommand(command);
256 command = NULL((void*)0);
257 }
258
259 /*
260 * There's room in the queue for more.
261 */
262 currentQueueSize -= size;
263 debugMonitorNotifyAll(commandQueueLock);
264 }
265
266 debugMonitorExit(commandQueueLock);
267
268 return command;
269}
270
271void eventHelper_holdEvents(void)
272{
273 debugMonitorEnter(commandQueueLock);
274 holdEvents = JNI_TRUE1;
275 debugMonitorNotifyAll(commandQueueLock);
276 debugMonitorExit(commandQueueLock);
277}
278
279void eventHelper_releaseEvents(void)
280{
281 debugMonitorEnter(commandQueueLock);
282 holdEvents = JNI_FALSE0;
283 debugMonitorNotifyAll(commandQueueLock);
284 debugMonitorExit(commandQueueLock);
285}
286
287static void
288writeSingleStepEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
289{
290 (void)outStream_writeObjectRef(env, out, evinfo->thread);
291 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
292}
293
294static void
295writeBreakpointEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
296{
297 (void)outStream_writeObjectRef(env, out, evinfo->thread);
298 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
299}
300
301static void
302writeFieldAccessEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
303{
304 jbyte fieldClassTag;
305
306 fieldClassTag = referenceTypeTag(evinfo->u.field_access.field_clazz);
307
308 (void)outStream_writeObjectRef(env, out, evinfo->thread);
309 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
310 (void)outStream_writeByte(out, fieldClassTag);
311 (void)outStream_writeObjectRef(env, out, evinfo->u.field_access.field_clazz);
312 (void)outStream_writeFieldID(out, evinfo->u.field_access.field);
313 (void)outStream_writeObjectTag(env, out, evinfo->object);
314 (void)outStream_writeObjectRef(env, out, evinfo->object);
315}
316
317static void
318writeFieldModificationEvent(JNIEnv *env, PacketOutputStream *out,
319 EventInfo *evinfo)
320{
321 jbyte fieldClassTag;
322
323 fieldClassTag = referenceTypeTag(evinfo->u.field_modification.field_clazz);
324
325 (void)outStream_writeObjectRef(env, out, evinfo->thread);
326 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
327 (void)outStream_writeByte(out, fieldClassTag);
328 (void)outStream_writeObjectRef(env, out, evinfo->u.field_modification.field_clazz);
329 (void)outStream_writeFieldID(out, evinfo->u.field_modification.field);
330 (void)outStream_writeObjectTag(env, out, evinfo->object);
331 (void)outStream_writeObjectRef(env, out, evinfo->object);
332 (void)outStream_writeValue(env, out, (jbyte)evinfo->u.field_modification.signature_type,
333 evinfo->u.field_modification.new_value);
334}
335
336static void
337writeExceptionEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
338{
339 (void)outStream_writeObjectRef(env, out, evinfo->thread);
340 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
341 (void)outStream_writeObjectTag(env, out, evinfo->object);
342 (void)outStream_writeObjectRef(env, out, evinfo->object);
343 writeCodeLocation(out, evinfo->u.exception.catch_clazz,
344 evinfo->u.exception.catch_method, evinfo->u.exception.catch_location);
345}
346
347static void
348writeThreadEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
349{
350 (void)outStream_writeObjectRef(env, out, evinfo->thread);
351}
352
353static void
354writeMonitorEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
355{
356 jclass klass;
357 (void)outStream_writeObjectRef(env, out, evinfo->thread);
358 (void)outStream_writeObjectTag(env, out, evinfo->object);
359 (void)outStream_writeObjectRef(env, out, evinfo->object);
360 if (evinfo->ei == EI_MONITOR_WAIT || evinfo->ei == EI_MONITOR_WAITED) {
361 /* clazz of evinfo was set to class of monitor object for monitor wait event class filtering.
362 * So get the method class to write location info.
363 * See cbMonitorWait() and cbMonitorWaited() function in eventHandler.c.
364 */
365 klass=getMethodClass(gdata->jvmti, evinfo->method);
366 writeCodeLocation(out, klass, evinfo->method, evinfo->location);
367 if (evinfo->ei == EI_MONITOR_WAIT) {
368 (void)outStream_writeLong(out, evinfo->u.monitor.timeout);
369 } else if (evinfo->ei == EI_MONITOR_WAITED) {
370 (void)outStream_writeBoolean(out, evinfo->u.monitor.timed_out);
371 }
372 /* This runs in a command loop and this thread may not return to java.
373 * So we need to delete the local ref created by jvmti GetMethodDeclaringClass.
374 */
375 JNI_FUNC_PTR(env,DeleteLocalRef)(*((*((((gdata->log_flags & (0x00000002)) ?(log_message_begin
("JNI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,375), log_message_end ("%s()","DeleteLocalRef")):((void)0)),
(env))))->DeleteLocalRef))
(env, klass);
376 } else {
377 writeCodeLocation(out, evinfo->clazz, evinfo->method, evinfo->location);
378 }
379}
380
381static void
382writeClassEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
383{
384 jbyte classTag;
385 jint status;
386 char *signature = NULL((void*)0);
387 jvmtiError error;
388
389 classTag = referenceTypeTag(evinfo->clazz);
390 error = classSignature(evinfo->clazz, &signature, NULL((void*)0));
391 if (error != JVMTI_ERROR_NONE) {
392 EXIT_ERROR(error,"signature"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)error), error, ("signature"==((void
*)0)?"":"signature"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 392); debugInit_exit((jvmtiError)error, "signature"); }
;
393 }
394 status = classStatus(evinfo->clazz);
395
396 (void)outStream_writeObjectRef(env, out, evinfo->thread);
397 (void)outStream_writeByte(out, classTag);
398 (void)outStream_writeObjectRef(env, out, evinfo->clazz);
399 (void)outStream_writeString(out, signature);
400 (void)outStream_writeInt(out, map2jdwpClassStatus(status));
401 jvmtiDeallocate(signature);
402}
403
404static void
405writeVMDeathEvent(JNIEnv *env, PacketOutputStream *out, EventInfo *evinfo)
406{
407}
408
409static void
410handleEventCommandSingle(JNIEnv *env, PacketOutputStream *out,
411 EventCommandSingle *command)
412{
413 EventInfo *evinfo = &command->info;
414
415 (void)outStream_writeByte(out, eventIndex2jdwp(evinfo->ei));
416 (void)outStream_writeInt(out, command->id);
417
418 switch (evinfo->ei) {
419 case EI_SINGLE_STEP:
420 writeSingleStepEvent(env, out, evinfo);
421 break;
422 case EI_BREAKPOINT:
423 writeBreakpointEvent(env, out, evinfo);
424 break;
425 case EI_FIELD_ACCESS:
426 writeFieldAccessEvent(env, out, evinfo);
427 break;
428 case EI_FIELD_MODIFICATION:
429 writeFieldModificationEvent(env, out, evinfo);
430 break;
431 case EI_EXCEPTION:
432 writeExceptionEvent(env, out, evinfo);
433 break;
434 case EI_THREAD_START:
435 case EI_THREAD_END:
436 writeThreadEvent(env, out, evinfo);
437 break;
438 case EI_CLASS_LOAD:
439 case EI_CLASS_PREPARE:
440 writeClassEvent(env, out, evinfo);
441 break;
442 case EI_MONITOR_CONTENDED_ENTER:
443 case EI_MONITOR_CONTENDED_ENTERED:
444 case EI_MONITOR_WAIT:
445 case EI_MONITOR_WAITED:
446 writeMonitorEvent(env, out, evinfo);
447 break;
448 case EI_VM_DEATH:
449 writeVMDeathEvent(env, out, evinfo);
450 break;
451 default:
452 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"unknown event index"){ 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)), ("unknown event index"
==((void*)0)?"":"unknown event index"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 452); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+24)), "unknown event index"); }
;
453 break;
454 }
455 tossEventInfoRefs(env, evinfo);
456}
457
458static void
459handleUnloadCommandSingle(JNIEnv* env, PacketOutputStream *out,
460 UnloadCommandSingle *command)
461{
462 (void)outStream_writeByte(out, JDWP_EVENT(CLASS_UNLOAD)9);
463 (void)outStream_writeInt(out, command->id);
464 (void)outStream_writeString(out, command->classSignature);
465 jvmtiDeallocate(command->classSignature);
466 command->classSignature = NULL((void*)0);
467}
468
469static void
470handleFrameEventCommandSingle(JNIEnv* env, PacketOutputStream *out,
471 FrameEventCommandSingle *command)
472{
473 if (command->typeKey) {
474 (void)outStream_writeByte(out, JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE)42);
475 } else {
476 (void)outStream_writeByte(out, eventIndex2jdwp(command->ei));
477 }
478 (void)outStream_writeInt(out, command->id);
479 (void)outStream_writeObjectRef(env, out, command->thread);
480 writeCodeLocation(out, command->clazz, command->method, command->location);
481 if (command->typeKey) {
482 (void)outStream_writeValue(env, out, command->typeKey, command->returnValue);
483 if (isReferenceTag(command->typeKey) &&
484 command->returnValue.l != NULL((void*)0)) {
485 tossGlobalRef(env, &(command->returnValue.l));
486 }
487 }
488 tossGlobalRef(env, &(command->thread));
489 tossGlobalRef(env, &(command->clazz));
490}
491
492static void
493suspendWithInvokeEnabled(jbyte policy, jthread thread)
494{
495 invoker_enableInvokeRequests(thread);
496
497 if (policy == JDWP_SUSPEND_POLICY(ALL)2) {
498 (void)threadControl_suspendAll();
499 } else {
500 (void)threadControl_suspendThread(thread, JNI_FALSE0);
501 }
502}
503
504static void
505handleReportEventCompositeCommand(JNIEnv *env,
506 ReportEventCompositeCommand *recc)
507{
508 PacketOutputStream out;
509 jint count = recc->eventCount;
510 jint i;
511
512 if (recc->suspendPolicy != JDWP_SUSPEND_POLICY(NONE)0) {
513 /* must determine thread to interrupt before writing */
514 /* since writing destroys it */
515 jthread thread = NULL((void*)0);
516 for (i = 0; i < count; i++) {
517 CommandSingle *single = &(recc->singleCommand[i]);
518 switch (single->singleKind) {
519 case COMMAND_SINGLE_EVENT11:
520 thread = single->u.eventCommand.info.thread;
521 break;
522 case COMMAND_SINGLE_FRAME_EVENT13:
523 thread = single->u.frameEventCommand.thread;
524 break;
525 }
526 if (thread != NULL((void*)0)) {
527 break;
528 }
529 }
530
531 if (thread == NULL((void*)0)) {
532 (void)threadControl_suspendAll();
533 } else {
534 suspendWithInvokeEnabled(recc->suspendPolicy, thread);
535 }
536 }
537
538 outStream_initCommand(&out, uniqueID(), 0x0,
539 JDWP_COMMAND_SET(Event)64,
540 JDWP_COMMAND(Event, Composite)100);
541 (void)outStream_writeByte(&out, recc->suspendPolicy);
542 (void)outStream_writeInt(&out, count);
543
544 for (i = 0; i < count; i++) {
545 CommandSingle *single = &(recc->singleCommand[i]);
546 switch (single->singleKind) {
547 case COMMAND_SINGLE_EVENT11:
548 handleEventCommandSingle(env, &out,
549 &single->u.eventCommand);
550 break;
551 case COMMAND_SINGLE_UNLOAD12:
552 handleUnloadCommandSingle(env, &out,
553 &single->u.unloadCommand);
554 break;
555 case COMMAND_SINGLE_FRAME_EVENT13:
556 handleFrameEventCommandSingle(env, &out,
557 &single->u.frameEventCommand);
558 break;
559 }
560 }
561
562 outStream_sendCommand(&out);
563 outStream_destroy(&out);
564}
565
566static void
567handleReportInvokeDoneCommand(JNIEnv* env, ReportInvokeDoneCommand *command)
568{
569 invoker_completeInvokeRequest(command->thread);
570 tossGlobalRef(env, &(command->thread));
571}
572
573static void
574handleReportVMInitCommand(JNIEnv* env, ReportVMInitCommand *command)
575{
576 PacketOutputStream out;
577
578 if (command->suspendPolicy == JDWP_SUSPEND_POLICY(ALL)2) {
579 (void)threadControl_suspendAll();
580 } else if (command->suspendPolicy == JDWP_SUSPEND_POLICY(EVENT_THREAD)1) {
581 (void)threadControl_suspendThread(command->thread, JNI_FALSE0);
582 }
583
584 outStream_initCommand(&out, uniqueID(), 0x0,
585 JDWP_COMMAND_SET(Event)64,
586 JDWP_COMMAND(Event, Composite)100);
587 (void)outStream_writeByte(&out, command->suspendPolicy);
588 (void)outStream_writeInt(&out, 1); /* Always one component */
589 (void)outStream_writeByte(&out, JDWP_EVENT(VM_INIT)90);
590 (void)outStream_writeInt(&out, 0); /* Not in response to an event req. */
591
592 (void)outStream_writeObjectRef(env, &out, command->thread);
593
594 outStream_sendCommand(&out);
595 outStream_destroy(&out);
596 /* Why aren't we tossing this: tossGlobalRef(env, &(command->thread)); */
597}
598
599static void
600handleSuspendThreadCommand(JNIEnv* env, SuspendThreadCommand *command)
601{
602 /*
603 * For the moment, there's nothing that can be done with the
604 * return code, so we don't check it here.
605 */
606 (void)threadControl_suspendThread(command->thread, JNI_TRUE1);
607 tossGlobalRef(env, &(command->thread));
608}
609
610static void
611handleCommand(JNIEnv *env, HelperCommand *command)
612{
613 switch (command->commandKind) {
614 case COMMAND_REPORT_EVENT_COMPOSITE1:
615 handleReportEventCompositeCommand(env,
616 &command->u.reportEventComposite);
617 break;
618 case COMMAND_REPORT_INVOKE_DONE2:
619 handleReportInvokeDoneCommand(env, &command->u.reportInvokeDone);
620 break;
621 case COMMAND_REPORT_VM_INIT3:
622 handleReportVMInitCommand(env, &command->u.reportVMInit);
623 break;
624 case COMMAND_SUSPEND_THREAD4:
625 handleSuspendThreadCommand(env, &command->u.suspendThread);
626 break;
627 default:
628 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"Event Helper Command"){ 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)), ("Event Helper Command"
==((void*)0)?"":"Event Helper Command"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 628); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+24)), "Event Helper Command"); }
;
629 break;
630 }
631}
632
633/*
634 * There was an assumption that only one event with a suspend-all
635 * policy could be processed by commandLoop() at one time. It was
636 * assumed that native thread suspension from the first suspend-all
637 * event would prevent the second suspend-all event from making it
638 * into the command queue. For the Classic VM, this was a reasonable
639 * assumption. However, in HotSpot all thread suspension requires a
640 * VM operation and VM operations take time.
641 *
642 * The solution is to add a mechanism to prevent commandLoop() from
643 * processing more than one event with a suspend-all policy. This is
644 * accomplished by forcing commandLoop() to wait for either
645 * ThreadReferenceImpl.c: resume() or VirtualMachineImpl.c: resume()
646 * when an event with a suspend-all policy has been completed.
647 */
648static jboolean blockCommandLoop = JNI_FALSE0;
649
650/*
651 * We wait for either ThreadReferenceImpl.c: resume() or
652 * VirtualMachineImpl.c: resume() to be called.
653 */
654static void
655doBlockCommandLoop(void) {
656 debugMonitorEnter(blockCommandLoopLock);
657 while (blockCommandLoop == JNI_TRUE1) {
658 debugMonitorWait(blockCommandLoopLock);
659 }
660 debugMonitorExit(blockCommandLoopLock);
661}
662
663/*
664 * If the command that we are about to execute has a suspend-all
665 * policy, then prepare for either ThreadReferenceImpl.c: resume()
666 * or VirtualMachineImpl.c: resume() to be called.
667 */
668static jboolean
669needBlockCommandLoop(HelperCommand *cmd) {
670 if (cmd->commandKind == COMMAND_REPORT_EVENT_COMPOSITE1
671 && cmd->u.reportEventComposite.suspendPolicy == JDWP_SUSPEND_POLICY(ALL)2) {
672 debugMonitorEnter(blockCommandLoopLock);
673 blockCommandLoop = JNI_TRUE1;
674 debugMonitorExit(blockCommandLoopLock);
675
676 return JNI_TRUE1;
677 }
678
679 return JNI_FALSE0;
680}
681
682/*
683 * Used by either ThreadReferenceImpl.c: resume() or
684 * VirtualMachineImpl.c: resume() to resume commandLoop().
685 */
686void
687unblockCommandLoop(void) {
688 debugMonitorEnter(blockCommandLoopLock);
689 blockCommandLoop = JNI_FALSE0;
690 debugMonitorNotifyAll(blockCommandLoopLock);
691 debugMonitorExit(blockCommandLoopLock);
692}
693
694/*
695 * The event helper thread. Dequeues commands and processes them.
696 */
697static void JNICALL
698commandLoop(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg)
699{
700 LOG_MISC(("Begin command loop thread"))((gdata->log_flags & (0x00000008)) ?(log_message_begin
("MISC","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,700), log_message_end ("Begin command loop thread")):((void)
0))
;
701
702 while (JNI_TRUE1) {
703 HelperCommand *command = dequeueCommand();
704 if (command != NULL((void*)0)) {
705 /*
706 * Setup for a potential doBlockCommand() call before calling
707 * handleCommand() to prevent any races.
708 */
709 jboolean doBlock = needBlockCommandLoop(command);
710 debugMonitorEnter(vmDeathLock);
711 commandLoopEnteredVmDeathLock = JNI_TRUE1;
712 if (!gdata->vmDead) {
713 log_debugee_location("commandLoop(): command being handled", NULL((void*)0), NULL((void*)0), 0);
714 handleCommand(jni_env, command);
715 }
716 completeCommand(command);
717 debugMonitorExit(vmDeathLock);
718 commandLoopEnteredVmDeathLock = JNI_FALSE0;
719 /* if we just finished a suspend-all cmd, then we block here */
720 if (doBlock) {
721 doBlockCommandLoop();
722 }
723 }
724 }
725 /* This loop never ends, even as connections come and go with server=y */
726}
727
728void
729eventHelper_initialize(jbyte sessionID)
730{
731 jvmtiStartFunction func;
732
733 currentSessionID = sessionID;
734 holdEvents = JNI_FALSE0;
735 commandQueue.head = NULL((void*)0);
736 commandQueue.tail = NULL((void*)0);
737
738 commandQueueLock = debugMonitorCreate("JDWP Event Helper Queue Monitor");
739 commandCompleteLock = debugMonitorCreate("JDWP Event Helper Completion Monitor");
740 blockCommandLoopLock = debugMonitorCreate("JDWP Event Block CommandLoop Monitor");
741 vmDeathLock = debugMonitorCreate("JDWP VM_DEATH CommandLoop Monitor");
742
743 /* Start the event handler thread */
744 func = &commandLoop;
745 (void)spawnNewThread(func, NULL((void*)0), COMMAND_LOOP_THREAD_NAME"JDWP Event Helper Thread");
746}
747
748void
749eventHelper_reset(jbyte newSessionID)
750{
751 debugMonitorEnter(commandQueueLock);
752 currentSessionID = newSessionID;
753 holdEvents = JNI_FALSE0;
754 debugMonitorNotifyAll(commandQueueLock);
755 debugMonitorExit(commandQueueLock);
756 unblockCommandLoop();
757}
758
759/*
760 * Provide a means for threadControl to ensure that crucial locks are not
761 * held by suspended threads.
762 */
763void
764eventHelper_lock(void)
765{
766 debugMonitorEnter(commandQueueLock);
767 debugMonitorEnter(commandCompleteLock);
768}
769
770void
771eventHelper_unlock(void)
772{
773 debugMonitorExit(commandCompleteLock);
774 debugMonitorExit(commandQueueLock);
775}
776
777void commandLoop_exitVmDeathLockOnError()
778{
779 const char* MSG_BASE = "exitVmDeathLockOnError: error in JVMTI %s: %d\n";
780 jthread cur_thread = NULL((void*)0);
781 jvmtiThreadInfo thread_info;
782 jvmtiError err = JVMTI_ERROR_NONE;
783
784 err = JVMTI_FUNC_PTR(gdata->jvmti, GetCurrentThread)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,784), log_message_end ("%s()","GetCurrentThread")):((void)0)
),(gdata->jvmti))))->GetCurrentThread))
785 (gdata->jvmti, &cur_thread);
786 if (err != JVMTI_ERROR_NONE) {
787 LOG_ERROR((MSG_BASE, "GetCurrentThread", err))((gdata->log_flags & (0x00000080))?(log_message_begin(
"ERROR","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,787), log_message_end (MSG_BASE, "GetCurrentThread", err)):(
(void)0))
;
788 return;
789 }
790
791 err = JVMTI_FUNC_PTR(gdata->jvmti, GetThreadInfo)(*((*((((gdata->log_flags & (0x00000004))?(log_message_begin
("JVMTI","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,791), log_message_end ("%s()","GetThreadInfo")):((void)0)),(
gdata->jvmti))))->GetThreadInfo))
792 (gdata->jvmti, cur_thread, &thread_info);
793 if (err != JVMTI_ERROR_NONE) {
794 LOG_ERROR((MSG_BASE, "GetThreadInfo", err))((gdata->log_flags & (0x00000080))?(log_message_begin(
"ERROR","/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
,794), log_message_end (MSG_BASE, "GetThreadInfo", err)):((void
)0))
;
795 return;
796 }
797 if (strcmp(thread_info.name, COMMAND_LOOP_THREAD_NAME"JDWP Event Helper Thread") != 0) {
798 return;
799 }
800 if (commandLoopEnteredVmDeathLock == JNI_TRUE1) {
801 debugMonitorExit(vmDeathLock);
802 commandLoopEnteredVmDeathLock = JNI_FALSE0;
803 }
804}
805
806void
807commandLoop_sync(void)
808{
809 debugMonitorEnter(vmDeathLock);
810 debugMonitorExit(vmDeathLock);
811}
812
813/* Change all references to global in the EventInfo struct */
814static void
815saveEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
816{
817 jthread *pthread;
818 jclass *pclazz;
819 jobject *pobject;
820 jthread thread;
821 jclass clazz;
822 jobject object;
823 char sig;
824
825 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/eventHelper.c"
,825), log_message_end ("%s()","ExceptionClear")):((void)0)),
(env))))->ExceptionClear))
(env);
826
827 if ( evinfo->thread != NULL((void*)0) ) {
828 pthread = &(evinfo->thread);
829 thread = *pthread;
830 *pthread = NULL((void*)0);
831 saveGlobalRef(env, thread, pthread);
832 }
833 if ( evinfo->clazz != NULL((void*)0) ) {
834 pclazz = &(evinfo->clazz);
835 clazz = *pclazz;
836 *pclazz = NULL((void*)0);
837 saveGlobalRef(env, clazz, pclazz);
838 }
839 if ( evinfo->object != NULL((void*)0) ) {
840 pobject = &(evinfo->object);
841 object = *pobject;
842 *pobject = NULL((void*)0);
843 saveGlobalRef(env, object, pobject);
844 }
845
846 switch (evinfo->ei) {
847 case EI_FIELD_MODIFICATION:
848 if ( evinfo->u.field_modification.field_clazz != NULL((void*)0) ) {
849 pclazz = &(evinfo->u.field_modification.field_clazz);
850 clazz = *pclazz;
851 *pclazz = NULL((void*)0);
852 saveGlobalRef(env, clazz, pclazz);
853 }
854 sig = evinfo->u.field_modification.signature_type;
855 if (isReferenceTag(sig)) {
856 if ( evinfo->u.field_modification.new_value.l != NULL((void*)0) ) {
857 pobject = &(evinfo->u.field_modification.new_value.l);
858 object = *pobject;
859 *pobject = NULL((void*)0);
860 saveGlobalRef(env, object, pobject);
861 }
862 }
863 break;
864 case EI_FIELD_ACCESS:
865 if ( evinfo->u.field_access.field_clazz != NULL((void*)0) ) {
866 pclazz = &(evinfo->u.field_access.field_clazz);
867 clazz = *pclazz;
868 *pclazz = NULL((void*)0);
869 saveGlobalRef(env, clazz, pclazz);
870 }
871 break;
872 case EI_EXCEPTION:
873 if ( evinfo->u.exception.catch_clazz != NULL((void*)0) ) {
874 pclazz = &(evinfo->u.exception.catch_clazz);
875 clazz = *pclazz;
876 *pclazz = NULL((void*)0);
877 saveGlobalRef(env, clazz, pclazz);
878 }
879 break;
880 default:
881 break;
882 }
883
884 if (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/eventHelper.c"
,884), log_message_end ("%s()","ExceptionOccurred")):((void)0
)), (env))))->ExceptionOccurred))
(env)) {
885 EXIT_ERROR(AGENT_ERROR_INVALID_EVENT_TYPE,"ExceptionOccurred"){ 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)), ("ExceptionOccurred"
==((void*)0)?"":"ExceptionOccurred"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 885); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+24)), "ExceptionOccurred"); }
;
886 }
887}
888
889static void
890tossEventInfoRefs(JNIEnv *env, EventInfo *evinfo)
891{
892 char sig;
893 if ( evinfo->thread != NULL((void*)0) ) {
894 tossGlobalRef(env, &(evinfo->thread));
895 }
896 if ( evinfo->clazz != NULL((void*)0) ) {
897 tossGlobalRef(env, &(evinfo->clazz));
898 }
899 if ( evinfo->object != NULL((void*)0) ) {
900 tossGlobalRef(env, &(evinfo->object));
901 }
902 switch (evinfo->ei) {
903 case EI_FIELD_MODIFICATION:
904 if ( evinfo->u.field_modification.field_clazz != NULL((void*)0) ) {
905 tossGlobalRef(env, &(evinfo->u.field_modification.field_clazz));
906 }
907 sig = evinfo->u.field_modification.signature_type;
908 if (isReferenceTag(sig)) {
909 if ( evinfo->u.field_modification.new_value.l != NULL((void*)0) ) {
910 tossGlobalRef(env, &(evinfo->u.field_modification.new_value.l));
911 }
912 }
913 break;
914 case EI_FIELD_ACCESS:
915 if ( evinfo->u.field_access.field_clazz != NULL((void*)0) ) {
916 tossGlobalRef(env, &(evinfo->u.field_access.field_clazz));
917 }
918 break;
919 case EI_EXCEPTION:
920 if ( evinfo->u.exception.catch_clazz != NULL((void*)0) ) {
921 tossGlobalRef(env, &(evinfo->u.exception.catch_clazz));
922 }
923 break;
924 default:
925 break;
926 }
927}
928
929struct bag *
930eventHelper_createEventBag(void)
931{
932 return bagCreateBag(sizeof(CommandSingle), 5 /* events */ );
933}
934
935/* Return the combined suspend policy for the event set
936 */
937static jboolean
938enumForCombinedSuspendPolicy(void *cv, void *arg)
939{
940 CommandSingle *command = cv;
941 jbyte thisPolicy;
942 jbyte *policy = arg;
943
944 switch(command->singleKind) {
945 case COMMAND_SINGLE_EVENT11:
946 thisPolicy = command->u.eventCommand.suspendPolicy;
947 break;
948 case COMMAND_SINGLE_FRAME_EVENT13:
949 thisPolicy = command->u.frameEventCommand.suspendPolicy;
950 break;
951 default:
952 thisPolicy = JDWP_SUSPEND_POLICY(NONE)0;
953 }
954 /* Expand running policy value if this policy demands it */
955 if (*policy == JDWP_SUSPEND_POLICY(NONE)0) {
956 *policy = thisPolicy;
957 } else if (*policy == JDWP_SUSPEND_POLICY(EVENT_THREAD)1) {
958 *policy = (thisPolicy == JDWP_SUSPEND_POLICY(ALL)2)?
959 thisPolicy : *policy;
960 }
961
962 /* Short circuit if we reached maximal suspend policy */
963 if (*policy == JDWP_SUSPEND_POLICY(ALL)2) {
964 return JNI_FALSE0;
965 } else {
966 return JNI_TRUE1;
967 }
968}
969
970/* Determine whether we are reporting VM death
971 */
972static jboolean
973enumForVMDeath(void *cv, void *arg)
974{
975 CommandSingle *command = cv;
976 jboolean *reportingVMDeath = arg;
977
978 if (command->singleKind == COMMAND_SINGLE_EVENT11) {
979 if (command->u.eventCommand.info.ei == EI_VM_DEATH) {
980 *reportingVMDeath = JNI_TRUE1;
981 return JNI_FALSE0;
982 }
983 }
984 return JNI_TRUE1;
985}
986
987struct singleTracker {
988 ReportEventCompositeCommand *recc;
989 int index;
990};
991
992static jboolean
993enumForCopyingSingles(void *command, void *tv)
994{
995 struct singleTracker *tracker = (struct singleTracker *)tv;
996 (void)memcpy(&tracker->recc->singleCommand[tracker->index++],
997 command,
998 sizeof(CommandSingle));
999 return JNI_TRUE1;
1000}
1001
1002jbyte
1003eventHelper_reportEvents(jbyte sessionID, struct bag *eventBag)
1004{
1005 int size = bagSize(eventBag);
1006 jbyte suspendPolicy = JDWP_SUSPEND_POLICY(NONE)0;
1007 jboolean reportingVMDeath = JNI_FALSE0;
1008 jboolean wait;
1009 int command_size;
1010
1011 HelperCommand *command;
1012 ReportEventCompositeCommand *recc;
1013 struct singleTracker tracker;
1014
1015 if (size == 0) {
1016 return suspendPolicy;
1017 }
1018 (void)bagEnumerateOver(eventBag, enumForCombinedSuspendPolicy, &suspendPolicy);
1019 (void)bagEnumerateOver(eventBag, enumForVMDeath, &reportingVMDeath);
1020
1021 /*LINTED*/
1022 command_size = (int)(sizeof(HelperCommand) +
1023 sizeof(CommandSingle)*(size-1));
1024 command = jvmtiAllocate(command_size);
1025 (void)memset(command, 0, command_size);
1026 command->commandKind = COMMAND_REPORT_EVENT_COMPOSITE1;
1027 command->sessionID = sessionID;
1028 recc = &command->u.reportEventComposite;
1029 recc->suspendPolicy = suspendPolicy;
1030 recc->eventCount = size;
1031 tracker.recc = recc;
1032 tracker.index = 0;
1033 (void)bagEnumerateOver(eventBag, enumForCopyingSingles, &tracker);
1034
1035 /*
1036 * We must wait if this thread (the event thread) is to be
1037 * suspended or if the VM is about to die. (Waiting in the latter
1038 * case ensures that we get the event out before the process dies.)
1039 */
1040 wait = (jboolean)((suspendPolicy != JDWP_SUSPEND_POLICY(NONE)0) ||
1041 reportingVMDeath);
1042 enqueueCommand(command, wait, reportingVMDeath);
1043 return suspendPolicy;
1044}
1045
1046void
1047eventHelper_recordEvent(EventInfo *evinfo, jint id, jbyte suspendPolicy,
1048 struct bag *eventBag)
1049{
1050 JNIEnv *env = getEnv();
1051 CommandSingle *command = bagAdd(eventBag);
1052 if (command == NULL((void*)0)) {
1053 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"bagAdd(eventBag)"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("bagAdd(eventBag)"
==((void*)0)?"":"bagAdd(eventBag)"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1053); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "bagAdd(eventBag)"); }
;
1054 }
1055
1056 command->singleKind = COMMAND_SINGLE_EVENT11;
1057 command->u.eventCommand.suspendPolicy = suspendPolicy;
1058 command->u.eventCommand.id = id;
1059
1060 /*
1061 * Copy the event into the command so that it can be used
1062 * asynchronously by the event helper thread.
1063 */
1064 (void)memcpy(&command->u.eventCommand.info, evinfo, sizeof(*evinfo));
1065 saveEventInfoRefs(env, &command->u.eventCommand.info);
1066}
1067
1068void
1069eventHelper_recordClassUnload(jint id, char *signature, struct bag *eventBag)
1070{
1071 CommandSingle *command = bagAdd(eventBag);
1072 if (command == NULL((void*)0)) {
1073 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"bagAdd(eventBag)"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("bagAdd(eventBag)"
==((void*)0)?"":"bagAdd(eventBag)"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1073); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "bagAdd(eventBag)"); }
;
1074 }
1075 command->singleKind = COMMAND_SINGLE_UNLOAD12;
1076 command->u.unloadCommand.id = id;
1077 command->u.unloadCommand.classSignature = signature;
1078}
1079
1080void
1081eventHelper_recordFrameEvent(jint id, jbyte suspendPolicy, EventIndex ei,
1082 jthread thread, jclass clazz,
1083 jmethodID method, jlocation location,
1084 int needReturnValue,
1085 jvalue returnValue,
1086 struct bag *eventBag)
1087{
1088 JNIEnv *env = getEnv();
1089 FrameEventCommandSingle *frameCommand;
1090 CommandSingle *command = bagAdd(eventBag);
1091 jvmtiError err = JVMTI_ERROR_NONE;
1092 if (command == NULL((void*)0)) {
1093 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"bagAdd(eventBag)"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("bagAdd(eventBag)"
==((void*)0)?"":"bagAdd(eventBag)"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1093); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "bagAdd(eventBag)"); }
;
1094 }
1095
1096 command->singleKind = COMMAND_SINGLE_FRAME_EVENT13;
1097 frameCommand = &command->u.frameEventCommand;
1098 frameCommand->suspendPolicy = suspendPolicy;
1099 frameCommand->id = id;
1100 frameCommand->ei = ei;
1101 saveGlobalRef(env, thread, &(frameCommand->thread));
1102 saveGlobalRef(env, clazz, &(frameCommand->clazz));
1103 frameCommand->method = method;
1104 frameCommand->location = location;
1105 if (needReturnValue) {
1106 err = methodReturnType(method, &frameCommand->typeKey);
1107 JDI_ASSERT(err == JVMTI_ERROR_NONE)do { if (gdata && gdata->assertOn && !(err
== JVMTI_ERROR_NONE)) { jdiAssertionFailed("/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1107, "err == JVMTI_ERROR_NONE"); } } while (0)
;
1108
1109 /*
1110 * V or B C D F I J S Z L <classname> ; [ ComponentType
1111 */
1112 if (isReferenceTag(frameCommand->typeKey) &&
1113 returnValue.l != NULL((void*)0)) {
1114 saveGlobalRef(env, returnValue.l, &(frameCommand->returnValue.l));
1115 } else {
1116 frameCommand->returnValue = returnValue;
1117 }
1118 } else {
1119 /* This is not a JDWP METHOD_EXIT_WITH_RETURN_VALUE request,
1120 * so signal this by setting typeKey = 0 which is not
1121 * a legal typekey.
1122 */
1123 frameCommand->typeKey = 0;
1124 }
1125}
1126
1127void
1128eventHelper_reportInvokeDone(jbyte sessionID, jthread thread)
1129{
1130 JNIEnv *env = getEnv();
1131 HelperCommand *command = jvmtiAllocate(sizeof(*command));
1
'command' initialized here
1132 if (command == NULL((void*)0)) {
2
Assuming 'command' is equal to NULL
3
Taking true branch
1133 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommand"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("HelperCommand"
==((void*)0)?"":"HelperCommand"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1133); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "HelperCommand"); }
;
4
'?' condition is false
1134 }
1135 (void)memset(command, 0, sizeof(*command));
5
Null pointer passed to 1st parameter expecting 'nonnull'
1136 command->commandKind = COMMAND_REPORT_INVOKE_DONE2;
1137 command->sessionID = sessionID;
1138 saveGlobalRef(env, thread, &(command->u.reportInvokeDone.thread));
1139 enqueueCommand(command, JNI_TRUE1, JNI_FALSE0);
1140}
1141
1142/*
1143 * This, currently, cannot go through the normal event handling code
1144 * because the JVMTI event does not contain a thread.
1145 */
1146void
1147eventHelper_reportVMInit(JNIEnv *env, jbyte sessionID, jthread thread, jbyte suspendPolicy)
1148{
1149 HelperCommand *command = jvmtiAllocate(sizeof(*command));
1150 if (command == NULL((void*)0)) {
1151 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommmand"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("HelperCommmand"
==((void*)0)?"":"HelperCommmand"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1151); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "HelperCommmand"); }
;
1152 }
1153 (void)memset(command, 0, sizeof(*command));
1154 command->commandKind = COMMAND_REPORT_VM_INIT3;
1155 command->sessionID = sessionID;
1156 saveGlobalRef(env, thread, &(command->u.reportVMInit.thread));
1157 command->u.reportVMInit.suspendPolicy = suspendPolicy;
1158 enqueueCommand(command, JNI_TRUE1, JNI_FALSE0);
1159}
1160
1161void
1162eventHelper_suspendThread(jbyte sessionID, jthread thread)
1163{
1164 JNIEnv *env = getEnv();
1165 HelperCommand *command = jvmtiAllocate(sizeof(*command));
1166 if (command == NULL((void*)0)) {
1167 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"HelperCommmand"){ print_message(stderr, "JDWP exit error ", "\n", "%s(%d): %s [%s:%d]"
, jvmtiErrorText((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX+64
+8))), ((jvmtiError)(JVMTI_ERROR_MAX+64+8)), ("HelperCommmand"
==((void*)0)?"":"HelperCommmand"), "/home/daniel/Projects/java/jdk/src/jdk.jdwp.agent/share/native/libjdwp/eventHelper.c"
, 1167); debugInit_exit((jvmtiError)((jvmtiError)(JVMTI_ERROR_MAX
+64+8)), "HelperCommmand"); }
;
1168 }
1169 (void)memset(command, 0, sizeof(*command));
1170 command->commandKind = COMMAND_SUSPEND_THREAD4;
1171 command->sessionID = sessionID;
1172 saveGlobalRef(env, thread, &(command->u.suspendThread.thread));
1173 enqueueCommand(command, JNI_TRUE1, JNI_FALSE0);
1174}