/** * Clear a watchpoint if this is the last one on this field. */ static jint clearWatchpoint(HandlerNode *node) { jint error = JVMDI_ERROR_NONE; Filter *filter; filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly)); if (filter == NULL) { /* event with no field filter */ error = JVMDI_ERROR_INTERNAL; } else { FieldFilter *ff = &(filter->u.FieldOnly); /* if this is the last handler for this * field, clear wp at jvmdi level */ if (!eventHandlerRestricted_iterator( KIND(node), matchWatchpoint, ff)) { error = (KIND(node) == JVMDI_EVENT_FIELD_ACCESS) ? jvmdi->ClearFieldAccessWatch(ff->clazz, ff->field) : jvmdi->ClearFieldModificationWatch(ff->clazz, ff->field); } } return error; }
/** * Set a breakpoint if this is the first one at this location. */ static jvmtiError setBreakpoint(HandlerNode *node) { jvmtiError error = JVMTI_ERROR_NONE; Filter *filter; filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly)); if (filter == NULL) { /* bp event with no location filter */ error = AGENT_ERROR_INTERNAL; } else { LocationFilter *lf = &(filter->u.LocationOnly); /* if this is the first handler for this * location, set bp at JVMTI level */ if (!eventHandlerRestricted_iterator( EI_BREAKPOINT, matchBreakpoint, lf)) { LOG_LOC(("SetBreakpoint at location: method=%p,location=%d", lf->method, (int)lf->location)); error = JVMTI_FUNC_PTR(gdata->jvmti,SetBreakpoint) (gdata->jvmti, lf->method, lf->location); } } return error; }
/** * Clear a watchpoint if this is the last one on this field. */ static jvmtiError clearWatchpoint(HandlerNode *node) { jvmtiError error = JVMTI_ERROR_NONE; Filter *filter; filter = findFilter(node, JDWP_REQUEST_MODIFIER(FieldOnly)); if (filter == NULL) { /* event with no field filter */ error = AGENT_ERROR_INTERNAL; } else { FieldFilter *ff = &(filter->u.FieldOnly); /* if this is the last handler for this * field, clear wp at JVMTI level */ if (!eventHandlerRestricted_iterator( NODE_EI(node), matchWatchpoint, ff)) { error = (NODE_EI(node) == EI_FIELD_ACCESS) ? JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldAccessWatch) (gdata->jvmti, ff->clazz, ff->field) : JVMTI_FUNC_PTR(gdata->jvmti,ClearFieldModificationWatch) (gdata->jvmti, ff->clazz, ff->field); } } return error; }
/** * Return true if a breakpoint is set at the specified location. */ jboolean isBreakpointSet(jclass clazz, jmethodID method, jlocation location) { LocationFilter lf; lf.clazz = clazz; lf.method = method; lf.location = location; return eventHandlerRestricted_iterator(JVMDI_EVENT_BREAKPOINT, matchBreakpoint, &lf); }
/** * Do any disabling of events (including clearing breakpoints etc) * needed to no longer get the events requested by this handler node. */ static jvmtiError disableEvents(HandlerNode *node) { jvmtiError error = JVMTI_ERROR_NONE; jvmtiError error2 = JVMTI_ERROR_NONE; jthread thread; switch (NODE_EI(node)) { /* The stepping code directly enables/disables stepping as * necessary */ case EI_SINGLE_STEP: /* Internal thread event handlers are always present * (hardwired in the event hook), so we don't change the * notification mode here. */ case EI_THREAD_START: case EI_THREAD_END: case EI_VM_INIT: case EI_VM_DEATH: case EI_CLASS_PREPARE: case EI_GC_FINISH: return error; case EI_FIELD_ACCESS: case EI_FIELD_MODIFICATION: error = clearWatchpoint(node); break; case EI_BREAKPOINT: error = clearBreakpoint(node); break; default: break; } thread = requestThread(node); /* If this is the last request of it's kind on this thread * (or all threads (thread == NULL)) then disable these * events on this thread. * * Disable even if the above caused an error */ if (!eventHandlerRestricted_iterator(NODE_EI(node), matchThread, thread)) { error2 = threadControl_setEventMode(JVMTI_DISABLE, NODE_EI(node), thread); } return error != JVMTI_ERROR_NONE? error : error2; }
/** * Do any enabling of events (including setting breakpoints etc) * needed to get the events requested by this handler node. */ static jint enableEvents(HandlerNode *node) { jint error = JVMDI_ERROR_NONE; switch (KIND(node)) { /* The stepping code directly enables/disables stepping as * necessary */ case JVMDI_EVENT_SINGLE_STEP: /* Internal thread event handlers are always present * (hardwired in the event hook), so we don't change the * notification mode here. */ case JVMDI_EVENT_THREAD_START: case JVMDI_EVENT_THREAD_END: return error; case JVMDI_EVENT_FIELD_ACCESS: case JVMDI_EVENT_FIELD_MODIFICATION: error = setWatchpoint(node); break; case JVMDI_EVENT_BREAKPOINT: error = setBreakpoint(node); break; } /* Don't globally enable if the above failed */ if (error == JVMDI_ERROR_NONE) { jthread thread = requestThread(node); /* If this is the first request of it's kind on this * thread (or all threads (thread == NULL)) then enable * these events on this thread. */ if (!eventHandlerRestricted_iterator( KIND(node), matchThread, thread)) { error = threadControl_setEventMode(JVMDI_ENABLE, KIND(node), thread); } } return error; }
/** * Clear a breakpoint if this is the last one at this location. */ static jint clearBreakpoint(HandlerNode *node) { jint error = JVMDI_ERROR_NONE; Filter *filter; filter = findFilter(node, JDWP_REQUEST_MODIFIER(LocationOnly)); if (filter == NULL) { /* bp event with no location filter */ error = JVMDI_ERROR_INTERNAL; } else { LocationFilter *lf = &(filter->u.LocationOnly); /* if this is the last handler for this * location, clear bp at jvmdi level */ if (!eventHandlerRestricted_iterator( JVMDI_EVENT_BREAKPOINT, matchBreakpoint, lf)) { error = jvmdi->ClearBreakpoint(lf->clazz, lf->method, lf->location); } } return error; }