1 /* src/native/vm/VMjdwp.c - jvmti->jdwp interface
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Author: Martin Platter
32 $Id: VMjdwp.c 4996 2006-05-31 13:53:16Z motse $
36 #include "native/jvmti/jvmti.h"
37 #include "native/jvmti/VMjdwp.h"
42 void printjvmtierror(char *desc, jvmtiError err) {
45 if (err == JVMTI_ERROR_NONE) return;
46 (*jvmtienv)->GetErrorName(jvmtienv,err, &errdesc);
47 fprintf(stderr,"%s: jvmti error %s\n",desc, errdesc);
49 (*jvmtienv)->Deallocate(jvmtienv,(unsigned char*)errdesc);
54 static jmethodID notifymid = NULL;
55 static jclass Jdwpclass = NULL;
57 static void notify (JNIEnv* jni_env, jobject event){
58 fprintf(stderr,"VMjdwp notfiy called");
60 if (notifymid == NULL) {
61 notifymid = (*jni_env)->
62 GetStaticMethodID(jni_env,Jdwpclass,
63 "notify","(Lgnu/classpath/jdwp/event/Event;)V");
64 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
65 fprintf(stderr,"could not get notify method\n");
66 (*jni_env)->ExceptionDescribe(jni_env);
71 (*jni_env)->CallStaticVoidMethod(jni_env,Jdwpclass,notifymid,event);
72 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
73 fprintf(stderr,"Exception occourred in notify mehtod\n");
74 (*jni_env)->ExceptionDescribe(jni_env);
80 /*static void ThreadStart (jvmtiEnv *jvmti_env,
87 GETJNIMETHOD(jni_env,cl,"gnu/classpath/jdwp/event/ThreadStartEvent",cc,"<init>","(Ljava/lang/Thread;)V");
89 obj = builtin_new(cl);
90 if (!obj) throw_main_exception_exit();
92 fprintf(stderr,"VMjdwp:ThreadStart: thread %p\n",thread);
95 vm_call_method((methodinfo*)cc, obj, thread);
98 throw_main_exception_exit();
100 notify (jni_env,obj);
104 /* setup_jdwp_thread **********************************************************
106 Helper function to start JDWP listening thread
108 *******************************************************************************/
110 static void setup_jdwp_thread(JNIEnv* jni_env) {
115 /* new gnu.classpath.jdwp.Jdwp() */
116 Jdwpclass = (*jni_env)->FindClass(jni_env, "gnu/classpath/jdwp/Jdwp");
117 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
118 fprintf(stderr,"could not find gnu/classpath/jdwp/Jdwp\n");
119 (*jni_env)->ExceptionDescribe(jni_env);
124 m = (*jni_env)->GetMethodID(jni_env,Jdwpclass,"<init>","()V");
125 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
126 fprintf(stderr,"could not get Jdwp constructor\n");
127 (*jni_env)->ExceptionDescribe(jni_env);
131 o = (*jni_env)->NewObject(jni_env, Jdwpclass, m);
132 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
133 fprintf(stderr,"error calling Jdwp constructor\n");
134 (*jni_env)->ExceptionDescribe(jni_env);
139 /* configure(jdwpoptions) */
140 m = (*jni_env)->GetMethodID(jni_env,Jdwpclass,"configure",
141 "(Ljava/lang/String;)V");
142 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
143 fprintf(stderr,"could not get Jdwp configure method\n");
144 (*jni_env)->ExceptionDescribe(jni_env);
149 s = (*jni_env)->NewStringUTF(jni_env,jdwpoptions);
151 fprintf(stderr,"could not get new java string from jdwp options\n");
157 (*jni_env)->CallVoidMethod(jni_env,o,m,s);
158 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
159 fprintf(stderr,"Exception occourred in Jdwp configure\n");
160 (*jni_env)->ExceptionDescribe(jni_env);
164 m = (*jni_env)->GetMethodID(jni_env,Jdwpclass,"_doInitialization","()V");
165 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
166 fprintf(stderr,"could not get Jdwp _doInitialization method\n");
167 (*jni_env)->ExceptionDescribe(jni_env);
172 (*jni_env)->CallVoidMethod(jni_env,o,m);
173 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
174 fprintf(stderr,"Exception occourred in Jdwp _doInitialization\n");
175 (*jni_env)->ExceptionDescribe(jni_env);
181 static void VMInit (jvmtiEnv *jvmti_env,
189 fprintf(stderr,"JDWP VMInit\n");
191 /* startup gnu classpath jdwp thread */
192 setup_jdwp_thread(jni_env);
194 fprintf(stderr,"JDWP listening thread started\n");
196 cl = (*jni_env)->FindClass(jni_env,
197 "gnu/classpath/jdwp/event/VmInitEvent");
198 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
199 fprintf(stderr,"could not find class VMInitEvent\n");
200 (*jni_env)->ExceptionDescribe(jni_env);
204 m = (*jni_env)->GetMethodID(jni_env,cl,"<init>",
205 "(Ljava/lang/Thread;)V");
206 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
207 fprintf(stderr,"could not get VmInitEvent constructor\n");
208 (*jni_env)->ExceptionDescribe(jni_env);
212 eventobj = (*jni_env)->NewObject(jni_env, cl, m, thread);
213 if ((*jni_env)->ExceptionOccurred(jni_env) != NULL) {
214 fprintf(stderr,"error calling VmInitEvent constructor\n");
215 (*jni_env)->ExceptionDescribe(jni_env);
220 notify (jni_env,eventobj);
223 fprintf(stderr,"suspend initial thread\n");
224 err = (*jvmti_env)->SuspendThread(jvmti_env,thread);
225 printjvmtierror("error suspending initial thread",err);
229 static void VMDeath (jvmtiEnv *jvmti_env,
231 fprintf(stderr,"JVMTI-Event: IMPLEMENT ME!!!");
234 static void usage() {
235 puts("usage jdwp:[help]|(<option>=<value>),*");
236 puts(" transport=[dt_socket|...]");
237 puts(" address=<hostname:port>");
238 puts(" server=[y|n]");
239 puts(" suspend=[y|n]");
242 static bool processoptions(char *options) {
245 if (strncmp(options,"help",4) == 0) {
250 suspend = true; /* default value */
253 /* copy options for later use in java jdwp listen thread configure */
254 jdwpoptions = malloc(sizeof(char)*strlen(options));
255 strncpy(jdwpoptions, options, sizeof(char)*strlen(options));
257 len = strlen(options);
261 if (strncmp("suspend=",&options[i],8)==0) {
262 if (8>=strlen(&options[i])) {
263 if ((options[i+8]== 'y') || (options[i+8]== 'n')) {
264 suspend = options[i+8]== 'y';
266 printf("jdwp error argument: %s\n",options);
272 /* these options will be handled by jdwp java configure */
273 if ((strncmp("transport=",options,10)==0) ||
274 (strncmp("server=",options,7)==0)) {
276 printf("jdwp unkown argument: %s\n",options);
281 while ((options[i]!=',')&&(i<len)) i++;
288 JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
291 jvmtiCapabilities cap;
295 fprintf(stderr,"jdwp Agent_OnLoad options: %s\n",options);
296 if (!processoptions(options)) return -1;
298 rc = (*vm)->GetEnv(vm, (void**)&jvmtienv, JVMTI_VERSION_1_0);
300 fprintf(stderr, "jdwp: Unable to get jvmtiEnv error=%d\n", rc);
304 /* set eventcallbacks */
305 if (JVMTI_ERROR_NONE !=
306 (e = (*jvmtienv)->SetEventCallbacks(jvmtienv,
307 &jvmti_jdwp_EventCallbacks,
308 sizeof(jvmtiEventCallbacks)))){
309 printjvmtierror("jdwp: unable to setup event callbacks", e);
313 e = (*jvmtienv)->GetPotentialCapabilities(jvmtienv, &cap);
314 printjvmtierror("jdwp: unable to get potential capabilities", e);
315 if (e == JVMTI_ERROR_NONE)
316 e = (*jvmtienv)->AddCapabilities(jvmtienv, &cap);
317 if (e != JVMTI_ERROR_NONE) {
318 printjvmtierror("jdwp: error adding jvmti capabilities", e);
323 end = sizeof(jvmtiEventCallbacks) / sizeof(void*);
324 for (i = 0; i < end; i++) {
325 /* enable VM callbacks */
326 if (((void**)&jvmti_jdwp_EventCallbacks)[i] != NULL) {
327 e = (*jvmtienv)->SetEventNotificationMode(jvmtienv,
329 JVMTI_EVENT_START_ENUM+i,
332 if (JVMTI_ERROR_NONE != e) {
333 printjvmtierror("jdwp: unable to setup event notification mode",e);
343 jvmtiEventCallbacks jvmti_jdwp_EventCallbacks = {
346 NULL, /* &ThreadStart,*/
347 NULL, /* &ThreadEnd, */
348 NULL, /* &ClassFileLoadHook, */
349 NULL, /* &ClassLoad, */
350 NULL, /* &ClassPrepare,*/
352 NULL, /* &Exception, */
353 NULL, /* &ExceptionCatch, */
354 NULL, /* &SingleStep, */
355 NULL, /* &FramePop, */
356 NULL, /* &Breakpoint, */
357 NULL, /* &FieldAccess, */
358 NULL, /* &FieldModification, */
359 NULL, /* &MethodEntry, */
360 NULL, /* &MethodExit, */
361 NULL, /* &NativeMethodBind, */
362 NULL, /* &CompiledMethodLoad, */
363 NULL, /* &CompiledMethodUnload, */
364 NULL, /* &DynamicCodeGenerated, */
365 NULL, /* &DataDumpRequest, */
367 NULL, /* &MonitorWait, */
368 NULL, /* &MonitorWaited, */
369 NULL, /* &MonitorContendedEnter, */
370 NULL, /* &MonitorContendedEntered, */
375 NULL, /* &GarbageCollectionStart, */
376 NULL, /* &GarbageCollectionFinish, */
377 NULL, /* &ObjectFree, */
378 NULL, /* &VMObjectAlloc, */
383 * These are local overrides for various environment variables in Emacs.
384 * Please do not remove this and leave it at the end of the file, where
385 * Emacs will automagically detect them.
386 * ---------------------------------------------------------------------
389 * indent-tabs-mode: t