/* src/native/jvmti/jvmti.c - implementation of the Java Virtual Machine Tool Interface functions Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, 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: Edwin Steiner Samuel Vinson $Id: jvmti.c 4908 2006-05-12 16:49:50Z edwin $ */ #include #include "native/jni.h" #include "native/native.h" #include "native/jvmti/cacaodbg.h" #include "native/jvmti/jvmti.h" #include "vm/global.h" #include "vm/loader.h" #include "vm/builtin.h" #include "vm/jit/asmpart.h" #include "vm/class.h" #include "vm/classcache.h" #include "mm/boehm.h" #include "toolbox/logging.h" #include "vm/options.h" #include "vm/stringlocal.h" #include "mm/memory.h" #include "threads/native/threads.h" #include "vm/exceptions.h" #include "native/include/java_util_Vector.h" #include "native/include/java_io_PrintStream.h" #include "native/include/java_io_InputStream.h" #include "native/include/java_lang_Cloneable.h" #include "native/include/java_lang_ThreadGroup.h" #include "native/include/java_lang_VMObject.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 #include #include #include "toolbox/logging.h" #include #include #include #include #include #if defined(USE_THREADS) && defined(NATIVE_THREADS) #include "threads/native/threads.h" #include #include #endif #include "native/jvmti/stacktrace.h" #include "dbg.h" typedef struct _environment environment; static environment *envs=NULL; pthread_mutex_t dbgcomlock; extern const struct JNIInvokeInterface _Jv_JNIInvokeInterface; static jvmtiPhase phase; typedef struct _jvmtiEventModeLL jvmtiEventModeLL; struct _jvmtiEventModeLL { jvmtiEventMode mode; jthread event_thread; jvmtiEventModeLL *next; }; typedef struct _jvmtiThreadLocalStorage jvmtiThreadLocalStorage; struct _jvmtiThreadLocalStorage{ jthread thread; void *data; jvmtiThreadLocalStorage *next; }; struct _environment { jvmtiEnv env; environment *next; jvmtiEventCallbacks callbacks; /* table for enabled/disabled jvmtiEvents - first element contains global behavior */ jvmtiEventModeLL events[JVMTI_EVENT_END_ENUM - JVMTI_EVENT_START_ENUM]; jvmtiCapabilities capabilities; void *EnvironmentLocalStorage; jvmtiThreadLocalStorage *tls; }; static struct jvmtiEnv_struct JVMTI_EnvTable; static jvmtiCapabilities JVMTI_Capabilities; static lt_ptr unload; #define CHECK_PHASE_START if (!(0 #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) \ return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; #define CHECK_THREAD_IS_ALIVE(t) if(check_thread_is_alive(t)== \ JVMTI_ERROR_THREAD_NOT_ALIVE) \ return JVMTI_ERROR_THREAD_NOT_ALIVE; /* check_thread_is_alive ******************************************************* checks if the given thread is alive *******************************************************************************/ static jvmtiError check_thread_is_alive(jthread t) { 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 *************************************************************** executes the registerd callbacks for the given jvmti event with parameter in the data structure. *******************************************************************************/ static void execcallback(jvmtiEvent e, functionptr ec, genericEventData* data) { JNIEnv* jni_env = (JNIEnv*)_Jv_env; fprintf(stderr,"execcallback called (event: %d)\n",e); switch (e) { case JVMTI_EVENT_VM_INIT: case JVMTI_EVENT_THREAD_START: case JVMTI_EVENT_THREAD_END: ((jvmtiEventThreadStart)ec) (data->jvmti_env, jni_env, data->thread); break; case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK: ((jvmtiEventClassFileLoadHook)ec) (data->jvmti_env, jni_env, data->klass, data->object, data->name, data->protection_domain, data->jint1, data->class_data, data->new_class_data_len, data->new_class_data); break; case JVMTI_EVENT_CLASS_PREPARE: case JVMTI_EVENT_CLASS_LOAD: ((jvmtiEventClassLoad)ec) (data->jvmti_env, jni_env, data->thread, data->klass); break; case JVMTI_EVENT_VM_DEATH: case JVMTI_EVENT_VM_START: ((jvmtiEventVMStart)ec) (data->jvmti_env, jni_env); break; case JVMTI_EVENT_EXCEPTION: ((jvmtiEventException)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->location, data->object, data->catch_method, data->catch_location); break; case JVMTI_EVENT_EXCEPTION_CATCH: ((jvmtiEventExceptionCatch)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->location, data->object); break; case JVMTI_EVENT_BREAKPOINT: case JVMTI_EVENT_SINGLE_STEP: ((jvmtiEventSingleStep)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->location); break; case JVMTI_EVENT_FRAME_POP: ((jvmtiEventFramePop)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->b); break; case JVMTI_EVENT_FIELD_ACCESS: ((jvmtiEventFieldAccess)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->location, data->klass, data->object, data->field); break; case JVMTI_EVENT_FIELD_MODIFICATION: ((jvmtiEventFieldModification)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->location, data->klass, data->object, data->field, data->signature_type, data->value); break; case JVMTI_EVENT_METHOD_ENTRY: ((jvmtiEventMethodEntry)ec) (data->jvmti_env, jni_env, data->thread, data->method); break; case JVMTI_EVENT_METHOD_EXIT: ((jvmtiEventMethodExit)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->b, data->value); break; case JVMTI_EVENT_NATIVE_METHOD_BIND: ((jvmtiEventNativeMethodBind)ec) (data->jvmti_env, jni_env, data->thread, data->method, data->address, data->new_address_ptr); break; case JVMTI_EVENT_COMPILED_METHOD_LOAD: ((jvmtiEventCompiledMethodLoad)ec) (data->jvmti_env, data->method, data->jint1, data->address, data->jint2, data->map, data->compile_info); break; case JVMTI_EVENT_COMPILED_METHOD_UNLOAD: ((jvmtiEventCompiledMethodUnload)ec) (data->jvmti_env, data->method, data->address); break; case JVMTI_EVENT_DYNAMIC_CODE_GENERATED: ((jvmtiEventDynamicCodeGenerated)ec) (data->jvmti_env, data->name, data->address, data->jint1); break; case JVMTI_EVENT_GARBAGE_COLLECTION_START: case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH: case JVMTI_EVENT_DATA_DUMP_REQUEST: ((jvmtiEventDataDumpRequest)ec) (data->jvmti_env); break; case JVMTI_EVENT_MONITOR_WAIT: ((jvmtiEventMonitorWait)ec) (data->jvmti_env, jni_env, data->thread, data->object, data->jlong); break; case JVMTI_EVENT_MONITOR_WAITED: ((jvmtiEventMonitorWaited)ec) (data->jvmti_env, jni_env, data->thread, data->object, data->b); break; case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: ((jvmtiEventMonitorContendedEnter)ec) (data->jvmti_env, jni_env, data->thread, data->object); break; case JVMTI_EVENT_OBJECT_FREE: ((jvmtiEventObjectFree)ec) (data->jvmti_env, data->jlong); break; case JVMTI_EVENT_VM_OBJECT_ALLOC: ((jvmtiEventVMObjectAlloc)ec) (data->jvmti_env, jni_env, data->thread, data->object, data->klass, data->jlong); break; default: log_text ("unknown event"); } } /* dofireEvent ****************************************************************** sends event if it is enabled either globally or for some threads *******************************************************************************/ static void dofireEvent(jvmtiEvent e, genericEventData* data) { environment* env; jvmtiEventModeLL *evm; functionptr ec; env = envs; while (env!=NULL) { if (env->events[e-JVMTI_EVENT_START_ENUM].mode == JVMTI_DISABLE) { evm = env->events[e-JVMTI_EVENT_START_ENUM].next; /* test if the event is enable for some threads */ while (evm!=NULL) { if (evm->mode == JVMTI_ENABLE) { data->jvmti_env=&env->env; ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM]; execcallback(e, ec, data); } evm=evm->next; } } else { /* event enabled globally */ data->jvmti_env=&env->env; ec = ((functionptr*)(&env->callbacks))[e-JVMTI_EVENT_START_ENUM]; execcallback(e, ec, data); } env=env->next; } } /* fireEvent ****************************************************************** fire event callback with data arguments. This function mainly fills the missing EventData. *******************************************************************************/ void fireEvent(genericEventData* d) { jthread thread; /* todo : respect event order JVMTI-Spec:Multiple Co-located Events */ if (d->ev != JVMTI_EVENT_VM_START) thread = getcurrentthread(); else thread = NULL; fprintf (stderr,"jvmti: fireEvent: %d\n",d->ev); d->thread = thread; dofireEvent(d->ev,d); /* if we need to send a VM_INIT event then also send a THREAD_START event */ if (d->ev == JVMTI_EVENT_VM_INIT) dofireEvent(JVMTI_EVENT_THREAD_START,d); } /* SetEventNotificationMode **************************************************** Control the generation of events *******************************************************************************/ jvmtiError SetEventNotificationMode (jvmtiEnv * env, jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) { environment* cacao_env; jvmtiEventModeLL *ll; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if(event_thread != NULL) { if (!builtin_instanceof(event_thread,class_java_lang_Thread)) return JVMTI_ERROR_INVALID_THREAD; CHECK_THREAD_IS_ALIVE(event_thread); } cacao_env = (environment*) env; if ((mode != JVMTI_ENABLE) && (mode != JVMTI_DISABLE)) return JVMTI_ERROR_ILLEGAL_ARGUMENT; switch (event_type) { /* check capability */ case JVMTI_EVENT_EXCEPTION: case JVMTI_EVENT_EXCEPTION_CATCH: CHECK_CAPABILITY(env,can_generate_exception_events) break; case JVMTI_EVENT_SINGLE_STEP: CHECK_CAPABILITY(env,can_generate_single_step_events) break; case JVMTI_EVENT_FRAME_POP: CHECK_CAPABILITY(env,can_generate_frame_pop_events) break; case JVMTI_EVENT_BREAKPOINT: CHECK_CAPABILITY(env,can_generate_breakpoint_events) break; case JVMTI_EVENT_FIELD_ACCESS: CHECK_CAPABILITY(env,can_generate_field_access_events) break; case JVMTI_EVENT_FIELD_MODIFICATION: CHECK_CAPABILITY(env,can_generate_field_modification_events) break; case JVMTI_EVENT_METHOD_ENTRY: CHECK_CAPABILITY(env,can_generate_method_entry_events) break; case JVMTI_EVENT_METHOD_EXIT: CHECK_CAPABILITY(env, can_generate_method_exit_events) break; case JVMTI_EVENT_NATIVE_METHOD_BIND: CHECK_CAPABILITY(env, can_generate_native_method_bind_events) break; case JVMTI_EVENT_COMPILED_METHOD_LOAD: case JVMTI_EVENT_COMPILED_METHOD_UNLOAD: CHECK_CAPABILITY(env,can_generate_compiled_method_load_events) break; case JVMTI_EVENT_MONITOR_WAIT: case JVMTI_EVENT_MONITOR_WAITED: case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: CHECK_CAPABILITY(env,can_generate_monitor_events) break; case JVMTI_EVENT_GARBAGE_COLLECTION_START: case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH: CHECK_CAPABILITY(env,can_generate_garbage_collection_events) break; case JVMTI_EVENT_OBJECT_FREE: CHECK_CAPABILITY(env,can_generate_object_free_events) break; case JVMTI_EVENT_VM_OBJECT_ALLOC: CHECK_CAPABILITY(env,can_generate_vm_object_alloc_events) 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; } if (event_thread != NULL) { /* thread level control */ if ((JVMTI_EVENT_VM_INIT == mode) || (JVMTI_EVENT_VM_DEATH == mode) || (JVMTI_EVENT_VM_START == mode) || (JVMTI_EVENT_THREAD_START == mode) || (JVMTI_EVENT_COMPILED_METHOD_LOAD == mode) || (JVMTI_EVENT_COMPILED_METHOD_UNLOAD == mode) || (JVMTI_EVENT_DYNAMIC_CODE_GENERATED == mode) || (JVMTI_EVENT_DATA_DUMP_REQUEST == mode)) return JVMTI_ERROR_ILLEGAL_ARGUMENT; ll = &(cacao_env->events[event_type-JVMTI_EVENT_START_ENUM]); while (ll->next != NULL) { ll = ll->next; if (ll->event_thread == event_thread) { ll->mode=mode; return JVMTI_ERROR_NONE; } } ll->next = heap_allocate(sizeof(jvmtiEventModeLL),true,NULL); ll->next->mode=mode; } else { /* global control */ cacao_env->events[event_type-JVMTI_EVENT_START_ENUM].mode=mode; } return JVMTI_ERROR_NONE; } /* GetAllThreads *************************************************************** Get all live threads *******************************************************************************/ jvmtiError GetAllThreads (jvmtiEnv * env, jint * threads_count_ptr, jthread ** threads_ptr) { threadobject** threads; int i; jvmtiError retval; log_text ("GetAllThreads called"); CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((threads_count_ptr == NULL) || (threads_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; 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] = threads[i]->o.thread; return JVMTI_ERROR_NONE; } /* SuspendThread *************************************************************** Suspend specified thread *******************************************************************************/ jvmtiError SuspendThread (jvmtiEnv * env, jthread thread) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_suspend); log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NOT_AVAILABLE; return JVMTI_ERROR_NONE; } /* ResumeThread *************************************************************** Resume a suspended thread *******************************************************************************/ jvmtiError ResumeThread (jvmtiEnv * env, jthread thread) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_suspend); log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NOT_AVAILABLE; return JVMTI_ERROR_NONE; } /* StopThread ***************************************************************** Send asynchronous exception to the specified thread. Similar to java.lang.Thread.stop(). Used to kill thread. *******************************************************************************/ jvmtiError StopThread (jvmtiEnv * env, jthread thread, jobject exception) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_signal_thread); log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NOT_AVAILABLE; return JVMTI_ERROR_NONE; } /* InterruptThread ************************************************************ Interrupt specified thread. Similar to java.lang.Thread.interrupt() *******************************************************************************/ jvmtiError InterruptThread (jvmtiEnv * env, jthread thread) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) 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); return JVMTI_ERROR_NONE; } /* GetThreadInfo *************************************************************** Get thread information. Details of the specified thread are stored in the jvmtiThreadInfo structure. *******************************************************************************/ jvmtiError GetThreadInfo (jvmtiEnv * env, jthread t, jvmtiThreadInfo * info_ptr) { java_lang_Thread* th = (java_lang_Thread*)t; log_text("GetThreadInfo called"); 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); return JVMTI_ERROR_NONE; } /* GetOwnedMonitorInfo ********************************************************* Get information about the monitors owned by the specified thread *******************************************************************************/ jvmtiError GetOwnedMonitorInfo (jvmtiEnv * env, jthread thread, jint * owned_monitor_count_ptr, jobject ** owned_monitors_ptr) { int i,j,size=20; java_objectheader **om; lock_record_pool_t* lrp; log_text("GetOwnedMonitorInfo called - todo: fix object mapping"); 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)) return JVMTI_ERROR_NULL_POINTER; 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) om=MNEW(java_objectheader*,size); pthread_mutex_lock(&lock_global_pool_lock); lrp=lock_global_pool; while (lrp != NULL) { for (j=0; jheader.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; } om[i]=lrp->lr[j].o; 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_monitor_count_ptr = i; #endif return JVMTI_ERROR_NONE; } /* GetCurrentContendedMonitor ************************************************* Get the object the specified thread waits for. *******************************************************************************/ jvmtiError GetCurrentContendedMonitor (jvmtiEnv * env, jthread thread, jobject * monitor_ptr) { int j; lock_record_pool_t* lrp; java_objectheader* monitor; 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; *monitor_ptr=NULL; 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) pthread_mutex_lock(&lock_global_pool_lock); lrp=lock_global_pool; while ((lrp != NULL)&&(monitor==NULL)) { for (j=0; jheader.size; j++) { if((lrp->lr[j].owner==(threadobject*)thread)&&(lrp->lr[j].waiting)) { monitor=lrp->lr[j].o; 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; } typedef struct { jvmtiStartFunction sf; jvmtiEnv* jvmti_env; void* arg; } runagentparam; static void *threadstartup(void *t) { runagentparam *rap = (runagentparam*)t; rap->sf(rap->jvmti_env,(JNIEnv*)&_Jv_JNINativeInterface,rap->arg); return NULL; } /* RunAgentThread ************************************************************* Starts the execution of an agent thread of the specified native function within the specified thread *******************************************************************************/ jvmtiError RunAgentThread (jvmtiEnv * env, jthread thread, jvmtiStartFunction proc, const void *arg, jint priority) { pthread_attr_t threadattr; struct sched_param sp; runagentparam rap; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if((thread != NULL)&&(!builtin_instanceof(thread,class_java_lang_Thread))) return JVMTI_ERROR_INVALID_THREAD; if (proc == NULL) return JVMTI_ERROR_NULL_POINTER; if ((priority < JVMTI_THREAD_MIN_PRIORITY) || (priority > JVMTI_THREAD_MAX_PRIORITY)) 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; #if defined(USE_THREADS) && defined(NATIVE_THREADS) pthread_attr_init(&threadattr); pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED); if (priority == JVMTI_THREAD_MIN_PRIORITY) { sp.__sched_priority = sched_get_priority_min(SCHED_FIFO); } if (priority == JVMTI_THREAD_MAX_PRIORITY) { sp.__sched_priority = sched_get_priority_min(SCHED_FIFO); } pthread_attr_setschedparam(&threadattr,&sp); if (pthread_create(&((threadobject*) thread)->info.tid, &threadattr, &threadstartup, &rap)) { log_text("pthread_create failed"); assert(0); } #endif return JVMTI_ERROR_NONE; } /* GetTopThreadGroups ********************************************************* Get all top-level thread groups in the VM. *******************************************************************************/ jvmtiError GetTopThreadGroups (jvmtiEnv * env, jint * group_count_ptr, jthreadGroup ** groups_ptr) { jint threads_count_ptr; threadobject *threads_ptr; int i,j,x,size=20; jthreadGroup **tg,*ttgp; CHECK_PHASE_START 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; #if defined(USE_THREADS) && defined(NATIVE_THREADS) tg = MNEW(jthreadGroup*,size); x = 0; if (JVMTI_ERROR_NONE!=GetAllThreads(env,&threads_count_ptr,(jthread**)&threads_ptr)) return JVMTI_ERROR_INTERNAL; for (i=0;igroup == NULL) { log_text("threadgroup not set"); return JVMTI_ERROR_INTERNAL; } ttgp = (jthreadGroup*)((java_lang_ThreadGroup*)threads_ptr[i].o.thread->group)->parent; if (ttgp == NULL) { j=0; while((j= size){ MREALLOC(tg,jthreadGroup*,size,size*2); size=size*2; } tg[x]=ttgp; x++; } } } *groups_ptr = heap_allocate(sizeof(jthreadGroup*)*x,true,NULL); memcpy(*groups_ptr,tg,x*sizeof(jthreadGroup*)); MFREE(tg,jthreadGroup*,size); *group_count_ptr = x; #else return JVMTI_ERROR_NOT_AVAILABLE; #endif return JVMTI_ERROR_NONE; } /* GetThreadGroupInfo ********************************************************* Get information about the specified thread group. *******************************************************************************/ jvmtiError GetThreadGroupInfo (jvmtiEnv * env, jthreadGroup group, jvmtiThreadGroupInfo * info_ptr) { int size; char* name; java_lang_ThreadGroup* grp; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (info_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof(group,class_java_lang_ThreadGroup)) return JVMTI_ERROR_INVALID_THREAD_GROUP; grp = (java_lang_ThreadGroup*)group; info_ptr->parent = (jthreadGroup) Java_java_lang_VMObject_clone(NULL, (jclass)grp->header.vftbl->class, (java_lang_Cloneable*) &grp->parent); name = javastring_tochar((java_objectheader*)grp->name); size = strlen(name); info_ptr->name=heap_allocate(size*sizeof(char),true,NULL); strncpy(info_ptr->name,name,size); info_ptr->max_priority= (jint)grp->maxpri; info_ptr->is_daemon= (jboolean)grp->daemon_flag; return JVMTI_ERROR_NONE; } /* GetThreadGroupChildren ***************************************************** Get the live threads and active subgroups in this thread group. *******************************************************************************/ jvmtiError GetThreadGroupChildren (jvmtiEnv * env, jthreadGroup group, jint * thread_count_ptr, jthread ** threads_ptr, jint * group_count_ptr, jthreadGroup ** groups_ptr) { java_lang_ThreadGroup* tgp; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((thread_count_ptr == NULL) || (threads_ptr == NULL) || (group_count_ptr == NULL) || (groups_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof(group,class_java_lang_ThreadGroup)) return JVMTI_ERROR_INVALID_THREAD_GROUP; tgp = (java_lang_ThreadGroup*)group; *thread_count_ptr = (jint)tgp->threads->elementCount; *threads_ptr = heap_allocate(sizeof(jthread*)*(*thread_count_ptr),true,NULL); memcpy(*threads_ptr, &tgp->threads->elementData, (*thread_count_ptr)*sizeof(jthread*)); *group_count_ptr = (jint) tgp->groups->elementCount; *groups_ptr = heap_allocate(sizeof(jthreadGroup*)*(*group_count_ptr),true,NULL); memcpy(*groups_ptr, &tgp->threads->elementData, (*group_count_ptr)*sizeof(jthreadGroup*)); return JVMTI_ERROR_NONE; } /* 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); */ 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) { stacktracebuffer* trace; jvmtiError er; 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(count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; er = getcacaostacktrace(&trace, thread); if (er==JVMTI_ERROR_NONE) return er; *count_ptr = trace->used; return JVMTI_ERROR_NONE; } /* GetThreadState ************************************************************** Get the state of a thread. *******************************************************************************/ jvmtiError GetThreadState (jvmtiEnv * env, jthread thread, jint * thread_state_ptr) { java_lang_Thread* th = (java_lang_Thread*)thread; threadobject* t = (threadobject*)th->vmThread; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if(!builtin_instanceof(thread,class_java_lang_Thread)) return JVMTI_ERROR_INVALID_THREAD; if (thread_state_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; *thread_state_ptr = 0; #if defined(USE_THREADS) && defined(NATIVE_THREADS) if((th->vmThread==NULL)&&(th->group==NULL)) { /* alive ? */ /* not alive */ if (((threadobject*)th->vmThread)->info.tid == 0) *thread_state_ptr = JVMTI_THREAD_STATE_TERMINATED; } else { /* alive */ *thread_state_ptr = JVMTI_THREAD_STATE_ALIVE; if (t->interrupted) *thread_state_ptr |= JVMTI_THREAD_STATE_INTERRUPTED; /* todo */ if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_SUSPENDED; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_IN_NATIVE; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_RUNNABLE; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER; if (false /* t->ee.waiting ? */) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT; if (false) *thread_state_ptr |= JVMTI_THREAD_STATE_PARKED; if (t->isSleeping) *thread_state_ptr |= JVMTI_THREAD_STATE_SLEEPING; } #else return JVMTI_ERROR_INTERNAL; #endif return JVMTI_ERROR_NONE; } /* GetFrameLocation ************************************************************ Get the location of the instruction currently executing *******************************************************************************/ jvmtiError GetFrameLocation (jvmtiEnv * env, jthread thread, jint depth, jmethodID * method_ptr, jlocation * location_ptr) { stackframeinfo *sfi; int i; 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 (depth < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT; if ((method_ptr == NULL)&&(location_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; sfi = ((threadobject*)thread)->info._stackframeinfo; i = 0; while ((sfi != NULL) && (iprev; i++; } if (i>depth) return JVMTI_ERROR_NO_MORE_FRAMES; *method_ptr=(jmethodID)sfi->method; *location_ptr = 0; /* todo: location MachinePC not avilable - Linenumber not expected */ return JVMTI_ERROR_NONE; } /* NotifyFramePop ************************************************************* *******************************************************************************/ jvmtiError NotifyFramePop (jvmtiEnv * env, jthread thread, jint depth) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_frame_pop_events) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetLocalObject ************************************************************* *******************************************************************************/ jvmtiError GetLocalObject (jvmtiEnv * env, jthread thread, jint depth, jint slot, jobject * value_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD-OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetLocalInt **************************************************************** *******************************************************************************/ jvmtiError GetLocalInt (jvmtiEnv * env, jthread thread, jint depth, jint slot, jint * value_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetLocalLong (jvmtiEnv * env, jthread thread, jint depth, jint slot, jlong * value_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetLocalFloat (jvmtiEnv * env, jthread thread, jint depth, jint slot, jfloat * value_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetLocalDouble (jvmtiEnv * env, jthread thread, jint depth, jint slot, jdouble * value_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetLocalObject (jvmtiEnv * env, jthread thread, jint depth, jint slot, jobject value) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetLocalInt (jvmtiEnv * env, jthread thread, jint depth, jint slot, jint value) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetLocalLong (jvmtiEnv * env, jthread thread, jint depth, jint slot, jlong value) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetLocalFloat (jvmtiEnv * env, jthread thread, jint depth, jint slot, jfloat value) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetLocalDouble (jvmtiEnv * env, jthread thread, jint depth, jint slot, jdouble value) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* CreateRawMonitor *********************************************************** This function creates a new raw monitor. *******************************************************************************/ jvmtiError CreateRawMonitor (jvmtiEnv * env, const char *name, jrawMonitorID * monitor_ptr) { struct _jrawMonitorID *monitor = (struct _jrawMonitorID*) monitor_ptr; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((name == NULL) || (monitor_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; #if defined(USE_THREADS) && defined(NATIVE_THREADS) monitor->name=javastring_new_from_ascii(name); #else log_text ("CreateRawMonitor not supported"); #endif return JVMTI_ERROR_NONE; } /* DestroyRawMonitor ********************************************************** This function destroys a raw monitor. *******************************************************************************/ jvmtiError DestroyRawMonitor (jvmtiEnv * env, jrawMonitorID monitor) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) if (!lock_does_thread_hold_lock((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name)) return JVMTI_ERROR_NOT_MONITOR_OWNER; lock_monitor_exit((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name); /* GC will clean monitor up */ #else log_text ("DestroyRawMonitor not supported"); #endif return JVMTI_ERROR_NONE; } /* RawMonitorEnter ************************************************************ Gain exclusive ownership of a raw monitor *******************************************************************************/ jvmtiError RawMonitorEnter (jvmtiEnv * env, jrawMonitorID monitor) { if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) builtin_monitorenter((java_objectheader*)monitor->name); #else log_text ("RawMonitorEnter not supported"); #endif return JVMTI_ERROR_NONE; } /* RawMonitorExit ************************************************************* Release raw monitor *******************************************************************************/ jvmtiError RawMonitorExit (jvmtiEnv * env, jrawMonitorID monitor) { if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) /* assure current thread owns this monitor */ if (!lock_does_thread_hold_lock((threadobject*)THREADOBJECT,(java_objectheader*)monitor->name)) return JVMTI_ERROR_NOT_MONITOR_OWNER; builtin_monitorexit((java_objectheader*)monitor->name); #else log_text ("RawMonitorExit not supported"); #endif return JVMTI_ERROR_NONE; } /* RawMonitorWait ************************************************************* Wait for notification of the raw monitor. *******************************************************************************/ jvmtiError RawMonitorWait (jvmtiEnv * env, jrawMonitorID monitor, jlong millis) { if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) /* assure current thread owns this monitor */ if (!lock_does_thread_hold_lock((threadobject*)THREADOBJECT,(java_objectheader*)monitor->name)) return JVMTI_ERROR_NOT_MONITOR_OWNER; lock_wait_for_object(&monitor->name->header, millis,0); if (builtin_instanceof((java_objectheader*)exceptionptr, load_class_bootstrap(utf_new_char("java/lang/InterruptedException")))) return JVMTI_ERROR_INTERRUPT; #else log_text ("RawMonitorWait not supported"); #endif return JVMTI_ERROR_NONE; } /* RawMonitorNotify *********************************************************** Notify one thread waiting on the given monitor. *******************************************************************************/ jvmtiError RawMonitorNotify (jvmtiEnv * env, jrawMonitorID monitor) { if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) /* assure current thread owns this monitor */ if (!lock_does_thread_hold_lock((threadobject*)THREADOBJECT,(java_objectheader*)monitor->name)) return JVMTI_ERROR_NOT_MONITOR_OWNER; lock_notify_object((java_objectheader*)&monitor->name); #else log_text ("RawMonitorNotify not supported"); #endif return JVMTI_ERROR_NONE; } /* RawMonitorNotifyAll ********************************************************* Notify all threads waiting on the given monitor. *******************************************************************************/ jvmtiError RawMonitorNotifyAll (jvmtiEnv * env, jrawMonitorID monitor) { if (!builtin_instanceof((java_objectheader*)monitor->name,class_java_lang_String)) return JVMTI_ERROR_INVALID_MONITOR; #if defined(USE_THREADS) && defined(NATIVE_THREADS) /* assure current thread owns this monitor */ if (!lock_does_thread_hold_lock((threadobject*)THREADOBJECT, (java_objectheader*)monitor->name)) return JVMTI_ERROR_NOT_MONITOR_OWNER; lock_notify_all_object((java_objectheader*)&monitor->name); #else log_text ("RawMonitorNotifyAll not supported"); #endif return JVMTI_ERROR_NONE; } /* SetBreakpoint ************************************************************** *******************************************************************************/ jvmtiError SetBreakpoint (jvmtiEnv * env, jmethodID method, jlocation location) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_breakpoint_events) /* addbrkpt */ log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError ClearBreakpoint (jvmtiEnv * env, jmethodID method, jlocation location) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_breakpoint_events) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* SetFieldAccessWatch ******************************************************** *******************************************************************************/ jvmtiError SetFieldAccessWatch (jvmtiEnv * env, jclass klass, jfieldID field) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_field_access_events) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError ClearFieldAccessWatch (jvmtiEnv * env, jclass klass, jfieldID field) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_field_access_events) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetFieldModificationWatch (jvmtiEnv * env, jclass klass, jfieldID field) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_field_modification_events) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError ClearFieldModificationWatch (jvmtiEnv * env, jclass klass, jfieldID field) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_generate_field_modification_events) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* Allocate ******************************************************************** Allocate an area of memory through the JVM TI allocator. The allocated memory should be freed with Deallocate *******************************************************************************/ jvmtiError Allocate (jvmtiEnv * env, jlong size, unsigned char **mem_ptr) { if (mem_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (size < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT; *mem_ptr = heap_allocate(sizeof(size),true,NULL); if (*mem_ptr == NULL) return JVMTI_ERROR_OUT_OF_MEMORY; else return JVMTI_ERROR_NONE; } /* Deallocate ****************************************************************** Deallocate mem using the JVM TI allocator. *******************************************************************************/ jvmtiError Deallocate (jvmtiEnv * env, unsigned char *mem) { /* let Boehm GC do the job */ return JVMTI_ERROR_NONE; } /* GetClassSignature ************************************************************ For the class indicated by klass, return the JNI type signature and the generic signature of the class. *******************************************************************************/ jvmtiError GetClassSignature (jvmtiEnv * env, jclass klass, char **signature_ptr, char **generic_ptr) { int nsize,psize; CHECK_PHASE_START 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; nsize=((classinfo*)klass)->name->blength; psize=((classinfo*)klass)->packagename->blength; *signature_ptr = (char*) heap_allocate(sizeof(char)* nsize+psize+4,true,NULL); *signature_ptr[0]='L'; memcpy(&(*signature_ptr[1]),((classinfo*)klass)->packagename->text, psize); *signature_ptr[psize+2]='/'; memcpy(&(*signature_ptr[psize+3]),((classinfo*)klass)->name->text, nsize); *signature_ptr[nsize+psize+3]=';'; *signature_ptr[nsize+psize+4]='\0'; *generic_ptr = NULL; return JVMTI_ERROR_NONE; } /* GetClassStatus ************************************************************* Get status of the class. *******************************************************************************/ jvmtiError GetClassStatus (jvmtiEnv * env, jclass klass, jint * status_ptr) { classinfo *c; CHECK_PHASE_START 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_CLASS; if (status_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; c = (classinfo*)klass; *status_ptr = 0; /* if (c) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_VERIFIED; ? */ if (c->state&=CLASS_LINKED) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PREPARED; if (c->state&=CLASS_INITIALIZED) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_INITIALIZED; if (c->state&=CLASS_ERROR) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_ERROR; if (c->vftbl->arraydesc != NULL) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_ARRAY; if (Java_java_lang_VMClass_isPrimitive(NULL,NULL,(struct java_lang_Class*)c)) *status_ptr = *status_ptr | JVMTI_CLASS_STATUS_PRIMITIVE; return JVMTI_ERROR_NONE; } /* GetSourceFileName ********************************************************** For the class indicated by klass, return the source file name. *******************************************************************************/ jvmtiError GetSourceFileName (jvmtiEnv * env, jclass klass, char **source_name_ptr) { int size; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_source_file_name) if ((klass == NULL)||(source_name_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; size = (((classinfo*)klass)->sourcefile->blength)+1; *source_name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL); memcpy(*source_name_ptr,((classinfo*)klass)->sourcefile->text, size); (*source_name_ptr)[size]='\0'; return JVMTI_ERROR_NONE; } /* GetClassModifiers ********************************************************** For class klass return the access flags *******************************************************************************/ jvmtiError GetClassModifiers (jvmtiEnv * env, jclass klass, jint * modifiers_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (modifiers_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof((java_objectheader*)klass,class_java_lang_Class)) return JVMTI_ERROR_INVALID_CLASS; *modifiers_ptr = (jint) ((classinfo*)klass)->flags; return JVMTI_ERROR_NONE; } /* GetClassMethods ************************************************************* For class klass return a count of methods and a list of method IDs *******************************************************************************/ jvmtiError GetClassMethods (jvmtiEnv * env, jclass klass, jint * method_count_ptr, jmethodID ** methods_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((klass == NULL)||(methods_ptr == NULL)||(method_count_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof((java_objectheader*)klass,class_java_lang_Class)) return JVMTI_ERROR_INVALID_CLASS; *method_count_ptr = (jint)((classinfo*)klass)->methodscount; *methods_ptr = (jmethodID*) heap_allocate(sizeof(jmethodID) * (*method_count_ptr),true,NULL); memcpy (*methods_ptr, ((classinfo*)klass)->methods, sizeof(jmethodID) * (*method_count_ptr)); return JVMTI_ERROR_NONE; } /* GetClassFields ************************************************************* For the class indicated by klass, return a count of fields and a list of field IDs. *******************************************************************************/ jvmtiError GetClassFields (jvmtiEnv * env, jclass klass, jint * field_count_ptr, jfieldID ** fields_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((klass == NULL)||(fields_ptr == NULL)||(field_count_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *field_count_ptr = (jint)((classinfo*)klass)->fieldscount; *fields_ptr = (jfieldID*) heap_allocate(sizeof(jfieldID) * (*field_count_ptr),true,NULL); memcpy (*fields_ptr, ((classinfo*)klass)->fields, sizeof(jfieldID) * (*field_count_ptr)); return JVMTI_ERROR_NONE; } /* GetImplementedInterfaces *************************************************** Return the direct super-interfaces of this class. *******************************************************************************/ jvmtiError GetImplementedInterfaces (jvmtiEnv * env, jclass klass, jint * interface_count_ptr, jclass ** interfaces_ptr) { int i; classref_or_classinfo *interfaces; classinfo *tmp; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((interfaces_ptr == NULL) || (interface_count_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof((java_objectheader*)klass,class_java_lang_Class)) return JVMTI_ERROR_INVALID_CLASS; *interface_count_ptr = (jint)((classinfo*)klass)->interfacescount; *interfaces_ptr = heap_allocate(sizeof(jclass*) * (*interface_count_ptr),true,NULL); interfaces = ((classinfo*)klass)->interfaces; for (i=0; i<*interface_count_ptr; i++) { if (IS_CLASSREF(interfaces[i])) tmp = load_class_bootstrap(interfaces[i].ref->name); else tmp = interfaces[i].cls; *interfaces_ptr[i]=tmp; } return JVMTI_ERROR_NONE; } /* IsInterface **************************************************************** Determines whether a class object reference represents an interface. *******************************************************************************/ jvmtiError IsInterface (jvmtiEnv * env, jclass klass, jboolean * is_interface_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((klass == NULL)||(is_interface_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *is_interface_ptr = (((classinfo*)klass)->flags & ACC_INTERFACE); return JVMTI_ERROR_NONE; } /* IsArrayClass *************************************************************** Determines whether a class object reference represents an array. *******************************************************************************/ jvmtiError IsArrayClass (jvmtiEnv * env, jclass klass, jboolean * is_array_class_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (is_array_class_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; *is_array_class_ptr = ((classinfo*)klass)->vftbl->arraydesc != NULL; return JVMTI_ERROR_NONE; } /* GetClassLoader ************************************************************* For the class indicated by klass, return via classloader_ptr a reference to the class loader for the class. *******************************************************************************/ jvmtiError GetClassLoader (jvmtiEnv * env, jclass klass, jobject * classloader_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((klass == NULL)||(classloader_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *classloader_ptr = (jobject)((classinfo*)klass)->classloader; return JVMTI_ERROR_NONE; } /* GetObjectHashCode ********************************************************** Return hash code for object object *******************************************************************************/ jvmtiError GetObjectHashCode (jvmtiEnv * env, jobject object, jint * hash_code_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (hash_code_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof(object,class_java_lang_Object)) return JVMTI_ERROR_INVALID_OBJECT; *hash_code_ptr = Java_java_lang_VMSystem_identityHashCode(NULL,NULL,(struct java_lang_Object*)object); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetObjectMonitorUsage (jvmtiEnv * env, jobject object, jvmtiMonitorUsage * info_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_monitor_info) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetFieldName *************************************************************** For the field indicated by klass and field, return the field name and signature. *******************************************************************************/ jvmtiError GetFieldName (jvmtiEnv * env, jclass klass, jfieldID field, char **name_ptr, char **signature_ptr, char **generic_ptr) { int size; CHECK_PHASE_START 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; size = (((fieldinfo*)field)->name->blength); *name_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL); memcpy(*name_ptr,((fieldinfo*)field)->name->text, size); size = (((fieldinfo*)field)->descriptor->blength); *signature_ptr = (char*) heap_allocate(sizeof(char)* size,true,NULL); memcpy(*signature_ptr,((fieldinfo*)field)->descriptor->text, size); *generic_ptr = NULL; return JVMTI_ERROR_NONE; } /* GetFieldDeclaringClass ***************************************************** For the field indicated by klass and field return the class that defined it The declaring class will either be klass, a superclass, or an implemented interface. *******************************************************************************/ jvmtiError GetFieldDeclaringClass (jvmtiEnv * env, jclass klass, jfieldID field, jclass * declaring_class_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; *declaring_class_ptr = (jclass) ((fieldinfo*)field)->class; return JVMTI_ERROR_NONE; } /* GetFieldModifiers ********************************************************** Return access flags of field field *******************************************************************************/ jvmtiError GetFieldModifiers (jvmtiEnv * env, jclass klass, jfieldID field, jint * modifiers_ptr) { CHECK_PHASE_START 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 (modifiers_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; /* todo: JVMTI_ERROR_INVALID_FIELDID; */ *modifiers_ptr = ((fieldinfo*)field)->flags; return JVMTI_ERROR_NONE; } /* IsFieldSynthetic *********************************************************** *******************************************************************************/ jvmtiError IsFieldSynthetic (jvmtiEnv * env, jclass klass, jfieldID field, jboolean * is_synthetic_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_synthetic_attribute) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetMethodName *************************************************************** For the method indicated by method, return the method name via name_ptr and method signature via signature_ptr. *******************************************************************************/ jvmtiError GetMethodName (jvmtiEnv * env, jmethodID method, char **name_ptr, char **signature_ptr, char **generic_ptr) { methodinfo* m = (methodinfo*)method; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) 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; 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); /* there is no generic signature attribute */ *generic_ptr = NULL; return JVMTI_ERROR_NONE; } /* GetMethodDeclaringClass ***************************************************** For the method indicated by method, return the class that defined it. *******************************************************************************/ jvmtiError GetMethodDeclaringClass (jvmtiEnv * env, jmethodID method, jclass * declaring_class_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL) || (declaring_class_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *declaring_class_ptr = (jclass)((methodinfo*)method)->class; return JVMTI_ERROR_NONE; } /* GetMethodModifiers ********************************************************** For the method indicated by method, return the access flags. *******************************************************************************/ jvmtiError GetMethodModifiers (jvmtiEnv * env, jmethodID method, jint * modifiers_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL) || (modifiers_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *modifiers_ptr = (jint) (((methodinfo*)method)->flags); return JVMTI_ERROR_NONE; } /* GetMaxLocals **************************************************************** For the method indicated by method, return the number of local variable slots used by the method, including the local variables used to pass parameters to the method on its invocation. *******************************************************************************/ jvmtiError GetMaxLocals (jvmtiEnv * env, jmethodID method, jint * max_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL)||(max_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (((methodinfo*)method)->flags & ACC_NATIVE) return JVMTI_ERROR_NATIVE_METHOD; *max_ptr = (jint) ((methodinfo*)method)->maxlocals; return JVMTI_ERROR_NONE; } /* GetArgumentsSize ************************************************************ Return the number of local variable slots used by the method's arguments. *******************************************************************************/ jvmtiError GetArgumentsSize (jvmtiEnv * env, jmethodID method, jint * size_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL)||(size_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (((methodinfo*)method)->flags & ACC_NATIVE) return JVMTI_ERROR_NATIVE_METHOD; /* todo *size_ptr = (jint)((methodinfo*)method)->paramcount;*/ return JVMTI_ERROR_NONE; } /* GetLineNumberTable *********************************************************** Return table of source line number entries for a given method *******************************************************************************/ jvmtiError GetLineNumberTable (jvmtiEnv * env, jmethodID method, jint * entry_count_ptr, jvmtiLineNumberEntry ** table_ptr) { int i; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_line_numbers) 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; *entry_count_ptr= (jint)((methodinfo*)method)->linenumbercount; *table_ptr = (jvmtiLineNumberEntry*) heap_allocate( sizeof(jvmtiLineNumberEntry) * (*entry_count_ptr),true,NULL); for (i=0; i < *entry_count_ptr; i++) { (*table_ptr[i]).start_location = (jlocation) ((methodinfo*)method)->linenumbers[i].start_pc; (*table_ptr[i]).line_number = (jint) ((methodinfo*)method)->linenumbers[i].line_number; } return JVMTI_ERROR_NONE; } /* GetMethodLocation *********************************************************** For the method indicated by method, return the beginning and ending addresses through start_location_ptr and end_location_ptr. In cacao this points to entry point in machine code and length of machine code *******************************************************************************/ jvmtiError GetMethodLocation (jvmtiEnv * env, jmethodID method, jlocation * start_location_ptr, jlocation * end_location_ptr) { methodinfo* m = (methodinfo*)method; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL) || (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 * than one location. -Edwin */ /* 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; *start_location_ptr = (jlocation)m->code->mcode; *end_location_ptr = (jlocation)(m->code->mcode)+m->code->mcodelength; return JVMTI_ERROR_NONE; } /* GetLocalVariableTable ******************************************************* Return local variable information. *******************************************************************************/ jvmtiError GetLocalVariableTable (jvmtiEnv * env, jmethodID method, jint * entry_count_ptr, jvmtiLocalVariableEntry ** table_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_access_local_variables) log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetBytecode ***************************************************************** For the method indicated by method, return the byte codes that implement the method. *******************************************************************************/ jvmtiError GetBytecodes (jvmtiEnv * env, jmethodID method, jint * bytecode_count_ptr, unsigned char **bytecodes_ptr) { methodinfo* m = (methodinfo*)method;; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_bytecodes) if ((method == NULL) || (bytecode_count_ptr == NULL) || (bytecodes_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *bytecode_count_ptr = m->jcodelength; *bytecodes_ptr = (unsigned char*)heap_allocate(m->jcodelength,true,NULL); memcpy(*bytecodes_ptr, m->jcode, m->jcodelength); return JVMTI_ERROR_NONE; } /* IsMethodNative ************************************************************** For the method indicated by method, return a value indicating whether the method is a native function *******************************************************************************/ jvmtiError IsMethodNative (jvmtiEnv * env, jmethodID method, jboolean * is_native_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((method == NULL)||(is_native_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; if (((methodinfo*)method)->flags & ACC_NATIVE) *is_native_ptr = JNI_TRUE; else *is_native_ptr = JNI_FALSE; return JVMTI_ERROR_NONE; } /* IsMethodSynthetic *********************************************************** return a value indicating whether the method is synthetic. Synthetic methods are generated by the compiler but not present in the original source code. *******************************************************************************/ jvmtiError IsMethodSynthetic (jvmtiEnv * env, jmethodID method, jboolean * is_synthetic_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_synthetic_attribute) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetLoadedClasses ************************************************************ Return an array of all classes loaded in the virtual machine. *******************************************************************************/ jvmtiError GetLoadedClasses (jvmtiEnv * env, jint * class_count_ptr, jclass ** classes_ptr) { int i,j; char* data; hashtable* ht; classcache_name_entry *cne; classcache_class_entry *cce; log_text ("GetLoadedClasses called %d ", phase); /* XXX todo */ *class_count_ptr = 0; 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; log_text ("GetLoadedClasses1"); /* CLASSCACHE_LOCK(); log_text ("GetLoadedClasses2"); getchildproc(&data, &hashtable_classcache, sizeof(hashtable)); ht = (hashtable*) &data; log_text ("GetLoadedClasses got ht pointer"); *classes_ptr = heap_allocate(sizeof(jclass*) * (ht->entries),true,NULL); fprintf (stderr,"hashtable_classcache.entries = %d\n",ht->entries); fflush(stderr); *class_count_ptr = ht->entries; log_text ("GetLoadedClasses %d", *class_count_ptr); j=0; look in every slot of the hashtable for (i=0; isize; i++) { cne = ht->ptr[i]; while (cne != NULL) { iterate over hashlink getchildproc(&data, cne, sizeof(classcache_name_entry)); cne =(classcache_name_entry*) &data; cce = cne->classes; while (cce != NULL){ iterate over classes with same name getchildproc(&data, cce, sizeof(classcache_class_entry)); cce =(classcache_class_entry*) &data; if (cce->classobj != NULL) { get only loaded classes assert(jentries); * classes_ptr[j]=cce->classobj; j++; } cce = cce->next; } cne = cne->hashlink; } } log_text ("GetLoadedClasses continue"); CLASSCACHE_UNLOCK(); */ log_text ("GetLoadedClasses finished"); return JVMTI_ERROR_NONE; } /* GetClassLoaderClasses ******************************************************* Returns an array of those classes for which this class loader has been recorded as an initiating loader. *******************************************************************************/ jvmtiError GetClassLoaderClasses (jvmtiEnv * env, jobject initiating_loader, jint * class_count_ptr, jclass ** classes_ptr) { log_text("GetClassLoaderClasses called"); CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; /* if (class_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (classes_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;*/ /* behave like jdk 1.1 and make no distinction between initiating and defining class loaders */ return GetLoadedClasses(env, class_count_ptr, classes_ptr); } /* PopFrame ******************************************************************* *******************************************************************************/ jvmtiError PopFrame (jvmtiEnv * env, jthread thread) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_pop_frame) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* RedefineClasses ************************************************************ *******************************************************************************/ jvmtiError RedefineClasses (jvmtiEnv * env, jint class_count, const jvmtiClassDefinition * class_definitions) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) 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; } /* GetVersionNumber *********************************************************** Return the JVM TI version identifier. *******************************************************************************/ jvmtiError GetVersionNumber (jvmtiEnv * env, jint * version_ptr) { if (version_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; *version_ptr = JVMTI_VERSION_1_0; return JVMTI_ERROR_NONE; } /* GetCapabilities ************************************************************ Returns the optional JVM TI features which this environment currently possesses. *******************************************************************************/ jvmtiError GetCapabilities (jvmtiEnv * env, jvmtiCapabilities * capabilities_ptr) { if (capabilities_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; memcpy(capabilities_ptr, &(((environment*) env)->capabilities), sizeof(JVMTI_Capabilities)); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetSourceDebugExtension (jvmtiEnv * env, jclass klass, char **source_debug_extension_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_source_debug_extension) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* IsMethodObsolete ************************************************************ Determine if a method ID refers to an obsolete method version. *******************************************************************************/ jvmtiError IsMethodObsolete (jvmtiEnv * env, jmethodID method, jboolean * is_obsolete_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_redefine_classes) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* SuspendThreadList ********************************************************** *******************************************************************************/ jvmtiError SuspendThreadList (jvmtiEnv * env, jint request_count, const jthread * request_list, jvmtiError * results) { 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!!!"); return JVMTI_ERROR_NONE; } /* ResumeThreadList *********************************************************** *******************************************************************************/ jvmtiError ResumeThreadList (jvmtiEnv * env, jint request_count, const jthread * request_list, jvmtiError * results) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_suspend); log_text ("JVMTI-Call: TBD OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetStackTrace ************************************************************** Get information about the stack of a thread *******************************************************************************/ jvmtiError GetStackTrace (jvmtiEnv * env, jthread thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo * frame_buffer, jint * count_ptr) { stacktracebuffer* trace; jvmtiError er; int i,j; 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((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 ((trace->used >= start_depth) || ((trace->used * -1) > start_depth)) return JVMTI_ERROR_ILLEGAL_ARGUMENT; for (i=start_depth, j=0;iused;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; } /* GetThreadListStackTraces *************************************************** Get information about the stacks of the supplied threads. *******************************************************************************/ jvmtiError GetThreadListStackTraces (jvmtiEnv * env, jint thread_count, const jthread * thread_list, jint max_frame_count, jvmtiStackInfo ** stack_info_ptr) { int i; jvmtiError er; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((stack_info_ptr == NULL)||(thread_list == NULL)) return JVMTI_ERROR_NULL_POINTER; if (thread_count < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT; if (max_frame_count < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT; *stack_info_ptr = (jvmtiStackInfo*) heap_allocate(sizeof(jvmtiStackInfo) * thread_count, true, NULL); for(i=0; itls; while ((tls->thread != thread) && (tls != NULL)) { tls = tls->next; } if (tls == NULL) return JVMTI_ERROR_INTERNAL; /* env/thread pair not found */ *data_ptr = tls->data; return JVMTI_ERROR_NONE; } /* SetThreadLocalStorage ******************************************************* Stores a pointer value associated with each environment-thread pair. The value is NULL unless set with this function. Agents can allocate memory in which they store thread specific information *******************************************************************************/ jvmtiError SetThreadLocalStorage (jvmtiEnv * jenv, jthread thread, const void *data) { jvmtiThreadLocalStorage *tls, *pre; environment* env = (environment*)jenv; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if(thread == NULL) thread = (jthread) THREADOBJECT; else { if (!builtin_instanceof(thread,class_java_lang_Thread)) return JVMTI_ERROR_INVALID_THREAD; CHECK_THREAD_IS_ALIVE(thread); } if (env->tls == NULL) { tls = env->tls = heap_allocate(sizeof(jvmtiThreadLocalStorage),true,NULL); } else { tls = env->tls; while ((tls->thread != thread) && (tls->next != NULL)) { tls = tls->next; } if (tls->thread != thread) { tls->next = heap_allocate(sizeof(jvmtiThreadLocalStorage),true,NULL); tls = tls->next; } } if (data != NULL) { tls->data = (void*)data; } else { /* remove current tls */ pre = env->tls; while (pre->next == tls) pre = pre->next; pre->next = tls->next; } return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetTag (jvmtiEnv * env, jobject object, jlong * tag_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError SetTag (jvmtiEnv * env, jobject object, jlong tag) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ForceGarbageCollection ***************************************************** Force boehm-gc to perform a garbage collection *******************************************************************************/ jvmtiError ForceGarbageCollection (jvmtiEnv * env) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; gc_call(); return JVMTI_ERROR_NONE; } /* IterateOverObjectsReachableFromObject ************************************** *******************************************************************************/ jvmtiError IterateOverObjectsReachableFromObject (jvmtiEnv * env, jobject object, jvmtiObjectReferenceCallback object_reference_callback, void *user_data) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* IterateOverReachableObjects ************************************************ *******************************************************************************/ jvmtiError IterateOverReachableObjects (jvmtiEnv * env, jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, void *user_data) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* IterateOverHeap ************************************************************ *******************************************************************************/ jvmtiError IterateOverHeap (jvmtiEnv * env, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, void *user_data) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* IterateOverInstancesOfClass ************************************************ *******************************************************************************/ jvmtiError IterateOverInstancesOfClass (jvmtiEnv * env, jclass klass, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, void *user_data) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetObjectsWithTags (jvmtiEnv * env, jint tag_count, const jlong * tags, jint * count_ptr, jobject ** object_result_ptr, jlong ** tag_result_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_tag_objects) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* SetJNIFunctionTable ********************************************************** Set the JNI function table in all current and future JNI environments *******************************************************************************/ jvmtiError SetJNIFunctionTable (jvmtiEnv * env, const jniNativeInterface * function_table) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END;; if (function_table == NULL) return JVMTI_ERROR_NULL_POINTER; _Jv_env->env = (void*)heap_allocate(sizeof(jniNativeInterface),true,NULL); memcpy((void*)_Jv_env->env, function_table, sizeof(jniNativeInterface)); return JVMTI_ERROR_NONE; } /* GetJNIFunctionTable ********************************************************* Get the JNI function table. The JNI function table is copied into allocated memory. *******************************************************************************/ jvmtiError GetJNIFunctionTable (jvmtiEnv * env, jniNativeInterface ** function_table) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (function_table == NULL) return JVMTI_ERROR_NULL_POINTER; *function_table = (jniNativeInterface*) heap_allocate(sizeof(jniNativeInterface),true,NULL); memcpy(*function_table, _Jv_env->env, sizeof(jniNativeInterface)); return JVMTI_ERROR_NONE; } /* SetEventCallbacks ********************************************************** Set the functions to be called for each event. The callbacks are specified by supplying a replacement function table. *******************************************************************************/ jvmtiError SetEventCallbacks (jvmtiEnv * env, const jvmtiEventCallbacks * callbacks, jint size_of_callbacks) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (size_of_callbacks < 0) return JVMTI_ERROR_ILLEGAL_ARGUMENT; if (callbacks == NULL) { /* remove the existing callbacks */ memset(&(((environment* )env)->callbacks), 0, sizeof(jvmtiEventCallbacks)); } memcpy (&(((environment* )env)->callbacks),callbacks,size_of_callbacks); return JVMTI_ERROR_NONE; } /* GenerateEvents ************************************************************* Generate events (CompiledMethodLoad and DynamicCodeGenerated) to represent the current state of the VM. *******************************************************************************/ jvmtiError GenerateEvents (jvmtiEnv * env, jvmtiEvent event_type) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; log_text ("JVMTI-Call: IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetExtensionFunctions ****************************************************** Returns the set of extension functions. *******************************************************************************/ jvmtiError GetExtensionFunctions (jvmtiEnv * env, jint * extension_count_ptr, jvmtiExtensionFunctionInfo ** extensions) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((extension_count_ptr== NULL)||(extensions == NULL)) return JVMTI_ERROR_NULL_POINTER; /* cacao has no extended functions yet */ *extension_count_ptr = 0; return JVMTI_ERROR_NONE; } /* GetExtensionEvents ********************************************************* Returns the set of extension events. *******************************************************************************/ jvmtiError GetExtensionEvents (jvmtiEnv * env, jint * extension_count_ptr, jvmtiExtensionEventInfo ** extensions) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((extension_count_ptr== NULL)||(extensions == NULL)) return JVMTI_ERROR_NULL_POINTER; /* cacao has no extended events yet */ *extension_count_ptr = 0; return JVMTI_ERROR_NONE; } /* SetExtensionEventCallback ************************************************** Sets the callback function for an extension event and enables the event. *******************************************************************************/ jvmtiError SetExtensionEventCallback (jvmtiEnv * env, jint extension_event_index, jvmtiExtensionEvent callback) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; /* cacao has no extended events yet */ return JVMTI_ERROR_ILLEGAL_ARGUMENT; } /* DisposeEnvironment ********************************************************** Shutdown a JVM TI connection created with JNI GetEnv. *******************************************************************************/ jvmtiError DisposeEnvironment (jvmtiEnv * env) { environment* cacao_env = (environment*)env; environment* tenvs = envs; jvmtiThreadLocalStorage *jtls, *tjtls; if (tenvs != cacao_env) { while (tenvs->next != cacao_env) { tenvs = tenvs->next; } tenvs->next = cacao_env->next; } else envs = NULL; 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; } /* GetErrorName *************************************************************** Return the symbolic name for an error code. *******************************************************************************/ #define COPY_RESPONSE(name_ptr,str) *name_ptr = (char*) heap_allocate(sizeof(str),true,NULL); \ memcpy(*name_ptr, &str, sizeof(str)); \ break jvmtiError GetErrorName (jvmtiEnv * env, jvmtiError error, char **name_ptr) { if (name_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; switch (error) { case JVMTI_ERROR_NONE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NONE"); case JVMTI_ERROR_NULL_POINTER : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NULL_POINTER"); case JVMTI_ERROR_OUT_OF_MEMORY : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_OUT_OF_MEMORY"); case JVMTI_ERROR_ACCESS_DENIED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_ACCESS_DENIED"); case JVMTI_ERROR_UNATTACHED_THREAD : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNATTACHED_THREAD"); case JVMTI_ERROR_INVALID_ENVIRONMENT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_ENVIRONMENT"); case JVMTI_ERROR_WRONG_PHASE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_WRONG_PHASE"); case JVMTI_ERROR_INTERNAL : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INTERNAL"); case JVMTI_ERROR_INVALID_PRIORITY : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_PRIORITY"); case JVMTI_ERROR_THREAD_NOT_SUSPENDED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_THREAD_NOT_SUSPENDED"); case JVMTI_ERROR_THREAD_SUSPENDED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_THREAD_SUSPENDED"); case JVMTI_ERROR_THREAD_NOT_ALIVE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_THREAD_NOT_ALIVE"); case JVMTI_ERROR_CLASS_NOT_PREPARED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_CLASS_NOT_PREPARED"); case JVMTI_ERROR_NO_MORE_FRAMES : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NO_MORE_FRAMES"); case JVMTI_ERROR_OPAQUE_FRAME : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_OPAQUE_FRAME"); case JVMTI_ERROR_DUPLICATE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_DUPLICATE"); case JVMTI_ERROR_NOT_FOUND : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NOT_FOUND"); case JVMTI_ERROR_NOT_MONITOR_OWNER : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NOT_MONITOR_OWNER"); case JVMTI_ERROR_INTERRUPT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INTERRUPT"); case JVMTI_ERROR_UNMODIFIABLE_CLASS : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNMODIFIABLE_CLASS"); case JVMTI_ERROR_NOT_AVAILABLE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NOT_AVAILABLE"); case JVMTI_ERROR_ABSENT_INFORMATION : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_ABSENT_INFORMATION"); case JVMTI_ERROR_INVALID_EVENT_TYPE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_EVENT_TYPE"); case JVMTI_ERROR_NATIVE_METHOD : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NATIVE_METHOD"); case JVMTI_ERROR_INVALID_THREAD : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_THREAD"); case JVMTI_ERROR_INVALID_FIELDID : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_FIELDID"); case JVMTI_ERROR_INVALID_METHODID : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_METHODID"); case JVMTI_ERROR_INVALID_LOCATION : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_LOCATION"); case JVMTI_ERROR_INVALID_OBJECT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_OBJECT"); case JVMTI_ERROR_INVALID_CLASS : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_CLASS"); case JVMTI_ERROR_TYPE_MISMATCH : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_TYPE_MISMATCH"); case JVMTI_ERROR_INVALID_SLOT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_SLOT"); case JVMTI_ERROR_MUST_POSSESS_CAPABILITY : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_MUST_POSSESS_CAPABILITY"); case JVMTI_ERROR_INVALID_THREAD_GROUP : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_THREAD_GROUP"); case JVMTI_ERROR_INVALID_MONITOR : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_MONITOR"); case JVMTI_ERROR_ILLEGAL_ARGUMENT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_ILLEGAL_ARGUMENT"); case JVMTI_ERROR_INVALID_TYPESTATE : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_TYPESTATE"); case JVMTI_ERROR_UNSUPPORTED_VERSION : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_VERSION"); case JVMTI_ERROR_INVALID_CLASS_FORMAT : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_INVALID_CLASS_FORMAT"); case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED"); case JVMTI_ERROR_FAILS_VERIFICATION : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_FAILS_VERIFICATION"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED"); case JVMTI_ERROR_NAMES_DONT_MATCH : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_NAMES_DONT_MATCH"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED"); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED : COPY_RESPONSE (name_ptr, "JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED"); default: return JVMTI_ERROR_ILLEGAL_ARGUMENT; } return JVMTI_ERROR_NONE; } /* GetJLocationFormat ********************************************************** This function describes the representation of jlocation used in this VM. *******************************************************************************/ jvmtiError GetJLocationFormat (jvmtiEnv * env, jvmtiJlocationFormat * format_ptr) { *format_ptr = JVMTI_JLOCATION_MACHINEPC; return JVMTI_ERROR_NONE; } /* GetSystemProperties ******************************************************** The list of VM system property keys which may be used with GetSystemProperty is returned. *******************************************************************************/ jvmtiError GetSystemProperties (jvmtiEnv * env, jint * count_ptr, char ***property_ptr) { jmethodID mid, moremid; classinfo *sysclass, *propclass, *enumclass; java_objectheader *sysprop, *keys, *obj; char* ch; int i; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((count_ptr == NULL) || (property_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; sysclass = load_class_from_sysloader( utf_new_char_classname ("java/lang/System")); if (!sysclass) throw_main_exception_exit(); mid = (jmethodID)class_resolvemethod(sysclass, utf_new_char("getProperties"), utf_new_char("()Ljava/util/Properties;")); if (!mid) throw_main_exception_exit(); sysprop = _Jv_JNINativeInterface.CallStaticObjectMethod(NULL, sysclass, mid); if (!sysprop) throw_main_exception_exit(); propclass = sysprop->vftbl->class; mid = (jmethodID)class_resolvemethod(propclass, utf_new_char("size"), utf_new_char("()I")); if (!mid) throw_main_exception_exit(); *count_ptr = _Jv_JNINativeInterface.CallIntMethod(NULL, sysprop, mid); *property_ptr = heap_allocate(sizeof(char*) * (*count_ptr) ,true,NULL); mid = (jmethodID)class_resolvemethod(propclass, utf_new_char("keys"), utf_new_char("()Ljava/util/Enumeration;")); if (!mid) throw_main_exception_exit(); keys = _Jv_JNINativeInterface.CallObjectMethod(NULL, sysprop, mid); enumclass = keys->vftbl->class; moremid = (jmethodID)class_resolvemethod(enumclass, utf_new_char("hasMoreElements"), utf_new_char("()Z")); if (!moremid) throw_main_exception_exit(); mid = (jmethodID)class_resolvemethod(propclass, utf_new_char("nextElement"), utf_new_char("()Ljava/lang/Object;")); if (!mid) throw_main_exception_exit(); i = 0; while (_Jv_JNINativeInterface.CallBooleanMethod(NULL,keys,(jmethodID)moremid)) { obj = _Jv_JNINativeInterface.CallObjectMethod(NULL, keys, mid); ch = javastring_tochar(obj); *property_ptr[i] = heap_allocate(sizeof(char*) * strlen (ch),true,NULL); memcpy(*property_ptr[i], ch, strlen (ch)); MFREE(ch,char,strlen(ch)+1); i++; } return JVMTI_ERROR_NONE; } /* GetSystemProperty ********************************************************** Return a VM system property value given the property key. *******************************************************************************/ jvmtiError GetSystemProperty (jvmtiEnv * env, const char *property, char **value_ptr) { jmethodID mid; classinfo *sysclass, *propclass; java_objectheader *sysprop, *obj; char* ch; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((value_ptr == NULL) || (property == NULL)) return JVMTI_ERROR_NULL_POINTER; sysclass = load_class_from_sysloader(utf_new_char("java/lang/System")); if (!sysclass) throw_main_exception_exit(); mid = (jmethodID)class_resolvemethod(sysclass, utf_new_char("getProperties"), utf_new_char("()Ljava/util/Properties;")); if (!mid) throw_main_exception_exit(); sysprop = _Jv_JNINativeInterface.CallStaticObjectMethod(NULL, (jclass)sysclass, mid); propclass = sysprop->vftbl->class; mid = (jmethodID)class_resolvemethod(propclass, utf_new_char("getProperty"), utf_new_char("(Ljava/lang/String;)Ljava/lang/String;")); if (!mid) throw_main_exception_exit(); obj = (java_objectheader*)_Jv_JNINativeInterface.CallObjectMethod( NULL, sysprop, mid, javastring_new_from_ascii(property)); if (!obj) return JVMTI_ERROR_NOT_AVAILABLE; ch = javastring_tochar(obj); *value_ptr = heap_allocate(sizeof(char*) * strlen (ch),true,NULL); memcpy(*value_ptr, ch, strlen (ch)); MFREE(ch,char,strlen(ch)+1); return JVMTI_ERROR_NONE; } /* SetSystemProperty ********************************************************** Set a VM system property value. *******************************************************************************/ jvmtiError SetSystemProperty (jvmtiEnv * env, const char *property, const char *value) { jmethodID mid; classinfo *sysclass, *propclass; java_objectheader *sysprop; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE_END; if (property == NULL) return JVMTI_ERROR_NULL_POINTER; if (value == NULL) return JVMTI_ERROR_NOT_AVAILABLE; sysclass = load_class_from_sysloader(utf_new_char("java/lang/System")); if (!sysclass) throw_main_exception_exit(); mid = (jmethodID)class_resolvemethod(sysclass, utf_new_char("getProperties"), utf_new_char("()Ljava/util/Properties;")); if (!mid) throw_main_exception_exit(); sysprop = _Jv_JNINativeInterface.CallStaticObjectMethod(NULL, (jclass)sysclass, mid); propclass = sysprop->vftbl->class; mid = (jmethodID)class_resolvemethod(propclass, utf_new_char("setProperty"), utf_new_char("(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;")); if (!mid) throw_main_exception_exit(); _Jv_JNINativeInterface.CallObjectMethod( NULL, sysprop, mid, javastring_new_from_ascii(property),javastring_new_from_ascii(value)); return JVMTI_ERROR_NONE; } /* GetPhase ******************************************************************** Return the current phase of VM execution *******************************************************************************/ jvmtiError GetPhase (jvmtiEnv * env, jvmtiPhase * phase_ptr) { if (phase_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; *phase_ptr = phase; return JVMTI_ERROR_NONE; } /* GetCurrentThreadCpuTimerInfo ************************************************ *******************************************************************************/ jvmtiError GetCurrentThreadCpuTimerInfo (jvmtiEnv * env, jvmtiTimerInfo * info_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_current_thread_cpu_time) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetCurrentThreadCpuTime **************************************************** *******************************************************************************/ jvmtiError GetCurrentThreadCpuTime (jvmtiEnv * env, jlong * nanos_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_current_thread_cpu_time) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetThreadCpuTimerInfo ****************************************************** *******************************************************************************/ jvmtiError GetThreadCpuTimerInfo (jvmtiEnv * env, jvmtiTimerInfo * info_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_thread_cpu_time) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetThreadCpuTime *********************************************************** *******************************************************************************/ jvmtiError GetThreadCpuTime (jvmtiEnv * env, jthread thread, jlong * nanos_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; CHECK_CAPABILITY(env,can_get_thread_cpu_time) log_text ("JVMTI-Call: OPTIONAL IMPLEMENT ME!!!"); return JVMTI_ERROR_NONE; } /* GetTimerInfo *************************************************************** Get information about the GetTime timer. *******************************************************************************/ jvmtiError GetTimerInfo (jvmtiEnv * env, jvmtiTimerInfo * info_ptr) { if (info_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; info_ptr->max_value = !0x0; info_ptr->may_skip_forward = true; info_ptr->may_skip_backward = true; info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; return JVMTI_ERROR_NONE; } /* GetTime ******************************************************************** Return the current value of the system timer, in nanoseconds *******************************************************************************/ jvmtiError GetTime (jvmtiEnv * env, jlong * nanos_ptr) { /* Note: this implementation copied directly from Japhar's, by Chris Toshok. */ struct timeval tp; if (nanos_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (gettimeofday (&tp, NULL) == -1) _Jv_JNINativeInterface.FatalError (NULL, "gettimeofday call failed."); *nanos_ptr = (jlong) tp.tv_sec; *nanos_ptr *= 1000; *nanos_ptr += (tp.tv_usec / 1000); return JVMTI_ERROR_NONE; } /* GetPotentialCapabilities *************************************************** Returns the JVM TI features that can potentially be possessed by this environment at this time. *******************************************************************************/ jvmtiError GetPotentialCapabilities (jvmtiEnv * env, jvmtiCapabilities * capabilities_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (capabilities_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; memcpy(capabilities_ptr, &JVMTI_Capabilities, sizeof(JVMTI_Capabilities)); return JVMTI_ERROR_NONE; } #define CHECK_ADD_CAPABILITY(env,CAN) \ if ((capabilities_ptr->CAN == 1) && \ (JVMTI_Capabilities.CAN == 0)) \ return JVMTI_ERROR_NOT_AVAILABLE; \ env->capabilities.CAN = 1; /* AddCapabilities ************************************************************ Set new capabilities by adding the capabilities pointed to by capabilities_ptr. All previous capabilities are retained. *******************************************************************************/ jvmtiError AddCapabilities (jvmtiEnv * env, const jvmtiCapabilities * capabilities_ptr) { environment* cacao_env; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((env == NULL) || (capabilities_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; cacao_env = (environment*)env; CHECK_ADD_CAPABILITY(cacao_env,can_tag_objects) CHECK_ADD_CAPABILITY(cacao_env,can_generate_field_modification_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_field_access_events) CHECK_ADD_CAPABILITY(cacao_env,can_get_bytecodes) CHECK_ADD_CAPABILITY(cacao_env,can_get_synthetic_attribute) CHECK_ADD_CAPABILITY(cacao_env,can_get_owned_monitor_info) CHECK_ADD_CAPABILITY(cacao_env,can_get_current_contended_monitor) CHECK_ADD_CAPABILITY(cacao_env,can_get_monitor_info) CHECK_ADD_CAPABILITY(cacao_env,can_pop_frame) CHECK_ADD_CAPABILITY(cacao_env,can_redefine_classes) CHECK_ADD_CAPABILITY(cacao_env,can_signal_thread) CHECK_ADD_CAPABILITY(cacao_env,can_get_source_file_name) CHECK_ADD_CAPABILITY(cacao_env,can_get_line_numbers) CHECK_ADD_CAPABILITY(cacao_env,can_get_source_debug_extension) CHECK_ADD_CAPABILITY(cacao_env,can_access_local_variables) CHECK_ADD_CAPABILITY(cacao_env,can_maintain_original_method_order) CHECK_ADD_CAPABILITY(cacao_env,can_generate_single_step_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_exception_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_frame_pop_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_breakpoint_events) CHECK_ADD_CAPABILITY(cacao_env,can_suspend) CHECK_ADD_CAPABILITY(cacao_env,can_redefine_any_class) CHECK_ADD_CAPABILITY(cacao_env,can_get_current_thread_cpu_time) CHECK_ADD_CAPABILITY(cacao_env,can_get_thread_cpu_time) CHECK_ADD_CAPABILITY(cacao_env,can_generate_method_entry_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_method_exit_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_all_class_hook_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_compiled_method_load_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_monitor_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_vm_object_alloc_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_native_method_bind_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_garbage_collection_events) CHECK_ADD_CAPABILITY(cacao_env,can_generate_object_free_events) return JVMTI_ERROR_NONE; } #define CHECK_DEL_CAPABILITY(env,CAN) \ if (capabilities_ptr->CAN == 1) \ env->capabilities.CAN = 0; /* RelinquishCapabilities ***************************************************** Relinquish the capabilities pointed to by capabilities_ptr. *******************************************************************************/ jvmtiError RelinquishCapabilities (jvmtiEnv * env, const jvmtiCapabilities * capabilities_ptr) { environment* cacao_env; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if ((env == NULL) || (capabilities_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; cacao_env = (environment*)env; CHECK_DEL_CAPABILITY(cacao_env,can_tag_objects) CHECK_DEL_CAPABILITY(cacao_env,can_generate_field_modification_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_field_access_events) CHECK_DEL_CAPABILITY(cacao_env,can_get_bytecodes) CHECK_DEL_CAPABILITY(cacao_env,can_get_synthetic_attribute) CHECK_DEL_CAPABILITY(cacao_env,can_get_owned_monitor_info) CHECK_DEL_CAPABILITY(cacao_env,can_get_current_contended_monitor) CHECK_DEL_CAPABILITY(cacao_env,can_get_monitor_info) CHECK_DEL_CAPABILITY(cacao_env,can_pop_frame) CHECK_DEL_CAPABILITY(cacao_env,can_redefine_classes) CHECK_DEL_CAPABILITY(cacao_env,can_signal_thread) CHECK_DEL_CAPABILITY(cacao_env,can_get_source_file_name) CHECK_DEL_CAPABILITY(cacao_env,can_get_line_numbers) CHECK_DEL_CAPABILITY(cacao_env,can_get_source_debug_extension) CHECK_DEL_CAPABILITY(cacao_env,can_access_local_variables) CHECK_DEL_CAPABILITY(cacao_env,can_maintain_original_method_order) CHECK_DEL_CAPABILITY(cacao_env,can_generate_single_step_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_exception_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_frame_pop_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_breakpoint_events) CHECK_DEL_CAPABILITY(cacao_env,can_suspend) CHECK_DEL_CAPABILITY(cacao_env,can_redefine_any_class) CHECK_DEL_CAPABILITY(cacao_env,can_get_current_thread_cpu_time) CHECK_DEL_CAPABILITY(cacao_env,can_get_thread_cpu_time) CHECK_DEL_CAPABILITY(cacao_env,can_generate_method_entry_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_method_exit_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_all_class_hook_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_compiled_method_load_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_monitor_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_vm_object_alloc_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_native_method_bind_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_garbage_collection_events) CHECK_DEL_CAPABILITY(cacao_env,can_generate_object_free_events) return JVMTI_ERROR_NONE; } /* ***************************************************************************** *******************************************************************************/ jvmtiError GetAvailableProcessors (jvmtiEnv * env, jint * processor_count_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (processor_count_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; log_text ("GetAvailableProcessors IMPLEMENT ME!!!"); *processor_count_ptr = 1; /* where do I get this ?*/ return JVMTI_ERROR_NONE; } /* GetEnvironmentLocalStorage ************************************************** Called by the agent to get the value of the JVM TI environment-local storage. *******************************************************************************/ jvmtiError GetEnvironmentLocalStorage (jvmtiEnv * env, void **data_ptr) { if ((env == NULL) || (data_ptr == NULL)) return JVMTI_ERROR_NULL_POINTER; *data_ptr = ((environment*)env)->EnvironmentLocalStorage; return JVMTI_ERROR_NONE; } /* SetEnvironmentLocalStorage ************************************************** The VM stores a pointer value associated with each environment. Agents can allocate memory in which they store environment specific information. *******************************************************************************/ jvmtiError SetEnvironmentLocalStorage (jvmtiEnv * env, const void *data) { if (env == NULL) return JVMTI_ERROR_NULL_POINTER; ((environment*)env)->EnvironmentLocalStorage = (void*) data; return JVMTI_ERROR_NONE; } /* AddToBootstrapClassLoaderSearch ******************************************** After the bootstrap class loader unsuccessfully searches for a class, the specified platform-dependent search path segment will be searched as well. *******************************************************************************/ jvmtiError AddToBootstrapClassLoaderSearch (jvmtiEnv * env, const char *segment) { char* tmp_bcp; int ln; CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_ONLOAD) CHECK_PHASE_END; if (segment == NULL) return JVMTI_ERROR_NULL_POINTER; ln = strlen(bootclasspath) + strlen(":") + strlen(segment); tmp_bcp = MNEW(char, ln); strcat(tmp_bcp, bootclasspath); strcat(tmp_bcp, ":"); strcat(tmp_bcp, segment); MFREE(bootclasspath,char,ln); bootclasspath = tmp_bcp; return JVMTI_ERROR_NONE; } /* SetVerboseFlag ************************************************************* Control verbose output. This is the output which typically is sent to stderr *******************************************************************************/ jvmtiError SetVerboseFlag (jvmtiEnv * env, jvmtiVerboseFlag flag, jboolean value) { switch (flag) { case JVMTI_VERBOSE_OTHER: /* where is this defined ? runverbose = value; */ break; case JVMTI_VERBOSE_GC: opt_verbosegc = value; break; case JVMTI_VERBOSE_CLASS: loadverbose = value; break; case JVMTI_VERBOSE_JNI: break; default: return JVMTI_ERROR_ILLEGAL_ARGUMENT; } return JVMTI_ERROR_NONE; } /* GetObjectSize ************************************************************** For the object object return the size. *******************************************************************************/ jvmtiError GetObjectSize (jvmtiEnv * env, jobject object, jlong * size_ptr) { CHECK_PHASE_START CHECK_PHASE(JVMTI_PHASE_START) CHECK_PHASE(JVMTI_PHASE_LIVE) CHECK_PHASE_END; if (size_ptr == NULL) return JVMTI_ERROR_NULL_POINTER; if (!builtin_instanceof(object,class_java_lang_Object)) return JVMTI_ERROR_INVALID_OBJECT; *size_ptr = ((java_objectheader*)object)->vftbl->class->instancesize; return JVMTI_ERROR_NONE; } /* ***************************************************************************** Environment variables *******************************************************************************/ static jvmtiCapabilities JVMTI_Capabilities = { 0, /* can_tag_objects */ 0, /* can_generate_field_modification_events */ 0, /* can_generate_field_access_events */ 1, /* can_get_bytecodes */ 0, /* can_get_synthetic_attribute */ #if defined(USE_THREADS) && defined(NATIVE_THREADS) 1, /* can_get_owned_monitor_info */ 1, /* can_get_current_contended_monitor */ #else 0, /* can_get_owned_monitor_info */ 0, /* can_get_current_contended_monitor */ #endif 0, /* can_get_monitor_info */ 0, /* can_pop_frame */ 0, /* can_redefine_classes */ 0, /* can_signal_thread */ 1, /* can_get_source_file_name */ 1, /* can_get_line_numbers */ 0, /* can_get_source_debug_extension */ 0, /* can_access_local_variables */ 0, /* can_maintain_original_method_order */ 0, /* can_generate_single_step_events */ 0, /* can_generate_exception_events */ 0, /* can_generate_frame_pop_events */ 0, /* can_generate_breakpoint_events */ 0, /* 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 */ 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 */ 0, /* can_generate_vm_object_alloc_events */ 0, /* can_generate_native_method_bind_events */ 0, /* can_generate_garbage_collection_events */ 0, /* can_generate_object_free_events */ }; static struct jvmtiEnv_struct JVMTI_EnvTable = { NULL, &SetEventNotificationMode, NULL, &GetAllThreads, &SuspendThread, &ResumeThread, &StopThread, &InterruptThread, &GetThreadInfo, &GetOwnedMonitorInfo, &GetCurrentContendedMonitor, &RunAgentThread, &GetTopThreadGroups, &GetThreadGroupInfo, &GetThreadGroupChildren, &GetFrameCount, &GetThreadState, NULL, &GetFrameLocation, &NotifyFramePop, &GetLocalObject, &GetLocalInt, &GetLocalLong, &GetLocalFloat, &GetLocalDouble, &SetLocalObject, &SetLocalInt, &SetLocalLong, &SetLocalFloat, &SetLocalDouble, &CreateRawMonitor, &DestroyRawMonitor, &RawMonitorEnter, &RawMonitorExit, &RawMonitorWait, &RawMonitorNotify, &RawMonitorNotifyAll, &SetBreakpoint, &ClearBreakpoint, NULL, &SetFieldAccessWatch, &ClearFieldAccessWatch, &SetFieldModificationWatch, &ClearFieldModificationWatch, NULL, &Allocate, &Deallocate, &GetClassSignature, &GetClassStatus, &GetSourceFileName, &GetClassModifiers, &GetClassMethods, &GetClassFields, &GetImplementedInterfaces, &IsInterface, &IsArrayClass, &GetClassLoader, &GetObjectHashCode, &GetObjectMonitorUsage, &GetFieldName, &GetFieldDeclaringClass, &GetFieldModifiers, &IsFieldSynthetic, &GetMethodName, &GetMethodDeclaringClass, &GetMethodModifiers, NULL, &GetMaxLocals, &GetArgumentsSize, &GetLineNumberTable, &GetMethodLocation, &GetLocalVariableTable, NULL, NULL, &GetBytecodes, &IsMethodNative, &IsMethodSynthetic, &GetLoadedClasses, &GetClassLoaderClasses, &PopFrame, NULL, NULL, NULL, NULL, NULL, NULL, &RedefineClasses, &GetVersionNumber, &GetCapabilities, &GetSourceDebugExtension, &IsMethodObsolete, &SuspendThreadList, &ResumeThreadList, NULL, NULL, NULL, NULL, NULL, NULL, &GetAllStackTraces, &GetThreadListStackTraces, &GetThreadLocalStorage, &SetThreadLocalStorage, &GetStackTrace, NULL, &GetTag, &SetTag, &ForceGarbageCollection, &IterateOverObjectsReachableFromObject, &IterateOverReachableObjects, &IterateOverHeap, &IterateOverInstancesOfClass, NULL, &GetObjectsWithTags, NULL, NULL, NULL, NULL, NULL, &SetJNIFunctionTable, &GetJNIFunctionTable, &SetEventCallbacks, &GenerateEvents, &GetExtensionFunctions, &GetExtensionEvents, &SetExtensionEventCallback, &DisposeEnvironment, &GetErrorName, &GetJLocationFormat, &GetSystemProperties, &GetSystemProperty, &SetSystemProperty, &GetPhase, &GetCurrentThreadCpuTimerInfo, &GetCurrentThreadCpuTime, &GetThreadCpuTimerInfo, &GetThreadCpuTime, &GetTimerInfo, &GetTime, &GetPotentialCapabilities, NULL, &AddCapabilities, &RelinquishCapabilities, &GetAvailableProcessors, NULL, NULL, &GetEnvironmentLocalStorage, &SetEnvironmentLocalStorage, &AddToBootstrapClassLoaderSearch, &SetVerboseFlag, NULL, NULL, NULL, &GetObjectSize }; void set_jvmti_phase(jvmtiPhase p) { genericEventData d; fprintf (stderr,"set JVMTI phase %d\n",p); fflush(stderr); switch (p) { case JVMTI_PHASE_ONLOAD: phase = p; return; case JVMTI_PHASE_PRIMORDIAL: phase = p; return; case JVMTI_PHASE_START: phase = p; d.ev = JVMTI_EVENT_VM_START; /* this event is sent during start or live phase */ log_text("set sysbrk in setthreadobj"); setsysbrkpt(SETTHREADOBJECTBRK,(void*)&setthreadobject); break; case JVMTI_PHASE_LIVE: phase = p; d.ev = JVMTI_EVENT_VM_INIT; break; case JVMTI_PHASE_DEAD: phase = p; d.ev = JVMTI_EVENT_VM_DEATH; break; default: log_text("wrong jvmti phase to be set"); exit(1); } fireEvent(&d); } 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; 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), 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, 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]; 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 */ 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 */ 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"); retval = ((JNIEXPORT jint JNICALL (*) (JavaVM *vm, char *options, void *reserved)) onload) ((JavaVM *) _Jv_jvm, arg, NULL); if (retval != 0) exit (retval); } void agentunload() { if (unload != NULL) { ((JNIEXPORT void JNICALL (*) (JavaVM *vm)) unload) ((JavaVM*) &_Jv_JNIInvokeInterface); } } /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: * vim:noexpandtab:sw=4:ts=4: */