Changes: Edwin Steiner
Samuel Vinson
-
+ Christan Thalinger
- $Id: jvmti.c 4945 2006-05-23 19:52:47Z motse $
-
*/
+
+#include "config.h"
+
#include <assert.h>
+#include <string.h>
+#include <linux/unistd.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ltdl.h>
+#include <unistd.h>
+#include <sched.h>
#include "native/jni.h"
#include "native/native.h"
#include "native/jvmti/cacaodbg.h"
#include "native/jvmti/jvmti.h"
+#include "vm/jit/stacktrace.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 "mm/gc-common.h"
#include "toolbox/logging.h"
#include "vm/options.h"
#include "vm/stringlocal.h"
#include "native/include/java_lang_VMSystem.h"
#include "native/include/java_lang_VMClass.h"
#include "vm/suck.h"
-#include "boehm-gc/include/gc.h"
-
-#include <string.h>
-#include <linux/unistd.h>
-#include <sys/time.h>
-#include "toolbox/logging.h"
-#include <stdlib.h>
-#include <sys/types.h>
-#include <ltdl.h>
-#include <unistd.h>
-#include <sched.h>
+#include "boehm-gc/include/gc.h"
#if defined(ENABLE_THREADS)
#include "threads/native/threads.h"
#define CHECK_PHASE_START if (!(false
#define CHECK_PHASE(chkphase) || (phase == chkphase)
#define CHECK_PHASE_END )) return JVMTI_ERROR_WRONG_PHASE
-#define CHECK_CAPABILITY(env,CAP) if(((environment*)env)->capabilities.CAP == 0) \
+#define CHECK_CAPABILITY(env,CAP) if(((environment*) \
+ env)->capabilities.CAP == 0) \
return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
-#define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t)== \
- JVMTI_ERROR_THREAD_NOT_ALIVE) \
+#define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t) == \
+ JVMTI_ERROR_THREAD_NOT_ALIVE) \
return JVMTI_ERROR_THREAD_NOT_ALIVE;
*******************************************************************************/
static jvmtiError check_thread_is_alive(jthread t) {
- if(t==NULL) return JVMTI_ERROR_THREAD_NOT_ALIVE;
- if(((java_lang_Thread*) t)->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;
}
-/* execcallback ***************************************************************
+/* execute_callback ************************************************************
executes the registerd callbacks for the given jvmti event with parameter
in the data structure.
data->class_data,
data->new_class_data_len,
data->new_class_data);
+
+ /* if class data has been modified use it as class data for other agents
+ waiting for the same event */
+ if (data->new_class_data != NULL) {
+ data->jint1 = *(data->new_class_data_len);
+ data->class_data = *(data->new_class_data);
+ }
break;
functionptr ec;
env = envs;
- while (env!=NULL) {
+ 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 */
- while (evm!=NULL) {
+ while (evm != NULL) {
if (evm->mode == JVMTI_ENABLE) {
- data->jvmti_env=&env->env;
- ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
- execute_callback(e, ec, data);
+ ec = ((functionptr*)
+ (&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
+ if (ec != NULL) {
+ data->jvmti_env=&env->env;
+ execute_callback(e, ec, data);
+ }
}
evm=evm->next;
}
} else { /* event enabled globally */
data->jvmti_env=&env->env;
ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM];
- execute_callback(e, ec, data);
+ if (ec != NULL) execute_callback(e, ec, data);
}
env=env->next;
jthread thread;
/* XXX todo : respect event order JVMTI-Spec:Multiple Co-located Events */
- if (d->ev != JVMTI_EVENT_VM_START)
- thread = jvmti_get_current_thread();
- else
+ if (d->ev == JVMTI_EVENT_VM_START)
thread = NULL;
+ else
+ thread = jvmti_get_current_thread();
+
d->thread = thread;
dofireEvent(d->ev,d);
CHECK_THREAD_IS_ALIVE(event_thread);
}
-
cacao_env = (environment*) env;
if ((mode != JVMTI_ENABLE) && (mode != JVMTI_DISABLE))
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
case JVMTI_EVENT_VM_OBJECT_ALLOC:
CHECK_CAPABILITY(env,can_generate_vm_object_alloc_events)
break;
- case JVMTI_EVENT_THREAD_START:
- jvmti_set_system_breakpoint(THREADSTARTBRK, mode);
- break;
- case JVMTI_EVENT_THREAD_END:
- jvmti_set_system_breakpoint(THREADENDBRK, mode);
- break;
-
default:
/* all other events are required */
if ((event_type < JVMTI_EVENT_START_ENUM) ||
break;
}
+
if (event_thread != NULL) {
/* thread level control */
if ((JVMTI_EVENT_VM_INIT == mode) ||
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_suspend);
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
- return JVMTI_ERROR_NOT_AVAILABLE;
+ if(thread == NULL) return JVMTI_ERROR_INVALID_THREAD;
+ if (!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+ CHECK_THREAD_IS_ALIVE(thread);
+ /* threads_suspend_thread will implement suspend
+ threads_suspend_thread (
+ (threadobject*)((java_lang_Thread*) thread)->vmThread))*/
+
return JVMTI_ERROR_NONE;
}
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_suspend);
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
- return JVMTI_ERROR_NOT_AVAILABLE;
+ if(thread == NULL) return JVMTI_ERROR_INVALID_THREAD;
+ if (!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+ CHECK_THREAD_IS_ALIVE(thread);
+
+ /* threads_resume_thread will implement resume
+ threads_resume_thread (
+ (threadobject*)((java_lang_Thread*) thread)->vmThread))*/
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 defined(ENABLE_THREADS)
if(!builtin_instanceof(thread,class_java_lang_Thread))
return JVMTI_ERROR_INVALID_THREAD;
- CHECK_THREAD_IS_ALIVE(thread);
+ CHECK_THREAD_IS_ALIVE(thread);
+
+ threads_thread_interrupt(((java_lang_Thread *) thread)->vmThread);
+
return JVMTI_ERROR_NONE;
+#else
+ return JVMTI_ERROR_NOT_AVAILABLE;
+#endif
}
/* GetThreadInfo ***************************************************************
static jvmtiError
GetThreadInfo (jvmtiEnv * env, jthread t, jvmtiThreadInfo * info_ptr)
{
+ utf *name;
java_lang_Thread* th = (java_lang_Thread*)t;
+
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
+
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);
+
+ name = javastring_toutf(th->name,false);
+ info_ptr->name=(char*)heap_allocate(sizeof(char)*(utf_bytes(name)+1),true,NULL);
+ utf_sprint_convert_to_latin1(info_ptr->name, name);
return JVMTI_ERROR_NONE;
}
/* GetOwnedMonitorInfo *********************************************************
- Get information about the monitors owned by the specified thread
+ Gets all monitors owned by the specified thread
*******************************************************************************/
int i,j,size=20;
java_objectheader **om;
lock_record_pool_t* lrp;
-
- log_text("GetOwnedMonitorInfo called");
+ threadobject* t;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_get_owned_monitor_info);
- if ((owned_monitors_ptr==NULL)||(owned_monitor_count_ptr==NULL))
+ if ((owned_monitors_ptr == NULL)||(owned_monitor_count_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
-
- CHECK_THREAD_IS_ALIVE(thread);
+ if (thread == NULL) {
+ t = jvmti_get_current_thread();
+ } else {
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+
+ CHECK_THREAD_IS_ALIVE(thread);
+ t = (threadobject*) thread;
+ }
#if defined(ENABLE_THREADS)
pthread_mutex_lock(&lock_global_pool_lock);
lrp=lock_global_pool;
+ /* iterate over all lock record pools */
while (lrp != NULL) {
+ /* iterate over every lock record in a pool */
for (j=0; j<lrp->header.size; j++) {
-/* if((lrp->lr[j].owner==(threadobject*)thread)&&
- (!lrp->lr[j].waiting)) {
- if (i>=size) {
- MREALLOC(om,java_objectheader*,size,size*2);
- size=size*2;
+ /* if the lock record is owned by the given thread add it to
+ the result array */
+ if(lrp->lr[j].owner == t) {
+ if (i >= size) {
+ MREALLOC(om, java_objectheader*, size, size * 2);
+ size = size * 2;
}
- om[i]=lrp->lr[j].o;
+ om[i] = lrp->lr[j].obj;
i++;
- }*/
+ }
}
lrp=lrp->header.next;
}
pthread_mutex_unlock(&lock_global_pool_lock);
- *owned_monitors_ptr = heap_allocate(sizeof(java_objectheader*)*i,true,NULL);
- memcpy(*owned_monitors_ptr,om,i*sizeof(java_objectheader*));
- MFREE(om,java_objectheader*,size);
+ *owned_monitors_ptr =
+ heap_allocate(sizeof(java_objectheader*) * i, true, NULL);
+ memcpy(*owned_monitors_ptr, om, i * sizeof(java_objectheader*));
+ MFREE(om, java_objectheader*, size);
*owned_monitor_count_ptr = i;
{
int j;
lock_record_pool_t* lrp;
- java_objectheader* monitor;
+ threadobject* t;
+ lock_waiter_t* waiter;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
CHECK_CAPABILITY(env, can_get_current_contended_monitor)
- if (monitor_ptr==NULL) return JVMTI_ERROR_NULL_POINTER;
+ if (monitor_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
*monitor_ptr=NULL;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
-
- CHECK_THREAD_IS_ALIVE(thread);
-
+ if (thread == NULL) {
+ t = jvmti_get_current_thread();
+ } else {
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+
+ CHECK_THREAD_IS_ALIVE(thread);
+ t = (threadobject*) thread;
+ }
#if defined(ENABLE_THREADS)
lrp=lock_global_pool;
- while ((lrp != NULL)&&(monitor==NULL)) {
+ /* iterate over all lock record pools */
+ while ((lrp != NULL) && (*monitor_ptr == NULL)) {
+ /* iterate over every lock record in a pool */
for (j=0; j<lrp->header.size; j++) {
-/* if((lrp->lr[j].owner==(threadobject*)thread)&&(lrp->lr[j].waiting)) {
- monitor=lrp->lr[j].o;
- break;
- }*/
+ /* iterate over every thread that is wait on this lock record */
+ waiter = lrp->lr[j].waiters;
+ while (waiter != NULL)
+ /* if the waiting thread equals to the given thread we are
+ done. Stop iterateting. */
+ if(waiter->waiter == t) {
+ *monitor_ptr=lrp->lr[j].obj;
+ break;
+ }
}
lrp=lrp->header.next;
}
pthread_mutex_unlock(&lock_global_pool_lock);
- if (monitor!=NULL) {
- *monitor_ptr = heap_allocate(sizeof(java_objectheader*),true,NULL);
- *monitor_ptr = (jobject)monitor;
- }
#endif
return JVMTI_ERROR_NONE;
(priority > JVMTI_THREAD_MAX_PRIORITY))
return JVMTI_ERROR_INVALID_PRIORITY;
- /* XXX: Threads started with with this function should not be visible to
+ /* XXX: Threads started with this function should not be visible to
Java programming language queries but are included in JVM TI queries */
rap.sf = proc;
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;
*thread_count_ptr = (jint)tgp->threads->elementCount;
- *threads_ptr = heap_allocate(sizeof(jthread*)*(*thread_count_ptr),true,NULL);
+ *threads_ptr =
+ heap_allocate(sizeof(jthread)*(*thread_count_ptr),true,NULL);
memcpy(*threads_ptr, &tgp->threads->elementData,
- (*thread_count_ptr)*sizeof(jthread*));
+ (*thread_count_ptr)*sizeof(java_objectarray*));
*group_count_ptr = (jint) tgp->groups->elementCount;
- *groups_ptr = heap_allocate(sizeof(jthreadGroup*)*(*group_count_ptr),true,NULL);
+ *groups_ptr =
+ heap_allocate(sizeof(jthreadGroup)*(*group_count_ptr),true,NULL);
memcpy(*groups_ptr, &tgp->threads->elementData,
(*group_count_ptr)*sizeof(jthreadGroup*));
/* getcacaostacktrace *********************************************************
Helper function that retrives stack trace for specified thread.
- Has to take care of suspend/resume issuses
-
+
*******************************************************************************/
+
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); */
+ bool resume;
+
+ if (thread == NULL) {
+ t = jvmti_get_current_thread();
+ *trace = stacktrace_create(t);
+ } else {
+ t = (threadobject*)((java_lang_Thread*)thread)->vmThread;
+/* if (t != jvmti_get_current_thread())
+ resume = threads_suspend_thread_if_running(thread);
+
+ *trace = stacktrace_create(thread );
+
+ if (resume)
+ threads_resume_thread ( thread );*/
+ }
return JVMTI_ERROR_NONE;
}
/* GetFrameCount **************************************************************
- Get the number of frames in the specified thread's stack.
+ Get the number of frames in the specified thread's stack. Calling function
+ has to take care of suspending/resuming thread.
*******************************************************************************/
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
+ if (thread != NULL){
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
- CHECK_THREAD_IS_ALIVE(thread);
+ CHECK_THREAD_IS_ALIVE(thread);
+ }
if(count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
er = getcacaostacktrace(&trace, thread);
- if (er==JVMTI_ERROR_NONE) return er;
+ if (er == JVMTI_ERROR_NONE) {
+ heap_free(trace);
+ return er;
+ }
*count_ptr = trace->used;
+ heap_free(trace);
return JVMTI_ERROR_NONE;
}
*thread_state_ptr = 0;
#if defined(ENABLE_THREADS)
- if((th->vmThread==NULL)&&(th->group==NULL)) { /* alive ? */
+ if((th->vmThread == NULL)&&(th->group == NULL)) { /* alive ? */
/* not alive */
if (((threadobject*)th->vmThread)->tid == 0)
*thread_state_ptr = JVMTI_THREAD_STATE_TERMINATED;
/* alive */
*thread_state_ptr = JVMTI_THREAD_STATE_ALIVE;
if (t->interrupted) *thread_state_ptr |= JVMTI_THREAD_STATE_INTERRUPTED;
- /* todo */
+ /* XXX todo - info not available */
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;
{
stackframeinfo *sfi;
int i;
+ threadobject* th;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
-
- CHECK_THREAD_IS_ALIVE(thread);
+ if (thread == NULL) {
+ th = jvmti_get_current_thread();
+ } else {
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+
+ CHECK_THREAD_IS_ALIVE(thread);
+ th = (threadobject*) ((java_lang_Thread*)thread)->vmThread;
+ }
if (depth < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
if ((method_ptr == NULL)&&(location_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
- sfi = ((threadobject*)thread)->_stackframeinfo;
+ sfi = th->_stackframeinfo;
i = 0;
while ((sfi != NULL) && (i<depth)) {
if (!lock_is_held_by_current_thread((java_objectheader*)monitor->name))
return JVMTI_ERROR_NOT_MONITOR_OWNER;
- lock_monitor_exit((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name);
+ lock_monitor_exit((java_objectheader *) monitor->name);
- /* GC will clean monitor up */
+ heap_free(monitor);
#else
log_text ("DestroyRawMonitor not supported");
#endif
return JVMTI_ERROR_INVALID_MONITOR;
#if defined(ENABLE_THREADS)
- builtin_monitorenter((java_objectheader*)monitor->name);
+ lock_monitor_enter((java_objectheader *) monitor->name);
#else
log_text ("RawMonitorEnter not supported");
#endif
if (!lock_is_held_by_current_thread((java_objectheader*)monitor->name))
return JVMTI_ERROR_NOT_MONITOR_OWNER;
- builtin_monitorexit((java_objectheader*)monitor->name);
+ lock_monitor_exit((java_objectheader *) monitor->name);
#else
log_text ("RawMonitorExit not supported");
#endif
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
- if ((generic_ptr== NULL)||(signature_ptr == NULL))
- return JVMTI_ERROR_NULL_POINTER;
+
+ if (klass == NULL) return JVMTI_ERROR_INVALID_CLASS;
+ if (!builtin_instanceof(klass,class_java_lang_Class))
+ return JVMTI_ERROR_INVALID_CLASS;
- *signature_ptr = (char*)
- heap_allocate(sizeof(char) *
- ((classinfo*)klass)->name->blength,true,NULL);
+ if (signature_ptr != NULL) {
+ *signature_ptr = (char*)
+ heap_allocate(sizeof(char) *
+ utf_bytes(((classinfo*)klass)->name)+1,true,NULL);
+
+ utf_sprint_convert_to_latin1(*signature_ptr,((classinfo*)klass)->name);
+ }
- utf_sprint_convert_to_latin1(*signature_ptr, ((classinfo*)klass)->name);
- *generic_ptr = NULL;
+ if (generic_ptr!= NULL)
+ *generic_ptr = NULL;
return JVMTI_ERROR_NONE;
}
*status_ptr = 0;
/* if (c) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_VERIFIED; ? */
- if (c->state&=CLASS_LINKED)
+ if (c->state & CLASS_LINKED)
*status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PREPARED;
- if (c->state&=CLASS_INITIALIZED)
+ if (c->state & CLASS_INITIALIZED)
*status_ptr = *status_ptr | JVMTI_CLASS_STATUS_INITIALIZED;
- if (c->state&=CLASS_ERROR)
+ if (c->state & CLASS_ERROR)
*status_ptr = *status_ptr | JVMTI_CLASS_STATUS_ERROR;
if (c->vftbl->arraydesc != NULL)
if ((klass == NULL)||(source_name_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
- size = (((classinfo*)klass)->sourcefile->blength)+1;
+ size = utf_bytes(((classinfo*)klass)->sourcefile)+1;
*source_name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
- if ((field == NULL)||(name_ptr == NULL)||(signature_ptr == NULL))
- return JVMTI_ERROR_NULL_POINTER;
+
+ if (klass == NULL)
+ return JVMTI_ERROR_INVALID_CLASS;
+ else
+ if (!builtin_instanceof(klass,class_java_lang_Class))
+ return JVMTI_ERROR_INVALID_CLASS;
+ if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;
- size = (((fieldinfo*)field)->name->blength);
- *name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
- memcpy(*name_ptr,((fieldinfo*)field)->name->text, size);
+ if (name_ptr != NULL) {
+ size = utf_bytes(((fieldinfo*)field)->name)+1;
+ *name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
+ utf_sprint_convert_to_latin1(*name_ptr, ((fieldinfo*)field)->name);
+ }
- size = (((fieldinfo*)field)->descriptor->blength);
- *signature_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
- memcpy(*signature_ptr,((fieldinfo*)field)->descriptor->text, size);
+ if (signature_ptr != NULL) {
+ size = utf_bytes(((fieldinfo*)field)->descriptor)+1;
+ *signature_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL);
+ utf_sprint_convert_to_latin1(*signature_ptr,
+ ((fieldinfo*)field)->descriptor);
+ }
- *generic_ptr = NULL;
+ if (generic_ptr != NULL)
+ *generic_ptr = NULL;
return JVMTI_ERROR_NONE;
}
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
+
+ if (klass == NULL)
+ return JVMTI_ERROR_INVALID_CLASS;
+ else
+ if (!builtin_instanceof(klass,class_java_lang_Class))
+ return JVMTI_ERROR_INVALID_CLASS;
+
+ if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;
+
+ if (declaring_class_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
+
*declaring_class_ptr = (jclass) ((fieldinfo*)field)->class;
return JVMTI_ERROR_NONE;
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
- if (!builtin_instanceof((java_objectheader*)klass, class_java_lang_Class))
- return JVMTI_ERROR_INVALID_OBJECT;
+
+ if (klass == NULL)
+ return JVMTI_ERROR_INVALID_CLASS;
+ else
+ if (!builtin_instanceof(klass,class_java_lang_Class))
+ return JVMTI_ERROR_INVALID_CLASS;
+
+ if (field == NULL) return JVMTI_ERROR_INVALID_FIELDID;
if (modifiers_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
- /* todo: JVMTI_ERROR_INVALID_FIELDID; */
-
*modifiers_ptr = ((fieldinfo*)field)->flags;
return JVMTI_ERROR_NONE;
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if ((method == NULL) || (name_ptr == NULL) || (signature_ptr == NULL)
- || (generic_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER;
- *name_ptr = (char*)
- heap_allocate(sizeof(char) * (m->name->blength),true,NULL);
- utf_sprint_convert_to_latin1(*name_ptr, m->name);
+ if (method == NULL) return JVMTI_ERROR_INVALID_METHODID;
- *signature_ptr = (char*)
- heap_allocate(sizeof(char) * (m->descriptor->blength),true,NULL);
- utf_sprint_convert_to_latin1(*signature_ptr, m->descriptor);
+ if (name_ptr != NULL) {
+ *name_ptr = (char*)
+ heap_allocate(sizeof(char) * (utf_bytes(m->name)+1),true,NULL);
+ utf_sprint_convert_to_latin1(*name_ptr, m->name);
+ }
+
+ if (signature_ptr != NULL) {
+ *signature_ptr = (char*)
+ heap_allocate(sizeof(char)*(utf_bytes(m->descriptor)+1),true,NULL);
+ utf_sprint_convert_to_latin1(*signature_ptr, m->descriptor);
+ }
- /* there is no generic signature attribute */
- *generic_ptr = NULL;
+ if (generic_ptr != NULL) {
+ /* there is no generic signature attribute */
+ *generic_ptr = NULL;
+ }
return JVMTI_ERROR_NONE;
}
if (((methodinfo*)method)->flags & ACC_NATIVE)
return JVMTI_ERROR_NATIVE_METHOD;
-
+
*max_ptr = (jint) ((methodinfo*)method)->maxlocals;
return JVMTI_ERROR_NONE;
if (((methodinfo*)method)->flags & ACC_NATIVE)
return JVMTI_ERROR_NATIVE_METHOD;
-/* todo *size_ptr = (jint)((methodinfo*)method)->paramcount;*/
+ *size_ptr = (jint)((methodinfo*)method)->parseddesc->paramslots;
return JVMTI_ERROR_NONE;
}
-/* GetLineNumberTable ***********************************************************
+/* GetLineNumberTable **********************************************************
Return table of source line number entries for a given method
if ((method == NULL) || (entry_count_ptr == NULL) || (table_ptr == NULL))
return JVMTI_ERROR_NULL_POINTER;
+
if (((methodinfo*)method)->flags & ACC_NATIVE)
return JVMTI_ERROR_NATIVE_METHOD;
+
if (((methodinfo*)method)->linenumbers == NULL)
return JVMTI_ERROR_ABSENT_INFORMATION;
for (i=0; i < *entry_count_ptr; i++) {
- (*table_ptr[i]).start_location =
+ (*table_ptr)[i].start_location =
(jlocation) ((methodinfo*)method)->linenumbers[i].start_pc;
- (*table_ptr[i]).line_number =
+ (*table_ptr)[i].line_number =
(jint) ((methodinfo*)method)->linenumbers[i].line_number;
}
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if ((method == NULL) || (start_location_ptr == NULL) ||
- (end_location_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER;
+ if (method == NULL) return JVMTI_ERROR_INVALID_METHODID;
+
+ if (((methodinfo*)method)->flags & ACC_NATIVE)
+ return JVMTI_ERROR_NATIVE_METHOD;
+
+ if ((start_location_ptr == NULL) || (end_location_ptr == NULL))
+ return JVMTI_ERROR_NULL_POINTER;
/* XXX we return the location of the most recent code. Don't know
* if there is a way to teach jvmti that a method can have more
/* 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;
-
+ fprintf(stderr,"GetMethodLocation *** XXX todo \n");
+
+
+ /* -1 states location information is not available */
+ *start_location_ptr = (jlocation)-1;
+ *end_location_ptr = (jlocation)-1;
+
+/*
*start_location_ptr = (jlocation)m->code->mcode;
- *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength;
+ *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength;*/
return JVMTI_ERROR_NONE;
}
static jvmtiError
GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr)
{
- int i,j=0;
- classcache_name_entry *nameentry;
- classcache_class_entry *classentry;
-
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
- if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
-
- CLASSCACHE_LOCK();
- *classes_ptr =
- heap_allocate(sizeof(jclass)*(hashtable_classcache.entries),true,NULL);
-
- /* look in every slot of the hashtable */
- for (i=0; i<hashtable_classcache.size; i++) {
- nameentry = hashtable_classcache.ptr[i];
- while (nameentry != NULL) { /* iterate over hashlink */
-
- /* filter pseudo classes $NEW$,$NULL$,$ARRAYSTUB$ out */
- if (nameentry->name->text[0]=='$')
- {
- log_println("%s", nameentry->name->text);
- *class_count_ptr -= 1;
- break;
- }
+ if (class_count_ptr == NULL)
+ return JVMTI_ERROR_NULL_POINTER;
- classentry = nameentry->classes;
- while (classentry != NULL){ /* iterate over classes with same name */
- if (classentry->classobj != NULL) { /*get only loaded classes */
- assert(j<hashtable_classcache.entries);
- (*classes_ptr)[j]=classentry->classobj;
- j++;
- }
- classentry = classentry->next;
- }
- nameentry = nameentry->hashlink;
- }
- }
-
- CLASSCACHE_UNLOCK();
+ if (classes_ptr == NULL)
+ return JVMTI_ERROR_NULL_POINTER;
- *class_count_ptr = j;
+ classcache_jvmti_GetLoadedClasses(class_count_ptr, classes_ptr);
return JVMTI_ERROR_NONE;
}
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-/* if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
- if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;*/
+ if ((class_count_ptr == NULL) || (classes_ptr == NULL))
+ return JVMTI_ERROR_NULL_POINTER;
/* behave like jdk 1.1 and make no distinction between initiating and
defining class loaders */
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_redefine_classes)
CHECK_CAPABILITY(env,can_redefine_any_class)
+
log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!");
return JVMTI_ERROR_NONE;
}
/* SuspendThreadList **********************************************************
-
+ Suspend all threads in the request list.
*******************************************************************************/
SuspendThreadList (jvmtiEnv * env, jint request_count,
const jthread * request_list, jvmtiError * results)
{
+ int i;
+ int suspendme = -1;
+ jthread me;
+
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_START)
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_suspend);
-
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+
+ if (request_count<0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+ if ((request_list == NULL) || (results == NULL))
+ return JVMTI_ERROR_NULL_POINTER;
+
+ me = jvmti_get_current_thread();
+
+ for (i=0;i<request_count;i++) {
+ if (request_list[i] == me)
+ suspendme = i;
+ else
+ results[i]=SuspendThread(env, request_list[i]);
+ }
+
+ if (suspendme != -1)
+ results[suspendme]=SuspendThread(env, request_list[suspendme]);
return JVMTI_ERROR_NONE;
}
/* ResumeThreadList ***********************************************************
-
+ Resumes all threads in the request list.
*******************************************************************************/
ResumeThreadList (jvmtiEnv * env, jint request_count,
const jthread * request_list, jvmtiError * results)
{
+ int i;
+
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
CHECK_CAPABILITY(env,can_suspend);
-
- log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!");
+
+ if (request_count<0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+ if ((request_list == NULL) || (results == NULL))
+ return JVMTI_ERROR_NULL_POINTER;
+
+ for (i=0;i<request_count;i++)
+ results[i]=ResumeThread(env, request_list[i]);
return JVMTI_ERROR_NONE;
}
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
+ if (thread != NULL){
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
- CHECK_THREAD_IS_ALIVE(thread);
+ CHECK_THREAD_IS_ALIVE(thread);
+ }
if((count_ptr == NULL)||(frame_buffer == NULL))
return JVMTI_ERROR_NULL_POINTER;
if (max_frame_count <0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
er = getcacaostacktrace(&trace, thread);
- if (er==JVMTI_ERROR_NONE) return er;
+ if (er == JVMTI_ERROR_NONE) {
+ heap_free(trace);
+ return er;
+ }
if ((trace->used >= start_depth) || ((trace->used * -1) > start_depth))
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
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 */
+ /* XXX todo: location BCI/MachinePC not avilable - Linenumber not expected */
frame_buffer[j].location = 0;
}
+
+ heap_free(trace);
return JVMTI_ERROR_NONE;
}
if (thread_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
- /* todo: all threads have to be suspended */
-
if (JVMTI_ERROR_NONE!=GetAllThreads(env,thread_count_ptr,&threads_ptr))
return JVMTI_ERROR_INTERNAL;
GetThreadListStackTraces(env, *thread_count_ptr, threads_ptr,
max_frame_count, stack_info_ptr);
- /* todo: resume all threads have to be suspended */
if (er != JVMTI_ERROR_NONE) return er;
return JVMTI_ERROR_NONE;
if (size_of_callbacks < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+
if (callbacks == NULL) { /* remove the existing callbacks */
memset(&(((environment* )env)->callbacks), 0,
sizeof(jvmtiEventCallbacks));
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
-
- log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ CHECK_CAPABILITY(env,can_generate_compiled_method_load_events);
+
return JVMTI_ERROR_NONE;
}
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if ((extension_count_ptr== NULL)||(extensions == NULL))
+ if ((extension_count_ptr == NULL)||(extensions == NULL))
return JVMTI_ERROR_NULL_POINTER;
/* cacao has no extended functions yet */
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
- if ((extension_count_ptr== NULL)||(extensions == NULL))
+ if ((extension_count_ptr == NULL)||(extensions == NULL))
return JVMTI_ERROR_NULL_POINTER;
/* cacao has no extended events yet */
static jvmtiError
GetJLocationFormat (jvmtiEnv * env, jvmtiJlocationFormat * format_ptr)
{
- *format_ptr = JVMTI_JLOCATION_MACHINEPC;
+ *format_ptr = JVMTI_JLOCATION_OTHER;
return JVMTI_ERROR_NONE;
}
*******************************************************************************/
static jvmtiError
-GetPotentialCapabilities (jvmtiEnv * env,
- jvmtiCapabilities * capabilities_ptr)
+GetPotentialCapabilities (jvmtiEnv * env, jvmtiCapabilities * capabilities_ptr)
{
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_ONLOAD)
return JVMTI_ERROR_NONE;
}
-/* *****************************************************************************
+/* GetAvailableProcessors *****************************************************
-
+ Get number of processors available to the virtual machine.
*******************************************************************************/
0, /* can_access_local_variables */
0, /* can_maintain_original_method_order */
0, /* can_generate_single_step_events */
- 0, /* can_generate_exception_events */
+ 1, /* can_generate_exception_events */
0, /* can_generate_frame_pop_events */
- 0, /* can_generate_breakpoint_events */
- 0, /* can_suspend */
+ 1, /* can_generate_breakpoint_events */
+ 1, /* can_suspend */
0, /* can_redefine_any_class */
0, /* can_get_current_thread_cpu_time */
0, /* can_get_thread_cpu_time */
- 0, /* can_generate_method_entry_events */
+ 1, /* can_generate_method_entry_events */
0, /* can_generate_method_exit_events */
0, /* can_generate_all_class_hook_events */
0, /* can_generate_compiled_method_load_events */
- 0, /* can_generate_monitor_events */
+ 1, /* can_generate_monitor_events */
0, /* can_generate_vm_object_alloc_events */
0, /* can_generate_native_method_bind_events */
0, /* can_generate_garbage_collection_events */
&GetObjectSize
};
+/* jvmti_set_phase ************************************************************
+
+ sets a new jvmti phase a fires an apropriate event.
+
+*******************************************************************************/
void jvmti_set_phase(jvmtiPhase p) {
genericEventData d;
jvmti_fireEvent(&d);
}
+
+/* jvmti_new_environment ******************************************************
+
+ creates a new JVMTI environment
+
+*******************************************************************************/
+
jvmtiEnv* jvmti_new_environment() {
environment* env;
return (jvmtiEnv*)env;
}
+/* jvmti_agentload ************************************************************
+
+ loads the indicated shared library containing the jvmti agent and calls the
+ Agent_OnLoad function.
+
+*******************************************************************************/
+
void jvmti_agentload(char* opt_arg, bool agentbypath, lt_dlhandle *handle, char **libname) {
lt_ptr onload;
char *arg;
int i=0,len;
jint retval;
-
len = strlen(opt_arg);
- /* separate argumtents */
- while ((opt_arg[i]!='=')&&(i<=len)) i++;
- arg = &opt_arg[i];
+ /* separate arguments */
+
+ while ((opt_arg[i] != '=') && (i < len))
+ i++;
+
+ opt_arg[i] = '\0';
+
+ if (i < len)
+ arg = &opt_arg[i + 1];
+ else
+ arg = "";
if (agentbypath) {
/* -agentpath */
- *libname=heap_allocate(sizeof(char)*i,true,NULL);
- strncpy(*libname,opt_arg,i-1);
- (*libname)[i-1]='\0';
- } else {
+
+ *libname = GCMNEW(char, i);
+
+ strcpy(*libname, opt_arg);
+ }
+ 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);
+
+ len = strlen("lib") + i + strlen(".so") + strlen("0");
+
+ *libname = GCMNEW(char, len);
+
+ strcpy(*libname, "lib");
+ strcat(*libname, opt_arg);
+ strcat(*libname, ".so");
}
/* try to open the library */
if (retval != 0) exit (retval);
}
+/* jvmti_agentunload **********************************************************
+
+ calls the Agent_UnLoad function in the jvmti agent if present.
+
+*******************************************************************************/
+
void jvmti_agentunload() {
if (unload != NULL) {
((JNIEXPORT void JNICALL (*) (JavaVM *vm)) unload)
}
}
+
/*
* 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