1*e82f7db8SAndroid Build Coastguard Worker /*
2*e82f7db8SAndroid Build Coastguard Worker * Copyright (c) 1998, 2007, 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 "invoker.h"
28*e82f7db8SAndroid Build Coastguard Worker #include "eventHandler.h"
29*e82f7db8SAndroid Build Coastguard Worker #include "threadControl.h"
30*e82f7db8SAndroid Build Coastguard Worker #include "outStream.h"
31*e82f7db8SAndroid Build Coastguard Worker
32*e82f7db8SAndroid Build Coastguard Worker static jrawMonitorID invokerLock;
33*e82f7db8SAndroid Build Coastguard Worker
34*e82f7db8SAndroid Build Coastguard Worker void
invoker_initialize(void)35*e82f7db8SAndroid Build Coastguard Worker invoker_initialize(void)
36*e82f7db8SAndroid Build Coastguard Worker {
37*e82f7db8SAndroid Build Coastguard Worker invokerLock = debugMonitorCreate("JDWP Invocation Lock");
38*e82f7db8SAndroid Build Coastguard Worker }
39*e82f7db8SAndroid Build Coastguard Worker
40*e82f7db8SAndroid Build Coastguard Worker void
invoker_reset(void)41*e82f7db8SAndroid Build Coastguard Worker invoker_reset(void)
42*e82f7db8SAndroid Build Coastguard Worker {
43*e82f7db8SAndroid Build Coastguard Worker }
44*e82f7db8SAndroid Build Coastguard Worker
invoker_lock(void)45*e82f7db8SAndroid Build Coastguard Worker void invoker_lock(void)
46*e82f7db8SAndroid Build Coastguard Worker {
47*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
48*e82f7db8SAndroid Build Coastguard Worker }
49*e82f7db8SAndroid Build Coastguard Worker
invoker_unlock(void)50*e82f7db8SAndroid Build Coastguard Worker void invoker_unlock(void)
51*e82f7db8SAndroid Build Coastguard Worker {
52*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
53*e82f7db8SAndroid Build Coastguard Worker }
54*e82f7db8SAndroid Build Coastguard Worker
55*e82f7db8SAndroid Build Coastguard Worker static jbyte
returnTypeTag(char * signature)56*e82f7db8SAndroid Build Coastguard Worker returnTypeTag(char *signature)
57*e82f7db8SAndroid Build Coastguard Worker {
58*e82f7db8SAndroid Build Coastguard Worker char *tagPtr = strchr(signature, SIGNATURE_END_ARGS);
59*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(tagPtr);
60*e82f7db8SAndroid Build Coastguard Worker tagPtr++; /* 1st character after the end of args */
61*e82f7db8SAndroid Build Coastguard Worker return (jbyte)*tagPtr;
62*e82f7db8SAndroid Build Coastguard Worker }
63*e82f7db8SAndroid Build Coastguard Worker
64*e82f7db8SAndroid Build Coastguard Worker static jbyte
nextArgumentTypeTag(void ** cursor)65*e82f7db8SAndroid Build Coastguard Worker nextArgumentTypeTag(void **cursor)
66*e82f7db8SAndroid Build Coastguard Worker {
67*e82f7db8SAndroid Build Coastguard Worker char *tagPtr = *cursor;
68*e82f7db8SAndroid Build Coastguard Worker jbyte argumentTag = (jbyte)*tagPtr;
69*e82f7db8SAndroid Build Coastguard Worker
70*e82f7db8SAndroid Build Coastguard Worker if (*tagPtr != SIGNATURE_END_ARGS) {
71*e82f7db8SAndroid Build Coastguard Worker /* Skip any array modifiers */
72*e82f7db8SAndroid Build Coastguard Worker while (*tagPtr == JDWP_TAG(ARRAY)) {
73*e82f7db8SAndroid Build Coastguard Worker tagPtr++;
74*e82f7db8SAndroid Build Coastguard Worker }
75*e82f7db8SAndroid Build Coastguard Worker /* Skip class name */
76*e82f7db8SAndroid Build Coastguard Worker if (*tagPtr == JDWP_TAG(OBJECT)) {
77*e82f7db8SAndroid Build Coastguard Worker tagPtr = strchr(tagPtr, SIGNATURE_END_CLASS) + 1;
78*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(tagPtr);
79*e82f7db8SAndroid Build Coastguard Worker } else {
80*e82f7db8SAndroid Build Coastguard Worker /* Skip primitive sig */
81*e82f7db8SAndroid Build Coastguard Worker tagPtr++;
82*e82f7db8SAndroid Build Coastguard Worker }
83*e82f7db8SAndroid Build Coastguard Worker }
84*e82f7db8SAndroid Build Coastguard Worker
85*e82f7db8SAndroid Build Coastguard Worker *cursor = tagPtr;
86*e82f7db8SAndroid Build Coastguard Worker return argumentTag;
87*e82f7db8SAndroid Build Coastguard Worker }
88*e82f7db8SAndroid Build Coastguard Worker
89*e82f7db8SAndroid Build Coastguard Worker static jbyte
firstArgumentTypeTag(char * signature,void ** cursor)90*e82f7db8SAndroid Build Coastguard Worker firstArgumentTypeTag(char *signature, void **cursor)
91*e82f7db8SAndroid Build Coastguard Worker {
92*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(signature[0] == SIGNATURE_BEGIN_ARGS);
93*e82f7db8SAndroid Build Coastguard Worker *cursor = signature + 1; /* skip to the first arg */
94*e82f7db8SAndroid Build Coastguard Worker return nextArgumentTypeTag(cursor);
95*e82f7db8SAndroid Build Coastguard Worker }
96*e82f7db8SAndroid Build Coastguard Worker
97*e82f7db8SAndroid Build Coastguard Worker
98*e82f7db8SAndroid Build Coastguard Worker /*
99*e82f7db8SAndroid Build Coastguard Worker * Note: argument refs may be destroyed on out-of-memory error
100*e82f7db8SAndroid Build Coastguard Worker */
101*e82f7db8SAndroid Build Coastguard Worker static jvmtiError
createGlobalRefs(JNIEnv * env,InvokeRequest * request)102*e82f7db8SAndroid Build Coastguard Worker createGlobalRefs(JNIEnv *env, InvokeRequest *request)
103*e82f7db8SAndroid Build Coastguard Worker {
104*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
105*e82f7db8SAndroid Build Coastguard Worker jclass clazz = NULL;
106*e82f7db8SAndroid Build Coastguard Worker jobject instance = NULL;
107*e82f7db8SAndroid Build Coastguard Worker jint argIndex;
108*e82f7db8SAndroid Build Coastguard Worker jbyte argumentTag;
109*e82f7db8SAndroid Build Coastguard Worker jvalue *argument;
110*e82f7db8SAndroid Build Coastguard Worker void *cursor;
111*e82f7db8SAndroid Build Coastguard Worker jobject *argRefs = NULL;
112*e82f7db8SAndroid Build Coastguard Worker
113*e82f7db8SAndroid Build Coastguard Worker error = JVMTI_ERROR_NONE;
114*e82f7db8SAndroid Build Coastguard Worker
115*e82f7db8SAndroid Build Coastguard Worker if ( request->argumentCount > 0 ) {
116*e82f7db8SAndroid Build Coastguard Worker /*LINTED*/
117*e82f7db8SAndroid Build Coastguard Worker argRefs = jvmtiAllocate((jint)(request->argumentCount*sizeof(jobject)));
118*e82f7db8SAndroid Build Coastguard Worker if ( argRefs==NULL ) {
119*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_OUT_OF_MEMORY;
120*e82f7db8SAndroid Build Coastguard Worker } else {
121*e82f7db8SAndroid Build Coastguard Worker /*LINTED*/
122*e82f7db8SAndroid Build Coastguard Worker (void)memset(argRefs, 0, request->argumentCount*sizeof(jobject));
123*e82f7db8SAndroid Build Coastguard Worker }
124*e82f7db8SAndroid Build Coastguard Worker }
125*e82f7db8SAndroid Build Coastguard Worker
126*e82f7db8SAndroid Build Coastguard Worker if ( error == JVMTI_ERROR_NONE ) {
127*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, request->clazz, &clazz);
128*e82f7db8SAndroid Build Coastguard Worker if (clazz == NULL) {
129*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_OUT_OF_MEMORY;
130*e82f7db8SAndroid Build Coastguard Worker }
131*e82f7db8SAndroid Build Coastguard Worker }
132*e82f7db8SAndroid Build Coastguard Worker
133*e82f7db8SAndroid Build Coastguard Worker if ( error == JVMTI_ERROR_NONE && request->instance != NULL ) {
134*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, request->instance, &instance);
135*e82f7db8SAndroid Build Coastguard Worker if (instance == NULL) {
136*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_OUT_OF_MEMORY;
137*e82f7db8SAndroid Build Coastguard Worker }
138*e82f7db8SAndroid Build Coastguard Worker }
139*e82f7db8SAndroid Build Coastguard Worker
140*e82f7db8SAndroid Build Coastguard Worker if ( error == JVMTI_ERROR_NONE && argRefs!=NULL ) {
141*e82f7db8SAndroid Build Coastguard Worker argIndex = 0;
142*e82f7db8SAndroid Build Coastguard Worker argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
143*e82f7db8SAndroid Build Coastguard Worker argument = request->arguments;
144*e82f7db8SAndroid Build Coastguard Worker while (argumentTag != SIGNATURE_END_ARGS) {
145*e82f7db8SAndroid Build Coastguard Worker if ( argIndex > request->argumentCount ) {
146*e82f7db8SAndroid Build Coastguard Worker break;
147*e82f7db8SAndroid Build Coastguard Worker }
148*e82f7db8SAndroid Build Coastguard Worker if ((argumentTag == JDWP_TAG(OBJECT)) ||
149*e82f7db8SAndroid Build Coastguard Worker (argumentTag == JDWP_TAG(ARRAY))) {
150*e82f7db8SAndroid Build Coastguard Worker /* Create a global ref for any non-null argument */
151*e82f7db8SAndroid Build Coastguard Worker if (argument->l != NULL) {
152*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, argument->l, &argRefs[argIndex]);
153*e82f7db8SAndroid Build Coastguard Worker if (argRefs[argIndex] == NULL) {
154*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_OUT_OF_MEMORY;
155*e82f7db8SAndroid Build Coastguard Worker break;
156*e82f7db8SAndroid Build Coastguard Worker }
157*e82f7db8SAndroid Build Coastguard Worker }
158*e82f7db8SAndroid Build Coastguard Worker }
159*e82f7db8SAndroid Build Coastguard Worker argument++;
160*e82f7db8SAndroid Build Coastguard Worker argIndex++;
161*e82f7db8SAndroid Build Coastguard Worker argumentTag = nextArgumentTypeTag(&cursor);
162*e82f7db8SAndroid Build Coastguard Worker }
163*e82f7db8SAndroid Build Coastguard Worker }
164*e82f7db8SAndroid Build Coastguard Worker
165*e82f7db8SAndroid Build Coastguard Worker #ifdef FIXUP /* Why isn't this an error? */
166*e82f7db8SAndroid Build Coastguard Worker /* Make sure the argument count matches */
167*e82f7db8SAndroid Build Coastguard Worker if ( error == JVMTI_ERROR_NONE && argIndex != request->argumentCount ) {
168*e82f7db8SAndroid Build Coastguard Worker error = AGENT_ERROR_INVALID_COUNT;
169*e82f7db8SAndroid Build Coastguard Worker }
170*e82f7db8SAndroid Build Coastguard Worker #endif
171*e82f7db8SAndroid Build Coastguard Worker
172*e82f7db8SAndroid Build Coastguard Worker /* Finally, put the global refs into the request if no errors */
173*e82f7db8SAndroid Build Coastguard Worker if ( error == JVMTI_ERROR_NONE ) {
174*e82f7db8SAndroid Build Coastguard Worker request->clazz = clazz;
175*e82f7db8SAndroid Build Coastguard Worker request->instance = instance;
176*e82f7db8SAndroid Build Coastguard Worker if ( argRefs!=NULL ) {
177*e82f7db8SAndroid Build Coastguard Worker argIndex = 0;
178*e82f7db8SAndroid Build Coastguard Worker argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
179*e82f7db8SAndroid Build Coastguard Worker argument = request->arguments;
180*e82f7db8SAndroid Build Coastguard Worker while ( argIndex < request->argumentCount ) {
181*e82f7db8SAndroid Build Coastguard Worker if ((argumentTag == JDWP_TAG(OBJECT)) ||
182*e82f7db8SAndroid Build Coastguard Worker (argumentTag == JDWP_TAG(ARRAY))) {
183*e82f7db8SAndroid Build Coastguard Worker argument->l = argRefs[argIndex];
184*e82f7db8SAndroid Build Coastguard Worker }
185*e82f7db8SAndroid Build Coastguard Worker argument++;
186*e82f7db8SAndroid Build Coastguard Worker argIndex++;
187*e82f7db8SAndroid Build Coastguard Worker argumentTag = nextArgumentTypeTag(&cursor);
188*e82f7db8SAndroid Build Coastguard Worker }
189*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(argRefs);
190*e82f7db8SAndroid Build Coastguard Worker }
191*e82f7db8SAndroid Build Coastguard Worker return JVMTI_ERROR_NONE;
192*e82f7db8SAndroid Build Coastguard Worker
193*e82f7db8SAndroid Build Coastguard Worker } else {
194*e82f7db8SAndroid Build Coastguard Worker /* Delete global references */
195*e82f7db8SAndroid Build Coastguard Worker if ( clazz != NULL ) {
196*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &clazz);
197*e82f7db8SAndroid Build Coastguard Worker }
198*e82f7db8SAndroid Build Coastguard Worker if ( instance != NULL ) {
199*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &instance);
200*e82f7db8SAndroid Build Coastguard Worker }
201*e82f7db8SAndroid Build Coastguard Worker if ( argRefs!=NULL ) {
202*e82f7db8SAndroid Build Coastguard Worker for ( argIndex=0; argIndex < request->argumentCount; argIndex++ ) {
203*e82f7db8SAndroid Build Coastguard Worker if ( argRefs[argIndex] != NULL ) {
204*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &argRefs[argIndex]);
205*e82f7db8SAndroid Build Coastguard Worker }
206*e82f7db8SAndroid Build Coastguard Worker }
207*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(argRefs);
208*e82f7db8SAndroid Build Coastguard Worker }
209*e82f7db8SAndroid Build Coastguard Worker }
210*e82f7db8SAndroid Build Coastguard Worker
211*e82f7db8SAndroid Build Coastguard Worker return error;
212*e82f7db8SAndroid Build Coastguard Worker }
213*e82f7db8SAndroid Build Coastguard Worker
214*e82f7db8SAndroid Build Coastguard Worker /*
215*e82f7db8SAndroid Build Coastguard Worker * Delete saved global references - if any - for:
216*e82f7db8SAndroid Build Coastguard Worker * - a potentially thrown Exception
217*e82f7db8SAndroid Build Coastguard Worker * - a returned refernce/array value
218*e82f7db8SAndroid Build Coastguard Worker * See invoker_doInvoke() and invoke* methods where global references
219*e82f7db8SAndroid Build Coastguard Worker * are being saved.
220*e82f7db8SAndroid Build Coastguard Worker */
221*e82f7db8SAndroid Build Coastguard Worker static void
deletePotentiallySavedGlobalRefs(JNIEnv * env,InvokeRequest * request)222*e82f7db8SAndroid Build Coastguard Worker deletePotentiallySavedGlobalRefs(JNIEnv *env, InvokeRequest *request)
223*e82f7db8SAndroid Build Coastguard Worker {
224*e82f7db8SAndroid Build Coastguard Worker /* Delete potentially saved return value */
225*e82f7db8SAndroid Build Coastguard Worker if ((request->invokeType == INVOKE_CONSTRUCTOR) ||
226*e82f7db8SAndroid Build Coastguard Worker (returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT)) ||
227*e82f7db8SAndroid Build Coastguard Worker (returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY))) {
228*e82f7db8SAndroid Build Coastguard Worker if (request->returnValue.l != NULL) {
229*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &(request->returnValue.l));
230*e82f7db8SAndroid Build Coastguard Worker }
231*e82f7db8SAndroid Build Coastguard Worker }
232*e82f7db8SAndroid Build Coastguard Worker /* Delete potentially saved exception */
233*e82f7db8SAndroid Build Coastguard Worker if (request->exception != NULL) {
234*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &(request->exception));
235*e82f7db8SAndroid Build Coastguard Worker }
236*e82f7db8SAndroid Build Coastguard Worker }
237*e82f7db8SAndroid Build Coastguard Worker
238*e82f7db8SAndroid Build Coastguard Worker /*
239*e82f7db8SAndroid Build Coastguard Worker * Delete global argument references from the request which got put there before a
240*e82f7db8SAndroid Build Coastguard Worker * invoke request was carried out. See fillInvokeRequest().
241*e82f7db8SAndroid Build Coastguard Worker */
242*e82f7db8SAndroid Build Coastguard Worker static void
deleteGlobalArgumentRefs(JNIEnv * env,InvokeRequest * request)243*e82f7db8SAndroid Build Coastguard Worker deleteGlobalArgumentRefs(JNIEnv *env, InvokeRequest *request)
244*e82f7db8SAndroid Build Coastguard Worker {
245*e82f7db8SAndroid Build Coastguard Worker void *cursor;
246*e82f7db8SAndroid Build Coastguard Worker jint argIndex = 0;
247*e82f7db8SAndroid Build Coastguard Worker jvalue *argument = request->arguments;
248*e82f7db8SAndroid Build Coastguard Worker jbyte argumentTag = firstArgumentTypeTag(request->methodSignature, &cursor);
249*e82f7db8SAndroid Build Coastguard Worker
250*e82f7db8SAndroid Build Coastguard Worker if (request->clazz != NULL) {
251*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &(request->clazz));
252*e82f7db8SAndroid Build Coastguard Worker }
253*e82f7db8SAndroid Build Coastguard Worker if (request->instance != NULL) {
254*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &(request->instance));
255*e82f7db8SAndroid Build Coastguard Worker }
256*e82f7db8SAndroid Build Coastguard Worker /* Delete global argument references */
257*e82f7db8SAndroid Build Coastguard Worker while (argIndex < request->argumentCount) {
258*e82f7db8SAndroid Build Coastguard Worker if ((argumentTag == JDWP_TAG(OBJECT)) ||
259*e82f7db8SAndroid Build Coastguard Worker (argumentTag == JDWP_TAG(ARRAY))) {
260*e82f7db8SAndroid Build Coastguard Worker if (argument->l != NULL) {
261*e82f7db8SAndroid Build Coastguard Worker tossGlobalRef(env, &(argument->l));
262*e82f7db8SAndroid Build Coastguard Worker }
263*e82f7db8SAndroid Build Coastguard Worker }
264*e82f7db8SAndroid Build Coastguard Worker argument++;
265*e82f7db8SAndroid Build Coastguard Worker argIndex++;
266*e82f7db8SAndroid Build Coastguard Worker argumentTag = nextArgumentTypeTag(&cursor);
267*e82f7db8SAndroid Build Coastguard Worker }
268*e82f7db8SAndroid Build Coastguard Worker }
269*e82f7db8SAndroid Build Coastguard Worker
270*e82f7db8SAndroid Build Coastguard Worker static jvmtiError
fillInvokeRequest(JNIEnv * env,InvokeRequest * request,jbyte invokeType,jbyte options,jint id,jthread thread,jclass clazz,jmethodID method,jobject instance,jvalue * arguments,jint argumentCount)271*e82f7db8SAndroid Build Coastguard Worker fillInvokeRequest(JNIEnv *env, InvokeRequest *request,
272*e82f7db8SAndroid Build Coastguard Worker jbyte invokeType, jbyte options, jint id,
273*e82f7db8SAndroid Build Coastguard Worker jthread thread, jclass clazz, jmethodID method,
274*e82f7db8SAndroid Build Coastguard Worker jobject instance,
275*e82f7db8SAndroid Build Coastguard Worker jvalue *arguments, jint argumentCount)
276*e82f7db8SAndroid Build Coastguard Worker {
277*e82f7db8SAndroid Build Coastguard Worker jvmtiError error;
278*e82f7db8SAndroid Build Coastguard Worker if (!request->available) {
279*e82f7db8SAndroid Build Coastguard Worker /*
280*e82f7db8SAndroid Build Coastguard Worker * Thread is not at a point where it can invoke.
281*e82f7db8SAndroid Build Coastguard Worker */
282*e82f7db8SAndroid Build Coastguard Worker return AGENT_ERROR_INVALID_THREAD;
283*e82f7db8SAndroid Build Coastguard Worker }
284*e82f7db8SAndroid Build Coastguard Worker if (request->pending) {
285*e82f7db8SAndroid Build Coastguard Worker /*
286*e82f7db8SAndroid Build Coastguard Worker * Pending invoke
287*e82f7db8SAndroid Build Coastguard Worker */
288*e82f7db8SAndroid Build Coastguard Worker return AGENT_ERROR_ALREADY_INVOKING;
289*e82f7db8SAndroid Build Coastguard Worker }
290*e82f7db8SAndroid Build Coastguard Worker
291*e82f7db8SAndroid Build Coastguard Worker request->invokeType = invokeType;
292*e82f7db8SAndroid Build Coastguard Worker request->options = options;
293*e82f7db8SAndroid Build Coastguard Worker request->detached = JNI_FALSE;
294*e82f7db8SAndroid Build Coastguard Worker request->id = id;
295*e82f7db8SAndroid Build Coastguard Worker request->clazz = clazz;
296*e82f7db8SAndroid Build Coastguard Worker request->method = method;
297*e82f7db8SAndroid Build Coastguard Worker request->instance = instance;
298*e82f7db8SAndroid Build Coastguard Worker request->arguments = arguments;
299*e82f7db8SAndroid Build Coastguard Worker request->arguments = arguments;
300*e82f7db8SAndroid Build Coastguard Worker request->argumentCount = argumentCount;
301*e82f7db8SAndroid Build Coastguard Worker
302*e82f7db8SAndroid Build Coastguard Worker request->returnValue.j = 0;
303*e82f7db8SAndroid Build Coastguard Worker request->exception = 0;
304*e82f7db8SAndroid Build Coastguard Worker
305*e82f7db8SAndroid Build Coastguard Worker /*
306*e82f7db8SAndroid Build Coastguard Worker * Squirrel away the method signature
307*e82f7db8SAndroid Build Coastguard Worker */
308*e82f7db8SAndroid Build Coastguard Worker error = methodSignature(method, NULL, &request->methodSignature, NULL);
309*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
310*e82f7db8SAndroid Build Coastguard Worker return error;
311*e82f7db8SAndroid Build Coastguard Worker }
312*e82f7db8SAndroid Build Coastguard Worker
313*e82f7db8SAndroid Build Coastguard Worker /*
314*e82f7db8SAndroid Build Coastguard Worker * The given references for class and instance are not guaranteed
315*e82f7db8SAndroid Build Coastguard Worker * to be around long enough for invocation, so create new ones
316*e82f7db8SAndroid Build Coastguard Worker * here.
317*e82f7db8SAndroid Build Coastguard Worker */
318*e82f7db8SAndroid Build Coastguard Worker error = createGlobalRefs(env, request);
319*e82f7db8SAndroid Build Coastguard Worker if (error != JVMTI_ERROR_NONE) {
320*e82f7db8SAndroid Build Coastguard Worker jvmtiDeallocate(request->methodSignature);
321*e82f7db8SAndroid Build Coastguard Worker return error;
322*e82f7db8SAndroid Build Coastguard Worker }
323*e82f7db8SAndroid Build Coastguard Worker
324*e82f7db8SAndroid Build Coastguard Worker request->pending = JNI_TRUE;
325*e82f7db8SAndroid Build Coastguard Worker request->available = JNI_FALSE;
326*e82f7db8SAndroid Build Coastguard Worker return JVMTI_ERROR_NONE;
327*e82f7db8SAndroid Build Coastguard Worker }
328*e82f7db8SAndroid Build Coastguard Worker
329*e82f7db8SAndroid Build Coastguard Worker void
invoker_enableInvokeRequests(jthread thread)330*e82f7db8SAndroid Build Coastguard Worker invoker_enableInvokeRequests(jthread thread)
331*e82f7db8SAndroid Build Coastguard Worker {
332*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
333*e82f7db8SAndroid Build Coastguard Worker
334*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(thread);
335*e82f7db8SAndroid Build Coastguard Worker
336*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
337*e82f7db8SAndroid Build Coastguard Worker if (request == NULL) {
338*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
339*e82f7db8SAndroid Build Coastguard Worker }
340*e82f7db8SAndroid Build Coastguard Worker
341*e82f7db8SAndroid Build Coastguard Worker request->available = JNI_TRUE;
342*e82f7db8SAndroid Build Coastguard Worker }
343*e82f7db8SAndroid Build Coastguard Worker
344*e82f7db8SAndroid Build Coastguard Worker jvmtiError
invoker_requestInvoke(jbyte invokeType,jbyte options,jint id,jthread thread,jclass clazz,jmethodID method,jobject instance,jvalue * arguments,jint argumentCount)345*e82f7db8SAndroid Build Coastguard Worker invoker_requestInvoke(jbyte invokeType, jbyte options, jint id,
346*e82f7db8SAndroid Build Coastguard Worker jthread thread, jclass clazz, jmethodID method,
347*e82f7db8SAndroid Build Coastguard Worker jobject instance,
348*e82f7db8SAndroid Build Coastguard Worker jvalue *arguments, jint argumentCount)
349*e82f7db8SAndroid Build Coastguard Worker {
350*e82f7db8SAndroid Build Coastguard Worker JNIEnv *env = getEnv();
351*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
352*e82f7db8SAndroid Build Coastguard Worker jvmtiError error = JVMTI_ERROR_NONE;
353*e82f7db8SAndroid Build Coastguard Worker
354*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
355*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
356*e82f7db8SAndroid Build Coastguard Worker if (request != NULL) {
357*e82f7db8SAndroid Build Coastguard Worker error = fillInvokeRequest(env, request, invokeType, options, id,
358*e82f7db8SAndroid Build Coastguard Worker thread, clazz, method, instance,
359*e82f7db8SAndroid Build Coastguard Worker arguments, argumentCount);
360*e82f7db8SAndroid Build Coastguard Worker }
361*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
362*e82f7db8SAndroid Build Coastguard Worker
363*e82f7db8SAndroid Build Coastguard Worker if (error == JVMTI_ERROR_NONE) {
364*e82f7db8SAndroid Build Coastguard Worker if (options & JDWP_INVOKE_OPTIONS(SINGLE_THREADED) ) {
365*e82f7db8SAndroid Build Coastguard Worker /* true means it is okay to unblock the commandLoop thread */
366*e82f7db8SAndroid Build Coastguard Worker (void)threadControl_resumeThread(thread, JNI_TRUE);
367*e82f7db8SAndroid Build Coastguard Worker } else {
368*e82f7db8SAndroid Build Coastguard Worker (void)threadControl_resumeAll();
369*e82f7db8SAndroid Build Coastguard Worker }
370*e82f7db8SAndroid Build Coastguard Worker }
371*e82f7db8SAndroid Build Coastguard Worker
372*e82f7db8SAndroid Build Coastguard Worker return error;
373*e82f7db8SAndroid Build Coastguard Worker }
374*e82f7db8SAndroid Build Coastguard Worker
375*e82f7db8SAndroid Build Coastguard Worker static void
invokeConstructor(JNIEnv * env,InvokeRequest * request)376*e82f7db8SAndroid Build Coastguard Worker invokeConstructor(JNIEnv *env, InvokeRequest *request)
377*e82f7db8SAndroid Build Coastguard Worker {
378*e82f7db8SAndroid Build Coastguard Worker jobject object;
379*e82f7db8SAndroid Build Coastguard Worker
380*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT_MSG(request->clazz, "Request clazz null");
381*e82f7db8SAndroid Build Coastguard Worker object = JNI_FUNC_PTR(env,NewObjectA)(env, request->clazz,
382*e82f7db8SAndroid Build Coastguard Worker request->method,
383*e82f7db8SAndroid Build Coastguard Worker request->arguments);
384*e82f7db8SAndroid Build Coastguard Worker request->returnValue.l = NULL;
385*e82f7db8SAndroid Build Coastguard Worker if (object != NULL) {
386*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, object, &(request->returnValue.l));
387*e82f7db8SAndroid Build Coastguard Worker }
388*e82f7db8SAndroid Build Coastguard Worker }
389*e82f7db8SAndroid Build Coastguard Worker
390*e82f7db8SAndroid Build Coastguard Worker static void
invokeStatic(JNIEnv * env,InvokeRequest * request)391*e82f7db8SAndroid Build Coastguard Worker invokeStatic(JNIEnv *env, InvokeRequest *request)
392*e82f7db8SAndroid Build Coastguard Worker {
393*e82f7db8SAndroid Build Coastguard Worker switch(returnTypeTag(request->methodSignature)) {
394*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(OBJECT):
395*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(ARRAY): {
396*e82f7db8SAndroid Build Coastguard Worker jobject object;
397*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT_MSG(request->clazz, "Request clazz null");
398*e82f7db8SAndroid Build Coastguard Worker object = JNI_FUNC_PTR(env,CallStaticObjectMethodA)(env,
399*e82f7db8SAndroid Build Coastguard Worker request->clazz,
400*e82f7db8SAndroid Build Coastguard Worker request->method,
401*e82f7db8SAndroid Build Coastguard Worker request->arguments);
402*e82f7db8SAndroid Build Coastguard Worker request->returnValue.l = NULL;
403*e82f7db8SAndroid Build Coastguard Worker if (object != NULL) {
404*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, object, &(request->returnValue.l));
405*e82f7db8SAndroid Build Coastguard Worker }
406*e82f7db8SAndroid Build Coastguard Worker break;
407*e82f7db8SAndroid Build Coastguard Worker }
408*e82f7db8SAndroid Build Coastguard Worker
409*e82f7db8SAndroid Build Coastguard Worker
410*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BYTE):
411*e82f7db8SAndroid Build Coastguard Worker request->returnValue.b = JNI_FUNC_PTR(env,CallStaticByteMethodA)(env,
412*e82f7db8SAndroid Build Coastguard Worker request->clazz,
413*e82f7db8SAndroid Build Coastguard Worker request->method,
414*e82f7db8SAndroid Build Coastguard Worker request->arguments);
415*e82f7db8SAndroid Build Coastguard Worker break;
416*e82f7db8SAndroid Build Coastguard Worker
417*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(CHAR):
418*e82f7db8SAndroid Build Coastguard Worker request->returnValue.c = JNI_FUNC_PTR(env,CallStaticCharMethodA)(env,
419*e82f7db8SAndroid Build Coastguard Worker request->clazz,
420*e82f7db8SAndroid Build Coastguard Worker request->method,
421*e82f7db8SAndroid Build Coastguard Worker request->arguments);
422*e82f7db8SAndroid Build Coastguard Worker break;
423*e82f7db8SAndroid Build Coastguard Worker
424*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(FLOAT):
425*e82f7db8SAndroid Build Coastguard Worker request->returnValue.f = JNI_FUNC_PTR(env,CallStaticFloatMethodA)(env,
426*e82f7db8SAndroid Build Coastguard Worker request->clazz,
427*e82f7db8SAndroid Build Coastguard Worker request->method,
428*e82f7db8SAndroid Build Coastguard Worker request->arguments);
429*e82f7db8SAndroid Build Coastguard Worker break;
430*e82f7db8SAndroid Build Coastguard Worker
431*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(DOUBLE):
432*e82f7db8SAndroid Build Coastguard Worker request->returnValue.d = JNI_FUNC_PTR(env,CallStaticDoubleMethodA)(env,
433*e82f7db8SAndroid Build Coastguard Worker request->clazz,
434*e82f7db8SAndroid Build Coastguard Worker request->method,
435*e82f7db8SAndroid Build Coastguard Worker request->arguments);
436*e82f7db8SAndroid Build Coastguard Worker break;
437*e82f7db8SAndroid Build Coastguard Worker
438*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(INT):
439*e82f7db8SAndroid Build Coastguard Worker request->returnValue.i = JNI_FUNC_PTR(env,CallStaticIntMethodA)(env,
440*e82f7db8SAndroid Build Coastguard Worker request->clazz,
441*e82f7db8SAndroid Build Coastguard Worker request->method,
442*e82f7db8SAndroid Build Coastguard Worker request->arguments);
443*e82f7db8SAndroid Build Coastguard Worker break;
444*e82f7db8SAndroid Build Coastguard Worker
445*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(LONG):
446*e82f7db8SAndroid Build Coastguard Worker request->returnValue.j = JNI_FUNC_PTR(env,CallStaticLongMethodA)(env,
447*e82f7db8SAndroid Build Coastguard Worker request->clazz,
448*e82f7db8SAndroid Build Coastguard Worker request->method,
449*e82f7db8SAndroid Build Coastguard Worker request->arguments);
450*e82f7db8SAndroid Build Coastguard Worker break;
451*e82f7db8SAndroid Build Coastguard Worker
452*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(SHORT):
453*e82f7db8SAndroid Build Coastguard Worker request->returnValue.s = JNI_FUNC_PTR(env,CallStaticShortMethodA)(env,
454*e82f7db8SAndroid Build Coastguard Worker request->clazz,
455*e82f7db8SAndroid Build Coastguard Worker request->method,
456*e82f7db8SAndroid Build Coastguard Worker request->arguments);
457*e82f7db8SAndroid Build Coastguard Worker break;
458*e82f7db8SAndroid Build Coastguard Worker
459*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BOOLEAN):
460*e82f7db8SAndroid Build Coastguard Worker request->returnValue.z = JNI_FUNC_PTR(env,CallStaticBooleanMethodA)(env,
461*e82f7db8SAndroid Build Coastguard Worker request->clazz,
462*e82f7db8SAndroid Build Coastguard Worker request->method,
463*e82f7db8SAndroid Build Coastguard Worker request->arguments);
464*e82f7db8SAndroid Build Coastguard Worker break;
465*e82f7db8SAndroid Build Coastguard Worker
466*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(VOID):
467*e82f7db8SAndroid Build Coastguard Worker JNI_FUNC_PTR(env,CallStaticVoidMethodA)(env,
468*e82f7db8SAndroid Build Coastguard Worker request->clazz,
469*e82f7db8SAndroid Build Coastguard Worker request->method,
470*e82f7db8SAndroid Build Coastguard Worker request->arguments);
471*e82f7db8SAndroid Build Coastguard Worker break;
472*e82f7db8SAndroid Build Coastguard Worker
473*e82f7db8SAndroid Build Coastguard Worker default:
474*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"Invalid method signature");
475*e82f7db8SAndroid Build Coastguard Worker break;
476*e82f7db8SAndroid Build Coastguard Worker }
477*e82f7db8SAndroid Build Coastguard Worker }
478*e82f7db8SAndroid Build Coastguard Worker
479*e82f7db8SAndroid Build Coastguard Worker static void
invokeVirtual(JNIEnv * env,InvokeRequest * request)480*e82f7db8SAndroid Build Coastguard Worker invokeVirtual(JNIEnv *env, InvokeRequest *request)
481*e82f7db8SAndroid Build Coastguard Worker {
482*e82f7db8SAndroid Build Coastguard Worker switch(returnTypeTag(request->methodSignature)) {
483*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(OBJECT):
484*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(ARRAY): {
485*e82f7db8SAndroid Build Coastguard Worker jobject object;
486*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT_MSG(request->instance, "Request instance null");
487*e82f7db8SAndroid Build Coastguard Worker object = JNI_FUNC_PTR(env,CallObjectMethodA)(env,
488*e82f7db8SAndroid Build Coastguard Worker request->instance,
489*e82f7db8SAndroid Build Coastguard Worker request->method,
490*e82f7db8SAndroid Build Coastguard Worker request->arguments);
491*e82f7db8SAndroid Build Coastguard Worker request->returnValue.l = NULL;
492*e82f7db8SAndroid Build Coastguard Worker if (object != NULL) {
493*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, object, &(request->returnValue.l));
494*e82f7db8SAndroid Build Coastguard Worker }
495*e82f7db8SAndroid Build Coastguard Worker break;
496*e82f7db8SAndroid Build Coastguard Worker }
497*e82f7db8SAndroid Build Coastguard Worker
498*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BYTE):
499*e82f7db8SAndroid Build Coastguard Worker request->returnValue.b = JNI_FUNC_PTR(env,CallByteMethodA)(env,
500*e82f7db8SAndroid Build Coastguard Worker request->instance,
501*e82f7db8SAndroid Build Coastguard Worker request->method,
502*e82f7db8SAndroid Build Coastguard Worker request->arguments);
503*e82f7db8SAndroid Build Coastguard Worker break;
504*e82f7db8SAndroid Build Coastguard Worker
505*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(CHAR):
506*e82f7db8SAndroid Build Coastguard Worker request->returnValue.c = JNI_FUNC_PTR(env,CallCharMethodA)(env,
507*e82f7db8SAndroid Build Coastguard Worker request->instance,
508*e82f7db8SAndroid Build Coastguard Worker request->method,
509*e82f7db8SAndroid Build Coastguard Worker request->arguments);
510*e82f7db8SAndroid Build Coastguard Worker break;
511*e82f7db8SAndroid Build Coastguard Worker
512*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(FLOAT):
513*e82f7db8SAndroid Build Coastguard Worker request->returnValue.f = JNI_FUNC_PTR(env,CallFloatMethodA)(env,
514*e82f7db8SAndroid Build Coastguard Worker request->instance,
515*e82f7db8SAndroid Build Coastguard Worker request->method,
516*e82f7db8SAndroid Build Coastguard Worker request->arguments);
517*e82f7db8SAndroid Build Coastguard Worker break;
518*e82f7db8SAndroid Build Coastguard Worker
519*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(DOUBLE):
520*e82f7db8SAndroid Build Coastguard Worker request->returnValue.d = JNI_FUNC_PTR(env,CallDoubleMethodA)(env,
521*e82f7db8SAndroid Build Coastguard Worker request->instance,
522*e82f7db8SAndroid Build Coastguard Worker request->method,
523*e82f7db8SAndroid Build Coastguard Worker request->arguments);
524*e82f7db8SAndroid Build Coastguard Worker break;
525*e82f7db8SAndroid Build Coastguard Worker
526*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(INT):
527*e82f7db8SAndroid Build Coastguard Worker request->returnValue.i = JNI_FUNC_PTR(env,CallIntMethodA)(env,
528*e82f7db8SAndroid Build Coastguard Worker request->instance,
529*e82f7db8SAndroid Build Coastguard Worker request->method,
530*e82f7db8SAndroid Build Coastguard Worker request->arguments);
531*e82f7db8SAndroid Build Coastguard Worker break;
532*e82f7db8SAndroid Build Coastguard Worker
533*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(LONG):
534*e82f7db8SAndroid Build Coastguard Worker request->returnValue.j = JNI_FUNC_PTR(env,CallLongMethodA)(env,
535*e82f7db8SAndroid Build Coastguard Worker request->instance,
536*e82f7db8SAndroid Build Coastguard Worker request->method,
537*e82f7db8SAndroid Build Coastguard Worker request->arguments);
538*e82f7db8SAndroid Build Coastguard Worker break;
539*e82f7db8SAndroid Build Coastguard Worker
540*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(SHORT):
541*e82f7db8SAndroid Build Coastguard Worker request->returnValue.s = JNI_FUNC_PTR(env,CallShortMethodA)(env,
542*e82f7db8SAndroid Build Coastguard Worker request->instance,
543*e82f7db8SAndroid Build Coastguard Worker request->method,
544*e82f7db8SAndroid Build Coastguard Worker request->arguments);
545*e82f7db8SAndroid Build Coastguard Worker break;
546*e82f7db8SAndroid Build Coastguard Worker
547*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BOOLEAN):
548*e82f7db8SAndroid Build Coastguard Worker request->returnValue.z = JNI_FUNC_PTR(env,CallBooleanMethodA)(env,
549*e82f7db8SAndroid Build Coastguard Worker request->instance,
550*e82f7db8SAndroid Build Coastguard Worker request->method,
551*e82f7db8SAndroid Build Coastguard Worker request->arguments);
552*e82f7db8SAndroid Build Coastguard Worker break;
553*e82f7db8SAndroid Build Coastguard Worker
554*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(VOID):
555*e82f7db8SAndroid Build Coastguard Worker JNI_FUNC_PTR(env,CallVoidMethodA)(env,
556*e82f7db8SAndroid Build Coastguard Worker request->instance,
557*e82f7db8SAndroid Build Coastguard Worker request->method,
558*e82f7db8SAndroid Build Coastguard Worker request->arguments);
559*e82f7db8SAndroid Build Coastguard Worker break;
560*e82f7db8SAndroid Build Coastguard Worker
561*e82f7db8SAndroid Build Coastguard Worker default:
562*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"Invalid method signature");
563*e82f7db8SAndroid Build Coastguard Worker break;
564*e82f7db8SAndroid Build Coastguard Worker }
565*e82f7db8SAndroid Build Coastguard Worker }
566*e82f7db8SAndroid Build Coastguard Worker
567*e82f7db8SAndroid Build Coastguard Worker static void
invokeNonvirtual(JNIEnv * env,InvokeRequest * request)568*e82f7db8SAndroid Build Coastguard Worker invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
569*e82f7db8SAndroid Build Coastguard Worker {
570*e82f7db8SAndroid Build Coastguard Worker switch(returnTypeTag(request->methodSignature)) {
571*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(OBJECT):
572*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(ARRAY): {
573*e82f7db8SAndroid Build Coastguard Worker jobject object;
574*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT_MSG(request->clazz, "Request clazz null");
575*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT_MSG(request->instance, "Request instance null");
576*e82f7db8SAndroid Build Coastguard Worker object = JNI_FUNC_PTR(env,CallNonvirtualObjectMethodA)(env,
577*e82f7db8SAndroid Build Coastguard Worker request->instance,
578*e82f7db8SAndroid Build Coastguard Worker request->clazz,
579*e82f7db8SAndroid Build Coastguard Worker request->method,
580*e82f7db8SAndroid Build Coastguard Worker request->arguments);
581*e82f7db8SAndroid Build Coastguard Worker request->returnValue.l = NULL;
582*e82f7db8SAndroid Build Coastguard Worker if (object != NULL) {
583*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, object, &(request->returnValue.l));
584*e82f7db8SAndroid Build Coastguard Worker }
585*e82f7db8SAndroid Build Coastguard Worker break;
586*e82f7db8SAndroid Build Coastguard Worker }
587*e82f7db8SAndroid Build Coastguard Worker
588*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BYTE):
589*e82f7db8SAndroid Build Coastguard Worker request->returnValue.b = JNI_FUNC_PTR(env,CallNonvirtualByteMethodA)(env,
590*e82f7db8SAndroid Build Coastguard Worker request->instance,
591*e82f7db8SAndroid Build Coastguard Worker request->clazz,
592*e82f7db8SAndroid Build Coastguard Worker request->method,
593*e82f7db8SAndroid Build Coastguard Worker request->arguments);
594*e82f7db8SAndroid Build Coastguard Worker break;
595*e82f7db8SAndroid Build Coastguard Worker
596*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(CHAR):
597*e82f7db8SAndroid Build Coastguard Worker request->returnValue.c = JNI_FUNC_PTR(env,CallNonvirtualCharMethodA)(env,
598*e82f7db8SAndroid Build Coastguard Worker request->instance,
599*e82f7db8SAndroid Build Coastguard Worker request->clazz,
600*e82f7db8SAndroid Build Coastguard Worker request->method,
601*e82f7db8SAndroid Build Coastguard Worker request->arguments);
602*e82f7db8SAndroid Build Coastguard Worker break;
603*e82f7db8SAndroid Build Coastguard Worker
604*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(FLOAT):
605*e82f7db8SAndroid Build Coastguard Worker request->returnValue.f = JNI_FUNC_PTR(env,CallNonvirtualFloatMethodA)(env,
606*e82f7db8SAndroid Build Coastguard Worker request->instance,
607*e82f7db8SAndroid Build Coastguard Worker request->clazz,
608*e82f7db8SAndroid Build Coastguard Worker request->method,
609*e82f7db8SAndroid Build Coastguard Worker request->arguments);
610*e82f7db8SAndroid Build Coastguard Worker break;
611*e82f7db8SAndroid Build Coastguard Worker
612*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(DOUBLE):
613*e82f7db8SAndroid Build Coastguard Worker request->returnValue.d = JNI_FUNC_PTR(env,CallNonvirtualDoubleMethodA)(env,
614*e82f7db8SAndroid Build Coastguard Worker request->instance,
615*e82f7db8SAndroid Build Coastguard Worker request->clazz,
616*e82f7db8SAndroid Build Coastguard Worker request->method,
617*e82f7db8SAndroid Build Coastguard Worker request->arguments);
618*e82f7db8SAndroid Build Coastguard Worker break;
619*e82f7db8SAndroid Build Coastguard Worker
620*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(INT):
621*e82f7db8SAndroid Build Coastguard Worker request->returnValue.i = JNI_FUNC_PTR(env,CallNonvirtualIntMethodA)(env,
622*e82f7db8SAndroid Build Coastguard Worker request->instance,
623*e82f7db8SAndroid Build Coastguard Worker request->clazz,
624*e82f7db8SAndroid Build Coastguard Worker request->method,
625*e82f7db8SAndroid Build Coastguard Worker request->arguments);
626*e82f7db8SAndroid Build Coastguard Worker break;
627*e82f7db8SAndroid Build Coastguard Worker
628*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(LONG):
629*e82f7db8SAndroid Build Coastguard Worker request->returnValue.j = JNI_FUNC_PTR(env,CallNonvirtualLongMethodA)(env,
630*e82f7db8SAndroid Build Coastguard Worker request->instance,
631*e82f7db8SAndroid Build Coastguard Worker request->clazz,
632*e82f7db8SAndroid Build Coastguard Worker request->method,
633*e82f7db8SAndroid Build Coastguard Worker request->arguments);
634*e82f7db8SAndroid Build Coastguard Worker break;
635*e82f7db8SAndroid Build Coastguard Worker
636*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(SHORT):
637*e82f7db8SAndroid Build Coastguard Worker request->returnValue.s = JNI_FUNC_PTR(env,CallNonvirtualShortMethodA)(env,
638*e82f7db8SAndroid Build Coastguard Worker request->instance,
639*e82f7db8SAndroid Build Coastguard Worker request->clazz,
640*e82f7db8SAndroid Build Coastguard Worker request->method,
641*e82f7db8SAndroid Build Coastguard Worker request->arguments);
642*e82f7db8SAndroid Build Coastguard Worker break;
643*e82f7db8SAndroid Build Coastguard Worker
644*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(BOOLEAN):
645*e82f7db8SAndroid Build Coastguard Worker request->returnValue.z = JNI_FUNC_PTR(env,CallNonvirtualBooleanMethodA)(env,
646*e82f7db8SAndroid Build Coastguard Worker request->instance,
647*e82f7db8SAndroid Build Coastguard Worker request->clazz,
648*e82f7db8SAndroid Build Coastguard Worker request->method,
649*e82f7db8SAndroid Build Coastguard Worker request->arguments);
650*e82f7db8SAndroid Build Coastguard Worker break;
651*e82f7db8SAndroid Build Coastguard Worker
652*e82f7db8SAndroid Build Coastguard Worker case JDWP_TAG(VOID):
653*e82f7db8SAndroid Build Coastguard Worker JNI_FUNC_PTR(env,CallNonvirtualVoidMethodA)(env,
654*e82f7db8SAndroid Build Coastguard Worker request->instance,
655*e82f7db8SAndroid Build Coastguard Worker request->clazz,
656*e82f7db8SAndroid Build Coastguard Worker request->method,
657*e82f7db8SAndroid Build Coastguard Worker request->arguments);
658*e82f7db8SAndroid Build Coastguard Worker break;
659*e82f7db8SAndroid Build Coastguard Worker
660*e82f7db8SAndroid Build Coastguard Worker default:
661*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"Invalid method signature");
662*e82f7db8SAndroid Build Coastguard Worker break;
663*e82f7db8SAndroid Build Coastguard Worker }
664*e82f7db8SAndroid Build Coastguard Worker }
665*e82f7db8SAndroid Build Coastguard Worker
666*e82f7db8SAndroid Build Coastguard Worker jboolean
invoker_doInvoke(jthread thread)667*e82f7db8SAndroid Build Coastguard Worker invoker_doInvoke(jthread thread)
668*e82f7db8SAndroid Build Coastguard Worker {
669*e82f7db8SAndroid Build Coastguard Worker JNIEnv *env;
670*e82f7db8SAndroid Build Coastguard Worker jboolean startNow;
671*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
672*e82f7db8SAndroid Build Coastguard Worker jbyte options;
673*e82f7db8SAndroid Build Coastguard Worker jbyte invokeType;
674*e82f7db8SAndroid Build Coastguard Worker
675*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(thread);
676*e82f7db8SAndroid Build Coastguard Worker
677*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
678*e82f7db8SAndroid Build Coastguard Worker
679*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
680*e82f7db8SAndroid Build Coastguard Worker if (request == NULL) {
681*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
682*e82f7db8SAndroid Build Coastguard Worker }
683*e82f7db8SAndroid Build Coastguard Worker
684*e82f7db8SAndroid Build Coastguard Worker request->available = JNI_FALSE;
685*e82f7db8SAndroid Build Coastguard Worker startNow = request->pending && !request->started;
686*e82f7db8SAndroid Build Coastguard Worker
687*e82f7db8SAndroid Build Coastguard Worker if (startNow) {
688*e82f7db8SAndroid Build Coastguard Worker request->started = JNI_TRUE;
689*e82f7db8SAndroid Build Coastguard Worker }
690*e82f7db8SAndroid Build Coastguard Worker options = request->options;
691*e82f7db8SAndroid Build Coastguard Worker invokeType = request->invokeType;
692*e82f7db8SAndroid Build Coastguard Worker
693*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
694*e82f7db8SAndroid Build Coastguard Worker
695*e82f7db8SAndroid Build Coastguard Worker if (!startNow) {
696*e82f7db8SAndroid Build Coastguard Worker return JNI_FALSE;
697*e82f7db8SAndroid Build Coastguard Worker }
698*e82f7db8SAndroid Build Coastguard Worker
699*e82f7db8SAndroid Build Coastguard Worker env = getEnv();
700*e82f7db8SAndroid Build Coastguard Worker
701*e82f7db8SAndroid Build Coastguard Worker WITH_LOCAL_REFS(env, 2) { /* 1 for obj return values, 1 for exception */
702*e82f7db8SAndroid Build Coastguard Worker
703*e82f7db8SAndroid Build Coastguard Worker jobject exception;
704*e82f7db8SAndroid Build Coastguard Worker
705*e82f7db8SAndroid Build Coastguard Worker JNI_FUNC_PTR(env,ExceptionClear)(env);
706*e82f7db8SAndroid Build Coastguard Worker
707*e82f7db8SAndroid Build Coastguard Worker switch (invokeType) {
708*e82f7db8SAndroid Build Coastguard Worker case INVOKE_CONSTRUCTOR:
709*e82f7db8SAndroid Build Coastguard Worker invokeConstructor(env, request);
710*e82f7db8SAndroid Build Coastguard Worker break;
711*e82f7db8SAndroid Build Coastguard Worker case INVOKE_STATIC:
712*e82f7db8SAndroid Build Coastguard Worker invokeStatic(env, request);
713*e82f7db8SAndroid Build Coastguard Worker break;
714*e82f7db8SAndroid Build Coastguard Worker case INVOKE_INSTANCE:
715*e82f7db8SAndroid Build Coastguard Worker if (options & JDWP_INVOKE_OPTIONS(NONVIRTUAL) ) {
716*e82f7db8SAndroid Build Coastguard Worker invokeNonvirtual(env, request);
717*e82f7db8SAndroid Build Coastguard Worker } else {
718*e82f7db8SAndroid Build Coastguard Worker invokeVirtual(env, request);
719*e82f7db8SAndroid Build Coastguard Worker }
720*e82f7db8SAndroid Build Coastguard Worker break;
721*e82f7db8SAndroid Build Coastguard Worker default:
722*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(JNI_FALSE);
723*e82f7db8SAndroid Build Coastguard Worker }
724*e82f7db8SAndroid Build Coastguard Worker request->exception = NULL;
725*e82f7db8SAndroid Build Coastguard Worker exception = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
726*e82f7db8SAndroid Build Coastguard Worker if (exception != NULL) {
727*e82f7db8SAndroid Build Coastguard Worker JNI_FUNC_PTR(env,ExceptionClear)(env);
728*e82f7db8SAndroid Build Coastguard Worker saveGlobalRef(env, exception, &(request->exception));
729*e82f7db8SAndroid Build Coastguard Worker }
730*e82f7db8SAndroid Build Coastguard Worker
731*e82f7db8SAndroid Build Coastguard Worker } END_WITH_LOCAL_REFS(env);
732*e82f7db8SAndroid Build Coastguard Worker
733*e82f7db8SAndroid Build Coastguard Worker return JNI_TRUE;
734*e82f7db8SAndroid Build Coastguard Worker }
735*e82f7db8SAndroid Build Coastguard Worker
736*e82f7db8SAndroid Build Coastguard Worker void
invoker_completeInvokeRequest(jthread thread)737*e82f7db8SAndroid Build Coastguard Worker invoker_completeInvokeRequest(jthread thread)
738*e82f7db8SAndroid Build Coastguard Worker {
739*e82f7db8SAndroid Build Coastguard Worker JNIEnv *env = getEnv();
740*e82f7db8SAndroid Build Coastguard Worker PacketOutputStream out;
741*e82f7db8SAndroid Build Coastguard Worker jbyte tag;
742*e82f7db8SAndroid Build Coastguard Worker jobject exc;
743*e82f7db8SAndroid Build Coastguard Worker jvalue returnValue;
744*e82f7db8SAndroid Build Coastguard Worker jint id;
745*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
746*e82f7db8SAndroid Build Coastguard Worker jboolean detached;
747*e82f7db8SAndroid Build Coastguard Worker
748*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(thread);
749*e82f7db8SAndroid Build Coastguard Worker
750*e82f7db8SAndroid Build Coastguard Worker /* Prevent gcc errors on uninitialized variables. */
751*e82f7db8SAndroid Build Coastguard Worker tag = 0;
752*e82f7db8SAndroid Build Coastguard Worker exc = NULL;
753*e82f7db8SAndroid Build Coastguard Worker id = 0;
754*e82f7db8SAndroid Build Coastguard Worker
755*e82f7db8SAndroid Build Coastguard Worker eventHandler_lock(); /* for proper lock order */
756*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
757*e82f7db8SAndroid Build Coastguard Worker
758*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
759*e82f7db8SAndroid Build Coastguard Worker if (request == NULL) {
760*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
761*e82f7db8SAndroid Build Coastguard Worker }
762*e82f7db8SAndroid Build Coastguard Worker
763*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(request->pending);
764*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(request->started);
765*e82f7db8SAndroid Build Coastguard Worker
766*e82f7db8SAndroid Build Coastguard Worker request->pending = JNI_FALSE;
767*e82f7db8SAndroid Build Coastguard Worker request->started = JNI_FALSE;
768*e82f7db8SAndroid Build Coastguard Worker request->available = JNI_TRUE; /* For next time around */
769*e82f7db8SAndroid Build Coastguard Worker
770*e82f7db8SAndroid Build Coastguard Worker detached = request->detached;
771*e82f7db8SAndroid Build Coastguard Worker if (!detached) {
772*e82f7db8SAndroid Build Coastguard Worker if (request->options & JDWP_INVOKE_OPTIONS(SINGLE_THREADED)) {
773*e82f7db8SAndroid Build Coastguard Worker (void)threadControl_suspendThread(thread, JNI_FALSE);
774*e82f7db8SAndroid Build Coastguard Worker } else {
775*e82f7db8SAndroid Build Coastguard Worker (void)threadControl_suspendAll();
776*e82f7db8SAndroid Build Coastguard Worker }
777*e82f7db8SAndroid Build Coastguard Worker
778*e82f7db8SAndroid Build Coastguard Worker if (request->invokeType == INVOKE_CONSTRUCTOR) {
779*e82f7db8SAndroid Build Coastguard Worker /*
780*e82f7db8SAndroid Build Coastguard Worker * Although constructors technically have a return type of
781*e82f7db8SAndroid Build Coastguard Worker * void, we return the object created.
782*e82f7db8SAndroid Build Coastguard Worker */
783*e82f7db8SAndroid Build Coastguard Worker tag = specificTypeKey(env, request->returnValue.l);
784*e82f7db8SAndroid Build Coastguard Worker } else {
785*e82f7db8SAndroid Build Coastguard Worker tag = returnTypeTag(request->methodSignature);
786*e82f7db8SAndroid Build Coastguard Worker }
787*e82f7db8SAndroid Build Coastguard Worker id = request->id;
788*e82f7db8SAndroid Build Coastguard Worker exc = request->exception;
789*e82f7db8SAndroid Build Coastguard Worker returnValue = request->returnValue;
790*e82f7db8SAndroid Build Coastguard Worker }
791*e82f7db8SAndroid Build Coastguard Worker
792*e82f7db8SAndroid Build Coastguard Worker /*
793*e82f7db8SAndroid Build Coastguard Worker * At this time, there's no need to retain global references on
794*e82f7db8SAndroid Build Coastguard Worker * arguments since the reply is processed. No one will deal with
795*e82f7db8SAndroid Build Coastguard Worker * this request ID anymore, so we must call deleteGlobalArgumentRefs().
796*e82f7db8SAndroid Build Coastguard Worker *
797*e82f7db8SAndroid Build Coastguard Worker * We cannot delete saved exception or return value references
798*e82f7db8SAndroid Build Coastguard Worker * since otherwise a deleted handle would escape when writing
799*e82f7db8SAndroid Build Coastguard Worker * the response to the stream. Instead, we clean those refs up
800*e82f7db8SAndroid Build Coastguard Worker * after writing the respone.
801*e82f7db8SAndroid Build Coastguard Worker */
802*e82f7db8SAndroid Build Coastguard Worker deleteGlobalArgumentRefs(env, request);
803*e82f7db8SAndroid Build Coastguard Worker
804*e82f7db8SAndroid Build Coastguard Worker /*
805*e82f7db8SAndroid Build Coastguard Worker * Give up the lock before I/O operation
806*e82f7db8SAndroid Build Coastguard Worker */
807*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
808*e82f7db8SAndroid Build Coastguard Worker eventHandler_unlock();
809*e82f7db8SAndroid Build Coastguard Worker
810*e82f7db8SAndroid Build Coastguard Worker if (!detached) {
811*e82f7db8SAndroid Build Coastguard Worker outStream_initReply(&out, id);
812*e82f7db8SAndroid Build Coastguard Worker (void)outStream_writeValue(env, &out, tag, returnValue);
813*e82f7db8SAndroid Build Coastguard Worker (void)outStream_writeObjectTag(env, &out, exc);
814*e82f7db8SAndroid Build Coastguard Worker (void)outStream_writeObjectRef(env, &out, exc);
815*e82f7db8SAndroid Build Coastguard Worker outStream_sendReply(&out);
816*e82f7db8SAndroid Build Coastguard Worker }
817*e82f7db8SAndroid Build Coastguard Worker
818*e82f7db8SAndroid Build Coastguard Worker /*
819*e82f7db8SAndroid Build Coastguard Worker * Delete potentially saved global references of return value
820*e82f7db8SAndroid Build Coastguard Worker * and exception
821*e82f7db8SAndroid Build Coastguard Worker */
822*e82f7db8SAndroid Build Coastguard Worker eventHandler_lock(); // for proper lock order
823*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
824*e82f7db8SAndroid Build Coastguard Worker deletePotentiallySavedGlobalRefs(env, request);
825*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
826*e82f7db8SAndroid Build Coastguard Worker eventHandler_unlock();
827*e82f7db8SAndroid Build Coastguard Worker }
828*e82f7db8SAndroid Build Coastguard Worker
829*e82f7db8SAndroid Build Coastguard Worker jboolean
invoker_isPending(jthread thread)830*e82f7db8SAndroid Build Coastguard Worker invoker_isPending(jthread thread)
831*e82f7db8SAndroid Build Coastguard Worker {
832*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
833*e82f7db8SAndroid Build Coastguard Worker
834*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(thread);
835*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
836*e82f7db8SAndroid Build Coastguard Worker if (request == NULL) {
837*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
838*e82f7db8SAndroid Build Coastguard Worker }
839*e82f7db8SAndroid Build Coastguard Worker return request->pending;
840*e82f7db8SAndroid Build Coastguard Worker }
841*e82f7db8SAndroid Build Coastguard Worker
842*e82f7db8SAndroid Build Coastguard Worker jboolean
invoker_isEnabled(jthread thread)843*e82f7db8SAndroid Build Coastguard Worker invoker_isEnabled(jthread thread)
844*e82f7db8SAndroid Build Coastguard Worker {
845*e82f7db8SAndroid Build Coastguard Worker InvokeRequest *request;
846*e82f7db8SAndroid Build Coastguard Worker
847*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(thread);
848*e82f7db8SAndroid Build Coastguard Worker request = threadControl_getInvokeRequest(thread);
849*e82f7db8SAndroid Build Coastguard Worker if (request == NULL) {
850*e82f7db8SAndroid Build Coastguard Worker EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request");
851*e82f7db8SAndroid Build Coastguard Worker }
852*e82f7db8SAndroid Build Coastguard Worker return request->available;
853*e82f7db8SAndroid Build Coastguard Worker }
854*e82f7db8SAndroid Build Coastguard Worker
855*e82f7db8SAndroid Build Coastguard Worker void
invoker_detach(InvokeRequest * request)856*e82f7db8SAndroid Build Coastguard Worker invoker_detach(InvokeRequest *request)
857*e82f7db8SAndroid Build Coastguard Worker {
858*e82f7db8SAndroid Build Coastguard Worker JDI_ASSERT(request);
859*e82f7db8SAndroid Build Coastguard Worker debugMonitorEnter(invokerLock);
860*e82f7db8SAndroid Build Coastguard Worker request->detached = JNI_TRUE;
861*e82f7db8SAndroid Build Coastguard Worker debugMonitorExit(invokerLock);
862*e82f7db8SAndroid Build Coastguard Worker }
863