/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <ctype.h>
#include "util.h"
#include "transport.h"
#include "eventHandler.h"
#include "threadControl.h"
#include "outStream.h"
#include "inStream.h"
#include "invoker.h"
/* Global data area */
/* Forward declarations */
/* Save an object reference for use later (create a NewGlobalRef) */
void
{
}
}
}
}
}
}
/* Toss a previously saved object reference */
void
{
}
}
}
}
static jclass
{
jclass x;
}
}
if (x == NULL) {
}
}
return x;
}
static jmethodID
{
}
}
}
}
ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
}
ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
}
return method;
}
static jmethodID
{
}
}
}
}
ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
}
ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
}
return method;
}
void
{
/* Find some standard classes */
/* Save references */
/* Find some standard methods */
gdata->setProperty =
/* Find the system thread group */
groupCount = 0;
if (error != JVMTI_ERROR_NONE ) {
}
if ( groupCount == 0 ) {
}
localSystemThreadGroup = groups[0];
/* Get some basic Java property values we will need at some point */
/* Get agent properties: invoke sun.misc.VMSupport.getAgentProperties */
if (localVMSupportClass == NULL) {
}
} else {
"getAgentProperties", "()Ljava/util/Properties;");
"Exception occurred calling sun.misc.VMSupport.getAgentProperties");
}
}
}
void
util_reset(void)
{
}
}
{
return JDWP_TAG(THREAD_GROUP);
return JDWP_TAG(CLASS_LOADER);
return JDWP_TAG(CLASS_OBJECT);
} else {
}
}
static void
{
if (error != JVMTI_ERROR_NONE) {
return;
}
/*
* For primitive types, the type key is bounced back as is. Objects
* are handled in the switch statement below.
*/
}
switch (typeKey) {
break;
}
(void)outStream_writeByte(out,
break;
(void)outStream_writeChar(out,
break;
(void)outStream_writeFloat(out,
break;
(void)outStream_writeDouble(out,
break;
(void)outStream_writeInt(out,
break;
(void)outStream_writeLong(out,
break;
(void)outStream_writeShort(out,
break;
(void)outStream_writeBoolean(out,
break;
}
}
static void
{
if (error != JVMTI_ERROR_NONE) {
return;
}
/*
* For primitive types, the type key is bounced back as is. Objects
* are handled in the switch statement below.
*/
}
switch (typeKey) {
break;
}
(void)outStream_writeByte(out,
break;
(void)outStream_writeChar(out,
break;
(void)outStream_writeFloat(out,
break;
(void)outStream_writeDouble(out,
break;
(void)outStream_writeInt(out,
break;
(void)outStream_writeLong(out,
break;
(void)outStream_writeShort(out,
break;
(void)outStream_writeBoolean(out,
break;
}
}
void
{
if (isStatic) {
} else {
}
if (inStream_error(in)) {
return;
}
int i;
if (isStatic) {
} else {
}
}
}
{
/*
* Instance methods start with the instance, thread and class,
* and statics and constructors start with the class and then the
* thread.
*/
} else { /* static method or constructor */
}
/*
* ... and the rest of the packet is identical for all commands
*/
if (inStream_error(in)) {
return JNI_TRUE;
}
/* If count == 0, don't try and allocate 0 bytes, you'll get NULL */
if ( argumentCount > 0 ) {
int i;
/*LINTED*/
return JNI_TRUE;
}
}
if (inStream_error(in)) {
return JNI_TRUE;
}
}
if (inStream_error(in)) {
}
return JNI_TRUE;
}
} else {
}
return JNI_TRUE;
}
/*
* Request the invoke. If there are no errors in the request,
* the interrupting thread will actually do the invoke and a
* reply will be generated subsequently, so we don't reply here.
*/
if (error != JVMTI_ERROR_NONE) {
}
return JNI_TRUE;
}
return JNI_FALSE; /* Don't reply */
}
uniqueID(void)
{
return currentID++;
}
int
{
int i;
int current;
/* Squish out all of the debugger-spawned threads */
if (!threadControl_isDebugThread(thread)) {
if (i > current) {
}
current++;
}
}
return current;
}
{
if (isInterface(clazz)) {
} else if (isArrayClass(clazz)) {
} else {
}
return tag;
}
/**
* Get field modifiers
*/
{
*pmodifiers = 0;
return error;
}
/**
* Get method modifiers
*/
{
*pmodifiers = 0;
return error;
}
/* Returns a local ref to the declaring class for a method, or NULL. */
{
return error;
}
/* Returns a local ref to the declaring class for a method, or NULL. */
{
return error;
}
/**
* Get method signature
*/
{
}
if ( psignature != NULL ) {
*psignature = signature;
}
if ( pgeneric_signature != NULL ) {
} else if ( generic_signature != NULL ) {
}
return error;
}
/*
* Get the return type key of the method
* V or B C D F I J S Z L [
*/
{
char *signature;
if (error == JVMTI_ERROR_NONE) {
} else {
char * xx;
} else {
}
}
}
return error;
}
/**
* Return class loader for a class (must be inside a WITH_LOCAL_REFS)
*/
{
return error;
}
/**
* Get field signature
*/
{
}
if ( psignature != NULL ) {
*psignature = signature;
}
if ( pgeneric_signature != NULL ) {
} else if ( generic_signature != NULL ) {
}
return error;
}
JNIEnv *
getEnv(void)
{
ERROR_MESSAGE(("JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = %d",
rc));
}
return env;
}
{
goto err;
}
goto err;
}
/*
* Make the debugger thread a daemon
*/
goto err;
}
if (error == JVMTI_ERROR_NONE) {
/*
* Debugger threads need cycles in all sorts of strange
* situations (e.g. infinite cpu-bound loops), so give the
* thread a high priority. Note that if the VM has an application
* thread running at the max priority, there is still a chance
* that debugger threads will be starved. (There needs to be
* a way to give debugger threads a priority higher than any
* application thread).
*/
}
err: ;
return error;
}
{
return AGENT_ERROR_VM_DEAD;
}
if (!gdata->haveCachedJvmtiCapabilities) {
if (error != JVMTI_ERROR_NONE) {
return error;
}
}
return JVMTI_ERROR_NONE;
}
static jint
jvmtiVersion(void)
{
if (gdata->cachedJvmtiVersion == 0) {
if (error != JVMTI_ERROR_NONE) {
}
}
return gdata->cachedJvmtiVersion;
}
jvmtiMajorVersion(void)
{
return (jvmtiVersion() & JVMTI_VERSION_MASK_MAJOR)
}
jvmtiMinorVersion(void)
{
return (jvmtiVersion() & JVMTI_VERSION_MASK_MINOR)
}
jvmtiMicroVersion(void)
{
return (jvmtiVersion() & JVMTI_VERSION_MASK_MICRO)
}
{
}
{
}
/*
* classname "java.lang.Foo" compatible with the pattern.
* Signature is overwritten in-place.
*/
void
{
char *p;
p = convert + 1;
while ((*p != ';') && (*p != '\0')) {
char c = *p;
if (c == '/') {
*(p-1) = '.';
} else {
*(p-1) = c;
}
p++;
}
*(p-1) = '\0';
}
static void
handleInterrupt(void)
{
/*
* An interrupt is handled:
*
* 1) for running application threads by deferring the interrupt
* until the current event handler has concluded.
*
* 2) for debugger threads by ignoring the interrupt; this is the
* most robust solution since debugger threads don't use interrupts
* to signal any condition.
*
* 3) for application threads that have not started or already
* ended by ignoring the interrupt. In the former case, the application
* is relying on timing to determine whether or not the thread sees
* the interrupt; in the latter case, the interrupt is meaningless.
*/
}
}
static jvmtiError
{
if (error == JVMTI_ERROR_WRONG_PHASE) {
LOG_MISC(("VM_DEAD, in debugMonitor*()?"));
return JVMTI_ERROR_NONE; /* JVMTI does this, not JVMDI? */
}
return error;
}
void
{
while (JNI_TRUE) {
if (error == JVMTI_ERROR_INTERRUPT) {
} else {
break;
}
}
if (error != JVMTI_ERROR_NONE) {
}
}
void
{
if (error != JVMTI_ERROR_NONE) {
}
}
void
{
/*
* According to the JLS (17.8), here we have
* either :
* a- been notified
* b- gotten a suprious wakeup
* c- been interrupted
* If both a and c have happened, the VM must choose
* which way to return - a or c. If it chooses c
* then the notify is gone - either to some other
* thread that is also waiting, or it is dropped
* on the floor.
*
* a is what we expect. b won't hurt us any -
* callers should be programmed to handle
* spurious wakeups. In case of c,
* then the interrupt has been cleared, but
* we don't want to consume it. It came from
* user code and is intended for user code, not us.
* So, we will remember that the interrupt has
* occured and re-activate it when this thread
* goes back into user code.
* That being said, what do we do here? Since
* we could have been notified too, here we will
* just pretend that we have been. It won't hurt
* anything to return in the same way as if
* we were notified since callers have to be able to
* handle spurious wakeups anyway.
*/
if (error == JVMTI_ERROR_INTERRUPT) {
}
if (error != JVMTI_ERROR_NONE) {
}
}
void
{
if (error == JVMTI_ERROR_INTERRUPT) {
/* See comment above */
}
if (error != JVMTI_ERROR_NONE) {
}
}
void
{
if (error != JVMTI_ERROR_NONE) {
}
}
void
{
if (error != JVMTI_ERROR_NONE) {
}
}
{
if (error != JVMTI_ERROR_NONE) {
}
return monitor;
}
void
{
if (error != JVMTI_ERROR_NONE) {
}
}
/**
* Return array of all threads (must be inside a WITH_LOCAL_REFS)
*/
jthread *
{
*count = 0;
if (error == AGENT_ERROR_OUT_OF_MEMORY) {
return NULL; /* Let caller deal with no memory? */
}
if (error != JVMTI_ERROR_NONE) {
}
return threads;
}
/**
* Fill the passed in structure with thread group info.
* name field is JVMTI allocated. parent is global ref.
*/
void
{
if (error != JVMTI_ERROR_NONE) {
}
}
/**
* Return class signature string
*/
{
/*
* pgeneric_signature can be NULL, and GetClassSignature
* accepts NULL.
*/
if ( psignature != NULL ) {
*psignature = signature;
}
return error;
}
/* Get class name (not signature) */
char *
{
char *classname;
} else {
/* Convert in place */
}
}
return classname; /* Caller must free this memory */
}
void
{
if (genericSignature == NULL) {
} else {
}
}
{
if (error != JVMTI_ERROR_NONE) {
}
return status;
}
static jboolean
{
if (error != JVMTI_ERROR_NONE) {
}
return isArray;
}
static jboolean
{
if (error != JVMTI_ERROR_NONE) {
}
return isInterface;
}
{
if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) {
/* If the query is not supported, we assume it is not synthetic. */
*psynthetic = JNI_FALSE;
return JVMTI_ERROR_NONE;
}
return error;
}
{
if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) {
/* If the query is not supported, we assume it is not synthetic. */
*psynthetic = JNI_FALSE;
return JVMTI_ERROR_NONE;
}
return error;
}
{
if (error != JVMTI_ERROR_NONE) {
}
return isNative;
}
{
return JNI_TRUE;
}
}
{
if (error != JVMTI_ERROR_NONE) {
}
}
return hashCode;
}
/* Get all implemented interfaces (must be inside a WITH_LOCAL_REFS) */
{
*pcount = 0;
*ppinterfaces = NULL;
return error;
}
/* Get all loaded classes (must be inside a WITH_LOCAL_REFS) */
{
*pcount = 0;
return error;
}
/* Get all loaded classes for a loader (must be inside a WITH_LOCAL_REFS) */
{
*pcount = 0;
return error;
}
static jboolean
{
char *inner;
/* Assumed outer class signature is "LOUTERCLASSNAME;"
* inner class signature is "LOUTERCLASSNAME$INNERNAME;"
*
* INNERNAME can take the form:
* [0-9][1-9]* anonymous class somewhere in the file
* [0-9][1-9]*NAME local class somewhere in the OUTER class
* NAME nested class in OUTER
*
* If NAME itself contains a $ (sep) then classname is further nested
* inside another class.
*
*/
/* Check prefix first */
return JNI_FALSE;
}
/* Prefix must be followed by a $ (sep) */
return JNI_FALSE; /* No sep follows the match, must not be nested. */
}
/* Walk past any digits, if we reach the end, must be pure anonymous */
#if 1 /* We want to return local classes */
inner++;
}
/* But anonymous class names can't be trusted. */
if ( *inner == ';' ) {
return JNI_FALSE; /* A pure anonymous class */
}
#else
return JNI_FALSE; /* A pure anonymous or local class */
}
#endif
/* Nested deeper? */
return JNI_FALSE; /* Nested deeper than we want? */
}
return JNI_TRUE;
}
/* Get all nested classes for a class (must be inside a WITH_LOCAL_REFS) */
{
char *signature;
int i;
*pcount = 0;
count = 0;
ncount = 0;
if (error != JVMTI_ERROR_NONE) {
return error;
}
if (error != JVMTI_ERROR_NONE) {
return error;
}
if ( error != JVMTI_ERROR_NONE ) {
return error;
}
for (i=0; i<count; i++) {
char *candidate_signature;
if (error != JVMTI_ERROR_NONE) {
break;
}
/* Float nested classes to top */
}
}
}
return error;
}
void
{
/*
* Save current exception since it might get overwritten by
* the calls below. Note we must depend on space in the existing
* frame because asking for a new frame may generate an exception.
*/
/*
* Use the current frame if necessary; otherwise create a new one
*/
}
/*
* TO DO: This could be more efficient if it used EnsureLocalCapacity,
* but that would not work if two functions on the call stack
* use this function. We would need to either track reserved
* references on a per-thread basis or come up with a convention
* that would prevent two functions from depending on this function
* at the same time.
*/
/*
* Restore exception state from before call
*/
} else {
}
}
{
}
{
}
{
}
{
}
{
}
{
return is;
}
/**
* Return property value as jstring
*/
static jstring
{
valueString = NULL;
/* Create new String object to hold the property name */
/* NULL will be returned below */
} else {
/* Call valueString = System.getProperty(nameString) */
valueString = NULL;
}
}
return valueString;
}
/**
* Set an agent property
*/
void
{
/* VMSupport doesn't exist; so ignore */
return;
}
/* Create jstrings for property name and value */
if (nameString != NULL) {
if (valueString != NULL) {
/* invoke Properties.setProperty */
}
}
}
}
/**
* Return property value as JDWP allocated string in UTF8 encoding
*/
static char *
{
char *value;
if (error != JVMTI_ERROR_NONE) {
if (valueString != NULL) {
const char *utf;
/* Get the UTF8 encoding for this property value string */
/* Make a copy for returning, release the JNI copy */
}
}
}
}
return value;
}
{
if (error != JVMTI_ERROR_NONE) {
}
}
return obsolete;
}
/* Get the jvmti environment to be used with tags */
static jvmtiEnv *
getSpecialJvmti(void)
{
int rc;
/* Get one time use JVMTI Env */
return NULL;
}
if ( error != JVMTI_ERROR_NONE ) {
return NULL;
}
return jvmti;
}
void
{
} else {
}
}
void *
{
void *ptr;
if ( numBytes == 0 ) {
return NULL;
}
if (error != JVMTI_ERROR_NONE ) {
}
return ptr;
}
void
{
return;
}
if (error != JVMTI_ERROR_NONE ) {
}
}
/* Rarely needed, transport library uses JDWP errors, only use? */
{
switch ( error ) {
case JDWP_ERROR(NONE):
return JVMTI_ERROR_NONE;
case JDWP_ERROR(INVALID_THREAD):
return JVMTI_ERROR_INVALID_THREAD;
case JDWP_ERROR(INVALID_THREAD_GROUP):
return JVMTI_ERROR_INVALID_THREAD_GROUP;
case JDWP_ERROR(INVALID_PRIORITY):
return JVMTI_ERROR_INVALID_PRIORITY;
case JDWP_ERROR(THREAD_NOT_SUSPENDED):
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
case JDWP_ERROR(THREAD_SUSPENDED):
return JVMTI_ERROR_THREAD_SUSPENDED;
case JDWP_ERROR(INVALID_OBJECT):
return JVMTI_ERROR_INVALID_OBJECT;
case JDWP_ERROR(INVALID_CLASS):
return JVMTI_ERROR_INVALID_CLASS;
case JDWP_ERROR(CLASS_NOT_PREPARED):
return JVMTI_ERROR_CLASS_NOT_PREPARED;
case JDWP_ERROR(INVALID_METHODID):
return JVMTI_ERROR_INVALID_METHODID;
case JDWP_ERROR(INVALID_LOCATION):
return JVMTI_ERROR_INVALID_LOCATION;
case JDWP_ERROR(INVALID_FIELDID):
return JVMTI_ERROR_INVALID_FIELDID;
case JDWP_ERROR(INVALID_FRAMEID):
return AGENT_ERROR_INVALID_FRAMEID;
case JDWP_ERROR(NO_MORE_FRAMES):
return JVMTI_ERROR_NO_MORE_FRAMES;
case JDWP_ERROR(OPAQUE_FRAME):
return JVMTI_ERROR_OPAQUE_FRAME;
case JDWP_ERROR(NOT_CURRENT_FRAME):
return AGENT_ERROR_NOT_CURRENT_FRAME;
case JDWP_ERROR(TYPE_MISMATCH):
return JVMTI_ERROR_TYPE_MISMATCH;
case JDWP_ERROR(INVALID_SLOT):
return JVMTI_ERROR_INVALID_SLOT;
case JDWP_ERROR(DUPLICATE):
return JVMTI_ERROR_DUPLICATE;
case JDWP_ERROR(NOT_FOUND):
return JVMTI_ERROR_NOT_FOUND;
case JDWP_ERROR(INVALID_MONITOR):
return JVMTI_ERROR_INVALID_MONITOR;
case JDWP_ERROR(NOT_MONITOR_OWNER):
return JVMTI_ERROR_NOT_MONITOR_OWNER;
case JDWP_ERROR(INTERRUPT):
return JVMTI_ERROR_INTERRUPT;
case JDWP_ERROR(INVALID_CLASS_FORMAT):
return JVMTI_ERROR_INVALID_CLASS_FORMAT;
case JDWP_ERROR(FAILS_VERIFICATION):
return JVMTI_ERROR_FAILS_VERIFICATION;
case JDWP_ERROR(INVALID_TYPESTATE):
return JVMTI_ERROR_INVALID_TYPESTATE;
case JDWP_ERROR(UNSUPPORTED_VERSION):
return JVMTI_ERROR_UNSUPPORTED_VERSION;
case JDWP_ERROR(NAMES_DONT_MATCH):
return JVMTI_ERROR_NAMES_DONT_MATCH;
case JDWP_ERROR(NOT_IMPLEMENTED):
return JVMTI_ERROR_NOT_AVAILABLE;
case JDWP_ERROR(NULL_POINTER):
return JVMTI_ERROR_NULL_POINTER;
case JDWP_ERROR(ABSENT_INFORMATION):
return JVMTI_ERROR_ABSENT_INFORMATION;
case JDWP_ERROR(INVALID_EVENT_TYPE):
return JVMTI_ERROR_INVALID_EVENT_TYPE;
case JDWP_ERROR(ILLEGAL_ARGUMENT):
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
case JDWP_ERROR(OUT_OF_MEMORY):
return JVMTI_ERROR_OUT_OF_MEMORY;
case JDWP_ERROR(ACCESS_DENIED):
return JVMTI_ERROR_ACCESS_DENIED;
case JDWP_ERROR(VM_DEAD):
return JVMTI_ERROR_WRONG_PHASE;
case JDWP_ERROR(UNATTACHED_THREAD):
return JVMTI_ERROR_UNATTACHED_THREAD;
case JDWP_ERROR(INVALID_TAG):
return AGENT_ERROR_INVALID_TAG;
case JDWP_ERROR(ALREADY_INVOKING):
return AGENT_ERROR_ALREADY_INVOKING;
case JDWP_ERROR(INVALID_INDEX):
return AGENT_ERROR_INVALID_INDEX;
case JDWP_ERROR(INVALID_LENGTH):
return AGENT_ERROR_INVALID_LENGTH;
case JDWP_ERROR(INVALID_STRING):
return AGENT_ERROR_INVALID_STRING;
case JDWP_ERROR(INVALID_CLASS_LOADER):
return AGENT_ERROR_INVALID_CLASS_LOADER;
case JDWP_ERROR(INVALID_ARRAY):
return AGENT_ERROR_INVALID_ARRAY;
case JDWP_ERROR(TRANSPORT_LOAD):
return AGENT_ERROR_TRANSPORT_LOAD;
case JDWP_ERROR(TRANSPORT_INIT):
return AGENT_ERROR_TRANSPORT_INIT;
case JDWP_ERROR(NATIVE_METHOD):
return AGENT_ERROR_NATIVE_METHOD;
case JDWP_ERROR(INVALID_COUNT):
return AGENT_ERROR_INVALID_COUNT;
case JDWP_ERROR(INTERNAL):
return AGENT_ERROR_JDWP_INTERNAL;
}
return AGENT_ERROR_INTERNAL;
}
void
eventIndexInit(void)
{
}
{
}
return index2jdwp[i-EI_min];
}
{
}
return index2jvmti[i-EI_min];
}
{
switch ( eventType ) {
case JDWP_EVENT(SINGLE_STEP):
return EI_SINGLE_STEP;
case JDWP_EVENT(BREAKPOINT):
return EI_BREAKPOINT;
case JDWP_EVENT(FRAME_POP):
return EI_FRAME_POP;
case JDWP_EVENT(EXCEPTION):
return EI_EXCEPTION;
case JDWP_EVENT(THREAD_START):
return EI_THREAD_START;
case JDWP_EVENT(THREAD_END):
return EI_THREAD_END;
case JDWP_EVENT(CLASS_PREPARE):
return EI_CLASS_PREPARE;
case JDWP_EVENT(CLASS_UNLOAD):
return EI_GC_FINISH;
case JDWP_EVENT(CLASS_LOAD):
return EI_CLASS_LOAD;
case JDWP_EVENT(FIELD_ACCESS):
return EI_FIELD_ACCESS;
case JDWP_EVENT(FIELD_MODIFICATION):
return EI_FIELD_MODIFICATION;
case JDWP_EVENT(EXCEPTION_CATCH):
return EI_EXCEPTION_CATCH;
case JDWP_EVENT(METHOD_ENTRY):
return EI_METHOD_ENTRY;
case JDWP_EVENT(METHOD_EXIT):
return EI_METHOD_EXIT;
return EI_METHOD_EXIT;
return EI_MONITOR_CONTENDED_ENTER;
return EI_MONITOR_CONTENDED_ENTERED;
case JDWP_EVENT(MONITOR_WAIT):
return EI_MONITOR_WAIT;
case JDWP_EVENT(MONITOR_WAITED):
return EI_MONITOR_WAITED;
case JDWP_EVENT(VM_INIT):
return EI_VM_INIT;
case JDWP_EVENT(VM_DEATH):
return EI_VM_DEATH;
default:
break;
}
/*
* Event type not recognized - don't exit with error as caller
* may wish to return error to debugger.
*/
return (EventIndex)0;
}
{
switch ( kind ) {
case JVMTI_EVENT_SINGLE_STEP:
return EI_SINGLE_STEP;
case JVMTI_EVENT_BREAKPOINT:
return EI_BREAKPOINT;
case JVMTI_EVENT_FRAME_POP:
return EI_FRAME_POP;
case JVMTI_EVENT_EXCEPTION:
return EI_EXCEPTION;
case JVMTI_EVENT_THREAD_START:
return EI_THREAD_START;
case JVMTI_EVENT_THREAD_END:
return EI_THREAD_END;
return EI_CLASS_PREPARE;
return EI_GC_FINISH;
case JVMTI_EVENT_CLASS_LOAD:
return EI_CLASS_LOAD;
case JVMTI_EVENT_FIELD_ACCESS:
return EI_FIELD_ACCESS;
return EI_FIELD_MODIFICATION;
return EI_EXCEPTION_CATCH;
case JVMTI_EVENT_METHOD_ENTRY:
return EI_METHOD_ENTRY;
case JVMTI_EVENT_METHOD_EXIT:
return EI_METHOD_EXIT;
/*
* There is no JVMTI_EVENT_METHOD_EXIT_WITH_RETURN_VALUE.
* The normal JVMTI_EVENT_METHOD_EXIT always contains the return value.
*/
return EI_MONITOR_CONTENDED_ENTER;
return EI_MONITOR_CONTENDED_ENTERED;
case JVMTI_EVENT_MONITOR_WAIT:
return EI_MONITOR_WAIT;
return EI_MONITOR_WAITED;
case JVMTI_EVENT_VM_INIT:
return EI_VM_INIT;
case JVMTI_EVENT_VM_DEATH:
return EI_VM_DEATH;
default:
break;
}
return (EventIndex)0;
}
/* This routine is commonly used, maps jvmti and agent errors to the best
* jdwp error code we can map to.
*/
{
switch ( error ) {
case JVMTI_ERROR_NONE:
return JDWP_ERROR(NONE);
return JDWP_ERROR(INVALID_THREAD);
return JDWP_ERROR(INVALID_THREAD_GROUP);
return JDWP_ERROR(INVALID_PRIORITY);
return JDWP_ERROR(THREAD_NOT_SUSPENDED);
return JDWP_ERROR(THREAD_SUSPENDED);
return JDWP_ERROR(INVALID_THREAD);
return JDWP_ERROR(INVALID_OBJECT);
return JDWP_ERROR(INVALID_CLASS);
return JDWP_ERROR(CLASS_NOT_PREPARED);
return JDWP_ERROR(INVALID_METHODID);
return JDWP_ERROR(INVALID_LOCATION);
return JDWP_ERROR(INVALID_FIELDID);
return JDWP_ERROR(NO_MORE_FRAMES);
case JVMTI_ERROR_OPAQUE_FRAME:
return JDWP_ERROR(OPAQUE_FRAME);
return JDWP_ERROR(TYPE_MISMATCH);
case JVMTI_ERROR_INVALID_SLOT:
return JDWP_ERROR(INVALID_SLOT);
case JVMTI_ERROR_DUPLICATE:
return JDWP_ERROR(DUPLICATE);
case JVMTI_ERROR_NOT_FOUND:
return JDWP_ERROR(NOT_FOUND);
return JDWP_ERROR(INVALID_MONITOR);
return JDWP_ERROR(NOT_MONITOR_OWNER);
case JVMTI_ERROR_INTERRUPT:
return JDWP_ERROR(INTERRUPT);
return JDWP_ERROR(INVALID_CLASS_FORMAT);
return JDWP_ERROR(CIRCULAR_CLASS_DEFINITION);
return JDWP_ERROR(FAILS_VERIFICATION);
return JDWP_ERROR(INVALID_TYPESTATE);
return JDWP_ERROR(UNSUPPORTED_VERSION);
return JDWP_ERROR(NAMES_DONT_MATCH);
case AGENT_ERROR_NULL_POINTER:
case JVMTI_ERROR_NULL_POINTER:
return JDWP_ERROR(NULL_POINTER);
return JDWP_ERROR(ABSENT_INFORMATION);
return JDWP_ERROR(INVALID_EVENT_TYPE);
return JDWP_ERROR(ILLEGAL_ARGUMENT);
return JDWP_ERROR(OUT_OF_MEMORY);
return JDWP_ERROR(ACCESS_DENIED);
case JVMTI_ERROR_WRONG_PHASE:
case AGENT_ERROR_VM_DEAD:
case AGENT_ERROR_NO_JNI_ENV:
return JDWP_ERROR(VM_DEAD);
return JDWP_ERROR(UNATTACHED_THREAD);
return JDWP_ERROR(NOT_IMPLEMENTED);
return JDWP_ERROR(DELETE_METHOD_NOT_IMPLEMENTED);
return JDWP_ERROR(ADD_METHOD_NOT_IMPLEMENTED);
return JDWP_ERROR(SCHEMA_CHANGE_NOT_IMPLEMENTED);
return JDWP_ERROR(NOT_CURRENT_FRAME);
case AGENT_ERROR_INVALID_TAG:
return JDWP_ERROR(INVALID_TAG);
return JDWP_ERROR(ALREADY_INVOKING);
return JDWP_ERROR(INVALID_INDEX);
return JDWP_ERROR(INVALID_LENGTH);
return JDWP_ERROR(INVALID_STRING);
return JDWP_ERROR(INVALID_CLASS_LOADER);
return JDWP_ERROR(INVALID_ARRAY);
return JDWP_ERROR(TRANSPORT_LOAD);
return JDWP_ERROR(TRANSPORT_INIT);
return JDWP_ERROR(NATIVE_METHOD);
return JDWP_ERROR(INVALID_COUNT);
return JDWP_ERROR(INVALID_FRAMEID);
case JVMTI_ERROR_INTERNAL:
case AGENT_ERROR_INTERNAL:
return JDWP_ERROR(INTERNAL);
default:
break;
}
return JDWP_ERROR(INTERNAL);
}
{
if ( ( state & JVMTI_THREAD_STATE_SUSPENDED ) != 0 ) {
}
return status;
}
{
if ( ! ( state & JVMTI_THREAD_STATE_ALIVE ) ) {
if ( state & JVMTI_THREAD_STATE_TERMINATED ) {
} else {
/* FIXUP? New JDWP #define for not started? */
}
} else {
if ( state & JVMTI_THREAD_STATE_SLEEPING ) {
} else if ( state & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) {
} else if ( state & JVMTI_THREAD_STATE_WAITING ) {
} else if ( state & JVMTI_THREAD_STATE_RUNNABLE ) {
}
}
return status;
}
{
if ( ( classStatus & JVMTI_CLASS_STATUS_VERIFIED ) != 0 ) {
}
if ( ( classStatus & JVMTI_CLASS_STATUS_PREPARED ) != 0 ) {
}
if ( ( classStatus & JVMTI_CLASS_STATUS_INITIALIZED ) != 0 ) {
}
if ( ( classStatus & JVMTI_CLASS_STATUS_ERROR ) != 0 ) {
}
return status;
}
void
{
if ( logging_locations ) {
char *method_name;
char *class_sig;
/* Get thread information */
if ( error != JVMTI_ERROR_NONE) {
}
if ( error != JVMTI_ERROR_NONE) {
state = 0;
}
/* Get method if necessary */
if ( error != JVMTI_ERROR_NONE ) {
location = 0;
}
}
/* Get method name */
method_name = NULL;
if ( error != JVMTI_ERROR_NONE ) {
method_name = NULL;
}
}
/* Get class signature */
if ( error == JVMTI_ERROR_NONE ) {
if ( error != JVMTI_ERROR_NONE ) {
}
}
}
/* Issue log message */
LOG_LOC(("%s: debugee: thread=%p(%s:0x%x),method=%p(%s@%d;%s)",
func,
/* Free memory */
}
if ( method_name != NULL ) {
}
}
}
}
/* ********************************************************************* */
/* JDK 6.0: Use of new Heap Iteration functions */
/* ********************************************************************* */
/* ********************************************************************* */
/* Instances */
/* Structure to hold class instances heap iteration data (arg user_data) */
typedef struct ClassInstancesData {
/* Callback for instance object tagging (heap_reference_callback). */
{
/* Check data structure */
return JVMTI_VISIT_ABORT;
}
/* If we have tagged enough objects, just abort */
return JVMTI_VISIT_ABORT;
}
/* If tagged already, just continue */
return JVMTI_VISIT_OBJECTS;
}
/* Tag the object so we don't count it again, and so we can retrieve it */
return JVMTI_VISIT_OBJECTS;
}
/* Get instances for one class */
{
/* Check interface assumptions */
return AGENT_ERROR_INVALID_OBJECT;
}
return AGENT_ERROR_ILLEGAL_ARGUMENT;
}
/* Initialize return information */
/* Get jvmti environment to use */
jvmti = getSpecialJvmti();
return AGENT_ERROR_INTERNAL;
}
/* Setup data to passed around the callbacks */
/* Clear out callbacks structure */
/* Set the callbacks we want */
/* Follow references, no initiating object, just this class, all objects */
if ( error == JVMTI_ERROR_NONE ) {
}
/* Get all the instances now that they are tagged */
if ( error == JVMTI_ERROR_NONE ) {
/* Verify we got the count we expected */
}
}
/* Dispose of any special jvmti environment */
return error;
}
/* ********************************************************************* */
/* Instance counts. */
/* Macros to convert a class or instance tag to an index and back again */
/* Structure to hold class count heap traversal data (arg user_data) */
typedef struct ClassCountData {
int classCount;
/* Two different cbObjectCounter's, one for FollowReferences, one for
* IterateThroughHeap. Pick a card, any card.
*/
/* Callback for object count heap traversal (heap_reference_callback) */
{
int index;
/* Check data structure */
return JVMTI_VISIT_ABORT;
}
/* Classes with no class_tag should have been filtered out. */
return JVMTI_VISIT_ABORT;
}
/* Class tag not one we really want (jclass not in supplied list) */
return JVMTI_VISIT_OBJECTS;
}
/* If object tag is negative, just continue, we counted it */
return JVMTI_VISIT_OBJECTS;
}
/* Tag the object with a negative value just so we don't count it again */
/* This object had no tag value, so we give it the negObjTag value */
} else {
/* If this object had a positive tag value, it must be one of the
* jclass objects we tagged. We need to preserve the value of
* this tag for later objects that might have this as a class
* tag, so we just make the existing tag value negative.
*/
}
/* Absolute value of class tag is an index into the counts[] array */
return JVMTI_VISIT_ABORT;
}
/* Bump instance count on this class */
return JVMTI_VISIT_OBJECTS;
}
/* Callback for instance count heap traversal (heap_iteration_callback) */
void* user_data)
{
int index;
/* Check data structure */
return JVMTI_VISIT_ABORT;
}
/* Classes with no tag should be filtered out. */
return JVMTI_VISIT_ABORT;
}
/* Class tag is actually an index into data arrays */
return JVMTI_VISIT_ABORT;
}
/* Bump instance count on this class */
return JVMTI_VISIT_OBJECTS;
}
/* Get instance counts for a set of classes */
{
int i;
/* Check interface assumptions */
return AGENT_ERROR_ILLEGAL_ARGUMENT;
}
/* Initialize return information */
for ( i = 0 ; i < classCount ; i++ ) {
}
/* Get jvmti environment to use */
jvmti = getSpecialJvmti();
return AGENT_ERROR_INTERNAL;
}
/* Setup class data structure */
/* Set tags on classes, use index in classes[] as the tag value. */
for ( i = 0 ; i < classCount ; i++ ) {
tag = INDEX2CLASSTAG(i);
if ( error != JVMTI_ERROR_NONE ) {
break;
}
}
}
/* Traverse heap, two ways to do this for instance counts. */
if ( error == JVMTI_ERROR_NONE ) {
/* Clear out callbacks structure */
/* Check debug flags to see how to do this. */
/* Using FollowReferences only gives us live objects, but we
* need to tag the objects to avoid counting them twice since
* the callback is per reference.
* The jclass objects have been tagged with their index in the
* supplied list, and that tag may flip to negative if it
* is also an object of interest.
* All other objects being counted that weren't in the
* supplied classes list will have a negative classCount
* tag value. So all objects counted will have negative tags.
* If the absolute tag value is an index in the supplied
* list, then it's one of the supplied classes.
*/
/* Setup callbacks, only using object reference callback */
/* Follow references, no initiating object, tagged classes only */
} else {
/* Using IterateThroughHeap means that we will visit each object
* once, so no special tag tricks here. Just simple counting.
* However in this case the object might not be live, so we do
* a GC beforehand to make sure we minimize this.
*/
/* FIXUP: Need some kind of trigger here to avoid excessive GC's? */
if ( error != JVMTI_ERROR_NONE ) {
/* Setup callbacks, just need object callback */
/* Iterate through entire heap, tagged classes only */
}
}
/* Use data error if needed */
if ( error == JVMTI_ERROR_NONE ) {
}
}
/* Dispose of any special jvmti environment */
return error;
}
/* ********************************************************************* */
/* Referrers */
/* Structure to hold object referrer heap traversal data (arg user_data) */
typedef struct ReferrerData {
int refCount;
int maxObjects;
} ReferrerData;
/* Callback for referrers object tagging (heap_reference_callback). */
{
/* Check data structure */
return JVMTI_VISIT_ABORT;
}
/* If we have tagged enough objects, just abort */
return JVMTI_VISIT_ABORT;
}
/* If not of interest, just continue */
return JVMTI_VISIT_OBJECTS;
}
/* Self reference that we haven't counted? */
if ( tag_ptr == referrer_tag_ptr ) {
}
return JVMTI_VISIT_OBJECTS;
}
/* If the referrer can be tagged, and hasn't been tagged, tag it */
if ( referrer_tag_ptr != NULL ) {
if ( (*referrer_tag_ptr) == (jlong)0 ) {
}
}
return JVMTI_VISIT_OBJECTS;
}
/* Heap traversal to find referrers of an object */
{
/* Check interface assumptions */
return AGENT_ERROR_INVALID_OBJECT;
}
return AGENT_ERROR_ILLEGAL_ARGUMENT;
}
/* Initialize return information */
/* Get jvmti environment to use */
jvmti = getSpecialJvmti();
return AGENT_ERROR_INTERNAL;
}
/* Fill in the data structure passed around the callbacks */
/* Tag the object of interest */
/* No need to go any further if we can't tag the object */
if ( error == JVMTI_ERROR_NONE ) {
/* Clear out callbacks structure */
/* Setup callbacks we want */
/* Follow references, no initiating object, all classes, 1 tagged objs */
/* Use data error if needed */
if ( error == JVMTI_ERROR_NONE ) {
}
}
/* Watch out for self-reference */
/* Tag itself as a referer */
}
/* Get the jobjects for the tagged referrer objects. */
if ( error == JVMTI_ERROR_NONE ) {
/* Verify we got the count we expected */
}
}
/* Dispose of any special jvmti environment */
return error;
}