Changes: Edwin Steiner
Samuel Vinson
- $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 <signal.h>
#include <stdlib.h>
#include <assert.h>
+#include <sys/wait.h>
-/* allthreads *****************************************************************
+/* jvmti_get_all_threads ******************************************************
Gets an array of threadobjects of all threads
*******************************************************************************/
-jvmtiError allthreads (jint * threads_count_ptr, threadobject*** threads_ptr) {
+jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
+ threadobject*** threads_ptr) {
int i = 0, cnt = 8;
threadobject *thread, **tthreads;
tthreads[i] = thread;
i++;
}
- thread = thread->info.prev;
+ thread = thread->prev;
/* repeat until we got the pointer to the mainthread twice */
} while (mainthreadobj != thread);
}
-/* getcurrentthread ***********************************************************
+/* jvmti_get_current_thread ***************************************************
Get jthread structure of current thread.
*******************************************************************************/
-jthread getcurrentthread() {
+jthread jvmti_get_current_thread() {
return (jthread)(threads_get_current_threadobject())->o.thread;
}
-/* brktablecreator*************************************************************
+/* breakpointtable_creator ***************************************************
helper function to enlarge the breakpoint table if needed
*******************************************************************************/
-static void brktablecreator() {
+static void breakpointtable_creator() {
struct _brkpt* tmp;
struct brkpts *jvmtibrkpt;
}
-/* setsysbrkpt ****************************************************************
+/* jvmti_set_system_breakpoint ************************************************
sets a system breakpoint in breakpoint table and calls set breakpoint
*******************************************************************************/
-void setsysbrkpt(int sysbrk, void* addr) {
+void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
struct brkpts *jvmtibrkpt;
pthread_mutex_lock(&dbgcomlock);
- jvmtibrkpt = &dbgcom->jvmtibrkpt;;
+ jvmtibrkpt = &dbgcom->jvmtibrkpt;
+ assert (sysbrk < BEGINUSERBRK);
if (jvmtibrkpt->size == jvmtibrkpt->num)
- brktablecreator();
-
- assert (sysbrk < BEGINUSERBRK);
- jvmtibrkpt->brk[sysbrk].addr = addr;
-
-
- dbgcom->setbrkpt = true;
- dbgcom->brkaddr = addr;
- jvmtibrkpt->brk[sysbrk].orig = dbgcom->brkorig;
+ breakpointtable_creator();
+
+ if (mode) {
+ /* add breakpoint*/
+ if (jvmtibrkpt->brk[sysbrk].count > 0) {
+ jvmtibrkpt->brk[sysbrk].count++;
+ pthread_mutex_unlock(&dbgcomlock);
+ return;
+ }
+ dbgcom->addbrkpt = true;
+ dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
+ } else {
+ /* remove breakpoint*/
+ if ((jvmtibrkpt->brk[sysbrk].count == 1) ) {
+ jvmtibrkpt->brk[sysbrk].count--;
+ /* remove breakpoint */
+ dbgcom->addbrkpt = false;
+ dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
+ } else {
+ /* avoid negative counter values */
+ if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
+ pthread_mutex_unlock(&dbgcomlock);
+ return;
+ }
+ }
pthread_mutex_unlock(&dbgcomlock);
-
/* call cacaodbgserver */
+ __asm__ ("setsysbrkpt:");
TRAP;
-
- fprintf (stderr,"setsysbrk %d %X done\n",sysbrk, addr);
}
-/* addbrkpt *******************************************************************
+/* jvmti_add_breakpoint *******************************************************
adds a breakpoint to breakpoint table and calls set breakpoint
*******************************************************************************/
-void addbrkpt(void* addr, jmethodID method, jlocation location) {
+void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
struct brkpts *jvmtibrkpt;
pthread_mutex_lock(&dbgcomlock);
jvmtibrkpt = &dbgcom->jvmtibrkpt;;
if (jvmtibrkpt->size == jvmtibrkpt->num)
- brktablecreator();
+ breakpointtable_creator();
assert (jvmtibrkpt->size > jvmtibrkpt->num);
- fprintf (stderr,"add brk add: %X\n",addr);
+ fprintf (stderr,"add brk add: %p\n",addr);
jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
}
-/* setup_jdwp_thread *****************************************************
- Helper function to start JDWP threads
-*******************************************************************************/
+/* jvmti_cacaodbgserver_quit **************************************************
-void setup_jdwp_thread(char* transport) {
- java_objectheader *o;
- methodinfo *m;
- java_lang_String *s;
- classinfo *class;
+ quits cacaodbgserver if the last jvmti environment gets disposed
- /* new gnu.classpath.jdwp.Jdwp() */
- class = load_class_from_sysloader(
- utf_new_char("gnu.classpath.jdwp.Jdwp"));
- if (!class)
- throw_main_exception_exit();
+*******************************************************************************/
+void jvmti_cacaodbgserver_quit(){
+ pthread_mutex_lock(&dbgcomlock);
+ dbgcom->running--;
+ if (dbgcom->running == 0) {
+ __asm__ ("cacaodbgserver_quit:");
+ TRAP;
+ /* get cacaodbserver exit */
+ wait(NULL);
+ dbgcom = NULL;
+ }
+ pthread_mutex_unlock(&dbgcomlock);
+}
- 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_from_ascii(&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);
-}
-/* cacaobreakpointhandler **********************************************************
+/* jvmti_cacao_generic_breakpointhandler **************************************
- handles breakpoints. called by cacaodbgserver.
+ convert cacao breakpoints in jvmti events and fire event
*******************************************************************************/
-void cacaobreakpointhandler() {
- basic_event ev;
- genericEventData data;
- int i;
-
- /* XXX to be continued :-) */
-
- 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++;
-
- fprintf(stderr,"cacaodbglisten SIGTRAP switch after while loop i %d\n",i);
-
- switch (i) {
- case SETTHREADOBJECTBRK:
- /* threads_set_current_threadobject */
- fprintf(stderr,"IP %X == threads_set_current_threadobject\n",ev.ip);
- data.ev=JVMTI_EVENT_THREAD_START;
- fireEvent(&data);
- break;
- default:
- 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");
- }
+static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
+ genericEventData data;
+
+ switch (kindofbrk) {
+ case THREADSTARTBRK:
+ data.ev=JVMTI_EVENT_THREAD_START;
+ break;
+ case THREADENDBRK:
+ data.ev=JVMTI_EVENT_THREAD_END;
+ break;
+ case CLASSLOADBRK:
+ data.ev=JVMTI_EVENT_CLASS_LOAD;
+ break;
+ case CLASSPREPARERK:
+ data.ev=JVMTI_EVENT_CLASS_PREPARE;
break;
- case SIGQUIT:
- log_text("debugger process SIGQUIT");
- data.ev=JVMTI_EVENT_VM_DEATH;
- fireEvent(&data);
+ case CLASSFILELOADHOOKBRK:
+ data.ev=JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
+ break;
+ case COMPILEDMETHODLOADBRK:
+ data.ev=JVMTI_EVENT_COMPILED_METHOD_LOAD;
+ break;
+ case COMPILEDMETHODUNLOADBRK:
+ data.ev=JVMTI_EVENT_COMPILED_METHOD_UNLOAD;
break;
default:
- log_text("signal not handled");
+ fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
+ return;
}
+ jvmti_fireEvent(&data);
+}
+
+
+
+/* jvmti_cacao_debug_init ***************************************************************
+
+ starts up a new cacaodbgserver process if needed
+
+*******************************************************************************/
+
+void jvmti_cacao_debug_init() {
+ pid_t dbgserver;
+
+ /* start new cacaodbgserver if needed*/
+ pthread_mutex_lock(&dbgcomlock);
+ if (dbgcom == NULL) {
+ dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
+ dbgcom->running = 1;
+ jvmti = true;
+
+ breakpointtable_creator();
+ /* set addresses of hard coded TRAPs */
+ __asm__ ("movl $setsysbrkpt,%0;"
+ :"=m"(dbgcom->jvmtibrkpt.brk[SETSYSBRKPT].addr));
+ __asm__ ("movl $cacaodbgserver_quit,%0;"
+ :"=m"(dbgcom->jvmtibrkpt.brk[CACAODBGSERVERQUIT].addr));
+
+ dbgserver = fork();
+ if (dbgserver == (-1)) {
+ log_text("cacaodbgserver fork error");
+ exit(1);
+ } else {
+ if (dbgserver == 0) {
+ if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
+ log_text("unable to execute cacaodbgserver");
+ exit(1);
+ }
+ }
+ }
+ pthread_mutex_unlock(&dbgcomlock);
+ /* let cacaodbgserver get ready */
+ sleep(1);
+ } else {
+ dbgcom->running++;
+ pthread_mutex_unlock(&dbgcomlock);
+ }
+}
+
+
+/* jvmti_ClassFileLoadHook ****************************************************
+
+ prepares firing a new Class File Load Hook event
+
+*******************************************************************************/
+
+void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
+ unsigned char* class_data,
+ java_objectheader* loader,
+ java_objectheader* protection_domain,
+ jint* new_class_data_len,
+ unsigned char** new_class_data) {
+ genericEventData d;
+
+ d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
+ d.klass = NULL; /* class is not redefined */
+ d.object = loader;
+ d.name = (char*)MNEW(char,(utf_bytes(name)+1));
+ utf_sprint_convert_to_latin1(d.name, name);
+ d.protection_domain = protection_domain;
+ d.class_data = class_data;
+ d.jint1 = class_data_len;
+ d.new_class_data_len = new_class_data_len;
+ d.new_class_data = new_class_data;
+
+ jvmti_fireEvent(&d);
+ MFREE(d.name,char,utf_bytes(name)+1);
}
+/* jvmti_ClassFileLoadHook ****************************************************
+
+ prepares firing a new Class Prepare or Load event
+
+*******************************************************************************/
+
+void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
+ genericEventData d;
+
+ if (prepared)
+ d.ev = JVMTI_EVENT_CLASS_PREPARE;
+ else
+ d.ev = JVMTI_EVENT_CLASS_LOAD;
+
+ d.klass = c;
+ jvmti_fireEvent(&d);
+}
+
+
+/* jvmti_MonitorContendedEntering *********************************************
+
+ prepares firing a new Monitor Contended Enter or Entered event
+
+*******************************************************************************/
+
+void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
+ genericEventData d;
+
+ if (entered)
+ d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
+ else
+ d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
+
+ d.object = obj;
+
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_MonitorWaiting ******************************************************
+
+ prepares firing a new Monitor Wait or Waited event
+
+*******************************************************************************/
+
+void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
+ genericEventData d;
+
+ if (wait) {
+ d.ev = JVMTI_EVENT_MONITOR_WAIT;
+ d.jlong = timeout;
+ } else {
+ d.ev = JVMTI_EVENT_MONITOR_WAITED;
+ d.b = timeout != 0;
+ }
+
+ d.object = obj;
+
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_ThreadStartEnd ********************************************************
+
+ prepares firing a new Thread Start or End event
+
+*******************************************************************************/
+
+void jvmti_ThreadStartEnd(jvmtiEvent ev) {
+ genericEventData d;
+
+ d.ev = ev;
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_NativeMethodBind *****************************************************
+
+ prepares firing a new Native Method Bind event
+
+*******************************************************************************/
+
+void jvmti_NativeMethodBind(jmethodID method, void* address,
+ void** new_address_ptr) {
+ genericEventData d;
+
+ d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
+ d.method = method;
+ d.address = address;
+ d.new_address_ptr = new_address_ptr;
+
+ jvmti_fireEvent(&d);
+}
+
+
+
/*
* 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