major rework of jvmti. now we have three processes in jvmti mode. there are still...
authormotse <none@none>
Tue, 21 Mar 2006 00:04:59 +0000 (00:04 +0000)
committermotse <none@none>
Tue, 21 Mar 2006 00:04:59 +0000 (00:04 +0000)
18 files changed:
src/cacao/cacao.c
src/native/jni.h
src/native/jvmti/Makefile.am
src/native/jvmti/VMjdwp.c
src/native/jvmti/cacaodbg.c [new file with mode: 0644]
src/native/jvmti/cacaodbg.h [new file with mode: 0644]
src/native/jvmti/cacaodbgserver.c [new file with mode: 0644]
src/native/jvmti/cacaodbgserver.h [new file with mode: 0644]
src/native/jvmti/dbg.c [new file with mode: 0644]
src/native/jvmti/dbg.h
src/native/jvmti/jvmti.c
src/native/jvmti/jvmti.h
src/native/native.c
src/native/vm/Makefile.am
src/native/vm/VMVirtualMachine.c
src/threads/native/threads.c
src/threads/native/threads.h
src/vm/vm.c

index 12e00846b1e73d1cbd704b53e0d8919b67de8081..154d1a9994944947ba0c69bb255a13751d69a32c 100644 (file)
@@ -31,7 +31,7 @@
             Philipp Tomsich
             Christian Thalinger
 
-   $Id: cacao.c 4630 2006-03-16 14:00:48Z twisti $
+   $Id: cacao.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
 
 #if defined(ENABLE_JVMTI)
 #include "native/jvmti/jvmti.h"
-#include "native/jvmti/dbg.h"
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/wait.h>
+#include "native/jvmti/cacaodbg.h"
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#include <pthread.h>
+#endif
 #endif
 
 #include "toolbox/logging.h"
 #include "vm/jit/verify/typeinfo.h"
 #endif
 
-
 #ifdef TYPECHECK_STATISTICS
 void typecheck_print_statistics(FILE *file);
 #endif
 
-/* setup_debugger_process *****************************************************
-
-   Helper function to start JDWP threads
-
-*******************************************************************************/
-#if defined(ENABLE_JVMTI)
-
-static void setup_debugger_process(char* transport) {
-       java_objectheader *o;
-       methodinfo *m;
-       java_lang_String  *s;
-
-       /* new gnu.classpath.jdwp.Jdwp() */
-       mainclass = 
-               load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
-       if (!mainclass)
-               throw_main_exception_exit();
-
-       o = builtin_new(mainclass);
-
-       if (!o)
-               throw_main_exception_exit();
-       
-       m = class_resolveclassmethod(mainclass,
-                                                                utf_init, 
-                                                                utf_java_lang_String__void,
-                                                                class_java_lang_Object,
-                                                                true);
-       if (!m)
-               throw_main_exception_exit();
-
-       (void) vm_call_method(m, o);
-
-       /* configure(transport,NULL) */
-       m = class_resolveclassmethod(
-               mainclass, utf_new_char("configure"), 
-               utf_new_char("(Ljava/lang/String;Ljava/lang/Thread;)V"),
-               class_java_lang_Object,
-               false);
-
-
-       s = javastring_new_char(transport);
-
-       (void) vm_call_method(m, o, s);
-
-       if (!m)
-               throw_main_exception_exit();
-
-       /* _doInitialization */
-       m = class_resolveclassmethod(mainclass,
-                                                                utf_new_char("_doInitialization"), 
-                                                                utf_new_char("()V"),
-                                                                mainclass,
-                                                                false);
-       
-       if (!m)
-               throw_main_exception_exit();
-
-       (void) vm_call_method(m, o);
-}
-#endif
-
-
 /* getmainclassfromjar *********************************************************
 
    Gets the name of the main class form a JAR's manifest file.
@@ -241,7 +177,6 @@ static char *getmainclassnamefromjar(char *mainstring)
        return javastring_tochar(o);
 }
 
-
 void exit_handler(void);
 
 
@@ -253,7 +188,9 @@ void exit_handler(void);
 
 int main(int argc, char **argv)
 {
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        void *dummy;
+#endif
        s4 i;
        
        /* local variables ********************************************************/
@@ -261,10 +198,11 @@ int main(int argc, char **argv)
        JavaVMInitArgs *vm_args;
        JavaVM         *jvm;                /* denotes a Java VM                  */
 
-#if defined(ENABLE_JVMTI)
-       bool dbg = false;
-       char *transport;
-       int waitval;
+
+#if defined(NDEBUG)
+       /* motse: for jdwp/jvmti debugging*/
+       for (i=0; i<argc; i++)
+               fprintf(stderr,"argument string[%d]: %s\n",i,argv[i]);
 #endif
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
@@ -290,7 +228,8 @@ int main(int argc, char **argv)
        JNI_CreateJavaVM(&jvm, (void **) &_Jv_env, vm_args);
 
 #if defined(ENABLE_JVMTI)
-       set_jvmti_phase(JVMTI_PHASE_START);
+       if (dbgprocess && jvmti && jdwp) /* is this the parent/debugger process ? */
+               set_jvmti_phase(JVMTI_PHASE_START);
 #endif
 
        /* do we have a main class? */
@@ -380,56 +319,24 @@ int main(int argc, char **argv)
 #endif
                /*class_showmethods(currentThread->group->header.vftbl->class); */
 
-#if defined(ENABLE_JVMTI) && defined(NATIVE_THREADS)
-               if(dbg) {
-                       debuggee = fork();
-                       if (debuggee == (-1)) {
-                               log_text("fork error");
-                               exit(1);
-                       } else {
-                               if (debuggee == 0) {
-                                       /* child: allow helper process to trace us  */
-                                       if (TRACEME != 0)  exit(0);
-                                       
-                                       /* give parent/helper debugger process control */
-                                       kill(0, SIGTRAP);  /* do we need this at this stage ? */
-
-                                       /* continue with normal startup */      
-
-                               } else {
-
-                                       /* parent/helper debugger process */
-                                       wait(&waitval);
-
-                                       remotedbgjvmtienv = new_jvmtienv();
-                                       /* set eventcallbacks */
-                                       if (JVMTI_ERROR_NONE == 
-                                               remotedbgjvmtienv->
-                                               SetEventCallbacks(remotedbgjvmtienv,
-                                                                                 &jvmti_jdwp_EventCallbacks,
-                                                                                 sizeof(jvmti_jdwp_EventCallbacks))){
-                                               log_text("unable to setup event callbacks");
-                                               vm_exit(1);
-                                       }
-
-                                       /* setup listening process (JDWP) */
-                                       setup_debugger_process(transport);
 
-                                       /* start to be debugged program */
-                                       CONT(debuggee);
 
-                    /* exit debugger process - todo: cleanup */
-                                       joinAllThreads();
-                                       cacao_exit(0);
-                               }
-                       }
+#if defined(ENABLE_JVMTI)
+               /* if this is the parent process than start the jdwp listening */
+               if (jvmti || jdwp) {
+                       fprintf(stderr, "jdwp/debugger set herewego brkpt %p\n",&&herewego);
+                       setsysbrkpt(HEREWEGOBRK,&&herewego);
+                       if (dbgprocess && jdwp) cacaodbglisten(transport); 
                }
-               else 
-                       debuggee= -1;
+
                
+               if (!dbgprocess) {
+                       fprintf(stderr,"debuggee: herewe go\n");
+                       fflush(stderr);
+               }
 #endif
                /* here we go... */
-
+       herewego:
                (void) vm_call_method(m, NULL, oa);
 
                /* exception occurred? */
index 8ab484cb8b371cb9fc1745732aeee4908a3a1df1..31a97446a2655a4087edabf5c5f17e1607b78aa1 100644 (file)
@@ -29,7 +29,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: jni.h 4565 2006-03-07 09:40:37Z twisti $
+   $Id: jni.h 4661 2006-03-21 00:04:59Z motse $
 
 */
 
@@ -110,9 +110,6 @@ bool jni_init(void);
 java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o,
                                                                                java_objectarray *params);
 
-extern void* ptr_env;
-extern struct JNINativeInterface JNI_JNIEnvTable;
-
 #endif /* _JNI_H */
 
 
index a0e48696f6943cd89d441bbadd7cccf475fad679..b9ce4697a4942ba65e20b2239ac0db7e0c9cf385 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes:
 ##
-## $Id: Makefile.am 4357 2006-01-22 23:33:38Z twisti $
+## $Id: Makefile.am 4661 2006-03-21 00:04:59Z motse $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -40,7 +40,13 @@ libjvmti_la_SOURCES = \
        jvmti.c \
        jvmti.h \
        VMjdwp.c \
-       dbg.h
+       dbg.h\
+        dbg.c\
+        cacaodbg.h \
+        cacaodbg.c \
+       cacaodbgserver.c \
+       cacaodbgserver.h
+
 
 
 ## Local variables:
index 030c125302ae4e02ec7f5ff443e31b8ad7041ec5..34811dcf86d354403e9852eb6d6d296b16fce8d5 100644 (file)
    Changes:             
 
 
-   $Id: VMjdwp.c 4357 2006-01-22 23:33:38Z twisti $
+   $Id: VMjdwp.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
-#include "jvmti.h"
+#include "native/jvmti/jvmti.h"
+#include "native/jvmti/cacaodbg.h"
 #include "vm/loader.h"
 #include "vm/exceptions.h"
 #include "vm/jit/asmpart.h"
 
