vm/vmcore/include/jvmti_internal.h (320 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Gregory Shimansky */ #ifndef _JVMTI_INTERNAL_H_ #define _JVMTI_INTERNAL_H_ #include "jvmti_utils.h" #include "vm_threads.h" #include "jit_export_jpda.h" #include <apr_dso.h> #include <apr_strings.h> #include "cxxlog.h" #include "lock_manager.h" #include "jvmti_dasm.h" //using namespace du_ti; typedef jint (JNICALL *f_Agent_OnLoad) (JavaVM *vm, char *options, void *reserved); typedef void (JNICALL *f_Agent_OnUnLoad) (JavaVM *vm); struct Agent { const char* agentName; jint agent_id; jboolean dynamic_agent; apr_dso_handle_t* agentLib; apr_pool_t* pool; f_Agent_OnLoad Agent_OnLoad_func; f_Agent_OnUnLoad Agent_OnUnLoad_func; Agent* next; Agent(const char *name): agentLib(NULL), Agent_OnLoad_func(NULL), Agent_OnUnLoad_func(NULL), next(NULL){ apr_pool_create(&pool, 0); agentName = apr_pstrdup(pool, name); } ~Agent() { apr_pool_destroy(pool); } }; struct TIEnvList { TIEnv *env; TIEnvList *next; }; struct jvmti_frame_pop_listener { jint depth; TIEnv *env; jvmti_frame_pop_listener *next; }; struct jvmti_StepLocation { struct Method* method; NativeCodePtr native_location; unsigned location; bool no_event; }; struct JVMTISingleStepState { VMBreakInterface* predicted_breakpoints; }; /* * Type which will describe one watched field */ class Watch { public: TIEnvList *envs; jfieldID field; Watch *next; Watch() : envs(NULL), field(0), next(NULL) {} void add_env(TIEnvList *el) { // FIXME: linked list modification without synchronization el->next = envs; envs = el; } TIEnvList *find_env(TIEnv *env) { for(TIEnvList *el = envs; NULL != el; el = el->next) if (el->env == env) return el; return NULL; } void remove_env(TIEnvList *el) { assert(envs); // FIXME: linked list modification without synchronization if (envs == el) { envs = envs->next; _deallocate((unsigned char *)el); return; } for (TIEnvList *p_el = envs->next; NULL != p_el->next; p_el = p_el->next) if (p_el->next == el) { p_el->next = el->next; _deallocate((unsigned char *)el); return; } DIE(("Can't find the element")); } }; typedef struct Class Class; class VMBreakPoints; struct VMBreakPoint; /* * JVMTI state of the VM */ class DebugUtilsTI { public: jint agent_counter; Lock_Manager TIenvs_lock; VMBreakPoints* vm_brpt; hythread_tls_key_t TL_ti_report; //thread local TI flag // TI event thread data vm_thread_t event_thread; hycond_t event_cond; int event_cond_initialized; DebugUtilsTI(); ~DebugUtilsTI(); jint Init(JavaVM *vm); void Shutdown(JavaVM *vm); void setExecutionMode(Global_Env *p_env); int getVersion(char* version); void addAgent(const char*); // add agent name (string) Agent *getAgents(); void setAgents(Agent *agent); bool isEnabled(); void addEventSubscriber(jvmtiEvent event_type); void removeEventSubscriber(jvmtiEvent event_type); bool hasSubscribersForEvent(jvmtiEvent event_type); bool shouldReportEvent(jvmtiEvent event_type); void setEnabled(); void setDisabled(); bool needCreateEventThread(); void enableEventThreadCreation(); void disableEventThreadCreation(); bool shouldReportLocally(); void doNotReportLocally(); void reportLocally(); jvmtiPhase getPhase() { return phase; } void nextPhase(jvmtiPhase phase) { this->phase = phase; } void addEnvironment(TIEnv *env) { // assert(TIenvs_lock._lock_or_null()); env->next = p_TIenvs; p_TIenvs = env; } void removeEnvironment(TIEnv *env) { TIEnv *e = p_TIenvs; if (NULL == e) return; // assert(TIenvs_lock._lock_or_null()); if (e == env) { p_TIenvs = env->next; return; } while (NULL != e->next) { if (e->next == env) { e->next = env->next; return; } e = e->next; } } TIEnv *getEnvironments(void) { // assert(TIenvs_lock._lock_or_null()); return p_TIenvs; } void enumerate(); // Watched fields' support Watch** get_access_watch_list() { return &access_watch_list; } Watch** get_modification_watch_list() { return &modification_watch_list; } Watch *find_watch(Watch** p_watch_list, jfieldID f) { for (Watch *w = *p_watch_list; NULL != w; w = w->next) if (w->field == f) return w; return NULL; } void add_watch(Watch** p_watch_list, Watch *w) { // FIXME: linked list modification without synchronization w->next = *p_watch_list; *p_watch_list = w; } void remove_watch(Watch** p_watch_list, Watch *w) { assert(*p_watch_list); if (w == *p_watch_list) { *p_watch_list = w->next; _deallocate((unsigned char *)w); return; } // FIXME: linked list modification without synchronization for (Watch *p_w = *p_watch_list; NULL != p_w->next; p_w = p_w->next) if (p_w->next == w) { p_w->next = w->next; _deallocate((unsigned char *)w); return; } DIE(("Can't find the watch")); } void SetPendingNotifyLoadClass( Class *klass ); void SetPendingNotifyPrepareClass( Class *klass ); unsigned GetNumberPendingNotifyLoadClass(); unsigned GetNumberPendingNotifyPrepareClass(); Class * GetPendingNotifyLoadClass( unsigned number ); Class * GetPendingNotifyPrepareClass( unsigned number ); void ReleaseNotifyLists(); enum GlobalCapabilities { TI_GC_ENABLE_METHOD_ENTRY = 0x01, TI_GC_ENABLE_METHOD_EXIT = 0x02, TI_GC_ENABLE_FRAME_POP_NOTIFICATION = 0x04, TI_GC_ENABLE_SINGLE_STEP = 0x08, TI_GC_ENABLE_EXCEPTION_EVENT = 0x10, TI_GC_ENABLE_FIELD_ACCESS_EVENT = 0x20, TI_GC_ENABLE_FIELD_MODIFICATION_EVENT = 0x40, TI_GC_ENABLE_POP_FRAME = 0x80, TI_GC_ENABLE_TAG_OBJECTS = 0x100, TI_GC_ENABLE_MONITOR_EVENTS = 0x200, }; void set_global_capability(GlobalCapabilities ti_gc) { global_capabilities |= ti_gc; } void reset_global_capability(GlobalCapabilities ti_gc) { global_capabilities &= ~ti_gc; } unsigned get_global_capability(GlobalCapabilities ti_gc) { return global_capabilities & ti_gc; } bool is_single_step_enabled(void) { return single_step_enabled && (phase == JVMTI_PHASE_LIVE); } // Single step functions jvmtiError jvmti_single_step_start(void); jvmtiError jvmti_single_step_stop(void); bool is_cml_report_inlined() { return cml_report_inlined; } void set_cml_report_inlined(bool value) { cml_report_inlined = value; } char *get_method_entry_flag_address() { return &method_entry_enabled_flag; } char *get_method_exit_flag_address() { return &method_exit_enabled_flag; } char get_method_entry_flag() { return method_entry_enabled_flag; } char get_method_exit_flag() { return method_exit_enabled_flag; } void set_method_entry_flag(char value) { method_entry_enabled_flag = value; } void set_method_exit_flag(char value) { method_exit_enabled_flag = value; } private: protected: friend jint JNICALL create_jvmti_environment(JavaVM *vm, void **env, jint version); Watch *access_watch_list; Watch *modification_watch_list; bool status; bool need_create_event_thread; Agent* agents; TIEnv* p_TIenvs; jvmtiPhase phase; const unsigned MAX_NOTIFY_LIST; Class **notifyLoadList; unsigned loadListNumber; Class **notifyPrepareList; unsigned prepareListNumber; unsigned global_capabilities; bool single_step_enabled; bool cml_report_inlined; char method_entry_enabled_flag, method_exit_enabled_flag; unsigned event_needed[TOTAL_EVENT_TYPE_NUM]; }; /* end of class DebugUtilsTI */ jvmtiError add_event_to_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread); void remove_event_from_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread); void add_event_to_global(jvmtiEnv *env, jvmtiEvent event_type); void remove_event_from_global(jvmtiEnv *env, jvmtiEvent event_type); jthread getCurrentThread(); jint load_agentlib(Agent *agent, const char *str, JavaVM_Internal *vm); jint load_agentpath(Agent *agent, const char *str, JavaVM_Internal *vm); // Breakpoints internal functions jvmtiError jvmti_get_next_bytecodes_from_native(VM_thread *thread, jvmti_StepLocation **next_step, unsigned *count, bool invoked_frame); void jvmti_set_single_step_breakpoints(DebugUtilsTI *ti, jvmti_thread_t jvmti_thread, jvmti_StepLocation *locations, unsigned locations_number); void jvmti_set_single_step_breakpoints_for_method(DebugUtilsTI *ti, jvmti_thread_t jvmti_thread, Method* method); void jvmti_remove_single_step_breakpoints(DebugUtilsTI *ti, jvmti_thread_t jvmti_thread); // NCAI extension jvmtiError JNICALL jvmtiGetNCAIEnvironment(jvmtiEnv* jvmti_env, ...); // Object check functions Boolean is_valid_throwable_object(jthread thread); Boolean is_valid_thread_object(jthread thread); Boolean is_valid_thread_group_object(jthreadGroup group); Boolean is_valid_class_object(jclass klass); // JIT support jvmtiError jvmti_translate_jit_error(OpenExeJpdaError error); // Single step support void jvmti_SingleStepLocation(VM_thread* thread, Method *method, unsigned location, jvmti_StepLocation **next_step, unsigned *count); // Callback function for JVMTI breakpoint processing bool jvmti_process_breakpoint_event(TIEnv *env, const VMBreakPoint* bp, const POINTER_SIZE_INT data); #endif /* _JVMTI_INTERNAL_H_ */