1998-12-03 21:10:47 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-02 06:38:29 +00:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (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.mozilla.org/NPL/
|
1998-12-03 21:10:47 +00:00
|
|
|
*
|
1999-11-02 06:38:29 +00:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-12-03 21:10:47 +00:00
|
|
|
*
|
1999-11-02 06:38:29 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1998-12-03 21:10:47 +00:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-02 06:38:29 +00:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1998-12-03 21:10:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "JavaVM.h"
|
|
|
|
#include "Debugger.h"
|
|
|
|
#include "jvmdi.h"
|
|
|
|
#include "NativeCodeCache.h"
|
|
|
|
#include "Thread.h"
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
static JVMDI_EventHook eventHook;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "statusPtr" the status of the thread as one of
|
|
|
|
* JVMDI_THREAD_STATUS_*.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetThreadStatus(JNIEnv * /* env */, jthread thread, jint *statusPtr)
|
|
|
|
{
|
|
|
|
if (statusPtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
|
|
|
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
|
|
|
|
|
|
|
*statusPtr = t->getStatus();
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note: jvm.h has suspend/resume (which may be deprecated - as
|
|
|
|
* Thread.suspend() has been). JVMDI version is different, as it
|
|
|
|
* takes precautions to attempt to avoid deadlock. Also it
|
|
|
|
* cannot be depreciated.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Suspend the specified thread.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_SUSPENDED,
|
|
|
|
* JVMDI_ERROR_VM_DEAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SuspendThread(JNIEnv * /*env*/, jthread thread)
|
|
|
|
{
|
|
|
|
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
|
|
|
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
|
|
|
|
|
|
|
t->suspend();
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Resume the specified thread.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD, JVMDI_ERROR_THREAD_NOT_SUSPENDED,
|
|
|
|
* JVMDI_ERROR_VM_DEAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_ResumeThread(JNIEnv * /*env*/, jthread thread)
|
|
|
|
{
|
|
|
|
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
|
|
|
Thread *t = (Thread*)static_cast<int32>(jt->eetop);
|
|
|
|
|
|
|
|
t->resume();
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If shouldStep is true cause the thread to generate a
|
|
|
|
* JVMDI_EVENT_SINGLE_STEP event with each byte-code executed.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD,
|
|
|
|
* JVMDI_ERROR_THREAD_NOT_SUSPENDED (should suspension be a requirement?),
|
|
|
|
* JVMDI_ERROR_VM_DEAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetSingleStep(JNIEnv * /*env*/, jthread thread, jboolean shouldStep)
|
|
|
|
{
|
|
|
|
Thread::JavaThread *jt = (Thread::JavaThread *) thread;
|
|
|
|
|
|
|
|
jt->single_step = shouldStep;
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Thread Groups
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return in 'groupsPtr' an array of top-level thread groups (parentless
|
|
|
|
* thread groups).
|
|
|
|
* Note: array returned via 'groupsPtr' is allocated globally and must be
|
|
|
|
* explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetTopThreadGroups(JNIEnv * /*env*/, jobjectArray * /*groupsPtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return in 'threadsPtr' an array of the threads within the specified
|
|
|
|
* thread group.
|
|
|
|
* Note: array returned via 'threadsPtr' is allocated globally and must be
|
|
|
|
* explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetGroupsThreads(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
|
|
|
jobjectArray * /*threadsPtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return in 'groupsPtr' an array of the thread groups within the
|
|
|
|
* specified thread group.
|
|
|
|
* Note: array returned via 'groupsPtr' is allocated globally and must be
|
|
|
|
* explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetGroupsThreadGroups(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
|
|
|
jobjectArray * /*groupsPtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Suspend all threads recursively contained in the thread group,
|
|
|
|
* except the specified threads.
|
|
|
|
* If except is NULL suspend all threads in group.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SuspendThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/,
|
|
|
|
jobjectArray /*except*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Resume all threads (recursively) in the thread group, except the
|
|
|
|
* specified threads. If except is NULL resume all threads in group.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_THREAD_GROUP, JVMDI_ERROR_INVALID_THREAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_ResumeThreadGroup(JNIEnv * /*env*/, jthreadGroup /*group*/, jobjectArray /*except*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stack access
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "framePtr" the frame ID for the current stack frame
|
|
|
|
* of this thread. Thread must be suspended. Only Java and
|
|
|
|
* Java native frames are returned. FrameIDs become invalid if
|
|
|
|
* the frame is resumed.
|
|
|
|
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_THREAD,
|
|
|
|
* JVMDI_ERROR_THREAD_NOT_SUSPENDED, JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetCurrentFrame(JNIEnv * /*env*/, jthread /*thread*/, jframeID* framePtr)
|
|
|
|
{
|
|
|
|
if (framePtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "framePtr" the frame ID for the stack frame that called
|
|
|
|
* the specified frame. Only Java and Java native frames are returned.
|
|
|
|
* Errors: JVMDI_ERROR_NO_MORE_FRAMES, JVMDI_ERROR_INVALID_FRAMEID,
|
|
|
|
* JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetCallerFrame(JNIEnv * /* env */, jframeID /* called*/, jframeID * /*framePtr*/)
|
|
|
|
{
|
|
|
|
// Use code from the stackwalker here
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "classPtr" and "methodPtr" the active method in the
|
|
|
|
* specified frame.
|
|
|
|
* Note: class returned via 'classPtr' is allocated globally and must be
|
|
|
|
* explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NULL_POINTER
|
|
|
|
* JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetFrameMethod(JNIEnv * /*env*/, jframeID /*frame*/,
|
|
|
|
jclass * /*classPtr*/, jmethodID * /*methodPtr*/)
|
|
|
|
{
|
|
|
|
// Use code from the stackwalker here
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "bciPtr" the byte-code index within the active method of
|
|
|
|
* the specified frame. This is the index of the currently executing
|
|
|
|
* instruction.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_NATIVE_FRAME,
|
|
|
|
* JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetFrameBCI(JNIEnv * /*env*/, jframeID /*frame*/, jint * /*bciPtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "valuePtr" the value of the local variable at the
|
|
|
|
* specificied slot.
|
|
|
|
* Note: object returned via 'valuePtr' is allocated globally and must be
|
|
|
|
* explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_NATIVE_FRAME, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
|
|
|
jobject * /*valuePtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "valuePtr" the value of the local variable at the
|
|
|
|
* specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
|
|
|
jint * /*valuePtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "valuePtr" the value of the local variable at the
|
|
|
|
* specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
|
|
|
jlong * /*valuePtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "valuePtr" the value of the local variable at the
|
|
|
|
* specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
|
|
|
jfloat * /*valuePtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "valuePtr" the value of the local variable at the
|
|
|
|
* specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NULL_POINTER,
|
|
|
|
* JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/,
|
|
|
|
jdouble * /*valuePtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the value of the local variable at the specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetLocalObject(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jobject /*value*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the value of the local variable at the specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetLocalInt(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jint /*value*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the value of the local variable at the specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetLocalLong(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jlong /*value*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the value of the local variable at the specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetLocalFloat(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jfloat /*value*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the value of the local variable at the specificied slot.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_FRAMEID, JVMDI_ERROR_INVALID_SLOT,
|
|
|
|
* JVMDI_ERROR_TYPE_MISMATCH, JVMDI_ERROR_NATIVE_FRAME
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetLocalDouble(JNIEnv * /*env*/, jframeID /*frame*/, jint /*slot*/, jdouble /*value*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Breakpoints
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set a breakpoint. Send a JVMDI_EVENT_BREAKPOINT event when the
|
|
|
|
* instruction at the specified byte-code index in the specified
|
|
|
|
* method is about to be executed.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
|
|
|
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_DUPLICATE_BREAKPOINT,
|
|
|
|
* JVMDI_ERROR_VM_DEAD, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetBreakpoint(JNIEnv * /*env*/, jclass /* clazz */,
|
|
|
|
jmethodID method, jint /*bci*/)
|
|
|
|
{
|
|
|
|
CacheEntry* ce;
|
|
|
|
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
|
|
|
|
|
|
|
if (ce == NULL) {
|
|
|
|
/* either the method is not compiled - in which case compile it */
|
|
|
|
return JVMDI_ERROR_INVALID_METHODID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *code = addressFunction(ce->descriptor.method->getCode());
|
|
|
|
|
|
|
|
if (code == NULL) {
|
|
|
|
return JVMDI_ERROR_INVALID_METHODID;
|
|
|
|
} // else if (code == stub) compile and then break;
|
|
|
|
|
|
|
|
// Convert the bci to a pc offset and add it to code
|
|
|
|
|
|
|
|
VM::debugger.setBreakPoint(code);
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear a breakpoint.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
|
|
|
* JVMDI_ERROR_INVALID_BCI, JVMDI_ERROR_NO_SUCH_BREAKPOINT,
|
|
|
|
* JVMDI_ERROR_VM_DEAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_ClearBreakpoint(JNIEnv * /*env*/, jclass /*clazz*/, jmethodID /*method*/, jint /*bci*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear all breakpoints.
|
|
|
|
* Errors: JVMDI_ERROR_VM_DEAD
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_ClearAllBreakpoints(JNIEnv * /*env*/)
|
|
|
|
{
|
|
|
|
VM::debugger.clearAllBreakPoints();
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the routine which will handle in-coming events.
|
|
|
|
* Passing NULL as hook unsets hook.
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_SetEventHook(JNIEnv * /*env*/, JVMDI_EventHook hook)
|
|
|
|
{
|
|
|
|
eventHook = hook;
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Method access
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "namePtr" the method's name and via "signaturePtr" the
|
|
|
|
* method's signature.
|
|
|
|
* Note: strings returned via 'namePtr' and 'signaturePtr' are
|
|
|
|
* allocated globally and must be explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
|
|
|
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetMethodName(JNIEnv * env, jclass /*clazz*/, jmethodID method,
|
|
|
|
jstring *namePtr, jstring *signaturePtr)
|
|
|
|
{
|
|
|
|
CacheEntry* ce;
|
|
|
|
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
|
|
|
|
|
|
|
if (namePtr == NULL || signaturePtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
if (ce == NULL) {
|
|
|
|
return JVMDI_ERROR_INVALID_METHODID;
|
|
|
|
}
|
|
|
|
|
|
|
|
*namePtr = (jstring) env->NewGlobalRef(
|
|
|
|
env->NewStringUTF(ce->descriptor.method->toString()));
|
|
|
|
*signaturePtr = (jstring) env->NewGlobalRef(
|
|
|
|
env->NewStringUTF(ce->descriptor.method->getSignatureString()));
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "definingClassPtr" the class in which this method is
|
|
|
|
* defined.
|
|
|
|
* Note: class returned via 'definingClassPtr' is allocated globally
|
|
|
|
* and must be explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
|
|
|
* JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetMethodDefiningClass(JNIEnv * env, jclass /* clazz */, jmethodID method,
|
|
|
|
jclass * definingClassPtr)
|
|
|
|
{
|
|
|
|
CacheEntry* ce;
|
|
|
|
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
|
|
|
|
|
|
|
if (definingClassPtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
*definingClassPtr = (jclass) (env->NewGlobalRef((jobject)
|
|
|
|
ce->descriptor.method->getDeclaringClass()));
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "isNativePtr" a boolean indicating whether the method
|
|
|
|
* is native.
|
|
|
|
* Errors: JVMDI_ERROR_INVALID_METHODID, JVMDI_ERROR_INVALID_CLASS,
|
|
|
|
* JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_IsMethodNative(JNIEnv * /* env */, jclass /* clazz */, jmethodID method,
|
|
|
|
jboolean * isNativePtr)
|
|
|
|
{
|
|
|
|
if (isNativePtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
|
|
|
CacheEntry* ce;
|
|
|
|
ce = NativeCodeCache::getCache().lookupByRange((Uint8*) method);
|
|
|
|
|
|
|
|
if (ce == NULL) {
|
|
|
|
/* either the method is not compiled - in which case compile it */
|
|
|
|
return JVMDI_ERROR_INVALID_METHODID;
|
|
|
|
}
|
|
|
|
|
|
|
|
*isNativePtr = ce->descriptor.method->getMethodInfo().isNative();
|
|
|
|
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Misc
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "classesPtr" all classes currently loaded in the VM.
|
|
|
|
* Note: array returned via 'classesPtr' is allocated globally
|
|
|
|
* and must be explictly freed with DeleteGlobalRef.
|
|
|
|
* Errors: JVMDI_ERROR_NULL_POINTER, JVMDI_ERROR_OUT_OF_MEMORY
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetLoadedClasses(JNIEnv * /*env*/, jobjectArray * /*classesPtr*/)
|
|
|
|
{
|
|
|
|
return JVMDI_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return via "versionPtr" the JVMDI version number.
|
|
|
|
* Higher 16 bits is major version number, lower 16 bit is minor
|
|
|
|
* version number.
|
|
|
|
* Errors: JVMDI_ERROR_NULL_POINTER
|
|
|
|
*/
|
|
|
|
JNIEXPORT JNICALL(jvmdiError)
|
|
|
|
JVMDI_GetVersionNumber(JNIEnv * /*env*/, jint *versionPtr)
|
|
|
|
{
|
|
|
|
if (versionPtr == NULL) {
|
|
|
|
return JVMDI_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
*versionPtr = 0x00000003;
|
|
|
|
return JVMDI_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // extern C
|