-static jmethodID notifymid = NULL;
-static jclass Jdwpclass = NULL;
+#include <stdlib.h>
+
+
+static methodinfo *notifymid = NULL;
+static classinfo *Jdwpclass = NULL;
+
+
+#define FINDCLASS(jni_env,class,classname) \
+  class = load_class_from_sysloader(utf_new_char(classname)); \
+  if (!class) throw_main_exception_exit();
+
+#define GETJNIMETHOD(jni_env,class,classname,method,methodname,methodsig) \
+  FINDCLASS(jni_env,class,classname) \
+  method = class_resolveclassmethod (class,utf_new_char(methodname), \
+                                                                        utf_new_char(methodsig),        \
+                                                                        class_java_lang_Object,true);   \
+  if (!method) throw_main_exception_exit();
+#define GETJNISTATICMETHOD(jni_env,class,classname,method,methodname,methodsig) \
+  FINDCLASS(jni_env,class,classname) \
+  method = class_resolveclassmethod (class,utf_new_char(methodname), \
+                                                                        utf_new_char(methodsig),        \
+                                                                        class_java_lang_Object,true);   \
+  if (!method) throw_main_exception_exit();  
+
+
+static void notify (JNIEnv* env, jobject event){
+       log_text("VMjdwp notfiy called");
 
-void notify (jobject event){
-       methodinfo *m;
     if (notifymid == NULL) {
-        Jdwpclass = 
-            load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
-        if (!Jdwpclass)
-            throw_main_exception_exit();
-        
-        notifymid = class_resolveclassmethod(
-            Jdwpclass,
-            utf_new_char("notify"), 
-            utf_new_char("(Lgnu.classpath.jdwp.event.Event;)V"),
-            class_java_lang_Object,
-            true);
-
-        if (!notifymid)
-            throw_main_exception_exit();
+               GETJNISTATICMETHOD(env,Jdwpclass,"gnu/classpath/jdwp/Jdwp",notifymid,
+                                                  "notify","(Lgnu/classpath/jdwp/event/Event;)V");
+               
     }
     
-    asm_calljavafunction(m, Jdwpclass, event, NULL, NULL);
+       vm_call_method(notifymid, NULL ,event);
+       if (*exceptionptr)
+               throw_main_exception_exit();
+
 }
 
 
@@ -161,7 +179,24 @@ static void ExceptionCatch (jvmtiEnv *jvmti_env,
 static void ThreadStart (jvmtiEnv *jvmti_env,
                          JNIEnv* jni_env,
                          jthread thread){
-  log_text ("JVMTI-Event: IMPLEMENT ME!!!");
+       jclass cl;
+       jmethodID cc;
+       jobject obj;
+
+       GETJNIMETHOD(jni_env,cl,"gnu/classpath/jdwp/event/ThreadStartEvent",cc,"<init>","(Ljava/lang/Thread;)V"); 
+
+       obj = builtin_new(cl);
+       if (!obj) throw_main_exception_exit();
+
+       fprintf(stderr,"VMjdwp:ThreadStart: thread %p\n",thread);
+       fflush(stderr);
+
+       vm_call_method((methodinfo*)cc, obj, thread);
+
+       if (*exceptionptr)
+               throw_main_exception_exit();
+
+       notify (jni_env,obj);
 }
 
 static void ThreadEnd (jvmtiEnv *jvmti_env,
@@ -199,13 +234,35 @@ static void ClassFileLoadHook (jvmtiEnv *jvmti_env,
 
 static void VMStart (jvmtiEnv *jvmti_env,
                      JNIEnv* jni_env) {
-  log_text ("JVMTI-Event: IMPLEMENT ME!!!");
+  log_text ("JVMTI-Event:VMStart IMPLEMENT ME!!!");
 }
 
 static void VMInit (jvmtiEnv *jvmti_env, 
                     JNIEnv* jni_env,
                     jthread thread) {
-  log_text ("JVMTI-Event: IMPLEMENT ME!!!");
+       classinfo* cl;
+       methodinfo* cc;
+       java_objectheader* obj;
+
+       log_text ("JVMTI-Event:VMInit");
+
+       GETJNIMETHOD(jni_env,cl,"gnu/classpath/jdwp/event/VmInitEvent",cc,"<init>",
+                                "(Ljava/lang/Thread;)V"); 
+
+       fprintf(stderr,"VMjdwp:VMInit: 1\n");
+
+       obj = builtin_new(cl);
+       if (!obj) throw_main_exception_exit();
+
+       fprintf(stderr,"VMjdwp:VMInit: thread %p\n",thread);
+       fflush(stderr);
+
+       vm_call_method((methodinfo*)cc, obj, thread);
+
+       if (*exceptionptr)
+               throw_main_exception_exit();
+
+       notify (jni_env,obj);
 }
 
 static void VMDeath (jvmtiEnv *jvmti_env,
@@ -294,7 +351,49 @@ static void GarbageCollectionFinish (jvmtiEnv *jvmti_env){
 }
 
 
-jvmtiEventCallbacks jvmti_jdwp_EventCallbacks = {
+bool VMjdwpInit(jvmtiEnv* env) {
+       int end, i=0;
+       jvmtiCapabilities cap;
+       jvmtiError e;
+
+
+       /* set eventcallbacks */
+       if (JVMTI_ERROR_NONE != 
+               (*env)->SetEventCallbacks(env,
+                                                          &jvmti_jdwp_EventCallbacks,
+                                                          sizeof(jvmti_jdwp_EventCallbacks))){
+               log_text("unable to setup event callbacks");
+               return false;
+       }
+       
+       e = (*env)->GetPotentialCapabilities(env, &cap);
+       if (e == JVMTI_ERROR_NONE) {
+               e = (*env)->AddCapabilities(env, &cap);
+       }
+       if (e != JVMTI_ERROR_NONE) {
+               log_text("error adding jvmti capabilities");
+               exit(1);
+       }
+
+       end = sizeof(jvmti_jdwp_EventCallbacks) / sizeof(void*);
+       for (i = 0; i < end; i++) {
+               /* enable standard VM callbacks  */
+               if (((void**)&jvmti_jdwp_EventCallbacks)[i] != NULL) {
+                       e = (*env)->SetEventNotificationMode(env,
+                                                                                               JVMTI_ENABLE,
+                                                                                               JVMTI_EVENT_START_ENUM+i,
+                                                                                               NULL);
+
+                       if (JVMTI_ERROR_NONE != e) {
+                               log_text("unable to setup event notification mode");
+                               return false;
+                       }
+               }
+       }
+       return true;
+}
+       
+       jvmtiEventCallbacks jvmti_jdwp_EventCallbacks = {
     &VMInit,
     &VMDeath,
     &ThreadStart,
@@ -302,7 +401,7 @@ jvmtiEventCallbacks jvmti_jdwp_EventCallbacks = {
     &ClassFileLoadHook,
     &ClassLoad,
     &ClassPrepare,
-    &VMStart,
+    NULL, /* &VMStart */
     &Exception,
     &ExceptionCatch,
     &SingleStep,
diff --git a/src/native/jvmti/cacaodbg.c b/src/native/jvmti/cacaodbg.c
new file mode 100644 (file)
index 0000000..cb0ad4b
--- /dev/null
@@ -0,0 +1,670 @@
+/* src/native/jvmti/cacaodbg.c - contains entry points for debugging support 
+                                 in cacao.
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Martin Platter
+
+   Changes: 
+
+
+   $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
+
+*/
+
+#include "native/jvmti/jvmti.h"
+#include "native/jvmti/cacaodbg.h"
+#include "native/jvmti/cacaodbgserver.h"
+#include "native/jvmti/dbg.h"
+#include "vm/vm.h"
+#include "vm/loader.h"
+#include "vm/exceptions.h"
+#include "vm/builtin.h"
+#include "vm/jit/asmpart.h"
+#include "vm/stringlocal.h"
+#include "toolbox/logging.h"
+#include "threads/native/threads.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <semaphore.h>
+#include <sys/msg.h>
+#include <linux/user.h>
+#include <assert.h>
+
+/* count the request for workingdatalock */
+static int workingdatanum = 0;
+
+
+/* msgqsendevent ***************************************************************
+
+   sends a ptrace request to the cacaodbgserver process through the message 
+   queue
+
+*******************************************************************************/
+
+static void msgqsendevent(ptrace_request *pt, ptrace_reply** rcvbuf, int buflen) {
+       int size;
+
+       pt->mtype = MSGQPTRACESND;
+
+       fprintf(stderr,"msgqsendevent send new message (kind %d)\n",pt->kind);
+       if (-1 == msgsnd(msgqid, pt, sizeof(ptrace_request), 0))
+               perror("debugger process: msgqsendevent send error: ");
+
+       size = sizeof(ptrace_reply)+buflen;
+       *rcvbuf =(ptrace_reply*) heap_allocate(size,true,NULL);
+
+       if (-1 == msgrcv(msgqid, *rcvbuf, size, MSGQPTRACERCV, 0))
+               perror("debugger process: msgqsendevent receive error: ");
+       fprintf(stderr,"msgqsendevent reply received(kind %d)\n",pt->kind);
+}
+
+
+/* getworkingdatalock *********************************************************
+
+   blocks until the workingdata lock has been obtained
+
+*******************************************************************************/
+
+void getworkingdatalock() {
+       workingdatanum++;
+       if (workingdatanum==1) sem_wait(&workingdata_lock);
+}
+
+/* releaseworkingdatalock *********************************************************
+
+   release workingdata lock
+
+*******************************************************************************/
+
+void releaseworkingdatalock() {
+       workingdatanum--;
+       assert(workingdatanum>=0);
+       if (workingdatanum==0) sem_post(&workingdata_lock);
+}
+
+/* getchildproc ***************************************************************
+
+   Get data count number of bytes from address addr for child process address 
+   space. After a successfull call *ptr points to a newly created array 
+   containing the requested data.
+
+*******************************************************************************/
+
+void getchildproc (char **ptr, void* addr, int count) {
+       ptrace_request pt;
+       ptrace_reply  *rcvbuf;
+       
+       stopdebuggee();
+
+       pt.kind = PTPEEKDATA;
+       pt.addr = addr;
+       pt.data = count;
+
+       msgqsendevent (&pt,&rcvbuf,count);
+       *ptr = rcvbuf->data;
+
+       contdebuggee(0);
+}
+
+/* threadobject2jthread *******************************************************
+
+   Convert a cacao threadobject to jthread (java_lang_Thread)
+
+*******************************************************************************/
+jthread threadobject2jthread(threadobject* thread) {
+       java_lang_Thread* t;
+       
+       stopdebuggee();
+
+       fprintf (stderr,"debugger: threadobject2jthread\n");
+       fflush(stderr); 
+
+       getchildproc((char**)&t, thread->o.thread, sizeof(java_lang_Thread));
+       t->header.vftbl = class_java_lang_Thread->vftbl;
+       t->vmThread = thread;
+
+       fprintf (stderr,"debugger: threadobject2jthread done (t: %p)\n",t);
+       fflush(stderr); 
+
+       contdebuggee(0);
+
+       return (jthread)t;
+}
+
+/* allthreads *****************************************************************
+
+   Gets an array of threadobjects of all threads
+
+*******************************************************************************/
+jvmtiError allthreads (jint * threads_count_ptr, threadobject ** threads_ptr) {
+    int i = 0, cnt = 8; 
+       char *data;
+    threadobject *thread, *tthreads;;
+       void **addr, *mainthread;
+
+       stopdebuggee();
+
+       fprintf (stderr,"debugger: allthreads: addr of mainthreadobj: %p sizeof(threadobject*) %d sizeof(long) %d\n",&mainthreadobj,sizeof(threadobject*),sizeof(long));
+       fflush(stderr); 
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       tthreads = MNEW(jthread, (sizeof(threadobject) * cnt));
+
+       stopdebuggee();
+       /* mainthreadobj is in the same place in the child process memory because 
+          the child is a copy of this process */
+       getchildproc(&data, &mainthreadobj,sizeof(threadobject*));
+       addr = (void**) data;
+       mainthread = *addr;
+
+    do {
+               getchildproc(&data, *addr, sizeof(threadobject));
+               thread = (threadobject*) data;
+               fprintf (stderr,"debugger: get all threads addr %X *addr %X thread->info.prev %p &data %p data %p\n",addr, *addr, &(thread->info.prev), &data, data);
+
+        if(thread->o.thread != NULL) {
+                       fprintf (stderr,"debugger: get all threads: thread alive (i %d cnt %d tthreads %p)\n",i,cnt,tthreads);
+                       fflush(stderr); 
+
+                  /* count and copy only live threads */
+                  if (i>=cnt) {
+                          MREALLOC(tthreads,threadobject,cnt,cnt+8);
+                          cnt += 8;
+                  }
+                  memcpy(&tthreads[i],thread,sizeof(threadobject));
+                  fprintf(stderr,"allthreads - i %d  tthreads[i].o.thread %p\n",i,tthreads[i].o.thread);
+                  i++;
+               }
+               *addr = (void*)thread->info.prev;
+
+               /* repeat until we got the pointer to the mainthread twice */
+       } while (mainthread != *addr);
+
+       fprintf (stderr,"debugger: get all threads: %d thread alive - going to copy\n",i);
+       fflush(stderr); 
+
+    *threads_count_ptr = i;
+       
+    *threads_ptr = (threadobject*) heap_allocate(sizeof(threadobject) * i,true,NULL);
+       memcpy(*threads_ptr,tthreads,sizeof(threadobject)*i);
+       MFREE(tthreads,threadobject,cnt);
+       
+       fprintf (stderr,"debugger: get all threads: done\n");
+       fflush(stderr); 
+
+       contdebuggee(0);
+
+    return JVMTI_ERROR_NONE;
+#else
+       return JVMTI_ERROR_NOT_AVAILABLE;
+#endif
+}
+
+
+/* getcurrentthread ***********************************************************
+
+   Get jthread structure of current thread. 
+
+*******************************************************************************/
+jthread getcurrentthread() {
+    /* get current thread through stacktrace. */
+       threadobject *threads;
+       threadobject *currthread=(threadobject*)0xffffffff; /* 32 bit max value */
+       jint tcnt;
+       int i;
+    struct user_regs_struct *regs;
+       ptrace_request pt;
+       ptrace_reply* rcvbuf;
+
+       assert (allthreads(&tcnt, &threads) == JVMTI_ERROR_NONE);
+       
+       pt.kind=PTGETREG;
+       msgqsendevent(&pt,&rcvbuf,sizeof(struct user_regs_struct));
+       regs = rcvbuf->data;
+       
+
+       /* ebp address of current thread has to have a smaller nummeric value then
+          the bottom of the stack whose address is in 
+          currentthread->info._stackframeinfo; and a stack can belong to only one 
+          thread.
+          exception: before mainthread has been started
+        */
+       
+       if (threads[0].info._stackframeinfo != NULL) { 
+               fprintf (stderr,"debugger: get all threads: done\n");
+               for (i=0;i<tcnt;i++) {
+                       if ((regs->ebp < (long)threads[i].info._stackframeinfo)
+                               && ((long)&threads[i]> (long)currthread))
+                               currthread = &threads[i];
+               }
+       } else {
+        /* if the mainthread has not been started yet return mainthread */
+               fprintf (stderr,"debugger: getcurrentthread mainthreadobj - threads[0].o.thread %p\n",threads[0].o.thread);
+               currthread = &threads[0];
+       }
+
+       return (jthread)threadobject2jthread(currthread);
+}
+
+
+/* contdebuggee ****************************************************************
+
+   Send request to continue debuggee process through the message queue to the 
+   cacaodbgserver process.
+
+*******************************************************************************/
+
+bool contdebuggee(int signal) {
+       ptrace_request pt;
+       ptrace_reply  *rcvbuf;
+
+       /* get lock for running state */ 
+       getworkingdatalock();
+       cdbgshmem->hastostop--; 
+
+       if ((!cdbgshmem->running)&&(cdbgshmem->hastostop==0)) {
+               /* release lock for running state */ 
+               releaseworkingdatalock();
+               pt.kind=PTCONT;
+               pt.data=signal;
+               msgqsendevent (&pt,&rcvbuf,sizeof(bool));
+               return  *((bool*)rcvbuf->data);
+       } else {
+               /* release lock for running state */ 
+               releaseworkingdatalock();
+               return false;
+       }
+}
+
+
+/* stopdebuggee ***************************************************************
+
+   Helper function to stop debugge process. It only sends a signal to stop if 
+   the debuggee is not already stopped.
+
+*******************************************************************************/
+void stopdebuggee() {
+       /* get lock for running state */ 
+       getworkingdatalock();
+       cdbgshmem->hastostop++;
+       if (cdbgshmem->running) {
+               fprintf (stderr,"debugger process: going to stop debuggee\n");
+               fflush(stderr); 
+               /* release lock for running state */ 
+               releaseworkingdatalock();
+
+               if (kill (debuggee, SIGUSR2)==-1) {
+                       perror("debugger process: stopdebuggee kill error: ");
+               }
+       } else 
+               /* release lock for running state */ 
+               releaseworkingdatalock();
+}
+
+
+/* brktablecreator*************************************************************
+
+   helper function to enlarge the breakpoint table if needed
+
+*******************************************************************************/
+
+static void brktablecreator() {
+       struct _brkpt* tmp;
+       if (jvmtibrkpt.size == 0) {
+               jvmtibrkpt.brk = MNEW(struct _brkpt, 16);
+               memset(jvmtibrkpt.brk, 0, sizeof(struct _brkpt)*16);
+               jvmtibrkpt.size = 16;
+               jvmtibrkpt.num = BEGINUSERBRK;
+       } else {
+               jvmtibrkpt.size += 16;
+               tmp = jvmtibrkpt.brk;
+               jvmtibrkpt.brk = MNEW(struct _brkpt, jvmtibrkpt.size);
+               memset(jvmtibrkpt.brk, 0, sizeof(struct _brkpt)*jvmtibrkpt.size);
+               memcpy((void*)jvmtibrkpt.brk,(void*)tmp,jvmtibrkpt.size);
+               MFREE(tmp,struct _brkpt,jvmtibrkpt.size-16);
+       }       
+}
+
+
+/* setsysbrkpt ****************************************************************
+
+   sets a system breakpoint int breakpoint table and calls set breakpoint
+
+*******************************************************************************/
+
+void setsysbrkpt(int sysbrk, void* addr) {
+       ptrace_request pt;
+       ptrace_reply  *rcvbuf;
+       
+       if (jvmtibrkpt.size == jvmtibrkpt.num)
+               brktablecreator();
+
+       assert (sysbrk < BEGINUSERBRK);
+       jvmtibrkpt.brk[sysbrk].addr = addr;
+
+       pt.kind = PTSETBRK;
+       pt.addr = addr;
+       msgqsendevent (&pt, &rcvbuf, sizeof(long));
+
+       jvmtibrkpt.brk[sysbrk].orig = ((long*)rcvbuf->data)[0];
+
+       fprintf (stderr,"setsysbrk %d %X  done\n",sysbrk, addr);
+}
+
+
+/* addbrkpt *******************************************************************
+
+   adds a breakpoint to breakpoint table and calls set breakpoint
+
+*******************************************************************************/
+
+void addbrkpt(void* addr, jmethodID method, jlocation location) {
+       ptrace_request pt;
+       ptrace_reply  *rcvbuf;
+
+       if (jvmtibrkpt.size == jvmtibrkpt.num)
+               brktablecreator();
+
+       assert (jvmtibrkpt.size > jvmtibrkpt.num);
+       fprintf (stderr,"add brk add: %X\n",addr);
+       jvmtibrkpt.brk[jvmtibrkpt.num].addr = addr;
+       jvmtibrkpt.brk[jvmtibrkpt.num].method = method;
+       jvmtibrkpt.brk[jvmtibrkpt.num].location = location;
+
+       pt.kind = PTSETBRK;
+       pt.addr = addr;
+       msgqsendevent (&pt, &rcvbuf, sizeof(long));
+       
+       jvmtibrkpt.brk[jvmtibrkpt.num].orig = ((long*)rcvbuf->data)[0];
+       jvmtibrkpt.num++;
+
+       fprintf (stderr,"add brk done\n");
+}
+
+
+/* setup_jdwp_thread *****************************************************
+
+   Helper function to start JDWP threads
+
+*******************************************************************************/
+
+static void setup_jdwp_thread(char* transport) {
+       java_objectheader *o;
+       methodinfo *m;
+       java_lang_String  *s;
+       classinfo *class;
+
+       /* new gnu.classpath.jdwp.Jdwp() */
+       class = load_class_from_sysloader(
+            utf_new_char("gnu.classpath.jdwp.Jdwp"));
+       if (!class)
+               throw_main_exception_exit();
+
+       o = builtin_new(class);
+
+       if (!o)
+               throw_main_exception_exit();
+       
+       m = class_resolveclassmethod(class,
+                                     utf_init, 
+                                     NULL,
+                                     class_java_lang_Object,
+                                     true);
+       if (!m)
+            throw_main_exception_exit();
+        
+       vm_call_method(m,o);
+        
+       /* configure(transport,NULL) */
+       m = class_resolveclassmethod(
+            class, utf_new_char("configure"), 
+            utf_new_char("(Ljava/lang/String;)V"),
+            class_java_lang_Object,
+            false);
+
+       s = javastring_new_char(&transport[1]);
+
+       vm_call_method(m,o,s);
+
+       if (!m)
+               throw_main_exception_exit();
+
+
+       /* _doInitialization */
+       m = class_resolveclassmethod(class,
+                                     utf_new_char("_doInitialization"), 
+                                     utf_new_char("()V"),
+                                     class,
+                                     false);
+       
+       if (!m)
+            throw_main_exception_exit();
+        
+       vm_call_method(m,o);
+}
+
+/* cacaodbglisten *************************************************************
+
+   setup listener thread for JDWP
+
+*******************************************************************************/
+
+void cacaodbglisten(char* transport) {
+       basic_event ev;
+       genericEventData data;
+       int i;
+
+       fprintf(stderr, "jdwp/debugger process jdwp pid %d\n",getpid()); 
+    fflush (stderr); 
+
+    log_text("jdwp/debugger process - set up jdwp listening thread");
+
+    /* setup listening thread (JDWP) */
+    setup_jdwp_thread(transport);
+
+    log_text("jdwp/debugger process - continue debuggee");
+    /* start to be debugged program */
+       contdebuggee(0);
+
+       /* handle messages from cacaodbgserver */
+       while (true) {
+               if (-1 == msgrcv(msgqid,&ev,sizeof(basic_event),MSGQDEBUGGER,0))
+                       perror("debugger process: cacaodbglisten: ");
+               
+               switch (ev.signal) {
+               case SIGTRAP:
+                       /* search the breakpoint that has been triggered */
+                       i=0;
+                       while ((ev.ip!=jvmtibrkpt.brk[i].addr) && (i<jvmtibrkpt.num)) i++;
+
+                       fprintf(stderr,"cacaodbglisten SIGTRAP switch after while loop i %d\n",i);
+
+                       switch (i) {
+                       case HEREWEGOBRK:
+                               /* herewego trap */
+                               if (!suspend) {
+                                       fprintf(stderr,"cacaodbglisten suspend false -> continue debuggee\n");
+                                       contdebuggee(0);
+                               } else {
+                                       fprintf(stderr,"cacaodbglisten suspend true -> do no continue debuggee\n");
+                                       getworkingdatalock();
+                                       cdbgshmem->hastostop=1;
+                                       releaseworkingdatalock();       
+                               }
+                               set_jvmti_phase(JVMTI_PHASE_LIVE);
+                               break;
+                       case SETTHREADOBJECTBRK:
+                                /* setthreadobject */
+                               fprintf(stderr,"IP %X == setthreadobject\n",ev.ip);
+                               data.ev=JVMTI_EVENT_THREAD_START;
+                               fireEvent(&data);
+                               break;
+                       default:
+                               if ((i >= BEGINUSERBRK) && (i<jvmtibrkpt.num)) {
+                                       log_text("todo: user defined breakpoints are not handled yet");
+                               } else {
+                                       log_text("breakpoint not handled - continue anyway");
+                                       contdebuggee(0);
+                               }
+                       }
+                       break;
+               case SIGQUIT:
+                       log_text("debugger process SIGQUIT");
+                       data.ev=JVMTI_EVENT_VM_DEATH;
+                       fireEvent(&data);               
+                       break;
+               default:
+                       log_text("signal not handled");
+               }
+       }
+}
+
+/* ipcrm ***********************************************************************
+
+   removes messages queue 
+
+********************************************************************************/
+void ipcrm() {
+       struct msqid_ds msgbuf;
+       struct shmid_ds shmbuf;
+       msgctl(msgqid, IPC_RMID, &msgbuf);
+       shmctl(shmid, IPC_RMID, &shmbuf);
+}
+
+
+/* cacaodbgfork ****************************************************************
+
+   create debugger/jdwp and debuggee process. Returns true if this is the 
+   parent (debugger/jdwp) process
+
+********************************************************************************/
+
+bool cacaodbgfork() {
+       int waitproc;
+
+       /* todo: remove shared memory and msg queue on exit */
+    /* create/initialize semaphores/shared memory/message queue */
+       sem_init(&workingdata_lock, 1, 1);
+
+       shmid = shmget(IPC_PRIVATE, sizeof(cacaodbgserver_data), IPC_CREAT | 0x180);
+       if ((cdbgshmem = (cacaodbgserver_data*)shmat(shmid, NULL, 0)) == -1) {
+               perror("cacaodbgfork: shared memory attach error: ");
+               exit(1);
+       }
+       cdbgshmem->running = false;
+       cdbgshmem->hastostop = 1;
+
+       if ((msgqid =  msgget(IPC_PRIVATE, IPC_CREAT | 0x180)) == -1) {
+               perror("cacaodbgfork: message queue get error");
+               exit(1);
+       }
+       ;
+
+
+       /* with this function the following process structure is created:
+          
+          cacaodbgserver 
+           \_ debuggee (client/cacao vm)
+               \_ debugger (jdwp/cacao vm)
+
+        */
+
+       debuggee = fork();
+       if (debuggee  == (-1)) {
+               log_text("debuggee fork error");
+               exit(1);
+       } else {
+               if (debuggee == 0) { 
+                       /* debuggee process - this is where the java client is running */
+                       
+                       /* allow helper process to trace us  */
+                       if (TRACEME != 0)  exit(1);
+                       
+                       fprintf(stderr, "debugee pid %d\n",getpid()); 
+                       fflush (stderr); 
+                                       
+                       /* give parent/debugger process control */
+                       kill(getpid(),SIGUSR2);
+                       
+                       log_text("debuggee: continue with normal startup");
+                       
+                       /* continue with normal startup */      
+                       return false;
+               } else {
+                       log_text("debugger: fork listening jdwp process");
+                       waitproc = fork();
+
+                       if (waitproc == (-1)) {
+                               log_text("waitprocess fork error");
+                               exit(1);
+                       } else {
+                               if (waitproc == 0) {
+                                       log_text("jdwp process - create new jvmti environment");
+                                       
+                                       remotedbgjvmtienv = new_jvmtienv();
+
+                                       log_text("jdwp process - init VMjdwp");
+           
+                                       if (!VMjdwpInit(remotedbgjvmtienv)) exit(1);
+                                       
+                                       return true;
+                               } else {
+                                       /* Debugger process (parent of debugge process) 
+                                          Here a wait-loop is execute and all the ptrace calls are
+                                          done from within this process. 
+                                          
+                                          This call will never return */
+                                       
+                                       cacaodbgserver();
+                                       fprintf(stderr,"cacaodbgserver returned - exit\n");
+                                       ipcrm();
+                                       exit(0);
+                               } 
+                       }
+               }
+       }
+       return true; /* make compiler happy */
+}
+
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/native/jvmti/cacaodbg.h b/src/native/jvmti/cacaodbg.h
new file mode 100644 (file)
index 0000000..cf84fec
--- /dev/null
@@ -0,0 +1,159 @@
+/* src/native/jvmti/cacaodbg.h - contains cacao specifics for debugging support                                  
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Martin Platter
+
+   Changes: 
+
+
+   $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
+
+*/
+
+#ifndef _CACAODBG_H
+#define _CACAODBG_H
+
+#include "threads/native/threads.h"
+#include "native/jvmti/jvmti.h"
+
+#define MSGQEVENT        1
+#define MSGQPTRACEREQ    2
+#define MSGQPTRACEANS    3
+
+typedef struct {
+       jvmtiEvent ev;
+       jvmtiEnv *jvmti_env;
+       jthread thread;
+       jmethodID method;
+       jlocation location;
+       jclass klass;
+       jobject object;
+       jfieldID field;
+       char signature_type;
+       jvalue value;
+       jboolean b;
+       void* address;
+       void** new_address_ptr;
+       jmethodID catch_method;
+       jlocation catch_location;
+       char* name;
+       jobject protection_domain;
+       jint jint1;
+       jint jint2;
+       unsigned char* class_data;
+       jint* new_class_data_len;
+       unsigned char** new_class_data;
+       jvmtiAddrLocationMap* map;
+       void* compile_info;
+       jlong jlong;
+} genericEventData;
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+struct _jrawMonitorID {
+    java_lang_String *name;
+};
+
+struct _threadmap {
+       pthread_t tid;
+       threadobject* cacaothreadobj;   
+};
+
+struct threadmap {
+       struct _threadmap* map;
+       int num;
+       int size;
+};
+
+struct threadmap thmap;
+#endif
+
+
+/* constants where system breakpoints are stored in the breakpoint table     */
+#define HEREWEGOBRK           0 /* used for suspend VM on startup            */
+#define SETTHREADOBJECTBRK    1 /* used for EVENT_THREAD_START               */
+#define BEGINUSERBRK          2 /* here is where the first user breakpoint is 
+                                                                  stored                                    */
+struct _brkpt {
+    jmethodID method;
+    jlocation location;
+    void* addr;
+    long orig; /* original memory content */
+};
+
+
+struct brkpts {
+       struct _brkpt* brk;
+       int num;
+       int size;
+};
+
+struct brkpts jvmtibrkpt;
+
+bool jdwp;                  /* debugger via jdwp                              */
+bool jvmti;                 /* jvmti agent                                    */
+bool dbgprocess;            /* ture if debugger else debuggee process         */
+pid_t debuggee;             /* PID of debuggee                                */
+
+char *transport, *agentarg; /* arguments for jdwp transport and agent load    */
+bool suspend;               /* should the virtual machine suspend on startup? */
+
+
+bool cacaodbgfork();
+void cacaodbglisten(char* transport);
+jvmtiEnv* new_jvmtienv();
+void set_jvmti_phase(jvmtiPhase p);
+bool contdebuggee(int signal);
+void stopdebuggee();
+void fireEvent(genericEventData* data);
+bool VMjdwpInit(jvmtiEnv *jvmti_env);
+jvmtiEnv* remotedbgjvmtienv;
+jvmtiEventCallbacks jvmti_jdwp_EventCallbacks;
+void agentload(char* opt_arg);
+void agentunload();
+
+void getchildproc (char **ptr, void* addr, int count);
+void addbrkpt(void* addr, jmethodID method, jlocation location);
+void setsysbrkpt(int sysbrk, void* addr);
+jthread threadobject2jthread(threadobject* thread);
+jvmtiError allthreads (jint * threads_count_ptr, threadobject ** threads_ptr);
+jthread getcurrentthread();
+
+void ipcrm();
+
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/native/jvmti/cacaodbgserver.c b/src/native/jvmti/cacaodbgserver.c
new file mode 100644 (file)
index 0000000..d05b356
--- /dev/null
@@ -0,0 +1,314 @@
+/* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
+                                       process controls the debuggee.
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Martin Platter
+
+   Changes: 
+
+
+   $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
+
+*/
+
+#include "native/jvmti/cacaodbgserver.h"
+#include "native/jvmti/cacaodbg.h"
+#include "native/jvmti/dbg.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <semaphore.h>
+#include <sys/msg.h>
+#include <linux/user.h>
+
+
+/* getchildprocptrace *********************************************************
+
+   Get data count number of bytes from address addr for child process address 
+   space. Requested  data is stored in the array pointed to by ptr.
+
+*******************************************************************************/
+static void getchildprocptrace (char *ptr, void* addr, int cnt) {
+       int i, longcnt;
+       long *p = (long*) ptr;
+       
+       longcnt = cnt/sizeof(long);
+       for (i=0; i<longcnt; i++) {
+               p[i]=GETMEM(debuggee,addr);
+               if (p[i]==-1) 
+                       perror("cacaodbgserver process: getchildprocptrace: ");
+               addr+=sizeof(long);
+       }
+       longcnt = GETMEM(debuggee,addr);
+       memcpy(ptr,&longcnt,cnt%sizeof(long));
+}
+
+/* contchild ******************************************************************
+
+   Helper function to continue child process. 
+
+*******************************************************************************/
+static bool contchild(int signal) {
+       /* get lock for running state */ 
+       sem_wait(&workingdata_lock);
+       fprintf(stderr,"cacaodbgserver: contchild called (hastostop: %d)\n",cdbgshmem->hastostop);
+       if(cdbgshmem->hastostop < 1) {
+               fprintf(stderr,"cacaodbgserver: going to continue child\n");
+               CONT(debuggee,signal);
+               cdbgshmem->hastostop = 0;
+               cdbgshmem->running=true;
+               /* release lock for running state */ 
+               sem_post(&workingdata_lock);
+               return true;
+       } else {
+               sem_post(&workingdata_lock);
+               return false;           
+       }
+}
+
+/* msgqsendevent *******************************************************************
+
+   sends an event notification to the jdwp/debugger process through the 
+   message queue
+
+*******************************************************************************/
+static void msgqsendevent(basic_event *ev) {
+       ev->mtype = MSGQDEBUGGER;
+       
+       if (-1 == msgsnd(msgqid, ev, sizeof(basic_event), 0)) {
+               perror("cacaodbgserver process: cacaodbglisten send error: ");
+               exit(1);
+       }
+}
+
+/* waitloop *******************************************************************
+
+   waits and handles signals from debuggee/child process
+
+*******************************************************************************/
+
+static void waitloop() {
+    int status,retval,signal;
+    void* ip;
+       basic_event ev;
+
+       fprintf(stderr,"waitloop\n");
+    fflush (stderr); 
+
+    while (true) {
+               retval = wait(&status);
+
+               fprintf(stderr,"cacaodbgserver: waitloop we got something to do\n");
+               if (retval == -1) {
+                       fprintf(stderr,"error in waitloop\n");
+                       perror("cacaodbgserver process: waitloop: ");
+                       exit(1);
+               }
+
+               if (retval != debuggee) {
+                       fprintf(stderr,"cacaodbgserver got signal from process other then debuggee\n");
+                       exit(1);
+               }
+               
+               if (WIFEXITED(status)) {
+                       /* generate event VMDeath */
+                       ev.signal = SIGQUIT;
+                       ev.ip = NULL;
+                       msgqsendevent(&ev);
+                       return;
+               }
+               
+               if (WIFSTOPPED(status)) {
+                       signal = WSTOPSIG(status);
+
+                       /* ignore SIGSEGV, SIGPWR, SIGBUS and SIGXCPU for now.
+                          todo: in future this signals can be used to detect Garbage 
+                          Collection Start/Finish or NullPointerException Events */
+                       if ((signal == SIGSEGV) || (signal == SIGPWR) || 
+                               (signal == SIGBUS)      || (signal == SIGXCPU)) {
+                               fprintf(stderr,"cacaodbgserver: ignore internal signal (%d)\n",signal);
+                               contchild(signal);
+                               continue;
+                       }
+
+                       if (signal == SIGABRT) {
+                               fprintf(stderr,"cacaodbgserver: got SIGABRT from debugee - exit\n");
+                               exit(1);
+                       }
+
+                       ip = getip(debuggee);
+                       ip--; /* EIP has already been incremented */
+                       fprintf(stderr,"got signal: %d IP %X\n",signal,ip);
+                       
+                       sem_wait(&workingdata_lock);
+                       cdbgshmem->running = false;
+                       cdbgshmem->hastostop = 1;
+                       sem_post(&workingdata_lock);
+
+                       if (signal==SIGUSR2) {
+                               fprintf(stderr,"SIGUSR2 - debuggee has stopped by jdwp process\n");
+                               return;
+                       }
+                       
+                       ev.signal = signal;
+                       ev.ip = ip;
+                       msgqsendevent(&ev);
+                       return;
+               }
+       
+               fprintf(stderr,"wait not handled(child not exited or stopped)\n");
+               fprintf(stderr,"retval: %d status: %d\n",retval,status);
+       }
+}
+
+/* ptraceloop *****************************************************************
+
+   this function handles the ptrace request from the jdwp/debugger process.
+
+*******************************************************************************/
+
+void ptraceloop() {
+       bool contdebuggee=false;
+       ptrace_request pt;
+       ptrace_reply *buffer;
+       int size;
+    struct user_regs_struct *regs;
+
+       fprintf(stderr,"ptraceloop\n");
+    fflush (stderr); 
+       while (!contdebuggee) {
+               if (-1 == msgrcv(msgqid, &pt, sizeof(ptrace_request), MSGQPTRACESND, 0))
+                       perror("cacaodbgserver process: cacaodbglisten receive error: ");
+
+               switch(pt.kind){
+               case PTCONT:
+                       /* continue debuggee process */
+                       size= sizeof(ptrace_reply);
+                       buffer =(ptrace_reply*) MNEW(char,size);
+
+                       contdebuggee = contchild(pt.data);
+
+                       buffer->mtype = MSGQPTRACERCV;
+                       buffer->successful=true;
+                       buffer->datasize=0;
+                       break;
+               case PTPEEKDATA:
+                       /* get memory content from the debuggee process */
+                       size= sizeof(ptrace_reply)+pt.data;
+                       buffer =(ptrace_reply*) MNEW(char,size);
+
+                       buffer->mtype = MSGQPTRACERCV;
+                       buffer->datasize = size-sizeof(ptrace_reply);
+
+                       fprintf(stderr,"getchildprocptrace: pid %d get %p - %p cnt: %d (buffer %p buffer->data %p)\n",
+                                       debuggee, pt.addr,pt.addr+pt.data, buffer->datasize,buffer, buffer->data);
+                       fflush(stderr);
+
+                       getchildprocptrace(buffer->data,pt.addr,buffer->datasize);
+                       break;
+               case PTSETBRK:
+                       size= sizeof(ptrace_reply)+sizeof(long);
+                       buffer =(ptrace_reply*) MNEW(char,size);
+
+                       /* set new breakpoint */
+                       buffer->mtype = MSGQPTRACERCV;
+                       buffer->successful=true;
+                       buffer->datasize=sizeof(long);
+                       
+                       setbrk(debuggee,pt.addr, (long*)(buffer->data));
+                       break;
+               case PTDELBRK:
+                       /* delete breakpoint */
+                       size= sizeof(ptrace_reply);
+                       buffer =(ptrace_reply*) MNEW(char,size);
+                       
+                       DISABLEBRK(debuggee,pt.ldata,pt.addr);
+                       
+                       buffer->mtype = MSGQPTRACERCV;
+                       buffer->successful=true;
+                       buffer->datasize=0;
+                       break;
+               case PTGETREG:
+                       /* get registers */
+                       size= sizeof(ptrace_reply)+sizeof(struct user_regs_struct);
+                       buffer =(ptrace_reply*) MNEW(char,size);
+                       regs=buffer->data;
+
+                       GETREGS(debuggee,*regs);
+                       
+                       buffer->mtype = MSGQPTRACERCV;
+                       buffer->successful=true;
+                       buffer->datasize=sizeof(struct user_regs_struct);
+                       break;
+               default:
+                       fprintf(stderr,"unkown ptrace request %d\n",pt.kind);
+                       exit(1);
+               }
+
+               if (-1 == msgsnd(msgqid, buffer, size, 0)) {
+                       perror("cacaodbgserver process: cacaodbglisten send error: ");
+                       exit(1);
+               }
+               MFREE(buffer,char,size);
+       }
+}
+
+/* cacaodbgserver *************************************************************
+
+   waits for eventes from and issues ptrace calls to debuggee/child process
+
+*******************************************************************************/
+
+void cacaodbgserver() {
+       fprintf(stderr,"cacaodbgserver started\n");
+       fflush(stderr);
+       while(true) {
+               /* wait until debuggee process gets stopped 
+                  and inform debugger process */
+               waitloop();
+               /* give the debugger process the opportunity to issue ptrace calls */
+               ptraceloop();
+               /* ptraceloop returns after a PTRACE_CONT call has been issued     */
+       }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/native/jvmti/cacaodbgserver.h b/src/native/jvmti/cacaodbgserver.h
new file mode 100644 (file)
index 0000000..dd39fc7
--- /dev/null
@@ -0,0 +1,110 @@
+/* src/native/jvmti/cacaodbgserver.h - contains cacao specifics for 
+                                       debugging support
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Martin Platter
+
+   Changes: 
+
+
+   $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
+
+*/
+
+#ifndef _CACAODBGSERVER_H
+#define _CACAODBGSERVER_H
+
+#include "vm/global.h"
+#include <semaphore.h>
+
+/* supported message types */
+#define MSGQCACAODBGSRV  1  /* messages for cacaodbgserver process  */
+#define MSGQDEBUGGER     2  /* messages for debugger process        */
+#define MSGQPTRACESND    3  /* messages for ptrace request          */
+#define MSGQPTRACERCV    4  /* messages for ptrace return value     */
+
+/* supported ptrace loop calls */
+#define PTCONT           1  /* ptrace continue                      */
+#define PTPEEKDATA       2  /* ptrace peek data                     */
+#define PTSETBRK         3  /* set breakpiont                       */
+#define PTDELBRK         4  /* delete breakpiont                    */
+#define PTGETREG         5  /* get registers                        */
+
+
+typedef struct {
+       long mtype;
+       int kind; 
+       void* addr;
+       int data;
+       long ldata;
+} ptrace_request;
+
+typedef struct {
+       long mtype;
+       bool successful;
+       int  datasize;
+       char data[1];
+} ptrace_reply;
+
+
+typedef struct {
+       long mtype;
+       int signal; 
+       void *ip;
+} basic_event;
+
+typedef struct {
+       bool running;           /* true if debuggee process is running             */
+       int hastostop;          /* if greater then zero the debugger needs the 
+                                                          debuggee to be stopped                          */
+} cacaodbgserver_data;
+
+
+int  msgqid;                    /* message queue for the communication between 
+                                                              debugger/jdwp and cacaodbgserver process    */
+int shmid;                      /* shared memory for saving running state      */
+sem_t workingdata_lock;         /* semaphore for cacaodbgserver_data shared  
+                                                              memory structure                            */
+cacaodbgserver_data *cdbgshmem; /* cacaodbgserver shared memory pointer        */
+
+
+
+void cacaodbgserver();          /* entry point function to cacaodbgserver proc */
+
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/native/jvmti/dbg.c b/src/native/jvmti/dbg.c
new file mode 100644 (file)
index 0000000..4f669fa
--- /dev/null
@@ -0,0 +1,84 @@
+/* src/native/jvmti/dbg.c - jvmti os/architecture support
+
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Martin Platter
+
+   Changes: 
+
+
+   $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
+
+*/
+
+/* at the moment linux/i386 is the only plattform available */
+#if defined(__LINUX__)  && defined (__I386__)
+
+#include "dbg.h"
+#include <sys/ptrace.h>
+#include <linux/user.h>
+
+#include <stdio.h>
+
+void* getip(pid_t pid) {
+    struct user_regs_struct regs;
+
+    GETREGS(pid,regs);
+    return (void*)regs.eip;
+}
+
+void setip(pid_t pid, void* ip) {
+    struct user_regs_struct regs;
+
+    GETREGS(pid,regs);
+    regs.eip=(long)ip; 
+    ptrace(PTRACE_SETREGS, pid, 0, &regs); 
+}
+
+void setbrk(pid_t pid, void* addr, long* orig) {
+    long ins;
+       *orig = GETMEM(pid,addr);
+
+       ins = (*orig & ~0x000000FF) | TRAPINS; 
+
+       fprintf (stderr,"pid %d set brk at %p orig: %X new: %X\n",getpid(),addr,*orig,ins);
+       if (ptrace(PTRACE_POKEDATA, pid, (caddr_t) addr, ins)==-1) 
+               perror("setbrk error ");
+}
+
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
index 6313e1364a13840d6a19e357d350c4da59c10da0..44370c39e953bce035e63cede5002bc50cafda09 100644 (file)
    Changes:             
 
    
-   $Id: dbg.h 4357 2006-01-22 23:33:38Z twisti $
+   $Id: dbg.h 4661 2006-03-21 00:04:59Z motse $
 
 */
 
 /* at the moment linux/i386 is the only plattform available */
 #if defined(__LINUX__)  && defined (__I386__)
+
+#ifndef _DBG_H
+#define _DBG_H
+
+#include <sys/types.h>
 #include <sys/ptrace.h>
 
 #define TRACEME ptrace(PTRACE_TRACEME, 0, 0, 0)
-#define GETREGS(pid, regs) ptrace(PTRACE_GETREGS, pid, 0, &regs)
-#define GETMEM(pid, addr) ptrace(PTRACE_PEEKDATA, pid, (caddr_t) addr, 0)
-#define ENABLEBRK(pid,ins,addr) ptrace(PTRACE_POKEDATA, pid, (caddr_t) addr, (ins & ~0x000000FF) | 0xcc)
-#define CONT(pid) ptrace(PTRACE_CONT, pid, 0, 0)
+#define DETACH(pid,sig)  ptrace(PTRACE_DETACH, pid, 0, sig)
+#define TRAPINS 0xcc /* opcode for brk */
+#define TRAP asm("int3")
+#define GETMEM(pid, addr) ptrace(PTRACE_PEEKDATA, pid, addr, 0)
+#define CONT(pid,sig) if(ptrace(PTRACE_CONT, pid, 0, sig)==-1) \
+                         perror("continue failed: ");
 #define DISABLEBRK(pid,ins,addr) ptrace(PTRACE_POKEDATA, pid, (caddr_t) addr, ins)
-#define GETIP(pid,ip) ptrace(PTRACE_GETREGS, pid, 0, &regs); \
-                      ip=regs.eip;
-#define SETIP(pid,ip) ip=regs.eip; \
-                      ptrace(PTRACE_SETREGS, pid, 0, &regs); 
+#define GETREGS(pid,regs) ptrace(PTRACE_GETREGS, pid, 0, &regs)
+
+void* getip(pid_t pid);
+void setip(pid_t pid, void* ip);
+
+void setbrk(pid_t pid, void* addr,long* orig);
+
+#endif
 #endif
 
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
index d8e3f2130a739c2676ed060db47dd4817630ffa0..d4e673d4ff1f1eb02c4439bf7037ec45b4b807ea 100644 (file)
@@ -1,5 +1,5 @@
-/* src/native/jvmti/jvmti.c - implementation of the Java Virtual Machine Tool 
-                              Interface functions
+/* src/native/jvmti/jvmti.c - implementation of the Java Virtual Machine 
+                              Tool Interface functions
 
    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    Changes: Edwin Steiner
 
    
-   $Id: jvmti.c 4599 2006-03-14 22:30:58Z edwin $
+   $Id: jvmti.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
 #include <assert.h>
 
 #include "native/jni.h"
+#include "native/native.h"
+#include "native/jvmti/cacaodbg.h"
 #include "native/jvmti/jvmti.h"
 #include "vm/global.h"
 #include "vm/loader.h"
 #include "vm/builtin.h"
 #include "vm/jit/asmpart.h"
+#include "vm/class.h"
 #include "vm/classcache.h"
 #include "mm/boehm.h"
 #include "toolbox/logging.h"
 #include "vm/options.h"
-#include "cacao/cacao.h"
 #include "vm/stringlocal.h"
 #include "mm/memory.h"
 #include "threads/native/threads.h"
@@ -59,7 +61,8 @@
 #include "native/include/java_lang_VMObject.h"
 #include "native/include/java_lang_VMSystem.h"
 #include "native/include/java_lang_VMClass.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/suck.h"
+#include  "boehm-gc/include/gc.h"
 
 #include <string.h>
 #include <linux/unistd.h>
@@ -68,6 +71,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/user.h>
 #include <signal.h>
 #include <ltdl.h>
 
@@ -111,8 +115,7 @@ struct _environment {
        environment *next;
 };
 
-
-static jvmtiEnv JVMTI_EnvTable;
+static struct jvmtiEnv_struct JVMTI_EnvTable;
 static jvmtiCapabilities JVMTI_Capabilities;
 static lt_ptr unload;
 
@@ -121,14 +124,40 @@ static lt_ptr unload;
 #define CHECK_PHASE_END  )) return JVMTI_ERROR_WRONG_PHASE
 #define CHECK_CAPABILITY(env,CAP) if(((environment*)env)->capabilities.CAP == 0) \
                                      return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
-#define CHECK_THREAD_IS_ALIVE(t) if((((java_lang_Thread*)t)->vmThread==NULL)&& \
-                                    (((java_lang_Thread*)t)->group==NULL)) \
+#define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t)== \
+                                  JVMTI_ERROR_THREAD_NOT_ALIVE) \
                                        return JVMTI_ERROR_THREAD_NOT_ALIVE;
 
 
 
+
+/* check_thread_is_alive *******************************************************
+
+   checks if the given thread is alive
+
+*******************************************************************************/
+static jvmtiError check_thread_is_alive(jthread t) {
+       char* data;
+       java_lang_Thread* th;
+       if(t==NULL) 
+               return JVMTI_ERROR_THREAD_NOT_ALIVE;
+       getchildproc(&data, t, sizeof(java_lang_Thread));
+       th = (java_lang_Thread*)data;
+       if(th->vmThread==NULL) 
+               return JVMTI_ERROR_THREAD_NOT_ALIVE;
+       return JVMTI_ERROR_NONE;
+}
+
+/* execcallback ***************************************************************
+
+   executes the registerd callbacks for the given jvmti event with parameter
+   in the data structure.
+
+*******************************************************************************/
 static void execcallback(jvmtiEvent e, functionptr ec, genericEventData* data) {
-       JNIEnv* jni_env = ptr_env;
+       JNIEnv* jni_env = (JNIEnv*)&_Jv_JNINativeInterface;
+
+       fprintf(stderr,"execcallback called (event: %d)\n",e);
 
        switch (e) {
        case JVMTI_EVENT_VM_INIT:
@@ -160,7 +189,7 @@ static void execcallback(jvmtiEvent e, functionptr ec, genericEventData* data) {
 
     case JVMTI_EVENT_VM_DEATH:
     case JVMTI_EVENT_VM_START: 
-               ((jvmtiEventThreadStart)ec) (data->jvmti_env, jni_env, data->thread);
+               ((jvmtiEventVMStart)ec) (data->jvmti_env, jni_env);
                break;
 
     case JVMTI_EVENT_EXCEPTION:
@@ -309,27 +338,19 @@ static void execcallback(jvmtiEvent e, functionptr ec, genericEventData* data) {
        }
 }
 
-/* fireEvent **************************************************************
 
-   fire event callback with data arguments.
+/* dofireEvent ******************************************************************
 
-*******************************************************************************/
+   sends event if it is enabled either globally or for some threads
 
-void fireEvent(jvmtiEvent e, genericEventData* data) {
+*******************************************************************************/
+static void dofireEvent(jvmtiEvent e, genericEventData* data) {
        environment* env;
        jvmtiEventModeLL *evm;
-       jthread thread;
-
        functionptr ec;
-    /* todo : respect event order JVMTI-Spec:Multiple Co-located Events */
-
-       thread = (jthread)THREADOBJECT;
-
-       data->thread = thread;
 
        env = envs;
        while (env!=NULL) {
-
                if (env->events[e-JVMTI_EVENT_START_ENUM].mode == JVMTI_DISABLE) {
                        evm = env->events[e-JVMTI_EVENT_START_ENUM].next;
             /* test if the event is enable for some threads */
@@ -342,7 +363,7 @@ void fireEvent(jvmtiEvent e, genericEventData* data) {
                                evm=evm->next;
                        }
                } else { /* event enabled globally */
-                       data->jvmti_env=&env->env;
+                       data->jvmti_env=&env->env;
                        ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
                        execcallback(e, ec, data);
                }
@@ -352,21 +373,30 @@ void fireEvent(jvmtiEvent e, genericEventData* data) {
 }
 
 
+/* fireEvent ******************************************************************
 
-/* getchildproc ***************************************************************
-
-   Get data from child process
+   fire event callback with data arguments. This function mainly fills the
+   missing EventData.
 
 *******************************************************************************/
-static long getchildproc (void *ptr) {
-       if (debuggee > 0) {
-        /* get data from child process */
-               return GETMEM(debuggee,ptr);
-       } else {
-               return *((long*)ptr);
-       }
-}
+void fireEvent(genericEventData* d) {
+       jthread thread;
+    /* todo : respect event order JVMTI-Spec:Multiple Co-located Events */
+
+       if (d->ev != JVMTI_EVENT_VM_START)
+               thread = (jthread)getcurrentthread();
+       else
+               thread = NULL;
 
+       fprintf (stderr,"debugger: fireEvent: %d\n",d->ev);
+       d->thread = thread;
+       dofireEvent(d->ev,d);
+
+       fprintf (stderr,"debugger: fireEvent 2\n");
+       /* if we need to send a VM_INIT event then also send a THREAD_START event */
+       if (d->ev == JVMTI_EVENT_VM_INIT) 
+               dofireEvent(JVMTI_EVENT_THREAD_START,d);
+}
 
 
 /* SetEventNotificationMode ****************************************************
@@ -387,11 +417,11 @@ SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode,
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
 
-       if((event_thread != NULL)&&
-          (!builtin_instanceof(event_thread,class_java_lang_Thread))) 
-               return JVMTI_ERROR_INVALID_THREAD;
-
-       CHECK_THREAD_IS_ALIVE(event_thread);
+       if(event_thread != NULL) {
+               if (!builtin_instanceof(event_thread,class_java_lang_Thread))
+                       return JVMTI_ERROR_INVALID_THREAD;
+               CHECK_THREAD_IS_ALIVE(event_thread);
+       }
        
        cacao_env = (environment*) env;    
        if ((mode != JVMTI_ENABLE) && (mode != JVMTI_DISABLE))
@@ -486,7 +516,6 @@ SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode,
     return JVMTI_ERROR_NONE;
 }
 
-
 /* GetAllThreads ***************************************************************
 
    Get all live threads
@@ -497,8 +526,11 @@ jvmtiError
 GetAllThreads (jvmtiEnv * env, jint * threads_count_ptr,
               jthread ** threads_ptr)
 {
-    int i = 0; 
-    threadobject* thread;
+       threadobject* threads;
+       int i;
+       jvmtiError retval;
+       
+       log_text ("GetAllThreads called");
 
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
@@ -507,27 +539,15 @@ GetAllThreads (jvmtiEnv * env, jint * threads_count_ptr,
     if ((threads_count_ptr == NULL) || (threads_ptr == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-    thread = mainthreadobj;
-    do {
-        if((thread->o.thread->vmThread==NULL)&& (thread->o.thread->group==NULL)) 
-                  i++; /* count only live threads */
-                  thread = thread->info.prev;
-       } while (thread != mainthreadobj);
-    
-    *threads_count_ptr = i;
-       
-    *threads_ptr = (jthread*) heap_allocate(sizeof(jthread) * i,true,NULL);
-    i=0;
-    do {
-        memcpy(*threads_ptr[i],thread,sizeof(jthread));
-        thread = thread->info.prev;
-        i++;
-    } while (thread != mainthreadobj);
-#else
-       return JVMTI_ERROR_NOT_AVAILABLE;
-#endif
+       retval=allthreads(threads_count_ptr,&threads);
+       if (retval != JVMTI_ERROR_NONE) return retval;
+
+       *threads_ptr = 
+               heap_allocate(sizeof(jthread*)* (*threads_count_ptr),true,NULL);
 
+       for (i=0; i<*threads_count_ptr; i++) 
+               (*threads_ptr)[i] = threadobject2jthread(&threads[i]);
     return JVMTI_ERROR_NONE;
 }
 
@@ -546,9 +566,15 @@ SuspendThread (jvmtiEnv * env, jthread thread)
        CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend)
     
+/*    
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       suspendThread((thread *) thread->thread);
+       suspend_thread((thread *) thread->thread);
+#endif
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       suspend_thread((threadobject*) thread);
 #endif
+*/
 
     return JVMTI_ERROR_NONE;
 }
@@ -567,10 +593,15 @@ ResumeThread (jvmtiEnv * env, jthread thread)
     CHECK_PHASE_END;
     CHECK_CAPABILITY(env,can_suspend)
 
+/*
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       resumeThread((thread *) this->thread);
+       resume_thread((thread *) this->thread);
 #endif
 
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       resume_thread((threadobject*) thread);
+#endif
+*/
     return JVMTI_ERROR_NONE;
 }
 
@@ -613,7 +644,7 @@ InterruptThread (jvmtiEnv * env, jthread thread)
        CHECK_THREAD_IS_ALIVE(thread);        
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       interruptThread((java_lang_VMThread*)thread);
+/*     interruptThread((java_lang_VMThread*)thread);*/
 #else
        return JVMTI_ERROR_NOT_AVAILABLE;
 #endif
@@ -631,22 +662,27 @@ InterruptThread (jvmtiEnv * env, jthread thread)
 jvmtiError
 GetThreadInfo (jvmtiEnv * env, jthread th, jvmtiThreadInfo * info_ptr)
 {
-       java_lang_Thread* t = (java_lang_Thread*)th;
        int size;
-       char* name;
+       char* data;
+       struct java_lang_Thread *t;
+
+       log_text("GetThreadInfo called");
 
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
-       
-       name = javastring_tochar((java_objectheader*)t->name);
-       size = strlen(name);
-       info_ptr->name=heap_allocate(size*sizeof(char),true,NULL);
-       strncpy(info_ptr->name,name,size);
+
+       getchildproc(&data,th,sizeof(struct java_lang_Thread));
+       t = (java_lang_Thread*)data;
        info_ptr->priority=(jint)t->priority;
        info_ptr->is_daemon=(jboolean)t->daemon;
        info_ptr->thread_group=(jthreadGroup)t->group;
        info_ptr->context_class_loader=(jobject)t->contextClassLoader;
+       getchildproc(&data,t->name,sizeof(struct java_lang_String));
+       size = ((struct java_lang_String*)data)->count;
+       getchildproc(&(info_ptr->name),((struct java_lang_String*)data)->value,size);
+       info_ptr->name[size]='\0';
+
 
     return JVMTI_ERROR_NONE;
 }
@@ -663,8 +699,11 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
                     jobject ** owned_monitors_ptr)
 {
        int i,j,size=20;
-       jobject* om;
+       java_objectheader **om;
        lockRecordPool* lrp;
+       char *data;
+
+       log_text("GetOwnedMonitorInfo called");
 
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
@@ -683,9 +722,12 @@ GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread,
 
        om=MNEW(java_objectheader*,size);
 
-       pthread_mutex_lock(&pool_lock);
+       stopdebuggee();
 
-       lrp=global_pool;
+       /* global_pool is in the same place in the child process memory because the
+          the child is a copy of this process */
+       getchildproc(&data, &global_pool,sizeof(lockRecordPool*));
+       lrp=(lockRecordPool*)data;
 
        while (lrp != NULL) {
                for (j=0; j<lrp->header.size; j++) {
@@ -779,7 +821,7 @@ typedef struct {
 
 static void *threadstartup(void *t) {
        runagentparam *rap = (runagentparam*)t;
-       rap->sf(rap->jvmti_env,ptr_env,rap->arg);
+       rap->sf(rap->jvmti_env,&_Jv_JNINativeInterface,rap->arg);
        return NULL;
 }
 
@@ -805,7 +847,8 @@ RunAgentThread (jvmtiEnv * env, jthread thread, jvmtiStartFunction proc,
        if((thread != NULL)&&(!builtin_instanceof(thread,class_java_lang_Thread))) 
                return JVMTI_ERROR_INVALID_THREAD;
        if (proc == NULL) return JVMTI_ERROR_NULL_POINTER;
-       if ((priority < JVMTI_THREAD_MIN_PRIORITY) || (priority > JVMTI_THREAD_MAX_PRIORITY)) 
+       if ((priority < JVMTI_THREAD_MIN_PRIORITY) || 
+               (priority > JVMTI_THREAD_MAX_PRIORITY)) 
                return JVMTI_ERROR_INVALID_PRIORITY;
 
        rap.sf = proc;
@@ -822,7 +865,8 @@ RunAgentThread (jvmtiEnv * env, jthread thread, jvmtiStartFunction proc,
                sp.__sched_priority = sched_get_priority_min(SCHED_FIFO);
        }
        pthread_attr_setschedparam(&threadattr,&sp);
-       if (pthread_create(&((threadobject*) thread)->info.tid, &threadattr, &threadstartup, &rap)) {
+       if (pthread_create(&((threadobject*) 
+                                                thread)->info.tid, &threadattr, &threadstartup, &rap)) {
                log_text("pthread_create failed");
                assert(0);
        }
@@ -986,16 +1030,12 @@ GetThreadGroupChildren (jvmtiEnv * env, jthreadGroup group,
    Has to take care of suspend/resume issuses
 
 *******************************************************************************/
+static jvmtiError getcacaostacktrace(char** trace, jthread thread) {
 
-static jvmtiError getcacaostacktrace(stackTraceBuffer** trace, jthread thread) {
+       log_text("getcacaostacktrace");
+
+       
 
-       /* todo: suspend specified thread */
-/*     
-       if (!cacao_stacktrace_fillInStackTrace((void**)trace,&stackTraceCollector, (threadobject*)thread)) 
-               return JVMTI_ERROR_INTERNAL;
-*/
-       /* todo: resume specified thread */
-       log_text("todo: stacktraces");
     return JVMTI_ERROR_NONE;
 }
 
@@ -1009,7 +1049,7 @@ static jvmtiError getcacaostacktrace(stackTraceBuffer** trace, jthread thread) {
 jvmtiError
 GetFrameCount (jvmtiEnv * env, jthread thread, jint * count_ptr)
 {
-       stackTraceBuffer* trace;
+       char* trace;
        jvmtiError er;
 
        CHECK_PHASE_START
@@ -1026,7 +1066,7 @@ GetFrameCount (jvmtiEnv * env, jthread thread, jint * count_ptr)
        er = getcacaostacktrace(&trace, thread);
        if (er==JVMTI_ERROR_NONE) return er;
 
-       *count_ptr = trace->size;
+/*     todo: *count_ptr = trace->size;*/
 
     return JVMTI_ERROR_NONE;
 }
@@ -1042,6 +1082,8 @@ jvmtiError
 GetThreadState (jvmtiEnv * env, jthread thread, jint * thread_state_ptr)
 {
        java_lang_Thread* th = (java_lang_Thread*)thread;
+       threadobject* t = (threadobject*)th->vmThread;
+
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
@@ -1060,8 +1102,18 @@ GetThreadState (jvmtiEnv * env, jthread thread, jint * thread_state_ptr)
        } else {
                /* alive */
                *thread_state_ptr = JVMTI_THREAD_STATE_ALIVE;
-               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_SUSPENDED; /* todo */
+               if (t->interrupted) *thread_state_ptr |= JVMTI_THREAD_STATE_INTERRUPTED;
                /* todo */
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_SUSPENDED;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_IN_NATIVE;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_RUNNABLE;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
+               if (false /* t->ee.waiting ? */) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
+               if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_PARKED;
+               if (t->isSleeping) *thread_state_ptr |= JVMTI_THREAD_STATE_SLEEPING;
        }
 #else
        return JVMTI_ERROR_INTERNAL;
@@ -1535,6 +1587,7 @@ SetBreakpoint (jvmtiEnv * env, jmethodID method, jlocation location)
     CHECK_PHASE_END;
        CHECK_CAPABILITY(env,can_generate_breakpoint_events)
         
+               /* addbrkpt */
   log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
     return JVMTI_ERROR_NONE;
 }
@@ -1736,12 +1789,13 @@ GetClassStatus (jvmtiEnv * env, jclass klass, jint * status_ptr)
        *status_ptr = 0;        
 
 /*     if (c) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_VERIFIED; ? */
-/*     if () *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PREPARED;  ? */
+       if (c->state&=CLASS_LINKED) 
+               *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PREPARED;
 
-       if (c->initialized
+       if (c->state&=CLASS_INITIALIZED
                *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_INITIALIZED;
 
-       if (c->erroneous_state
+       if (c->state&=CLASS_ERROR
                *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_ERROR;
 
        if (c->vftbl->arraydesc != NULL) 
@@ -1774,11 +1828,12 @@ GetSourceFileName (jvmtiEnv * env, jclass klass, char **source_name_ptr)
     if ((klass == NULL)||(source_name_ptr == NULL)) 
         return JVMTI_ERROR_NULL_POINTER;
     
-    size = (((classinfo*)klass)->sourcefile->blength);
+    size = (((classinfo*)klass)->sourcefile->blength)+1;
 
     *source_name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
     
     memcpy(*source_name_ptr,((classinfo*)klass)->sourcefile->text, size);
+       (*source_name_ptr)[size]='\0';
 
     return JVMTI_ERROR_NONE;
 }
@@ -2268,7 +2323,7 @@ GetArgumentsSize (jvmtiEnv * env, jmethodID method, jint * size_ptr)
     if (((methodinfo*)method)->flags & ACC_NATIVE)  
         return JVMTI_ERROR_NATIVE_METHOD;
 
-    *size_ptr = (jint)((methodinfo*)method)->paramcount;
+/* todo    *size_ptr = (jint)((methodinfo*)method)->paramcount;*/
     return JVMTI_ERROR_NONE;
 }
 
@@ -2306,7 +2361,7 @@ GetLineNumberTable (jvmtiEnv * env, jmethodID method,
 
     for (i=0; i < *entry_count_ptr; i++) {
         (*table_ptr[i]).start_location = 
-            (jlocation) method->linenumbers[i].start_pc;
+            (jlocation) ((methodinfo*)method)->linenumbers[i].start_pc;
         (*table_ptr[i]).line_number = 
             (jint) ((methodinfo*)method)->linenumbers[i].line_number;
     }
@@ -2461,12 +2516,16 @@ IsMethodSynthetic (jvmtiEnv * env, jmethodID method,
 *******************************************************************************/
 
 jvmtiError
-GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr,
-                 jclass ** classes_ptr)
+GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr)
 {
        int i,j;
+       char* data;
+       hashtable* ht;
        classcache_name_entry *cne;
        classcache_class_entry *cce;
+
+       log_text ("GetLoadedClasses called");
+
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
@@ -2474,19 +2533,38 @@ GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr,
     if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
     if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
 
-       tables_lock();
+       log_text ("GetLoadedClasses1");
+
+       stopdebuggee();
+       log_text ("GetLoadedClasses2");
+       /* hashtable_classcache is in the same place in the child process memory 
+          because the child is a copy of this process */
+       getchildproc(&data, &hashtable_classcache, sizeof(hashtable));
+       ht = (hashtable*) &data;
 
-       *classes_ptr = heap_allocate(sizeof(jclass*)*classcache_hash.entries,true,NULL);
-       *class_count_ptr = classcache_hash.entries;
+       log_text ("GetLoadedClasses got ht pointer");
+       *classes_ptr = 
+               heap_allocate(sizeof(jclass*) * (ht->entries),true,NULL);
+       fprintf (stderr,"hashtable_classcache.entries = %d\n",ht->entries);
+       fflush(stderr);
+
+       *class_count_ptr = ht->entries;
        j=0;
     /* look in every slot of the hashtable */
-       for (i=0; i<classcache_hash.size; i++) { 
-               cne =(classcache_name_entry*) classcache_hash.ptr[i];
+       for (i=0; i<ht->size; i++) { 
+               cne = ht->ptr[i];
+
                while (cne != NULL) { /* iterate over hashlink */
+                       getchildproc(&data, cne, sizeof(classcache_name_entry));
+                       cne =(classcache_name_entry*) &data;
+
                        cce = cne->classes;
                        while (cce != NULL){ /* iterate over classes with same name */
+                               getchildproc(&data, cce, sizeof(classcache_class_entry));
+                               cce =(classcache_class_entry*) &data;
+                               
                                if (cce->classobj != NULL) { /* get only loaded classes */
-                                       assert(j<classcache_hash.entries);
+                                       assert(j<ht->entries);
                                        *classes_ptr[j]=cce->classobj;
                                        j++;
                                }
@@ -2496,7 +2574,11 @@ GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr,
                }
        }
 
-       tables_unlock();
+       log_text ("GetLoadedClasses continue");
+
+       contdebuggee(0);
+
+       log_text ("GetLoadedClasses finished");
 
     return JVMTI_ERROR_NONE;
 }
@@ -2513,6 +2595,8 @@ jvmtiError
 GetClassLoaderClasses (jvmtiEnv * env, jobject initiating_loader,
                       jint * class_count_ptr, jclass ** classes_ptr)
 {
+       log_text("GetClassLoaderClasses called");
+
     CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
     CHECK_PHASE_END;
@@ -2696,9 +2780,9 @@ GetStackTrace (jvmtiEnv * env, jthread thread, jint start_depth,
               jint max_frame_count, jvmtiFrameInfo * frame_buffer,
               jint * count_ptr)
 {
-       stackTraceBuffer* trace;
+       char* trace;
        jvmtiError er;
-       int i,j;
+/*     int i,j;*/
 
        CHECK_PHASE_START
     CHECK_PHASE(JVMTI_PHASE_LIVE)
@@ -2717,14 +2801,14 @@ GetStackTrace (jvmtiEnv * env, jthread thread, jint start_depth,
        er = getcacaostacktrace(&trace, thread);
        if (er==JVMTI_ERROR_NONE) return er;
 
-       if ((trace->size >= start_depth) || ((trace->size * -1) > start_depth)) 
-               return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+/*     todo: if ((trace->size >= start_depth) || ((trace->size * -1) > start_depth)) 
+       return JVMTI_ERROR_ILLEGAL_ARGUMENT; */
        
-       for (i=start_depth, j=0;i<trace->size;i++,j++) {
+/*     for (i=start_depth, j=0;i<trace->size;i++,j++) {
                frame_buffer[j].method = (jmethodID)trace[i].start->method;
-        /* todo: location MachinePC not avilable - Linenumber not expected */
+         todo: location MachinePC not avilable - Linenumber not expected 
                frame_buffer[j].location = 0;
-       }
+               }*/
        
     return JVMTI_ERROR_NONE;
 }
@@ -3084,8 +3168,8 @@ SetJNIFunctionTable (jvmtiEnv * env,
     CHECK_PHASE_END;;
     
     if (function_table == NULL) return JVMTI_ERROR_NULL_POINTER;
-    ptr_env = (void*)heap_allocate(sizeof(jniNativeInterface),true,NULL);
-    memcpy(ptr_env, function_table, sizeof(jniNativeInterface));
+    _Jv_env->env = (void*)heap_allocate(sizeof(jniNativeInterface),true,NULL);
+    memcpy(_Jv_env->env, function_table, sizeof(jniNativeInterface));
     return JVMTI_ERROR_NONE;
 }
 
@@ -3108,7 +3192,7 @@ GetJNIFunctionTable (jvmtiEnv * env, jniNativeInterface ** function_table)
     if (function_table == NULL) return JVMTI_ERROR_NULL_POINTER;
     *function_table = (jniNativeInterface*)
         heap_allocate(sizeof(jniNativeInterface),true,NULL);
-    memcpy(*function_table, ptr_env, sizeof(jniNativeInterface));
+    memcpy(*function_table, _Jv_env->env, sizeof(jniNativeInterface));
     return JVMTI_ERROR_NONE;
 }
 
@@ -3131,8 +3215,8 @@ SetEventCallbacks (jvmtiEnv * env,
     CHECK_PHASE_END;
 
     if (size_of_callbacks < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
-    
-    if (callbacks == NULL) { /* remove the existing callbacks */
+
+       if (callbacks == NULL) { /* remove the existing callbacks */
         memset(&(((environment* )env)->callbacks), 0, 
                           sizeof(jvmtiEventCallbacks));
     }
@@ -3402,8 +3486,7 @@ GetJLocationFormat (jvmtiEnv * env, jvmtiJlocationFormat * format_ptr)
 jvmtiError
 GetSystemProperties (jvmtiEnv * env, jint * count_ptr, char ***property_ptr)
 {
-    jmethodID mid;
-    jmethodID moremid;
+       jmethodID mid, moremid;
     classinfo *sysclass, *propclass, *enumclass;
     java_objectheader *sysprop, *keys, *obj;
     char* ch;
@@ -3422,18 +3505,18 @@ GetSystemProperties (jvmtiEnv * env, jint * count_ptr, char ***property_ptr)
 
     if (!sysclass) throw_main_exception_exit();
 
-    mid = class_resolvemethod(sysclass, 
+    mid = (jmethodID)class_resolvemethod(sysclass, 
                               utf_new_char("getProperties"),
                               utf_new_char("()Ljava/util/Properties;"));
     if (!mid) throw_main_exception_exit();
 
 
-    sysprop = asm_calljavafunction(mid, sysclass, NULL, NULL, NULL);
+    sysprop = _Jv_JNINativeInterface.CallStaticObjectMethod(NULL, sysclass, mid);
     if (!sysprop) throw_main_exception_exit();
 
     propclass = sysprop->vftbl->class;
 
-    mid = class_resolvemethod(propclass, 
+    mid = (jmethodID)class_resolvemethod(propclass, 
                               utf_new_char("size"),
                               utf_new_char("()I"));
     if (!mid) throw_main_exception_exit();
@@ -3442,7 +3525,7 @@ GetSystemProperties (jvmtiEnv * env, jint * count_ptr, char ***property_ptr)
         _Jv_JNINativeInterface.CallIntMethod(NULL, sysprop, mid);
     *property_ptr = heap_allocate(sizeof(char*) * (*count_ptr) ,true,NULL);
 
-    mid = class_resolvemethod(propclass, 
+    mid = (jmethodID)class_resolvemethod(propclass, 
                               utf_new_char("keys"),
                               utf_new_char("()Ljava/util/Enumeration;"));
     if (!mid) throw_main_exception_exit();
@@ -3450,12 +3533,12 @@ GetSystemProperties (jvmtiEnv * env, jint * count_ptr, char ***property_ptr)
     keys = _Jv_JNINativeInterface.CallObjectMethod(NULL, sysprop, mid);
     enumclass = keys->vftbl->class;
         
-    moremid = class_resolvemethod(enumclass, 
+    moremid = (jmethodID)class_resolvemethod(enumclass, 
                                   utf_new_char("hasMoreElements"),
                                   utf_new_char("()Z"));
     if (!moremid) throw_main_exception_exit();
 
-    mid = class_resolvemethod(propclass, 
+    mid = (jmethodID)class_resolvemethod(propclass, 
                               utf_new_char("nextElement"),
                               utf_new_char("()Ljava/lang/Object;"));
     if (!mid) throw_main_exception_exit();
@@ -3499,7 +3582,7 @@ GetSystemProperty (jvmtiEnv * env, const char *property, char **value_ptr)
     sysclass = load_class_from_sysloader(utf_new_char("java/lang/System"));
     if (!sysclass) throw_main_exception_exit();
 
-    mid = class_resolvemethod(sysclass, 
+    mid = (jmethodID)class_resolvemethod(sysclass, 
                               utf_new_char("getProperties"),
                               utf_new_char("()Ljava/util/Properties;"));
     if (!mid) throw_main_exception_exit();
@@ -3508,7 +3591,7 @@ GetSystemProperty (jvmtiEnv * env, const char *property, char **value_ptr)
 
     propclass = sysprop->vftbl->class;
 
-    mid = class_resolvemethod(propclass, 
+    mid = (jmethodID)class_resolvemethod(propclass, 
                               utf_new_char("getProperty"),
                               utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"));
     if (!mid) throw_main_exception_exit();
@@ -3549,7 +3632,7 @@ SetSystemProperty (jvmtiEnv * env, const char *property, const char *value)
     sysclass = load_class_from_sysloader(utf_new_char("java/lang/System"));
     if (!sysclass) throw_main_exception_exit();
 
-    mid = class_resolvemethod(sysclass, 
+    mid = (jmethodID)class_resolvemethod(sysclass, 
                               utf_new_char("getProperties"),
                               utf_new_char("()Ljava/util/Properties;"));
     if (!mid) throw_main_exception_exit();
@@ -3558,7 +3641,7 @@ SetSystemProperty (jvmtiEnv * env, const char *property, const char *value)
 
     propclass = sysprop->vftbl->class;
 
-    mid = class_resolvemethod(propclass, 
+    mid = (jmethodID)class_resolvemethod(propclass, 
                               utf_new_char("setProperty"),
                               utf_new_char("(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"));
     if (!mid) throw_main_exception_exit();
@@ -3954,7 +4037,9 @@ SetVerboseFlag (jvmtiEnv * env, jvmtiVerboseFlag flag, jboolean value)
 {
     switch (flag) {
     case JVMTI_VERBOSE_OTHER: 
-        runverbose = value;
+               /* where is this defined ? 
+                  runverbose = value;
+               */
         break;
     case JVMTI_VERBOSE_GC: 
         opt_verbosegc = value;
@@ -4019,7 +4104,8 @@ static jvmtiCapabilities JVMTI_Capabilities = {
   0,                           /* can_pop_frame */
   0,                           /* can_redefine_classes */
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-  1,                           /* can_signal_thread */
+  /* current implementation does not work if called from another process */
+  0,                           /* can_signal_thread */
 #else
   0,                           /* can_signal_thread */
 #endif
@@ -4033,7 +4119,8 @@ static jvmtiCapabilities JVMTI_Capabilities = {
   0,                           /* can_generate_frame_pop_events */
   0,                           /* can_generate_breakpoint_events */
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-  1,                           /* can_suspend */
+  /* current implementation does not work if called from another process */
+  0,                           /* can_suspend */
 #else
   0,                           /* can_suspend */
 #endif
@@ -4051,7 +4138,7 @@ static jvmtiCapabilities JVMTI_Capabilities = {
   0,                           /* can_generate_object_free_events */
 };
 
-static jvmtiEnv JVMTI_EnvTable = {
+static struct jvmtiEnv_struct JVMTI_EnvTable = {
     NULL,
     &SetEventNotificationMode,
     NULL,
@@ -4208,42 +4295,59 @@ static jvmtiEnv JVMTI_EnvTable = {
     &GetObjectSize
 };
 
+
 void set_jvmti_phase(jvmtiPhase p) {
        genericEventData d;
-       jvmtiEvent e;
 
-    phase = p;
+       fprintf (stderr,"set JVMTI pid %d phase %d\n",getpid(),p);
+       fflush(stderr);
+
     switch (p) {
     case JVMTI_PHASE_ONLOAD:
-        /* nothing to be done */
+               phase = p;
         return;
     case JVMTI_PHASE_PRIMORDIAL:
-        /* nothing to be done */
+               phase = p;
         return;
     case JVMTI_PHASE_START: 
-               e = JVMTI_EVENT_VM_START;
+               phase = p;
+               d.ev = JVMTI_EVENT_VM_START;
+               /* this event is sent during start or live phase */
+               log_text("debugger process - set brk in setthreadobj");
+               setsysbrkpt(SETTHREADOBJECTBRK,(void*)&setthreadobject);
         break;
     case JVMTI_PHASE_LIVE: 
-               e = JVMTI_EVENT_VM_INIT;
-        break;
+               phase = p; 
+               d.ev = JVMTI_EVENT_VM_INIT;
+               break;
     case JVMTI_PHASE_DEAD:
-               e = JVMTI_EVENT_VM_DEATH;
+               phase = p;
+               d.ev = JVMTI_EVENT_VM_DEATH;
         break;
+       default:
+               log_text("wrong jvmti phase to be set");
+               exit(1);
     }
 
-       fireEvent(e,&d);
+       fireEvent(&d);
 }
 
 jvmtiEnv* new_jvmtienv() {
     environment* env;
 
-       env = envs;
-       if (env != NULL) 
-               while (env->next!=NULL) {
-                       env=env->next;
-               }
-       env = heap_allocate(sizeof(environment),true,NULL);
-    memcpy(&(env->env),&JVMTI_EnvTable,sizeof(jvmtiEnv));
+       if (envs == NULL) {
+               envs = heap_allocate(sizeof(environment),true,NULL);
+               env = envs;
+       } else {
+               env = envs;
+               if (env != NULL) 
+                       while (env->next!=NULL) {
+                               env=env->next;
+                       }
+                       env = heap_allocate(sizeof(environment),true,NULL);
+       }
+       env->env = heap_allocate(sizeof(struct jvmtiEnv_struct),true,NULL);
+    memcpy(env->env,&JVMTI_EnvTable,sizeof(struct jvmtiEnv_struct));
        memset(&(env->events),JVMTI_DISABLE,(JVMTI_EVENT_END_ENUM - JVMTI_EVENT_START_ENUM)*
                   sizeof(jvmtiEventModeLL));
     /* To possess a capability, the agent must add the capability.*/
@@ -4251,7 +4355,8 @@ jvmtiEnv* new_jvmtienv() {
     RelinquishCapabilities(&(env->env),&(env->capabilities));
     env->EnvironmentLocalStorage = NULL;
        env->tls = NULL;
-       return &(env->env);
+
+       return (jvmtiEnv*)env;
 }
 
 void agentload(char* opt_arg) {
@@ -4260,6 +4365,7 @@ void agentload(char* opt_arg) {
        char *libname, *arg;
        int i=0,len;
        jint retval;
+       classinfo* ci;
        
        len = strlen(opt_arg);
        
@@ -4287,6 +4393,10 @@ void agentload(char* opt_arg) {
        /* resolve Agent_UnLoad function */
        unload = lt_dlsym(handle, "Agent_Unload");
 
+       /* add library to native library hashtable */
+       ci = load_class_from_sysloader(utf_new_char("java.lang.Object"));
+       native_hashtable_library_add(utf_new_char(libname), ci->classloader, handle);
+
        retval = 
                ((JNIEXPORT jint JNICALL (*) (JavaVM *vm, char *options, void *reserved))
                 onload) ((JavaVM*) &_Jv_JNIInvokeInterface, arg, NULL);
@@ -4295,8 +4405,6 @@ void agentload(char* opt_arg) {
        MFREE(arg,char,len-i);
        
        if (retval != 0) exit (retval);
-
-       /* todo: native_library_hash_add(name, (java_objectheader *) loader, handle); */
 }
 
 void agentunload() {
index ee26ad38d0e59fd44c639865a75be80845a651bb..3781e463530dc9cb360072fb0e5d0bb6ec6840dc 100644 (file)
    Changes:             
 
    
-   $Id: jvmti.h 4357 2006-01-22 23:33:38Z twisti $
+   $Id: jvmti.h 4661 2006-03-21 00:04:59Z motse $
 
 */
-#ifndef JVMTI_H
-#define JVMTI_H
+#ifndef _JVMTI_H
+#define _JVMTI_H
 
 #include "native/jni.h"
 #include "native/include/java_lang_String.h"
@@ -47,7 +47,7 @@ typedef jobject jthreadGroup;
 typedef jlong jlocation;
 struct _jrawMonitorID;
 typedef struct _jrawMonitorID *jrawMonitorID;
-typedef struct jvmtiEnv_struct jvmtiEnv;
+typedef struct jvmtiEnv_struct *jvmtiEnv;
 
 typedef enum {
     JVMTI_ERROR_NONE = 0, /* No error has occurred. This is the error code that is 
@@ -1177,48 +1177,6 @@ struct jvmtiEnv_struct {
 #define JVMTI_CLASS_STATUS_ARRAY  16  
 #define JVMTI_CLASS_STATUS_PRIMITIVE  32 
 
-/* cacao specific */
-
-typedef struct {
-       jvmtiEnv *jvmti_env;
-       jthread thread;
-       jmethodID method;
-       jlocation location;
-       jclass klass;
-       jobject object;
-       jfieldID field;
-       char signature_type;
-       jvalue value;
-       jboolean b;
-       void* address;
-       void** new_address_ptr;
-       jmethodID catch_method;
-       jlocation catch_location;
-       char* name;
-       jobject protection_domain;
-       jint jint1;
-       jint jint2;
-       unsigned char* class_data;
-       jint* new_class_data_len;
-       unsigned char** new_class_data;
-       jvmtiAddrLocationMap* map;
-       void* compile_info;
-       jlong jlong;
-} genericEventData;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-struct _jrawMonitorID {
-       java_lang_String *name;
-};
-#endif
-
-jvmtiEnv* new_jvmtienv();
-void set_jvmti_phase(jvmtiPhase p);
-pid_t debuggee;
-jvmtiEnv* remotedbgjvmtienv;
-jvmtiEventCallbacks jvmti_jdwp_EventCallbacks;
-void agentload(char* opt_arg);
-void agentunload();
 #endif
 
 
index 5ed7498e5040a3d451955e0b10cf2842e7f742c1..0e60622191ee3f83eec90b770f76b8d0fb45e5a0 100644 (file)
@@ -30,7 +30,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: native.c 4559 2006-03-05 23:24:50Z twisti $
+   $Id: native.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
 #include "native/include/java_lang_reflect_Method.h"
 #include "native/include/java_lang_reflect_VMProxy.h"
 #include "native/include/java_security_VMAccessController.h"
-
+#if defined(ENABLE_JVMTI)
+#include "native/include/gnu_classpath_jdwp_event_EventRequest.h"
+#include "native/include/java_nio_ByteBuffer.h"
+#include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
+#include "native/include/gnu_classpath_jdwp_VMFrame.h"
+#include "native/include/gnu_classpath_jdwp_VMMethod.h"
+#endif
 
 #if defined(WITH_STATIC_CLASSPATH)
 
@@ -222,6 +228,34 @@ static functionptr dummynativetable[] = {
        (functionptr) Java_java_lang_reflect_VMProxy_generateProxyClass,
 
        (functionptr) Java_java_security_VMAccessController_getStack,
+#if defined(ENABLE_JVMTI)
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllClassMethods,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getClassMethod,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrame,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getLoadRequests,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getSourceFile,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents,
+       (functionptr) Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasses,
+       (functionptr) Java_gnu_classpath_jdwp_VMFrame_setValue,
+       (functionptr) Java_gnu_classpath_jdwp_VMFrame_getValue,
+       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getName,
+       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getSignature,
+       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getModifiers,
+       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getLineTable,
+       (functionptr) Java_gnu_classpath_jdwp_VMMethod_getVariableTable
+#endif
+
 };
 
 #endif /* defined(WITH_STATIC_CLASSPATH) */
index f8c51c00530ae35f665e9de4a0dce455165b97f0..580370a89b4e490da1b8e6382b89dda63a19036b 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes:
 ##
-## $Id: Makefile.am 4627 2006-03-16 12:53:32Z twisti $
+## $Id: Makefile.am 4661 2006-03-21 00:04:59Z motse $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -58,7 +58,8 @@ libnativevm_la_SOURCES = \
 if ENABLE_JVMTI
 libnativevm_la_SOURCES += \
        VMFrame.c \
-       VMVirtualMachine.c
+       VMVirtualMachine.c \
+       VMMethod.c
 endif
 
 
index 49e376b76883a7924110e542664d2f6f09e76900..0a5bfaa37ec1030de6f0d75a6a5c3beab927a1e4 100644 (file)
@@ -29,7 +29,7 @@ Authors: Martin Platter
 Changes: 
 
 
-$Id: VMVirtualMachine.c 4357 2006-01-22 23:33:38Z twisti $
+$Id: VMVirtualMachine.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
@@ -43,6 +43,8 @@ $Id: VMVirtualMachine.c 4357 2006-01-22 23:33:38Z twisti $
 #include "native/include/gnu_classpath_jdwp_event_EventRequest.h"
 #include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
 #include "native/jvmti/jvmti.h"
+#include "native/jvmti/cacaodbg.h"
+#include <string.h>
 
 
 /*
@@ -52,7 +54,7 @@ $Id: VMVirtualMachine.c 4357 2006-01-22 23:33:38Z twisti $
  */
 JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1)
 {
-    remotedbgjvmtienv->SuspendThread(remotedbgjvmtienv, (jthread) par1);
+    (*remotedbgjvmtienv)->SuspendThread(remotedbgjvmtienv, (jthread) par1);
 }
 
 /*
@@ -62,7 +64,7 @@ JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread(JN
  */
 JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1)
 {
-    remotedbgjvmtienv->ResumeThread(remotedbgjvmtienv, (jthread) par1);
+    (*remotedbgjvmtienv)->ResumeThread(remotedbgjvmtienv, (jthread) par1);
 }
 
 
@@ -72,8 +74,8 @@ JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread(JNI
  * Signature: (Ljava/lang/Thread;)I
  */
 JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
+    log_text ("VMVirtualMachine_getSuspendCount: not supported");
+       return 1;
 }
 
 /*
@@ -85,17 +87,87 @@ JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasse
     jint count;
     jclass* classes;
 
-    remotedbgjvmtienv->GetLoadedClasses(remotedbgjvmtienv, &count, &classes);
+    (*remotedbgjvmtienv)->GetLoadedClasses(remotedbgjvmtienv, &count, &classes);
     return count;
 }
 
+/*
+ * Class:     gnu_classpath_jdwp_VMVirtualMachine
+ * Method:    getAllLoadedClasses
+ * Signature: ()Ljava/util/Iterator
+ */
+JNIEXPORT struct java_util_Iterator* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClasses(JNIEnv *env, jclass clazz) {
+       jclass *classes, *cl;
+       jint classcount;
+       jobjectArray joa;
+/*     jthrowable e;*/
+       jmethodID m;
+       jobject *ol,*oi;
+       int i;
+       jvmtiError err;
+       char* errdesc;
+
+       if (JVMTI_ERROR_NONE != (err= (*remotedbgjvmtienv)->
+               GetLoadedClasses(remotedbgjvmtienv, &classcount, &classes))) {
+               (*remotedbgjvmtienv)->GetErrorName(remotedbgjvmtienv,err, &errdesc);
+               fprintf(stderr,"jvmti error: %s\n",errdesc);
+               fflush(stderr);
+/*             env->ThrowNew(env,ec,"jvmti error occoured");*/
+       }
+       
+       cl = (*env)->FindClass(env,"java.lang.Class");
+
+       /* Arrays.asList(Object[] classes)->List.Iterator()->Iterator */
+       joa = (*env)->NewObjectArray(env, (jsize)classcount, cl , NULL);
+
+       for (i = 0; i < classcount; i++) 
+               (*env)->SetObjectArrayElement(env,joa,(jsize)i, (jobject)classes[i]);
+       
+       cl = (*env)->FindClass(env,"java.util.Arrays");
+       if (!cl) return NULL;
+
+       m = (*env)->GetStaticMethodID(env, cl, "asList", "([Ljava/lang/Object;)Ljava/util/List;");
+       if (!m) return NULL;
+
+       ol = (*env)->CallStaticObjectMethod(env,(jclass)cl,m,joa);
+       if (!ol) return NULL;
+
+       cl = (*env)->FindClass(env,"java.util.List");
+       if (!cl) return NULL;
+       m = (*env)->GetMethodID(env,cl,"Iterator","()Ljava/util/Iterator;");
+
+       oi = (*env)->CallObjectMethod(env,*ol,m);
+               
+       return (struct java_util_Iterator*)oi;
+}
+
 /* Class:     gnu/classpath/jdwp/VMVirtualMachine
  * Method:    getClassStatus
  * Signature: (Ljava/lang/Class;)I
  */
 JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
+       jint status;
+       (*remotedbgjvmtienv)->GetClassStatus(remotedbgjvmtienv, (jclass) par1, &status);
+       return status;
+}
+
+/*
+ * Class:     gnu/classpath/jdwp/VMVirtualMachine
+ * Method:    getAllClassMethods
+ * Signature: (Ljava/lang/Class;)[Lgnu/classpath/jdwp/VMMethod;
+ */
+JNIEXPORT java_objectarray* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getAllClassMethods(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
+    log_text ("VMVirtualMachine_getAllClassMethods: IMPLEMENT ME !!!");
+}
+
+
+/*
+ * Class:     gnu/classpath/jdwp/VMVirtualMachine
+ * Method:    getClassMethod
+ * Signature: (Ljava/lang/Class;J)Lgnu/classpath/jdwp/VMMethod;
+ */
+JNIEXPORT struct gnu_classpath_jdwp_VMMethod* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassMethod(JNIEnv *env, jclass clazz, struct java_lang_Class* par1, s8 par2) {
+    log_text ("VMVirtualMachine_getAllClassMethod: IMPLEMENT ME !!!");
 }
 
 
@@ -105,7 +177,10 @@ JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus(JNI
  * Signature: (Ljava/lang/Thread;II)Ljava/util/ArrayList;
  */
 JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1, s4 par2, s4 par3) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+    log_text ("VMVirtualMachine_getFrames - IMPLEMENT ME!!!");
+/*     jclass ec = (*env)->FindClass(env,"gnu/classpath/jdwp/JdwpInternalErrorException");
+       if (JVMTI_ERROR_NONE != (*remotedbgjvmtienv)->GetClassStatus(remotedbgjvmtienv, par1, &status))
+       env->ThrowNew(env,ec,"jvmti error occoured");*/
        return 0;
 }
 
@@ -116,7 +191,7 @@ JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualM
  * Signature: (Ljava/lang/Thread;Ljava/nio/ByteBuffer;)Lgnu/classpath/jdwp/VMFrame;
  */
 JNIEXPORT struct gnu_classpath_jdwp_VMFrame* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrame(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1, struct java_nio_ByteBuffer* par2) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+    log_text ("VMVirtualMachine_getFrame - IMPLEMENT ME!!!");
        return 0;
 }
 
@@ -127,8 +202,9 @@ JNIEXPORT struct gnu_classpath_jdwp_VMFrame* JNICALL Java_gnu_classpath_jdwp_VMV
  * Signature: (Ljava/lang/Thread;)I
  */
 JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
+       jint count;
+       (*remotedbgjvmtienv)->GetFrameCount(remotedbgjvmtienv, (jthread)par1, &count);
+       return count;
 }
 
 
@@ -138,8 +214,23 @@ JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount(JNIE
  * Signature: (Ljava/lang/Thread;)I
  */
 JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
+       jint status;
+       if (JVMTI_ERROR_NONE != (*remotedbgjvmtienv)->GetThreadState(remotedbgjvmtienv, (jthread)par1, &status))
+               return 0;
+       if (status && JVMTI_THREAD_STATE_ALIVE) {
+               if (status && JVMTI_THREAD_STATE_WAITING) {             
+                       return 4; /* WAIT - see JdwpConstants */
+               }
+               if (status && JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) { 
+                       return 3; /* MONITOR - see JdwpConstants */
+               }
+               if (status && JVMTI_THREAD_STATE_SLEEPING) { 
+                       return 2; /* SLEEPING - see JdwpConstants */
+               }
+               return 1; /* RUNNING - see JdwpConstants */
+       } else 
+               return 0; /* ZOMBIE - see JdwpConstants */
+       return -1; /* some error */
 }
 
 
@@ -149,7 +240,7 @@ JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus(JN
  * Signature: (Ljava/lang/ClassLoader;)Ljava/util/ArrayList;
  */
 JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getLoadRequests(JNIEnv *env, jclass clazz, struct java_lang_ClassLoader* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+    log_text ("VMVirtualMachine_getLoadRequests(");
        return 0;
 }
 
@@ -160,29 +251,7 @@ JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualM
  * Signature: (Ljava/lang/Object;Ljava/lang/Thread;Ljava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;Z)Lgnu/classpath/jdwp/util/MethodResult;
  */
 JNIEXPORT struct gnu_classpath_jdwp_util_MethodResult* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod(JNIEnv *env, jclass clazz, struct java_lang_Object* par1, struct java_lang_Thread* par2, struct java_lang_Class* par3, struct java_lang_reflect_Method* par4, java_objectarray* par5, s4 par6) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
-}
-
-
-/*
- * Class:     gnu/classpath/jdwp/VMVirtualMachine
- * Method:    getVarTable
- * Signature: (Ljava/lang/Class;Ljava/lang/reflect/Method;)Lgnu/classpath/jdwp/util/VariableTable;
- */
-JNIEXPORT struct gnu_classpath_jdwp_util_VariableTable* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getVarTable(JNIEnv *env, jclass clazz, struct java_lang_Class* par1, struct java_lang_reflect_Method* par2) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
-}
-
-
-/*
- * Class:     gnu/classpath/jdwp/VMVirtualMachine
- * Method:    getLineTable
- * Signature: (Ljava/lang/Class;Ljava/lang/reflect/Method;)Lgnu/classpath/jdwp/util/LineTable;
- */
-JNIEXPORT struct gnu_classpath_jdwp_util_LineTable* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getLineTable(JNIEnv *env, jclass clazz, struct java_lang_Class* par1, struct java_lang_reflect_Method* par2) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+    log_text ("VMVirtualMachine_executeMethod");
        return 0;
 }
 
@@ -193,10 +262,40 @@ JNIEXPORT struct gnu_classpath_jdwp_util_LineTable* JNICALL Java_gnu_classpath_j
  * Signature: (Ljava/lang/Class;)Ljava/lang/String;
  */
 JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getSourceFile(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
-       return 0;
+       char* srcname;
+       jstring str;
+
+    (*remotedbgjvmtienv)->
+               GetSourceFileName(remotedbgjvmtienv, (jclass)par1, &srcname);
+       str = (*env)->NewString(env,(jchar*)srcname,(jsize)strlen(srcname));
+
+       return (struct java_lang_String*)str;
 }
 
+/* match JdwpConstants.EventKind to jvmtiEvent constants */
+static jvmtiEvent EventKind2jvmtiEvent(jbyte kind){
+       switch (kind) {
+       case /* SINGLE_STEP */ 1: return JVMTI_EVENT_SINGLE_STEP;
+       case /* BREAKPOINT */ 2: return JVMTI_EVENT_BREAKPOINT;
+    case /*  FRAME_POP */ 3: return JVMTI_EVENT_FRAME_POP;
+    case /*  EXCEPTION */ 4: return JVMTI_EVENT_EXCEPTION;
+    case /*  USER_DEFINED */ 5: return -1; /* can this be matched ? */
+    case /*  THREAD_START */ 6: return JVMTI_EVENT_THREAD_START;
+    case /*  THREAD_END */ 7: return JVMTI_EVENT_THREAD_END;
+    case /*  CLASS_PREPARE */ 8: return JVMTI_EVENT_CLASS_PREPARE;
+    case /*  CLASS_UNLOAD */ 9: return -1; /* can this be matched ? */
+    case /*  CLASS_LOAD */ 10: return JVMTI_EVENT_CLASS_LOAD;
+    case /*  FIELD_ACCESS */ 20: return JVMTI_EVENT_FIELD_ACCESS;
+    case /*  FIELD_MODIFICATION */ 21: return JVMTI_EVENT_FIELD_MODIFICATION;
+    case /*  EXCEPTION_CATCH */ 30: return JVMTI_EVENT_EXCEPTION_CATCH;
+    case /*  METHOD_ENTRY */ 40: return JVMTI_EVENT_METHOD_ENTRY;
+    case /*  METHOD_EXIT */ 41: return JVMTI_EVENT_METHOD_EXIT;
+    case /*  VM_INIT */ 90: return JVMTI_EVENT_VM_INIT;
+    case /*  VM_DEATH */ 99: return JVMTI_EVENT_VM_DEATH;    
+    case /*  VM_DISCONNECTED */ 100: return -1; /* can this be matched ? */
+       default: return -1;
+       }
+}
 
 /*
  * Class:     gnu/classpath/jdwp/VMVirtualMachine
@@ -204,7 +303,20 @@ JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMVirtualMach
  * Signature: (Lgnu/classpath/jdwp/event/EventRequest;)V
  */
 JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent(JNIEnv *env, jclass clazz, struct gnu_classpath_jdwp_event_EventRequest* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+       jbyte kind;
+       jfieldID kindid;
+       jclass erc;
+
+       erc = (*env)->FindClass(env,"gnu.classpath.jdwp.event.EventRequest");
+       
+       kindid = (*env)->GetFieldID(env, erc, "_kind", "B");
+       kind = (*env)->GetByteField(env, (jobject)par1, kindid);
+
+       (*remotedbgjvmtienv)->
+               SetEventNotificationMode(remotedbgjvmtienv, JVMTI_ENABLE, 
+                                                                EventKind2jvmtiEvent(kind), NULL);
+
+       /* todo: error handling, suspend policy */
 }
 
 
@@ -214,7 +326,20 @@ JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_registerEvent(JN
  * Signature: (Lgnu/classpath/jdwp/event/EventRequest;)V
  */
 JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent(JNIEnv *env, jclass clazz, struct gnu_classpath_jdwp_event_EventRequest* par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+       jbyte kind;
+       jfieldID kindid;
+       jclass erc;
+
+       erc = (*env)->FindClass(env,"gnu.classpath.jdwp.event.EventRequest");
+       
+       kindid = (*env)->GetFieldID(env, erc, "_kind", "B");
+       kind = (*env)->GetByteField(env, (jobject)par1, kindid);
+
+       (*remotedbgjvmtienv)->
+               SetEventNotificationMode(remotedbgjvmtienv, JVMTI_DISABLE, 
+                                                                EventKind2jvmtiEvent(kind), NULL);
+
+       /* todo: error handling, suspend policy */
 }
 
 
@@ -224,7 +349,8 @@ JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_unregisterEvent(
  * Signature: (B)V
  */
 JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents(JNIEnv *env, jclass clazz, s4 par1) {
-    log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+       /* jvmti events are not saved */
+    log_text ("VMVirtualMachine_clearEvents IMPLEMENT ME!!!");
 }
 
 
index b696bd3dfeca386396acd5fa2699c24bb135110c..1be6857c153208c1e5a63d92597f68c1abe23801 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: threads.c 4559 2006-03-05 23:24:50Z twisti $
+   $Id: threads.c 4661 2006-03-21 00:04:59Z motse $
 
 */
 
@@ -463,7 +463,11 @@ int cacao_suspendhandler(ucontext_t *ctx)
 }
 #endif
 
+#if !defined(ENABLE_JVMTI)
 static void setthreadobject(threadobject *thread)
+#else
+void setthreadobject(threadobject *thread)
+#endif
 {
 #if !defined(HAVE___THREAD)
        pthread_setspecific(tkey_threadinfo, thread);
index 7a9099ce3d81e5ab03cf40fbd0edb5271e76128b..4f1afcbb7f93944092ad7168af9d66abc0dfe26a 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: threads.h 4475 2006-02-06 21:06:12Z twisti $
+   $Id: threads.h 4661 2006-03-21 00:04:59Z motse $
 
 */
 
@@ -211,6 +211,11 @@ void interruptThread(java_lang_VMThread *);
 bool interruptedThread();
 bool isInterruptedThread(java_lang_VMThread *);
 
+#if defined(ENABLE_JVMTI)
+void setthreadobject(threadobject *thread);
+#endif
+
+
 /* This must not be changed, it is used in asm_criticalsections */
 typedef struct {
        u1 *mcodebegin;
index 3a132e03b9f79e3ef25a62bd077769a538c1c700..a4c334dedc6abc65cf2a703eceebdb7b8abc8f05 100644 (file)
@@ -68,6 +68,9 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/profile/profile.h"
 
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
 
 /* Invocation API variables ***************************************************/
 
@@ -191,6 +194,8 @@ enum {
 
 #ifdef ENABLE_JVMTI
        OPT_DEBUG,
+       OPT_XRUNJDWP,
+       OPT_NOAGENT,
        OPT_AGENTLIB,
        OPT_AGENTPATH,
 #endif
@@ -276,6 +281,8 @@ opt_struct opts[] = {
        { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
 #ifdef ENABLE_JVMTI
        { "Xdebug",            false, OPT_DEBUG },
+       { "Xnoagent",          false, OPT_NOAGENT },
+       { "Xrunjdwp",          true,  OPT_XRUNJDWP },
 #endif 
        { "Xms",               true,  OPT_MS },
        { "ms",                true,  OPT_MS },
@@ -401,7 +408,11 @@ static void Xusage(void)
        puts("    -Xss<size>               set the thread stack size (default: 128kB)");
        puts("    -Xprof[:bb]              collect and print profiling data");
 #if defined(ENABLE_JVMTI)
-       puts("    -Xdebug<transport>       enable remote debugging");
+    /* -Xdebug option depend on gnu classpath JDWP options. options: 
+        transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
+       puts("    -Xdebug           enable remote debugging\n");
+       puts("    -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
+       puts("                      enable remote debugging\n");
 #endif 
 
        /* exit with error code */
@@ -503,6 +514,7 @@ bool vm_create(JavaVMInitArgs *vm_args)
        nogc_init(HEAP_MAXSIZE, HEAP_STARTSIZE);
 #endif
 
+
        /* set the bootclasspath */
 
        cp = getenv("BOOTCLASSPATH");
@@ -547,6 +559,15 @@ bool vm_create(JavaVMInitArgs *vm_args)
        heapstartsize = HEAP_STARTSIZE;
        opt_stacksize = STACK_SIZE;
 
+
+#if defined(ENABLE_JVMTI)
+       /* initialize JVMTI related  **********************************************/
+       jvmtibrkpt.brk=NULL;
+       jvmtibrkpt.num=0;
+       jvmtibrkpt.size=0;
+       jdwp = jvmti = dbgprocess = false;
+#endif
+
        /* initialize properties before commandline handling */
 
        if (!properties_init())
@@ -642,15 +663,39 @@ bool vm_create(JavaVMInitArgs *vm_args)
 
 #if defined(ENABLE_JVMTI)
                case OPT_DEBUG:
-                       dbg = true;
+                       jdwp=true;
+                       break;
+               case OPT_NOAGENT:
+                       /* I don't know yet what Xnoagent should do. This is only for 
+                          compatiblity with eclipse - motse */
+                       break;
+               case OPT_XRUNJDWP:
                        transport = opt_arg;
+                       j=0;
+                       while (transport[j]!='=') j++;
+                       j++;
+                       while (j<strlen(transport)) {
+                               if (strncmp("suspend=",&transport[j],8)==0) {
+                                       if ((j+8)>=strlen(transport) || 
+                                               (transport[j+8]!= 'y' && transport[j+8]!= 'n')) {
+                                               printf("bad Xrunjdwp option: -Xrunjdwp%s\n",transport);
+                                               usage();
+                                               break;
+                                       }
+                                       else {
+                                               suspend = transport[j+8] == 'y';
+                                               break;
+                                       }
+                               }
+                               while (transport[j]!=',') j++;
+                               j++;
+                       }
+                       
                        break;
-
                case OPT_AGENTPATH:
                case OPT_AGENTLIB:
-                       set_jvmti_phase(JVMTI_PHASE_ONLOAD);
-                       agentload(opt_arg);
-                       set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
+                       jvmti=true;
+                       agentarg = opt_arg;
                        break;
 #endif
                        
@@ -984,6 +1029,21 @@ bool vm_create(JavaVMInitArgs *vm_args)
                }
        }
 
+#if defined(ENABLE_JVMTI)
+       /* The fork has to occure before threads a created because threads  are 
+          not forked correctly (see man pthread_atfork). Varibale dbgprocess 
+          stores information whether this is the debugger or debuggee process. */
+       if (jvmti || jdwp) {
+               set_jvmti_phase(JVMTI_PHASE_ONLOAD);
+               dbgprocess = cacaodbgfork();
+       }
+
+       if (dbgprocess && jvmti) { /* is this the parent/debugger process ? */
+               agentload(agentarg);
+               set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
+       }
+#endif
+
 
        /* initialize this JVM ****************************************************/
 
@@ -1180,8 +1240,10 @@ void vm_exit(s4 status)
        assert(class_java_lang_System->state & CLASS_LOADED);
 
 #if defined(ENABLE_JVMTI)
-       set_jvmti_phase(JVMTI_PHASE_DEAD);
-       agentunload();
+       if (dbgprocess) {
+               set_jvmti_phase(JVMTI_PHASE_DEAD);
+               if (jvmti) agentunload();
+       }
 #endif
 
        if (!link_class(class_java_lang_System))
@@ -1222,9 +1284,12 @@ void vm_exit(s4 status)
 void vm_shutdown(s4 status)
 {
 #if defined(ENABLE_JVMTI)
-       agentunload();
+       if (dbgprocess) {
+               set_jvmti_phase(JVMTI_PHASE_DEAD);
+               if (jvmti) agentunload();
+               ipcrm();
+       }
 #endif
-
        if (opt_verbose || getcompilingtime || opt_stat) {
                log_text("CACAO terminated by shutdown");
                dolog("Exit status: %d\n", (s4) status);
@@ -1246,6 +1311,12 @@ void vm_shutdown(s4 status)
 
 void vm_exit_handler(void)
 {
+#if defined(ENABLE_JVMTI)
+       if (jvmti && jdwp) set_jvmti_phase(JVMTI_PHASE_DEAD);
+       if (jvmti) agentunload();
+       ipcrm();
+#endif
+
 #if !defined(NDEBUG)
        if (showmethods)
                class_showmethods(mainclass);