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