* src/cacao/cacao.c (main): changes for jvmti/jdwp startup due to removal of jdwp process
* src/native/jni.c (JNI_CreateJavaVM): change order vm_create and initialization of _Jv_jvm due to jvmti agent support.
* src/native/vm/VMVirtualMachine.c: change name of jvmtienv and bugfixes of Samuel Vinson
* src/native/include/Makefile.am: add VMMethod.h
* src/native/jvmti/Makefile.am: removal of cacaodbgserver
* src/native/jvmti/jvmti.c: remove jdwp process and convert to thread
* src/native/jvmti/cacaodbg.h: idem
* src/native/jvmti/jvmti.h: idem
* src/native/jvmti/dbg.h: idem
* src/native/jvmti/cacaodbg.c: idem
* src/native/jvmti/dbg.c: idem
* src/native/jvmti/cacaodbgserver.c: change to a autonomous program and removal of jdwp thread.
* src/native/jvmti/VMjdwp.c (VMInit): different invocation due to removal of jdwp thread
* src/native/jvmti/VMjdwp.h: export jvmti environment and event callbacks.
* src/native/vm/VMMethod.c: initial/dummy implementation of VMMetod native method
Philipp Tomsich
Christian Thalinger
- $Id: cacao.c 4879 2006-05-05 17:34:49Z edwin $
+ $Id: cacao.c 4892 2006-05-06 18:29:55Z motse $
*/
#if defined(ENABLE_JVMTI)
#include "native/jvmti/jvmti.h"
#include "native/jvmti/cacaodbg.h"
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
#include <pthread.h>
#endif
#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
stackbottom = &dummy;
#endif
-
+
if (atexit(vm_exit_handler))
throw_cacao_exception_exit(string_java_lang_InternalError,
"Unable to register exit_handler");
JNI_CreateJavaVM(&jvm, (void **) &_Jv_env, vm_args);
#if defined(ENABLE_JVMTI)
- if (dbgprocess && jvmti && jdwp) /* is this the parent/debugger process ? */
- set_jvmti_phase(JVMTI_PHASE_START);
+ pthread_mutex_init(&dbgcomlock,NULL);
+ set_jvmti_phase(JVMTI_PHASE_START);
#endif
/* do we have a main class? */
/*class_showmethods(currentThread->group->header.vftbl->class); */
#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);
+ /* start the jdwp listening */
+ if (jdwp) {
+ log_text("cacao vm - init VMjdwp");
+ if (!VMjdwpInit()) exit(1);
+ setup_jdwp_thread(transport);
+ if (!suspend) {
+ fprintf(stderr,"suspend false -> continue debuggee\n");
+ } else {
+ fprintf(stderr,"suspend true -> do no continue debuggee(todo)\n");
+ /* XXX todo*/
+ }
}
- if (!dbgprocess) {
- fprintf(stderr,"debuggee: herewe go\n");
- fflush(stderr);
- }
- /* here we go... */
- herewego:
+ set_jvmti_phase(JVMTI_PHASE_LIVE);
+
+ log_text("debuggee: herewe go");
#endif
+
(void) vm_call_method(m, NULL, oa);
/* exception occurred? */
##
## Changes:
##
-## $Id: Makefile.am 4594 2006-03-14 16:40:32Z twisti $
+## $Id: Makefile.am 4892 2006-05-06 18:29:55Z motse $
## Process this file with automake to produce Makefile.in
GEN_JVMTI_HEADER_FILES = \
java_nio_ByteBuffer.h \
gnu_classpath_jdwp_VMFrame.h \
+ gnu_classpath_jdwp_VMMethod.h \
gnu_classpath_jdwp_VMVirtualMachine.h \
gnu_classpath_jdwp_event_EventRequest.h
Christian Thalinger
Edwin Steiner
- $Id: jni.c 4874 2006-05-05 14:36:18Z edwin $
+ $Id: jni.c 4892 2006-05-06 18:29:55Z motse $
*/
_Jv_env = env;
- /* actually create the JVM */
-
- if (!vm_create(_vm_args))
- return -1;
/* create and fill a JavaVM structure */
jvm->functions = &_Jv_JNIInvokeInterface;
/* XXX Set the global variable. Maybe we should do that differently. */
-
+ /* XXX JVMTI Agents needs a JavaVM */
_Jv_jvm = jvm;
+
+ /* actually create the JVM */
+
+ if (!vm_create(_vm_args))
+ return -1;
+
/* setup the local ref table (must be created after vm_create) */
lrt = GCNEW(localref_table);
##
## Changes:
##
-## $Id: Makefile.am 4661 2006-03-21 00:04:59Z motse $
+## $Id: Makefile.am 4892 2006-05-06 18:29:55Z motse $
## Process this file with automake to produce Makefile.in
jvmti.c \
jvmti.h \
VMjdwp.c \
+ VMjdwp.h \
dbg.h\
dbg.c\
cacaodbg.h \
- cacaodbg.c \
- cacaodbgserver.c \
- cacaodbgserver.h
+ cacaodbg.c
+## seperate cacaodbgserver executable
+## cacaodbgserver.c \
+## cacaodbgserver.h \
## Local variables:
## mode: Makefile
Changes:
- $Id: VMjdwp.c 4661 2006-03-21 00:04:59Z motse $
+ $Id: VMjdwp.c 4892 2006-05-06 18:29:55Z motse $
*/
#include "native/jvmti/jvmti.h"
#include "native/jvmti/cacaodbg.h"
+#include "native/jvmti/VMjdwp.h"
#include "vm/loader.h"
#include "vm/exceptions.h"
#include "vm/jit/asmpart.h"
}
-bool VMjdwpInit(jvmtiEnv* env) {
+/* it would be more apropriate to call this function from gnu-cp jdwp */
+bool VMjdwpInit() {
int end, i=0;
jvmtiCapabilities cap;
jvmtiError e;
+ log_text("cacao vm - create new jvmti environment");
+ jvmtienv = new_jvmtienv();
/* set eventcallbacks */
if (JVMTI_ERROR_NONE !=
- (*env)->SetEventCallbacks(env,
+ (*jvmtienv)->SetEventCallbacks(jvmtienv,
&jvmti_jdwp_EventCallbacks,
sizeof(jvmti_jdwp_EventCallbacks))){
log_text("unable to setup event callbacks");
return false;
}
- e = (*env)->GetPotentialCapabilities(env, &cap);
+ e = (*jvmtienv)->GetPotentialCapabilities(jvmtienv, &cap);
if (e == JVMTI_ERROR_NONE) {
- e = (*env)->AddCapabilities(env, &cap);
+ e = (*jvmtienv)->AddCapabilities(jvmtienv, &cap);
}
if (e != JVMTI_ERROR_NONE) {
log_text("error adding jvmti capabilities");
for (i = 0; i < end; i++) {
/* enable standard VM callbacks */
if (((void**)&jvmti_jdwp_EventCallbacks)[i] != NULL) {
- e = (*env)->SetEventNotificationMode(env,
+ e = (*jvmtienv)->SetEventNotificationMode(jvmtienv,
JVMTI_ENABLE,
JVMTI_EVENT_START_ENUM+i,
NULL);
--- /dev/null
+/* src/native/vm/VMjdwp.c - jvmti->jdwp interface
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Contact: cacao@cacaojvm.org
+
+ Author: Martin Platter
+
+ Changes:
+
+
+ $Id: VMjdwp.c 4661 2006-03-21 00:04:59Z motse $
+
+*/
+
+#ifndef _VMJDWP_H
+#define _VMJDWP_H
+
+#include "native/jvmti/jvmti.h"
+
+jvmtiEnv* jvmtienv;
+jvmtiEventCallbacks jvmti_jdwp_EventCallbacks;
+
+#endif
Authors: Martin Platter
Changes: Edwin Steiner
-
+ Samuel Vinson
$Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
#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) threads_sem_wait(&workingdata_lock);
-}
-
-/* releaseworkingdatalock *********************************************************
-
- release workingdata lock
-
-*******************************************************************************/
-
-void releaseworkingdatalock() {
- workingdatanum--;
- assert(workingdatanum>=0);
- if (workingdatanum==0) threads_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) {
+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);
-
+ threadobject *thread, **tthreads;
+
#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;
+ tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
+ thread = mainthreadobj;
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);
+ 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);
+ tthreads[i] = thread;
i++;
}
- *addr = (void*)thread->info.prev;
+ thread = thread->info.prev;
/* repeat until we got the pointer to the mainthread twice */
- } while (mainthread != *addr);
+ } while (mainthreadobj != thread);
- 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);
+ *threads_ptr = tthreads;
return JVMTI_ERROR_NONE;
#else
*******************************************************************************/
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;
- }
+ return (jthread)((threadobject*)thread_getself())->o.thread;
}
-/* 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*************************************************************
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;
+ struct brkpts *jvmtibrkpt;
+
+ jvmtibrkpt = &dbgcom->jvmtibrkpt;;
+ 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);
+ 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
+ sets a system breakpoint in breakpoint table and calls set breakpoint
*******************************************************************************/
-void setsysbrkpt(int sysbrk, void* addr) {
- ptrace_request pt;
- ptrace_reply *rcvbuf;
-
- if (jvmtibrkpt.size == jvmtibrkpt.num)
+void setsysbrkpt(int sysbrk, void* addr) {
+ struct brkpts *jvmtibrkpt;
+
+ pthread_mutex_lock(&dbgcomlock);
+ jvmtibrkpt = &dbgcom->jvmtibrkpt;;
+
+ if (jvmtibrkpt->size == jvmtibrkpt->num)
brktablecreator();
assert (sysbrk < BEGINUSERBRK);
- jvmtibrkpt.brk[sysbrk].addr = addr;
+ jvmtibrkpt->brk[sysbrk].addr = addr;
+
- pt.kind = PTSETBRK;
- pt.addr = addr;
- msgqsendevent (&pt, &rcvbuf, sizeof(long));
+ dbgcom->setbrkpt = true;
+ dbgcom->brkaddr = addr;
+ jvmtibrkpt->brk[sysbrk].orig = dbgcom->brkorig;
+ pthread_mutex_unlock(&dbgcomlock);
- jvmtibrkpt.brk[sysbrk].orig = ((long*)rcvbuf->data)[0];
+ /* call cacaodbgserver */
+ TRAP;
fprintf (stderr,"setsysbrk %d %X done\n",sysbrk, addr);
}
*******************************************************************************/
void addbrkpt(void* addr, jmethodID method, jlocation location) {
- ptrace_request pt;
- ptrace_reply *rcvbuf;
+ struct brkpts *jvmtibrkpt;
+
+ pthread_mutex_lock(&dbgcomlock);
+ jvmtibrkpt = &dbgcom->jvmtibrkpt;;
- if (jvmtibrkpt.size == jvmtibrkpt.num)
+ if (jvmtibrkpt->size == jvmtibrkpt->num)
brktablecreator();
- assert (jvmtibrkpt.size > jvmtibrkpt.num);
+ 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;
+ 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++;
+ /* todo: set breakpoint */
+/* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
+ jvmtibrkpt->num++;
+ pthread_mutex_unlock(&dbgcomlock);
fprintf (stderr,"add brk done\n");
}
*******************************************************************************/
-static void setup_jdwp_thread(char* transport) {
+void setup_jdwp_thread(char* transport) {
java_objectheader *o;
methodinfo *m;
java_lang_String *s;
vm_call_method(m,o);
}
-/* cacaodbglisten *************************************************************
+/* cacaobreakpointhandler **********************************************************
- setup listener thread for JDWP
+ handles breakpoints. called by cacaodbgserver.
*******************************************************************************/
-void cacaodbglisten(char* transport) {
+void cacaobreakpointhandler() {
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);
+ /* XXX to be continued :-) */
- /* handle messages from cacaodbgserver */
- while (true) {
- if (-1 == msgrcv(msgqid,&ev,sizeof(basic_event),MSGQDEBUGGER,0))
- perror("debugger process: cacaodbglisten: ");
+ fprintf(stderr,"breakpoint handler called\n");
+ log_text(" - signal %d", ev.signal);
+ switch (ev.signal) {
+ case SIGTRAP:
+ /* search the breakpoint that has been triggered */
+ i=0;
+ while ((ev.ip!=dbgcom->jvmtibrkpt.brk[i].addr) && (i<dbgcom->jvmtibrkpt.num)) i++;
- 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);
+ fprintf(stderr,"cacaodbglisten SIGTRAP switch after while loop i %d\n",i);
+
+ switch (i) {
+ case SETTHREADOBJECTBRK:
+ /* setthreadobject */
+ fprintf(stderr,"IP %X == setthreadobject\n",ev.ip);
+ data.ev=JVMTI_EVENT_THREAD_START;
+ fireEvent(&data);
break;
default:
- log_text("signal not handled");
+ if ((i >= BEGINUSERBRK) && (i<dbgcom->jvmtibrkpt.num)) {
+ log_text("todo: user defined breakpoints are not handled yet");
+ } else
+ log_text("breakpoint not handled - continue anyway");
}
+ 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 */
- threads_sem_init(&workingdata_lock, true, 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.
#include "threads/native/threads.h"
#include "native/jvmti/jvmti.h"
+#include "native/include/java_lang_String.h"
+#include <ltdl.h>
+
+
-#define MSGQEVENT 1
-#define MSGQPTRACEREQ 2
-#define MSGQPTRACEANS 3
typedef struct {
jvmtiEvent ev;
jlong jlong;
} genericEventData;
+
+struct _brkpt {
+ jmethodID method;
+ jlocation location;
+ void* addr; /* memory address */
+ long orig; /* original memory content */
+};
+
+
+struct brkpts {
+ struct _brkpt* brk;
+ int num;
+ int size;
+};
+
+
+typedef struct {
+ int running;
+ void* breakpointhandler;
+ bool setbrkpt;
+ void* brkaddr;
+ long brkorig;
+ struct brkpts jvmtibrkpt;
+} cacaodbgcommunication;
+
+cacaodbgcommunication *dbgcom;
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
struct _jrawMonitorID {
java_lang_String *name;
/* 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
+#define SETTHREADOBJECTBRK 0 /* used for EVENT_THREAD_START */
+#define BEGINUSERBRK 1 /* 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? */
+extern pthread_mutex_t dbgcomlock;
-bool cacaodbgfork();
-void cacaodbglisten(char* transport);
+void setup_jdwp_thread(char* transport);
+void cacaobreakpointhandler();
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);
+bool VMjdwpInit();
+void agentload(char* opt_arg, bool agentbypath, lt_dlhandle *handle, char **libname);
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);
+jvmtiError allthreads (jint * threads_count_ptr, threadobject *** threads_ptr);
jthread getcurrentthread();
-void ipcrm();
-
#endif
/*
/* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
- process controls the debuggee.
+ process controls the debuggee/cacao vm.
Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
Authors: Martin Platter
Changes: Edwin Steiner
-
+ Samuel Vinson
$Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
#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>
+#include <stdio.h>
+pid_t debuggee;
/* getchildprocptrace *********************************************************
*******************************************************************************/
static void getchildprocptrace (char *ptr, void* addr, int cnt) {
- int i, longcnt;
+ long 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: ");
+ if (p[i]==-1)
+ {
+ fprintf(stderr,"cacaodbgserver process: getchildprocptrace: %ld\n",i);
+ perror("cacaodbgserver process: getchildprocptrace:");
+ exit(1);
+ }
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 */
- threads_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 */
- threads_sem_post(&workingdata_lock);
- return true;
- } else {
- threads_sem_post(&workingdata_lock);
- return false;
- }
+ i = GETMEM(debuggee,addr);
+ memcpy(p+longcnt,&i,cnt%sizeof(long));
}
-/* 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
+ waits and handles signals from debuggee/child process. Returns true if
+ cacaodbgserver should exit.
*******************************************************************************/
-static void waitloop() {
+static bool waitloop(void* dbgcvm) {
int status,retval,signal;
void* ip;
basic_event ev;
+ cacaodbgcommunication vm;
+ long data;
+ struct _brkpt* brk;
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);
- }
+ retval = wait(&status);
- if (retval != debuggee) {
- fprintf(stderr,"cacaodbgserver got signal from process other then debuggee\n");
- exit(1);
+ fprintf(stderr,"cacaodbgserver: waitloop we got something to do\n");
+ if (retval == -1) {
+ fprintf(stderr,"error in waitloop\n");
+ perror("cacaodbgserver process: waitloop: ");
+ return true;
+ }
+
+ if (retval != debuggee) {
+ fprintf(stderr,"cacaodbgserver got signal from process other then debuggee/cacao vm\n");
+ return false;
+ }
+
+ if (WIFSTOPPED(status)) {
+ signal = WSTOPSIG(status);
+
+ /* ignore SIGSEGV, SIGPWR, SIGBUS and SIGXCPU for now.
+ todo: in future this signals could 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);
+ CONT(debuggee,signal);
+ return false;
}
- if (WIFEXITED(status)) {
- /* generate event VMDeath */
- ev.signal = SIGQUIT;
- ev.ip = NULL;
- msgqsendevent(&ev);
- return;
+ if (signal == SIGABRT) {
+ fprintf(stderr,"cacaodbgserver: got SIGABRT from debugee - exit\n");
+ return true;
}
- 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);
-
- threads_sem_wait(&workingdata_lock);
- cdbgshmem->running = false;
- cdbgshmem->hastostop = 1;
- threads_sem_post(&workingdata_lock);
-
- if (signal==SIGUSR2) {
- fprintf(stderr,"SIGUSR2 - debuggee has stopped by jdwp process\n");
- return;
- }
+ ip = getip(debuggee);
+ ip--; /* EIP has already been incremented */
+ fprintf(stderr,"got signal: %d IP %X\n",signal,ip);
+
- ev.signal = signal;
- ev.ip = ip;
- msgqsendevent(&ev);
- return;
+ ev.signal = signal;
+ ev.ip = ip;
+
+ /* handle breakpoint */
+ getchildprocptrace((char*)&vm,dbgcvm,sizeof(cacaodbgcommunication));
+
+ if (vm.setbrkpt) {
+ /* set a breakpoint */
+ setbrk(debuggee, vm.brkaddr, &vm.brkorig);
+ CONT(debuggee,0);
+ return false;
}
+
+ if (signal == SIGTRAP) {
+ /* Breakpoint hit. Place original instruction and notify cacao vm to
+ handle it */
+ fprintf(stderr,"breakpoint hit\n");
+ }
+
+ return false;
+ }
- fprintf(stderr,"wait not handled(child not exited or stopped)\n");
- fprintf(stderr,"retval: %d status: %d\n",retval,status);
+ if (WIFEXITED(status)) {
+ fprintf(stderr,"cacaodbgserver: debuggee/cacao vm exited.\n");
+ return true;
+ }
+
+ if (WIFSIGNALED(status)) {
+ fprintf(stderr,"cacaodbgserver: child terminated by signal %d\n",WTERMSIG(status));
+ return true;
}
+
+ if (WIFCONTINUED(status)) {
+ fprintf(stderr,"cacaodbgserver: continued\n");
+ return false;
+ }
+
+
+ fprintf(stderr,"wait not handled(child not exited or stopped)\n");
+ fprintf(stderr,"retval: %d status: %d\n",retval,status);
+ CONT(debuggee,0);
+ return false;
}
-/* ptraceloop *****************************************************************
+/* main (cacaodbgserver) ******************************************************
- this function handles the ptrace request from the jdwp/debugger process.
+ main function for cacaodbgserver 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);
- }
+int main(int argc, char **argv) {
+ bool running = true;
+ void *dbgcvm;
+ int status;
+
+ if (argc != 2) {
+ fprintf(stderr,"cacaodbgserver: not enough arguments\n");
+ fprintf(stderr, "cacaodbgserver cacaodbgcommunicationaddress\n");
- if (-1 == msgsnd(msgqid, buffer, size, 0)) {
- perror("cacaodbgserver process: cacaodbglisten send error: ");
- exit(1);
- }
- MFREE(buffer,char,size);
+ fprintf(stderr,"argc %d argv[0] %s\n",argc,argv[0]);
+ exit(1);
}
-}
-/* cacaodbgserver *************************************************************
+ dbgcvm=(cacaodbgcommunication*)strtol(argv[1],NULL,16);
- waits for eventes from and issues ptrace calls to debuggee/child process
+ fprintf(stderr,"cacaodbgserver started pid %d ppid %d\n",getpid(), getppid());
-*******************************************************************************/
+ debuggee = getppid();
+
+ if (TRACEATTACH(debuggee) == -1) perror("cacaodbgserver: ");
-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 */
+ fprintf(stderr,"cacaovm attached\n");
+
+ if (wait(&status) == -1) {
+ fprintf(stderr,"error initial wait\n");
+ perror("cacaodbgserver: ");
+ exit(1);
+ }
+
+ if (WIFSTOPPED(status))
+ if (WSTOPSIG(status) == SIGSTOP)
+ CONT(debuggee,0);
+
+ while(running) {
+ running = !waitloop(dbgcvm);
}
+ fprintf(stderr,"cacaodbgserver exit\n");
}
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);
+ fprintf (stderr,"pid %d set brk at %p orig: %X new: %X\n",pid,addr,*orig,ins);
if (ptrace(PTRACE_POKEDATA, pid, (caddr_t) addr, ins)==-1)
perror("setbrk error ");
}
Changes:
- $Id: dbg.h 4661 2006-03-21 00:04:59Z motse $
+ $Id: dbg.h 4892 2006-05-06 18:29:55Z motse $
*/
#include <sys/types.h>
#include <sys/ptrace.h>
-#define TRACEME ptrace(PTRACE_TRACEME, 0, 0, 0)
+#define TRACEATTACH(pid) ptrace(PTRACE_ATTACH, pid, 0, 0)
#define DETACH(pid,sig) ptrace(PTRACE_DETACH, pid, 0, sig)
#define TRAPINS 0xcc /* opcode for brk */
#define TRAP asm("int3")
Author: Martin Platter
Changes: Edwin Steiner
+ Samuel Vinson
- $Id: jvmti.c 4874 2006-05-05 14:36:18Z edwin $
+ $Id: jvmti.c 4892 2006-05-06 18:29:55Z motse $
*/
#include "toolbox/logging.h"
#include <stdlib.h>
#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/user.h>
-#include <signal.h>
#include <ltdl.h>
+#include <unistd.h>
+#include <sched.h>
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
#include "threads/native/threads.h"
#include <pthread.h>
#endif
+#include "native/jvmti/stacktrace.h"
#include "dbg.h"
+
typedef struct _environment environment;
-environment *envs=NULL;
+static environment *envs=NULL;
+pthread_mutex_t dbgcomlock;
extern const struct JNIInvokeInterface _Jv_JNIInvokeInterface;
typedef struct _jvmtiThreadLocalStorage jvmtiThreadLocalStorage;
struct _jvmtiThreadLocalStorage{
jthread thread;
- jvmtiThreadLocalStorage *next;
void *data;
+ jvmtiThreadLocalStorage *next;
};
struct _environment {
jvmtiEnv env;
+ environment *next;
jvmtiEventCallbacks callbacks;
/* table for enabled/disabled jvmtiEvents - first element contains global
behavior */
jvmtiCapabilities capabilities;
void *EnvironmentLocalStorage;
jvmtiThreadLocalStorage *tls;
- environment *next;
};
static struct jvmtiEnv_struct JVMTI_EnvTable;
*******************************************************************************/
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)
+ if(t==NULL) return JVMTI_ERROR_THREAD_NOT_ALIVE;
+ if(((java_lang_Thread*) t)->vmThread==NULL)
return JVMTI_ERROR_THREAD_NOT_ALIVE;
return JVMTI_ERROR_NONE;
}
*******************************************************************************/
static void execcallback(jvmtiEvent e, functionptr ec, genericEventData* data) {
- JNIEnv* jni_env = (JNIEnv*)&_Jv_JNINativeInterface;
+ JNIEnv* jni_env = (JNIEnv*)_Jv_env;
fprintf(stderr,"execcallback called (event: %d)\n",e);
/* todo : respect event order JVMTI-Spec:Multiple Co-located Events */
if (d->ev != JVMTI_EVENT_VM_START)
- thread = (jthread)getcurrentthread();
+ thread = getcurrentthread();
else
thread = NULL;
- fprintf (stderr,"debugger: fireEvent: %d\n",d->ev);
+ fprintf (stderr,"jvmti: 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);
if ((mode != JVMTI_ENABLE) && (mode != JVMTI_DISABLE))
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
- if ((event_type < JVMTI_EVENT_START_ENUM) ||
- (event_type > JVMTI_EVENT_END_ENUM))
- return JVMTI_ERROR_INVALID_EVENT_TYPE;
-
-
switch (event_type) { /* check capability */
case JVMTI_EVENT_EXCEPTION:
case JVMTI_EVENT_EXCEPTION_CATCH:
break;
default:
/* all other events are required */
+ if ((event_type < JVMTI_EVENT_START_ENUM) ||
+ (event_type > JVMTI_EVENT_END_ENUM))
+ return JVMTI_ERROR_INVALID_EVENT_TYPE;
break;
}
GetAllThreads (jvmtiEnv * env, jint * threads_count_ptr,
jthread ** threads_ptr)
{
- threadobject* threads;
+ threadobject** threads;
int i;
jvmtiError retval;
if ((threads_count_ptr == NULL) || (threads_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
- retval=allthreads(threads_count_ptr,&threads);
+ 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]);
+ for (i=0; i<*threads_count_ptr; i++)
+ (*threads_ptr)[i] = threads[i]->o.thread;
return JVMTI_ERROR_NONE;
}
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- CHECK_CAPABILITY(env,can_suspend)
+ CHECK_CAPABILITY(env,can_suspend);
-/*
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- suspend_thread((thread *) thread->thread);
-#endif
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- suspend_thread((threadobject*) thread);
-#endif
-*/
+ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+ return JVMTI_ERROR_NOT_AVAILABLE;
return JVMTI_ERROR_NONE;
}
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- CHECK_CAPABILITY(env,can_suspend)
+ CHECK_CAPABILITY(env,can_suspend);
-/*
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- resume_thread((thread *) this->thread);
-#endif
+ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+ return JVMTI_ERROR_NOT_AVAILABLE;
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- resume_thread((threadobject*) thread);
-#endif
-*/
return JVMTI_ERROR_NONE;
}
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- CHECK_CAPABILITY(env,can_signal_thread)
+ CHECK_CAPABILITY(env,can_signal_thread);
- log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!");
+ log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!");
+ return JVMTI_ERROR_NOT_AVAILABLE;
+
return JVMTI_ERROR_NONE;
}
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_signal_thread)
+ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+
+ return JVMTI_ERROR_NOT_AVAILABLE;
+
if(!builtin_instanceof(thread,class_java_lang_Thread))
return JVMTI_ERROR_INVALID_THREAD;
CHECK_THREAD_IS_ALIVE(thread);
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-/* interruptThread((java_lang_VMThread*)thread);*/
-#else
- return JVMTI_ERROR_NOT_AVAILABLE;
-#endif
-
return JVMTI_ERROR_NONE;
}
*******************************************************************************/
jvmtiError
-GetThreadInfo (jvmtiEnv * env, jthread th, jvmtiThreadInfo * info_ptr)
+GetThreadInfo (jvmtiEnv * env, jthread t, jvmtiThreadInfo * info_ptr)
{
- int size;
- char* data;
- struct java_lang_Thread *t;
+ java_lang_Thread* th = (java_lang_Thread*)t;
log_text("GetThreadInfo called");
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
- 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';
-
+ info_ptr->priority=(jint)th->priority;
+ info_ptr->is_daemon=(jboolean)th->daemon;
+ info_ptr->thread_group=(jthreadGroup)th->group;
+ info_ptr->context_class_loader=(jobject)th->contextClassLoader;
+ info_ptr->name= javastring_tochar((java_objectheader *)th->name);
return JVMTI_ERROR_NONE;
}
int i,j,size=20;
java_objectheader **om;
lockRecordPool* lrp;
- char *data;
- log_text("GetOwnedMonitorInfo called");
+ log_text("GetOwnedMonitorInfo called - todo: fix object mapping");
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
om=MNEW(java_objectheader*,size);
- stopdebuggee();
-
- /* 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;
+ pthread_mutex_lock(&pool_lock);
+ lrp=global_pool;
while (lrp != NULL) {
for (j=0; j<lrp->header.size; j++) {
static void *threadstartup(void *t) {
runagentparam *rap = (runagentparam*)t;
- rap->sf(rap->jvmti_env,&_Jv_JNINativeInterface,rap->arg);
+ rap->sf(rap->jvmti_env,(JNIEnv*)&_Jv_JNINativeInterface,rap->arg);
return NULL;
}
(priority > JVMTI_THREAD_MAX_PRIORITY))
return JVMTI_ERROR_INVALID_PRIORITY;
+ /* XXX: Threads started with with this function should not be visible to
+ Java programming language queries but are included in JVM TI queries */
+
rap.sf = proc;
rap.arg = (void*)arg;
rap.jvmti_env = env;
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
+ log_text("GetTopThreadGroups called");
+
if ((groups_ptr == NULL) || (group_count_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
while((j<x)&&(tg[j]!=ttgp)) { /* unique ? */
j++;
}
-
if (j == x) {
if (x >= size){
MREALLOC(tg,jthreadGroup*,size,size*2);
Has to take care of suspend/resume issuses
*******************************************************************************/
-static jvmtiError getcacaostacktrace(char** trace, jthread thread) {
+static jvmtiError getcacaostacktrace(stacktracebuffer** trace, jthread thread) {
+ threadobject *t;
log_text("getcacaostacktrace");
-
+ t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
+
+/* XXX todo
+ *trace = stacktrace_create(t); */
return JVMTI_ERROR_NONE;
}
/* GetFrameCount **************************************************************
+
Get the number of frames in the specified thread's stack.
*******************************************************************************/
jvmtiError
GetFrameCount (jvmtiEnv * env, jthread thread, jint * count_ptr)
{
- char* trace;
+ stacktracebuffer* trace;
jvmtiError er;
CHECK_PHASE_START
er = getcacaostacktrace(&trace, thread);
if (er==JVMTI_ERROR_NONE) return er;
-/* todo: *count_ptr = trace->size;*/
+ *count_ptr = trace->used;
return JVMTI_ERROR_NONE;
}
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- /* todo: how do I find declaring class other then iterate over all fields in all classes ?*/
- log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ *declaring_class_ptr = (jclass) ((fieldinfo*)field)->class;
return JVMTI_ERROR_NONE;
}
if ((method == NULL) || (name_ptr == NULL) || (signature_ptr == NULL)
|| (generic_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER;
- *name_ptr = (char*)heap_allocate(m->name->blength,true,NULL);
- memcpy(*name_ptr, m->name->text, m->name->blength);
+ if (m->name == NULL) return JVMTI_ERROR_INTERNAL;
+
+ *name_ptr = (char*)
+ heap_allocate(sizeof(char) * (m->name->blength),true,NULL);
+ utf_sprint_convert_to_latin1(*name_ptr, m->name);
+
+ *signature_ptr = (char*)
+ heap_allocate(sizeof(char) * (m->descriptor->blength),true,NULL);
+ utf_sprint_convert_to_latin1(*signature_ptr, m->descriptor);
- *signature_ptr = (char*)heap_allocate(m->descriptor->blength,true,NULL);
- memcpy(*signature_ptr, m->descriptor->text, m->descriptor->blength);
-
/* there is no generic signature attribute */
*generic_ptr = NULL;
/* XXX Don't know if that's the right way to deal with not-yet-
* compiled methods. -Edwin */
+
if (!m->code)
return JVMTI_ERROR_NULL_POINTER;
classcache_name_entry *cne;
classcache_class_entry *cce;
- log_text ("GetLoadedClasses called");
+ log_text ("GetLoadedClasses called %d ", phase);
+
+
+ /* XXX todo */
+
+ *class_count_ptr = 0;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
log_text ("GetLoadedClasses1");
- stopdebuggee();
+/*
+ CLASSCACHE_LOCK();
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;
fflush(stderr);
*class_count_ptr = ht->entries;
+ log_text ("GetLoadedClasses %d", *class_count_ptr);
j=0;
- /* look in every slot of the hashtable */
+ look in every slot of the hashtable
for (i=0; i<ht->size; i++) {
cne = ht->ptr[i];
- while (cne != NULL) { /* iterate over hashlink */
+ 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<ht->entries);
- *classes_ptr[j]=cce->classobj;
+ 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<ht->entries);
+ * classes_ptr[j]=cce->classobj;
j++;
}
cce = cce->next;
cne = cne->hashlink;
}
}
-
+
log_text ("GetLoadedClasses continue");
- contdebuggee(0);
+ CLASSCACHE_UNLOCK();
+
+*/
log_text ("GetLoadedClasses finished");
}
-/* *****************************************************************************
+/* SuspendThreadList **********************************************************
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- CHECK_CAPABILITY(env,can_suspend)
+ CHECK_CAPABILITY(env,can_suspend);
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+
return JVMTI_ERROR_NONE;
}
-/* *****************************************************************************
+/* ResumeThreadList ***********************************************************
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- CHECK_CAPABILITY(env,can_suspend)
+ CHECK_CAPABILITY(env,can_suspend);
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+
return JVMTI_ERROR_NONE;
}
jint max_frame_count, jvmtiFrameInfo * frame_buffer,
jint * count_ptr)
{
- char* trace;
+ stacktracebuffer* trace;
jvmtiError er;
-/* int i,j;*/
+ int i,j;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
er = getcacaostacktrace(&trace, thread);
if (er==JVMTI_ERROR_NONE) return er;
-/* todo: if ((trace->size >= start_depth) || ((trace->size * -1) > start_depth))
- return JVMTI_ERROR_ILLEGAL_ARGUMENT; */
+ if ((trace->used >= start_depth) || ((trace->used * -1) > start_depth))
+ return JVMTI_ERROR_ILLEGAL_ARGUMENT;
-/* 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
+ for (i=start_depth, j=0;i<trace->used;i++,j++) {
+ frame_buffer[j].method = (jmethodID)trace->entries[i].method;
+ /* todo: location BCI/MachinePC not avilable - Linenumber not expected */
frame_buffer[j].location = 0;
- }*/
+ }
return JVMTI_ERROR_NONE;
}
if (function_table == NULL) return JVMTI_ERROR_NULL_POINTER;
_Jv_env->env = (void*)heap_allocate(sizeof(jniNativeInterface),true,NULL);
- memcpy(_Jv_env->env, function_table, sizeof(jniNativeInterface));
+ memcpy((void*)_Jv_env->env, function_table, sizeof(jniNativeInterface));
return JVMTI_ERROR_NONE;
}
{
environment* cacao_env = (environment*)env;
environment* tenvs = envs;
- memset(&((cacao_env)->events[0]),0,sizeof(jvmtiEventModeLL)*
- (JVMTI_EVENT_END_ENUM-JVMTI_EVENT_START_ENUM));
- (cacao_env)->EnvironmentLocalStorage = NULL;
-
- if (tenvs!=cacao_env) {
+ jvmtiThreadLocalStorage *jtls, *tjtls;
+
+ if (tenvs != cacao_env) {
while (tenvs->next != cacao_env) {
tenvs = tenvs->next;
}
} else
envs = NULL;
- /* let Boehm GC do the rest */
+ cacao_env->env=NULL;
+ memset(&(cacao_env->callbacks),0,sizeof(jvmtiEventCallbacks)*
+ (JVMTI_EVENT_END_ENUM-JVMTI_EVENT_START_ENUM));
+ memset(cacao_env->events,0,sizeof(jvmtiEventModeLL)*
+ (JVMTI_EVENT_END_ENUM-JVMTI_EVENT_START_ENUM));
+ cacao_env->EnvironmentLocalStorage = NULL;
+
+ jtls = cacao_env->tls;
+ while (jtls != NULL) {
+ tjtls = jtls;
+ jtls = jtls->next;
+ tjtls->next = NULL;
+ }
+ cacao_env->tls = NULL;
+
+
+ pthread_mutex_lock(&dbgcomlock);
+ dbgcom->running--;
+ if (dbgcom->running == 0) {
+ TRAP;
+ }
+ pthread_mutex_unlock(&dbgcomlock);
+
+ /* let the GC do the rest */
return JVMTI_ERROR_NONE;
}
0, /* can_get_monitor_info */
0, /* can_pop_frame */
0, /* can_redefine_classes */
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- /* current implementation does not work if called from another process */
- 0, /* can_signal_thread */
-#else
0, /* can_signal_thread */
-#endif
1, /* can_get_source_file_name */
1, /* can_get_line_numbers */
0, /* can_get_source_debug_extension */
0, /* can_generate_exception_events */
0, /* can_generate_frame_pop_events */
0, /* can_generate_breakpoint_events */
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
- /* current implementation does not work if called from another process */
- 0, /* can_suspend */
-#else
0, /* can_suspend */
-#endif
0, /* can_redefine_any_class */
0, /* can_get_current_thread_cpu_time */
0, /* can_get_thread_cpu_time */
void set_jvmti_phase(jvmtiPhase p) {
genericEventData d;
- fprintf (stderr,"set JVMTI pid %d phase %d\n",getpid(),p);
+ fprintf (stderr,"set JVMTI phase %d\n",p);
fflush(stderr);
switch (p) {
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");
+ log_text("set sysbrk in setthreadobj");
setsysbrkpt(SETTHREADOBJECTBRK,(void*)&setthreadobject);
break;
case JVMTI_PHASE_LIVE:
jvmtiEnv* new_jvmtienv() {
environment* env;
+ pid_t dbgserver;
+ char* comaddr;
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);
+ while (env->next != NULL) env = env->next;
+ env->next = heap_allocate(sizeof(environment),true,NULL);
+ env = env->next;
}
+
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.*/
- memset(&(env->capabilities), 1, sizeof(jvmtiCapabilities));
+ memset(&(env->capabilities), 0, sizeof(jvmtiCapabilities));
RelinquishCapabilities(&(env->env),&(env->capabilities));
env->EnvironmentLocalStorage = NULL;
env->tls = NULL;
+ /* start new cacaodbgserver if needed*/
+ pthread_mutex_lock(&dbgcomlock);
+ if (dbgcom == NULL) {
+ dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
+ dbgcom->running = 1;
+ dbgcom->breakpointhandler = (void*)cacaobreakpointhandler;
+ dbgserver = fork();
+ if (dbgserver == (-1)) {
+ log_text("cacaodbgserver fork error");
+ exit(1);
+ } else {
+ if (dbgserver == 0) {
+ comaddr = MNEW(char,11);
+ snprintf(comaddr,11,"%p",dbgcom);
+ if (execlp("cacaodbgserver","cacaodbgserver",comaddr,(char *) NULL) == -1) {
+ log_text("unable to execute cacaodbgserver");
+ exit(1);
+ }
+ }
+ }
+ } else {
+ dbgcom->running++;
+ }
+ pthread_mutex_unlock(&dbgcomlock);
+ sched_yield();
+
+
return (jvmtiEnv*)env;
}
-void agentload(char* opt_arg) {
- lt_dlhandle handle;
- lt_ptr onload;
- char *libname, *arg;
+void agentload(char* opt_arg, bool agentbypath, lt_dlhandle *handle, char **libname) {
+ lt_ptr onload;
+ char *arg;
int i=0,len;
jint retval;
- classinfo* ci;
+
len = strlen(opt_arg);
- while ((opt_arg[i]!='=')&&(i<len)) i++;
-
- libname=MNEW(char,i);
- strncpy(libname,opt_arg,i-1);
- libname[i-1]='\0';
-
- arg=MNEW(char, len-i);
- strcpy(arg,&opt_arg[i+1]);
+ /* separate argumtents */
+ while ((opt_arg[i]!='=')&&(i<=len)) i++;
+ arg = &opt_arg[i];
+
+ if (agentbypath) {
+ /* -agentpath */
+ *libname=heap_allocate(sizeof(char)*i,true,NULL);
+ strncpy(*libname,opt_arg,i-1);
+ (*libname)[i-1]='\0';
+ } else {
+ /* -agentlib */
+ *libname=heap_allocate(sizeof(char)*(i+7),true,NULL);
+ strncpy(*libname,"lib",3);
+ strncpy(&(*libname)[3],opt_arg,i-1);
+ strncpy(&(*libname)[i+2],".so",3);
+ }
/* try to open the library */
-
- if (!(handle = lt_dlopen(libname)))
- return;
-
+ lt_dlinit();
+ if (!(*handle = lt_dlopen(*libname))) {
+ fprintf(stderr,"Could not find agent library: %s (%s)\n",*libname,lt_dlerror());
+ vm_shutdown(1);
+ }
+
/* resolve Agent_OnLoad function */
- onload = lt_dlsym(handle, "Agent_OnLoad");
- if (onload == NULL) {
- fprintf(stderr, "unable to load Agent_OnLoad function in %s\n", libname);
- exit(1);
+ if (!(onload = lt_dlsym(*handle, "Agent_OnLoad"))) {
+ fprintf(stderr,"unable to load Agent_OnLoad function in %s (%s)\n",*libname,lt_dlerror());
+ vm_shutdown(1);
}
/* 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);
+ unload = lt_dlsym(*handle, "Agent_Unload");
retval =
((JNIEXPORT jint JNICALL (*) (JavaVM *vm, char *options, void *reserved))
- onload) ((JavaVM*) &_Jv_JNIInvokeInterface, arg, NULL);
-
- MFREE(libname,char,i);
- MFREE(arg,char,len-i);
-
+ onload) ((JavaVM *) _Jv_jvm, arg, NULL);
+
if (retval != 0) exit (retval);
}
Changes:
- $Id: jvmti.h 4661 2006-03-21 00:04:59Z motse $
+ $Id: jvmti.h 4892 2006-05-06 18:29:55Z motse $
*/
#ifndef _JVMTI_H
#define _JVMTI_H
#include "native/jni.h"
-#include "native/include/java_lang_String.h"
#include <sys/types.h>
#define JVMTI_VERSION_1_0 0x30010000
+#define JVMTI_VERSION JVMTI_VERSION_1_0
typedef jobject jthread;
typedef jobject jthreadGroup;
--- /dev/null
+/* src/native/vm/VMMethod.c - jdwp->jvmti interface
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+Contact: cacao@cacaojvm.org
+
+Authors: Samuel Vinson
+
+Changes:
+
+
+$Id: $
+
+*/
+
+#include "toolbox/logging.h"
+#include "native/jni.h"
+#include "native/include/gnu_classpath_jdwp_VMMethod.h"
+#include "vm/stringlocal.h"
+#include "toolbox/logging.h"
+
+/*
+ * Class: gnu/classpath/jdwp/VMMethod
+ * Method: getName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getName(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+{
+ classinfo *c;
+ methodinfo *m;
+
+ c = (classinfo *)this->_class;
+ m = &(c->methods[this->_methodId]);
+ log_message_utf("Method_getName %s", m->name);
+ return javastring_new(m->name);
+}
+
+
+/*
+ * Class: gnu/classpath/jdwp/VMMethod
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getSignature(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+{
+ log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ return 0;
+}
+
+
+/*
+ * Class: gnu/classpath/jdwp/VMMethod
+ * Method: getModifiers
+ * Signature: ()I
+ */
+JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMMethod_getModifiers(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+{
+ classinfo *c;
+ methodinfo *m;
+
+ c = (classinfo *) this->_class;
+ m = &(c->methods[this->_methodId]);
+
+ return m->flags;
+}
+
+
+/*
+ * Class: gnu/classpath/jdwp/VMMethod
+ * Method: getLineTable
+ * Signature: ()Lgnu/classpath/jdwp/util/LineTable;
+ */
+JNIEXPORT struct gnu_classpath_jdwp_util_LineTable* JNICALL Java_gnu_classpath_jdwp_VMMethod_getLineTable(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+{
+ log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ return 0;
+}
+
+
+/*
+ * Class: gnu/classpath/jdwp/VMMethod
+ * Method: getVariableTable
+ * Signature: ()Lgnu/classpath/jdwp/util/VariableTable;
+ */
+JNIEXPORT struct gnu_classpath_jdwp_util_VariableTable* JNICALL Java_gnu_classpath_jdwp_VMMethod_getVariableTable(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+{
+ log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ return 0;
+}
Authors: Martin Platter
-Changes:
+Changes: Samuel Vinson
-$Id: VMVirtualMachine.c 4661 2006-03-21 00:04:59Z motse $
+$Id: VMVirtualMachine.c 4892 2006-05-06 18:29:55Z motse $
*/
#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 "native/jvmti/VMjdwp.h"
#include <string.h>
*/
JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_suspendThread(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1)
{
- (*remotedbgjvmtienv)->SuspendThread(remotedbgjvmtienv, (jthread) par1);
+ (*jvmtienv)->SuspendThread(jvmtienv, (jthread) par1);
}
/*
*/
JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_resumeThread(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1)
{
- (*remotedbgjvmtienv)->ResumeThread(remotedbgjvmtienv, (jthread) par1);
+ (*jvmtienv)->ResumeThread(jvmtienv, (jthread) par1);
}
jint count;
jclass* classes;
- (*remotedbgjvmtienv)->GetLoadedClasses(remotedbgjvmtienv, &count, &classes);
+ (*jvmtienv)->GetLoadedClasses(jvmtienv, &count, &classes);
return count;
}
jvmtiError err;
char* errdesc;
- if (JVMTI_ERROR_NONE != (err= (*remotedbgjvmtienv)->
- GetLoadedClasses(remotedbgjvmtienv, &classcount, &classes))) {
- (*remotedbgjvmtienv)->GetErrorName(remotedbgjvmtienv,err, &errdesc);
+ if (JVMTI_ERROR_NONE != (err= (*jvmtienv)->
+ GetLoadedClasses(jvmtienv, &classcount, &classes))) {
+ (*jvmtienv)->GetErrorName(jvmtienv,err, &errdesc);
fprintf(stderr,"jvmti error: %s\n",errdesc);
fflush(stderr);
/* env->ThrowNew(env,ec,"jvmti error occoured");*/
/* Arrays.asList(Object[] classes)->List.Iterator()->Iterator */
joa = (*env)->NewObjectArray(env, (jsize)classcount, cl , NULL);
+ if (!joa) return NULL;
for (i = 0; i < classcount; i++)
(*env)->SetObjectArrayElement(env,joa,(jsize)i, (jobject)classes[i]);
cl = (*env)->FindClass(env,"java.util.List");
if (!cl) return NULL;
- m = (*env)->GetMethodID(env,cl,"Iterator","()Ljava/util/Iterator;");
-
+ m = (*env)->GetMethodID(env,cl,"iterator","()Ljava/util/Iterator;");
+ if (!m) return NULL;
oi = (*env)->CallObjectMethod(env,*ol,m);
return (struct java_util_Iterator*)oi;
*/
JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
jint status;
- (*remotedbgjvmtienv)->GetClassStatus(remotedbgjvmtienv, (jclass) par1, &status);
+ (*jvmtienv)->GetClassStatus(jvmtienv, (jclass) par1, &status);
return status;
}
*/
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 !!!");
+ return NULL;
}
*/
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 !!!");
+ return NULL;
}
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 ("VMVirtualMachine_getFrames - IMPLEMENT ME!!!");
/* jclass ec = (*env)->FindClass(env,"gnu/classpath/jdwp/JdwpInternalErrorException");
- if (JVMTI_ERROR_NONE != (*remotedbgjvmtienv)->GetClassStatus(remotedbgjvmtienv, par1, &status))
+ if (JVMTI_ERROR_NONE != (*jvmtienv)->GetClassStatus(jvmtienv, par1, &status))
env->ThrowNew(env,ec,"jvmti error occoured");*/
return 0;
}
*/
JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
jint count;
- (*remotedbgjvmtienv)->GetFrameCount(remotedbgjvmtienv, (jthread)par1, &count);
+ (*jvmtienv)->GetFrameCount(jvmtienv, (jthread)par1, &count);
return count;
}
*/
JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
jint status;
- if (JVMTI_ERROR_NONE != (*remotedbgjvmtienv)->GetThreadState(remotedbgjvmtienv, (jthread)par1, &status))
+ if (JVMTI_ERROR_NONE != (*jvmtienv)->GetThreadState(jvmtienv, (jthread)par1, &status))
return 0;
if (status && JVMTI_THREAD_STATE_ALIVE) {
if (status && JVMTI_THREAD_STATE_WAITING) {
char* srcname;
jstring str;
- (*remotedbgjvmtienv)->
- GetSourceFileName(remotedbgjvmtienv, (jclass)par1, &srcname);
+ (*jvmtienv)->
+ GetSourceFileName(jvmtienv, (jclass)par1, &srcname);
str = (*env)->NewString(env,(jchar*)srcname,(jsize)strlen(srcname));
return (struct java_lang_String*)str;
kindid = (*env)->GetFieldID(env, erc, "_kind", "B");
kind = (*env)->GetByteField(env, (jobject)par1, kindid);
- (*remotedbgjvmtienv)->
- SetEventNotificationMode(remotedbgjvmtienv, JVMTI_ENABLE,
+ (*jvmtienv)->
+ SetEventNotificationMode(jvmtienv, JVMTI_ENABLE,
EventKind2jvmtiEvent(kind), NULL);
/* todo: error handling, suspend policy */
kindid = (*env)->GetFieldID(env, erc, "_kind", "B");
kind = (*env)->GetByteField(env, (jobject)par1, kindid);
- (*remotedbgjvmtienv)->
- SetEventNotificationMode(remotedbgjvmtienv, JVMTI_DISABLE,
+ (*jvmtienv)->
+ SetEventNotificationMode(jvmtienv, JVMTI_DISABLE,
EventKind2jvmtiEvent(kind), NULL);
/* todo: error handling, suspend policy */
Authors: Christian Thalinger
- Changes:
+ Changes: Martin Platter
$Id: finalizer.c 4357 2006-01-22 23:33:38Z twisti $
s4 opt;
s4 i, j, k;
+
+#if defined(ENABLE_JVMTI)
+ lt_dlhandle handle;
+ char* libname;
+ bool agentbypath = false;;
+#endif
+
+
+
/* check the JNI version requested */
switch (vm_args->version) {
#if defined(ENABLE_JVMTI)
/* initialize JVMTI related **********************************************/
- jvmtibrkpt.brk=NULL;
- jvmtibrkpt.num=0;
- jvmtibrkpt.size=0;
- jdwp = jvmti = dbgprocess = false;
+ jdwp = jvmti = false;
#endif
/* initialize properties before commandline handling */
}
break;
+
case OPT_AGENTPATH:
+ agentbypath = true;
case OPT_AGENTLIB:
jvmti=true;
agentarg = opt_arg;
}
#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) {
+ if (jvmti) {
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);
+ agentload(agentarg, agentbypath, &handle, &libname);
}
+ set_jvmti_phase(JVMTI_PHASE_PRIMORDIAL);
#endif
/* throw_main_exception_exit(); */
#endif
+#if defined(ENABLE_JVMTI)
+ if (jvmti) {
+ /* add agent library to native library hashtable */
+ native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
+ }
+#endif
+
/* increment the number of VMs */
vms++;
assert(class_java_lang_System->state & CLASS_LOADED);
#if defined(ENABLE_JVMTI)
- if (dbgprocess) {
- set_jvmti_phase(JVMTI_PHASE_DEAD);
- if (jvmti) agentunload();
- }
+ set_jvmti_phase(JVMTI_PHASE_DEAD);
+ if (jvmti) agentunload();
#endif
if (!link_class(class_java_lang_System))
void vm_shutdown(s4 status)
{
-#if defined(ENABLE_JVMTI)
- if (dbgprocess) {
- set_jvmti_phase(JVMTI_PHASE_DEAD);
- if (jvmti) agentunload();
- ipcrm();
- }
-#endif
if (opt_verbose
#if defined(ENABLE_STATISTICS)
|| opt_getcompilingtime || opt_stat
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);