You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2007/11/21 17:29:54 UTC
svn commit: r597138 [13/15] - in /harmony/enhanced/drlvm/trunk: build/make/
build/make/components/vm/ vm/include/ vm/include/open/
vm/jitrino/src/codegenerator/ia32/ vm/port/src/encoder/ia32_em64t/
vm/port/src/lil/ia32/pim/ vm/tests/ncai/ vm/tests/ncai...
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/NCAI.html
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/NCAI.html?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/NCAI.html (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/NCAI.html Wed Nov 21 08:29:40 2007
@@ -0,0 +1,2221 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8" LANG="en-US">
+ <TITLE>This document describes specific support required from the VM</TITLE>
+ <style type="text/css">
+ <!--
+ body { color: #000000; background: #ffffff; font-family: verdana, helvetica;
+ font-weight: normal; font-style: normal; font-size: 12pt;
+ margin-left: 0.4in; margin-right: 0.4in }
+ code { font-family: monospace; color: #000000; margin-top: 0.5in; margin-bottom: 0.04in }
+ .indent { margin-left: 0.5in }
+ .smallindent { margin-left: 0.1in }
+ .novmargin { margin-top: 0.01in; margin-bottom: 0.01in }
+ table { border-collapse: collapse }
+ tr { vertical-align: top }
+ td { left: 0; background: #ffffff; font-size: 11pt }
+ td.header { font-weight: bold; background: #cccccc }
+ td.bold { font-weight: bold }
+ td.italic { font-style: italic }
+ p { margin-bottom: 0.04in; direction: ltr; color: #000000; widows: 2; orphans: 2 }
+ h1 { margin-bottom: 0.04in }
+ h2 { margin-bottom: 0.04in; font-style: italic }
+ h3 { margin-bottom: 0.04in }
+ a:link { color: #0000ff }
+ -->
+ </style>
+</HEAD>
+
+<BODY>
+
+<h2><a name="1.1. Native Code Access Interface"></a>Native Code Access Interface</h2>
+
+<p><i>Revision 0.1</i></p>
+<br>
+
+<table border="0">
+<tr>
+<td colspan="2"><a href="#1.1. Native Code Access Interface">Native Code Access Interface</a></td>
+<tr>
+<td colspan="2"><a href="#1.4. Overview">Overview</a></td>
+<tr>
+<td colspan="2"><a href="#1.5. Data types">Data types</a></td>
+<tr>
+<td colspan="2"><a href="#1.6. Modules">Modules</a></td>
+<tr>
+<td colspan="2"><a href="#1.7. Methods">Methods</a></td>
+<tr>
+<td colspan="2"><a href="#1.8. Threads">Threads</a></td>
+<tr>
+<td colspan="2"><a href="#1.9. Frames">Frames</a></td>
+<tr>
+<td colspan="2"><a href="#1.10. Registers">Registers</a></td>
+<tr>
+<td colspan="2"><a href="#1.11. Memory">Memory</a></td>
+<tr>
+<td colspan="2"><a href="#1.12. Signals">Signals</a></td>
+<tr>
+<td colspan="2"><a href="#1.13. Miscellaneous">Miscellaneous</a></td>
+<tr>
+<td colspan="2"><a href="#1.14. Capabilities">Capabilities</a></td>
+<tr>
+<td colspan="2"><a href="#1.15. Event Management">Event Management</a></td>
+<tr>
+<td colspan="2"><a href="#1.16. Event Callbacks">Event Callbacks</a></td>
+<tr>
+<td colspan="2"><a href="#1.17. Error codes">Error codes</a></td>
+<tr><td> </td>
+<td><a href="#1.17.1. Universal errors">Universal errors</a></td>
+<tr><td>
+<td><a href="#1.17.2. Function specific errors">Function specific errors</a></td>
+<tr>
+<td colspan="2"><a href="#1.18. Appendix 1. Priorities">Appendix 1. Priorities</a></td>
+</table>
+
+
+<h2><a name="1.4. Overview"></a>Overview</h2>
+
+<p>This document describes VM debug interface which extends JVMTI to support the debugging of
+mixed managed and native code, namely Native Code Access Interface - NCAI.</p>
+
+<p>The following cannot be done without knowing VM internals:</p>
+<ul>
+ <li><p>mapping of native thread to java thread</p>
+ <li><p>mapping of native frame to java frame</p>
+ <li><p>mapping of native code to java code</p>
+ <li><p>mapping of native register or memory to java field</p>
+</ul>
+
+<p>The following can be done behind the VM:</p>
+<ul>
+ <li><p>tracking of modules loaded into the VM process</p>
+ <li><p>mapping of native virtual address/register/stack offset to address/offset within a
+ module, and finally to symbol (class, method, variable)</p>
+</ul>
+
+<p>
+Processing of breakpoints/watchpoints/signals can be done behind the VM, but if
+VM use the same methods to implement java breakpoints/watchpoints
+over jitted code we get a conflict of interests, so we need common
+approach.</p>
+
+<p>
+NCAI features can be accessed via an interface pointer just like it can be
+done with JNI and JVMTI interface pointers. It is used to call it
+environment pointer, or briefly environment. A NCAI environment can
+be obtained via the following JVMTI extension function:</p>
+
+<p class="indent">
+<code>
+jvmtiError JNICALL GetExtensionEnv<br>
+
+(jvmtiEnv* jvmti_env, void** ncai_env_ptr, jint version);
+</code>
+</p>
+
+<p>where version is a NCAI version number like NCAI_VERSION_1_0.</p>
+
+<p>
+The function is provided by a standard JVMTI extension mechanism where it
+is identified as <code>org.apache.harmony.vm.GetExtensionEnv</code>. For
+example:</p>
+
+<p class="indent"><code>
+static const char* const GET_EXTENTION_ENV_FUNC =
+<br>
+
+"org.apache.harmony.vm.GetExtensionEnv";
+<br>
+jint extCount = 0;
+<br>
+jvmtiExtensionFunctionInfo* extensions = 0;
+<br>
+jvmtiError err = jvmti->GetExtensionFunctions(&extCount, &extensions);
+<br>
+jvmtiExtensionFunction
+<br>
+func = 0;
+<br>
+for (jint i = 0; i < extCount; i++) {
+<br>
+
+if (strcmp(extensions[i].id, GET_EXTENTION_ENV_FUNC) == 0) {
+<br>
+
+func = extensions[i].func;
+<br>
+
+}
+<br>
+
+jvmti->Deallocate(extensions[i].id);
+<br>
+
+jvmti->Deallocate(extensions[i].short_description);
+<br>
+
+for (jint j = 0; j < extensions[i].param_count; j++) {
+<br>
+
+jvmti->Deallocate(extensions[i].params[j].name);
+<br>
+
+}
+<br>
+
+jvmti->Deallocate(extensions[i].params);
+<br>
+
+jvmti->Deallocate(extensions[i].errors);
+<br>
+}
+<br>
+ncaiEnv* ncai = 0;
+<br>
+if (func != NULL) {
+<br>
+
+err = func(jvmti, &ncai, NCAI_VERSION_1_0);
+<br>
+}
+</code></p>
+
+<h2><a name="1.5. Data types"></a>Data types</h2>
+
+<p><code>
+struct _ncai;
+<br>
+typedef _ncai* ncaiEnv;
+</code></p>
+
+<p class="indent">Interface pointer to structure containing the NCAI function table
+just like JNI and JVMTI do.</p>
+
+<p><code>
+typedef enum {...} ncaiError;
+</code></p>
+
+<p class="indent">An error code which every NCAI function returns.</p>
+
+<p><code>
+struct _ncaiModule;
+<br>
+typedef _ncaiModule* ncaiModule;
+</code></p>
+
+<p class="indent">Opaque reference to VM
+internal data structure which represents a loadable module.</p>
+
+<p><code>
+struct ncaiModuleInfo;
+<br>
+struct ncaiSegmentInfo;
+</code></p>
+
+<p class="indent">Structures containing module information. See the GetModuleInfo function.</p>
+
+<p><code>
+typedef enum {} ncaiModuleKind;
+</code></p>
+
+<p class="indent">An identifier for a module type. See the GetModuleInfo function.</p>
+
+<p><code>
+typedef enum {} ncaiSegmentKind;
+</code></p>
+
+<p class="indent">An identifier for a segment type. See the GetModuleInfo function.</p>
+
+<p><code>
+struct _ncaiThread;
+<br>
+typedef _ncaiThread* ncaiThread;
+</code></p>
+
+<p class="indent">Opaque reference to VM internal data structure
+which represents a thread attached to the VM process.</p>
+
+<p><code>
+struct ncaiThreadInfo;
+</code></p>
+
+<p class="indent">Structure containing thread information. See the GetThreadInfo function.</p>
+
+<p><code>
+typedef enum {} ncaiThreadKind;
+</code></p>
+
+<p class="indent">An identifier for a thread type. See the GetThreadInfo function.</p>
+
+<p><code>
+struct ncaiFrameInfo;
+</code></p>
+
+<p class="indent">Structure containing frame information. See the GetStackTrace function.</p>
+
+<p><code>
+struct ncaiRegisterInfo;
+</code></p>
+
+<p class="indent">Structure containing register information. See the GetRegisterInfo function.</p>
+
+<p><code>
+struct ncaiSignalInfo;
+</code></p>
+
+<p class="indent">Structure containing signal information. See the GetSignalInfo function.</p>
+
+<p><code>
+struct ncaiCapabilities;
+</code></p>
+
+<p class="indent">Capabilities of a NCAI environment. TBD.</p>
+
+<p><code>
+struct ncaiEventCallbacks;
+</code></p>
+
+<p class="indent">Structure containing the list of event callback functions.</p>
+
+<p><code>
+typedef enum {} ncaiEventMode;<br>
+<br>
+typedef enum {} ncaiEventKind;
+</code></p>
+
+<p class="indent">Identifiers for event mode and type. See the SetEventNotificationMode function.</p>
+
+<p><code>
+typedef enum {} ncaiWatchpointMode;
+</code></p>
+
+<p class="indent">An identifier for the Watchpoint event mode. See the SetWatchpoint function.</p>
+
+<p><code>
+typedef enum {} ncaiStepMode;
+</code></p>
+
+<p class="indent">An identifier for the Step event mode. See the SetStepMode function.</p>
+
+
+
+<h2><a name="1.6. Modules"></a>Modules</h2>
+
+<p><code>ncaiError JNICALL GetAllLoadedModules
+<br>
+
+(ncaiEnv* env, jint* count_ptr, ncaiModule** modules_ptr);
+</code></p>
+
+<p>
+Get a list of all modules which are loaded to the
+VM process. <i>All the returned module pointers remain valid at least
+till the next function call.</i></p>
+
+<p class="indent"></p>
+Parameters:
+<ul>
+ <li class="indent">count_ptr -
+ pointer to a jint which will be set on return with number of
+ modules.
+ <li class="indent">modules_ptr -
+ pointer to a ncaiModule* which will be set on return with
+ address of a newly allocated array of ncaiModule's. The array
+ should be freed by JVMTI function Deallocate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors
+</ul>
+
+<p><code>
+ncaiError JNICALL GetModuleInfo
+<br>
+
+(ncaiEnv* env, ncaiModule module, ncaiModuleInfo* info_ptr);
+</code></p>
+
+<p>
+Get the module information. Fills the following
+structure:</p>
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_MODULE _JNI_LIBRARY,
+<br>
+
+NCAI_MODULE _VM_INTERNAL,
+<br>
+
+NCAI_MODULE _OTHER
+<br>
+} ncaiModuleKind;
+</code></p>
+
+<p class="indent"><code>
+typedef struct {
+<br>
+
+ncaiModuleKind kind;
+<br>
+
+char* name;
+<br>
+
+char* filename;
+<br>
+
+ncaiSegmentInfo* segments;
+<br>
+
+size_t segment_count;
+<br>
+} ncaiModuleInfo;
+</code></p>
+
+<p>The
+kind field determines the module kind from the point of view of VM.
+The segments field will be set on return with a pointer to array of
+the following structures:</p>
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_SEGMENT_UNKNOWN,
+<br>
+
+NCAI_SEGMENT_CODE,
+<br>
+
+NCAI_SEGMENT_DATA
+<br>
+} ncaiSegmentKind;
+</code></p>
+
+<p class="indent"><code>
+typedef struct {
+<br>
+
+ncaiSegmentKind kind;
+<br>
+
+void* base_address;
+<br>
+
+size_t size;
+<br>
+} ncaiSegmentInfo;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">module - the module to analyze.
+ <li class="indent">info_ptr -
+ pointer to a ncaiModuleInfo whose fields will be set on return
+ with information which includes module kind and newly allocated
+ arrays of name, filename and segments. The arrays of name, filename
+ and segments should be freed by JVMTI function Deallocate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li><p class="indent">NCAI_ERROR_INVALID_MODULE - module is not a valid ncaiModule.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetModuleClassLoader
+<br>
+
+(ncaiEnv* env, ncaiModule module, jobject* classloader_ptr);
+</code></p>
+
+<p>
+Get the JNI library module class loader. Returns
+NULL if the module was loaded by the bootstrap class loader. If the
+module is not of NCAI_MODULE _JNI_LIBRARY kind the function returns
+an error.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">module - the module to analyze.
+ <li class="indent">classloader_ptr - pointer to a jobject
+ which will be set on return with class loader object.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_MODULE - module is not a valid ncaiModule.
+</ul>
+</p>
+
+
+
+<h2><a name="1.7. Methods"></a>Methods</h2>
+
+<p><code>
+ncaiError JNICALL IsMethodCompiled
+<br>
+
+(ncaiEnv* env, jmethodID method, jboolean* is_compiled_ptr);
+</code></p>
+
+<p>
+Indicates if the java method is actually in
+compiled form.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">method - the method to analyze.
+ <li class="indent">is_compiled_ptr - pointer to a jboolean which will be set on return.
+</ul>
+
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_METHOD - method is not a valid java method id.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetMethodLocation
+<br>
+
+(ncaiEnv* env, jmethodID method, void** address_ptr, size_t* size_ptr);
+</code></p>
+
+<p>Get a native address where compiled method is loaded and the size of
+compiled code. <i>This is a convenience method corresponding to the
+CompiledMethodLoad event callback of JVMTI. So, the values returning
+in address_ptr and size_ptr should be the same as code_addr and
+code_size parameters of the callback.</i></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">method - the method to analyze.
+ <li class="indent">address_ptr - pointer to a void* which will be set on return
+ with starting address of compiled code.
+ <li class="indent">size_ptr - pointer to a zise_t which will be set on return
+ with size of compiled code.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_METHOD - method is not a valid java method id.
+ <li class="indent">NCAI_ERROR_NOT_COMPILED - method is not compiled yet.
+</ul>
+
+<p><code>
+ncaiError JNICALL FindJavaMethod
+<br>
+
+(ncaiEnv* env, void* address, jmethodID* method_ptr);
+</code></p>
+
+<p>Finds a compiled java
+method which corresponds to the given native address.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">address - the native address to analyze.
+ <li class="indent">method_ptr - pointer to a jmethodID which will be set on return with java
+ method id or 0 if such method does not exist.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_ADDRESS - address is not located inside a compiled java method.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetBytecodeLocation
+<br>
+
+(ncaiEnv* env, void* address, jmethodID method, jlocation* location_ptr);
+</code></p>
+
+<p>Get a bytecode location in compiled java method which corresponds to the
+given native address.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">address - the native address inside a compiled java method.
+ <li class="indent">method - the java method to analyze.
+ <li class="indent">location_ptr - pointer to a jlocation which will be set on return with index of
+ bytecode instruction corresponding to the native address.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_METHOD - method is not a valid java method id.
+ <li class="indent">NCAI_ERROR_INVALID_ADDRESS - address is not located inside the compiled java method.
+ <li class="indent">NCAI_ERROR_NOT_COMPILED - method is not compiled yet.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetNativeLocation
+<br>
+
+(ncaiEnv* env, jmethodID method, jlocation location, void** address_ptr);
+</code></p>
+
+<p>Get a native address which corresponds to the given bytecode location in
+compiled method. <i>This is a convenience method corresponding to the
+CompiledMethodLoad event callback of JVMTI. So, the value returning
+in address_ptr should be the same as start_address corresponding to
+the location in map parameter of the callback.</i></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">method - the java method to analyze.
+ <li class="indent">location - the index of the bytecode instruction inside the method.
+ <li class="indent">address_ptr - pointer to a void* which will be set on return with native address
+ of compiled code corresponding to the location.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_METHOD - method is not a valid java method id.
+ <li class="indent">NCAI_ERROR_INVALID_LOCATION - location is not a valid location.
+ <li class="indent">NCAI_ERROR_NOT_COMPILED - method is not compiled yet.
+</ul>
+
+
+
+<h2><a name="1.8. Threads"></a>Threads</h2>
+
+<p><code>
+ncaiError JNICALL GetAllThreads
+<br>
+
+(ncaiEnv* env, jint* count_ptr, ncaiThread** threads_ptr);
+</code></p>
+
+<p>Get a list of all known threads. <i>All the returned thread pointers
+remain valid at least till the next function call.</i></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">count_ptr - pointer to a jint which will be set on return with number of threads.
+ <li class="indent">threads_ptr - pointer to a ncaiThread * which will be set on return with address
+ of a newly allocated array of ncaiThreadâs. The array should be freed by JVMTI function Deallocate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetThreadInfo
+<br>
+
+(ncaiEnv* env, ncaiThread thread, ncaiThreadInfo* info_ptr);
+</code></p>
+
+<p>
+Get the thread information. Fills the following structure:</p>
+
+<p><code>
+typedef enum {
+<br>
+
+NCAI_THREAD_JAVA,
+<br>
+
+NCAI_THREAD_VM_INTERNAL,
+<br>
+
+NCAI_THREAD_OTHER
+<br>
+} ncaiThreadKind;
+</code></p>
+
+<p><code>
+typedef struct {
+<br>
+
+ncaiThreadKind kind;
+<br>
+
+char* name;
+<br>
+} ncaiThreadInfo;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to analyze.
+ <li class="indent">info_ptr - pointer to a ncaiThreadInfo whose fields will be set on return
+ with information which includes thread kind and newly allocated
+ array of name. The array of name should be freed by JVMTI function Deallocate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetThreadHandle
+<br>
+
+(ncaiEnv* env, jthread thread, ncaiThread* thread_ptr);
+</code></p>
+
+<p>
+Get a thread handle for the given java thread
+object (0, if such object does not exist).</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to analyze.
+ <li class="indent">thread_ptr - pointer to a ncaiThread which will be set on return with appropriate value.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid jthread.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetThreadObject
+<br>
+
+(ncaiEnv* env, ncaiThread thread, jthread* thread_ptr);
+</code></p>
+
+<p>
+Get a java thread object for the given thread
+handle (0, if such object does not exist).</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the ncaiThread to analyze.
+ <li class="indent">thread_ptr - pointer to a jthread which will be set on return with appropriate value.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL SuspendThread
+<br>
+
+(ncaiEnv* env, ncaiThread thread);
+</code></p>
+
+<p>
+Suspend the given thread. <i>This is really a hard
+suspend which means one should take care about possible deadlock if
+some thread will try to enter a monitor acquired by the suspended
+thread.</i></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to suspend.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_SUSPENDED - thread is already suspended.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL ResumeThread
+<br>
+
+(ncaiEnv* env, ncaiThread thread);
+</code></p>
+
+<p>Resume the given thread.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to resume.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_SUSPENDED - thread is not suspended.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL TerminateThread
+<br>
+
+(ncaiEnv* env, ncaiThread thread);
+</code></p>
+
+<p>
+Terminate the given thread. Not all acquired locks
+and owned JVMTI monitors could be released, so care must be taken to
+prevent a possible deadlock.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to terminate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetThreadState
+<br>
+
+(ncaiEnv* env, jthread thread, jint* state_ptr);
+</code></p>
+
+<p>Get a state for the given thread. <i>TBD</i>.</p>
+
+
+
+<h2><a name="1.9. Frames"></a>Frames</h2>
+
+<p><code>
+ncaiError JNICALL GetFrameCount
+<br>
+
+(ncaiEnv* env, ncaiThread thread, jint* count_ptr);
+</code></p>
+
+<p>
+Get the total number of frames in the given
+thread. The thread needs to be either suspended or the current thread
+in breakpoint or step callback.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to analyze.
+ <li class="indent">count_ptr - pointer to a jint which will be set on return with number of stack frames.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_SUSPENDED - thread is not suspended or current.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetStackTrace
+<br>
+
+(ncaiEnv* env, ncaiThread thread, jint depth, ncaiFrameInfo* frame_buffer, jint* count_ptr);
+</code></p>
+
+<p>
+Get the stack frame information for the given
+thread. The depth specifies capacity of the frame_buffer. The thread
+needs to be either suspended or the current thread in breakpoint or
+step callback.</p>
+
+
+<p><code>
+typedef struct {
+<br>
+
+jint java_frame_depth;
+<br>
+
+void* pc_address;
+<br>
+
+void* return_address;
+<br>
+
+void* frame_address;
+<br>
+
+void* stack_address;
+<br>
+} ncaiFrameInfo;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to analyze.
+ <li class="indent">depth - the maximum number of stack frames to retrieve.
+ <li class="indent">frame_buffer - preallocated buffer large enough to hold depth ncaiFrameInfo
+ objects which fields will be set on return with appropriate values.
+ <li class="indent">count_ptr - pointer to a jint which will be set on return with number of stack
+ frames passed to the buffer.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_SUSPENDED - thread is not suspended or current.
+</ul>
+
+
+
+<h2><a name="1.10. Registers"></a>Registers</h2>
+
+<p><code>
+ncaiError JNICALL GetRegisterCount
+<br>
+
+(ncaiEnv* env, jint* count_ptr);
+</code></p>
+
+<p>Get a number of native registers.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">count_ptr - pointer to a jint which will be set on return with number of registers.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.</p>
+</ul>
+
+<p><code>
+ncaiError JNICALL GetRegisterlInfo
+<br>
+
+(ncaiEnv* env, jint reg_number, ncaiRegisterInfo* info_ptr);
+</code></p>
+
+<p>Get the register information. Fills the following structure:</p>
+
+<p><code>
+typedef struct {
+<br>
+
+char* name;
+<br>
+
+jint size;
+<br>
+} ncaiRegisterInfo;
+</code></p>
+
+<p>
+Field name is the register name and size is the
+register size in bits.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">reg_number - the number of register to analyze.
+ <li class="indent">info_ptr - pointer to a ncaiRegisterInfo whose fields
+ will be set on return with information.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - reg_number is not a valid register number.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetRegisterValue
+<br>
+
+(ncaiEnv* env, ncaiThread thread, jint reg_number, void* buf);
+</code></p>
+
+<p>
+Get the register value for the given thread. The
+thread needs to be either suspended or the current thread in
+breakpoint or step callback.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">reg_number - the number of register.
+ <li class="indent">buf - preallocated buffer large enough to hold register value
+ which will be set on return.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - reg_number is not a valid register number.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_SUSPENDED - thread is not suspended or current.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetRegisterValue
+<br>
+
+(ncaiEnv* env, ncaiThread thread, jint reg_number, void* buf);
+</code></p>
+
+<p>
+Set the register value for the given thread. The
+thread needs to be either suspended or the current thread in
+breakpoint or step callback.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">reg_number - the number of register.
+ <li class="indent">buf - buffer which contains a register value.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - reg_number is not a valid register number.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_SUSPENDED - thread is not suspended or current.
+</ul>
+
+
+
+<h2><a name="1.11. Memory"></a>Memory</h2>
+
+<p>The following functions
+should hide/preserve any instrumentation of a native code done by the
+VM</p>
+
+<p><code>
+ncaiError JNICALL ReadMemory
+<br>
+
+(ncaiEnv* env, void* addr, size_t size, void* buf);
+</code></p>
+
+<p>Read the memory block.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">addr - the address of memory block
+ <li class="indent">size - the size of memory block in bytes.
+ <li class="indent">buf - preallocated buffer large enough to hold a copy of memory block.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ACCESS_DENIED - access to the memory block is denied.
+</ul>
+
+<p><code>
+ncaiError JNICALL WriteMemory
+<br>
+
+(ncaiEnv* env, void* addr, size_t size, void* buf);
+</code></p>
+
+<p>Write the memory block.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">addr - the address of memory block.
+ <li class="indent">size - the size of memory block in bytes.
+ <li class="indent">buf - buffer which contains values which will be copied to memory block.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ACCESS_DENIED - access to the memory block is denied.
+</ul>
+
+
+
+<h2><a name="1.12. Signals"></a>Signals</h2>
+
+<p><code>
+ncaiError JNICALL GetSignalCount
+<br>
+
+(ncaiEnv* env, jint* count_ptr);
+</code></p>
+
+<p>Get a number of signals supported by the platform.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">count_ptr - pointer to a jint which will be set on return with number of signals.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetSignalInfo
+<br>
+
+(ncaiEnv* env, jint signal, ncaiSignalInfo* info_ptr);
+</code></p>
+
+<p>Get the signal information. Fills the following structure:</p>
+
+<p><code>
+typedef struct {
+<br>
+
+char* name;
+<br>
+} ncaiSignalInfo;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">signal - the number of signal.
+ <li class="indent">info_ptr - pointer to a ncaiSignalInfo whose fields will be set on return with information.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - signal is not a valid signal number.
+</ul>
+
+
+
+<h2><a name="1.13. Miscellaneous"></a>Miscellaneous</h2>
+
+<p><code>
+ncaiError JNICALL GetJvmtiEnv
+<br>
+
+(ncaiEnv* env, jvmtiEnv** jvmti_env_ptr);
+</code></p>
+
+<p>Get JVMTI environment which NCAI environment extends.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">jvmti_env_ptr - pointer to a jvmtiEnv* which will be set on return with
+ appropriate JVMTI environment.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetVersion
+<br>
+
+(ncaiEnv* env, jint* version_ptr);
+</code></p>
+
+<p>Get the NCAI version number. The version number
+consists of major, minor and micro parts just like the JVMTI version
+identifier.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">version_ptr - pointer to a jint which will be set on return with actual version of
+ NCAI implementation.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetErrorName
+<br>
+
+(ncaiEnv* env, ncaiError err, const char** name_ptr);
+</code></p>
+
+<p>Get symbolic representation for the given error code.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">name_ptr - pointer to a char* which will be set on return with address of a
+ newly allocated array of characters. The array should be freed by
+ JVMTI function Deallocate.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - err is not a valid ncaiError.
+</ul>
+
+
+
+<h2><a name="1.14. Capabilities"></a>Capabilities</h2>
+
+<p><code>
+typedef struct {
+<br>
+
+// ...
+<br>
+} ncaiCapabilities;
+</code></p>
+
+<p><code>
+ncaiError JNICALL GetPotentialCapabilities
+<br>
+
+(ncaiEnv* env, ncaiCapabilities* caps_ptr);
+</code></p>
+
+<p>Get capabilities which the NCAI environment can potentially possess.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">caps_ptr - pointer to ncaiCapabilities which will be set on return with
+ potential capabilities.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL GetCapabilities
+<br>
+
+(ncaiEnv* env, ncaiCapabilities* caps_ptr);
+</code></p>
+
+<p>Get currently possessed capabilities.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">caps_ptr - pointer to ncaiCapabilities which will be set on return with
+ possessed capabilities.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL AddCapabilities
+<br>
+
+(ncaiEnv* env, ncaiCapabilities* caps_ptr);
+</code></p>
+
+<p>Add the specified capabilities.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">caps_ptr - pointer to ncaiCapabilities to add.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL RelinquishCapabilities
+<br>
+
+(ncaiEnv* env, ncaiCapabilities* caps_ptr);
+</code></p>
+
+<p>Relinquish the specified capabilities.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">caps_ptr - pointer to ncaiCapabilities to relinquish.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+
+
+<h2><a name="1.15. Event Management"></a>Event Management</h2>
+
+<p><code>
+ncaiError JNICALL GetEventCallbacks
+<br>
+
+(ncaiEnv* env, ncaiEventCallbacks* callbacks, size_t size);
+</code></p>
+
+<p>Get the event callbacks.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">callbacks - pointer to ncaiEventCallbacks which will be set on return with
+ current event callbacks.
+ <li class="indent">size - the size of callbacks.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetEventCallbacks
+<br>
+
+(ncaiEnv* env, ncaiEventCallbacks* callbacks, size_t size);
+</code></p>
+
+<p>Set the event callbacks.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">callbacks - pointer to ncaiEventCallbacks to set.
+ <li class="indent">size - the size of callbacks.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">no function specific errors.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetEventNotificationMode
+<br>
+
+(ncaiEnv* env, ncaiEventMode mode, ncaiEventKind event, ncaiThread thread);
+</code></p>
+
+<p>
+Set the event notification mode for the given
+thread. If thread is NULL, the mode is set for all the known threads.
+The ncaiEventMode and ncaiEventKind are the following:</p>
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_ENABLE = 1,
+<br>
+
+NCAI_DISABLE = 0
+<br>
+} ncaiEventMode;
+</code></p>
+
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_EVENT_THREAD_START = 1,
+<br>
+
+NCAI_EVENT_THREAD_END,
+<br>
+
+NCAI_EVENT_BREAKPOINT,
+<br>
+
+NCAI_EVENT_STEP,
+<br>
+
+NCAI_EVENT_WATCHPOINT,
+<br>
+
+NCAI_EVENT_METHOD_ENTRY,
+<br>
+
+NCAI_EVENT_METHOD_EXIT,
+<br>
+
+NCAI_EVENT_FRAME_POP,
+<br>
+
+NCAI_EVENT_SIGNAL,
+<br>
+
+NCAI_EVENT_EXCEPTION,
+<br>
+
+NCAI_EVENT_MODULE_LOAD,
+<br>
+
+NCAI_EVENT_MODULE_UNLOAD,
+<br>
+
+NCAI_EVENT_CONSOLE_INPUT,
+<br>
+
+NCAI_EVENT_CONSOLE_OUTPUT,
+<br>
+
+NCAI_EVENT_DEBUG_OUTPUT
+<br>
+} ncaiEventKind;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">mode - the mode to set.
+ <li class="indent">event - the event to control.
+ <li class="indent">thread - the thread to control.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - mode or event is not valid.
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetBreakpoint
+<br>
+
+(ncaiEnv* env, void* code_addr);
+</code></p>
+
+<p>Set a breakpoint at the given address code_addr.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">code_addr - the native address of the breakpoint.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_DUPLICATE - the designated breakpoint is already set.
+</ul>
+
+<p><code>
+ncaiError JNICALL ClearBreakpoint
+<br>
+
+(ncaiEnv* env, void* code_addr);
+</code></p>
+
+<p>Clear a breakpoint at the given address code_addr.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">code_addr - the native address of the breakpoint.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_NOT_FOUND - the designated breakpoint is not found.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetWatchpoint
+<br>
+
+(ncaiEnv* env, void* data_addr, size_t len, ncaiWatchpointMode mode);
+</code></p>
+
+<p>Set a watchpoint starting at the given address data_addr for len bytes.</p>
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_WATCHPOINT_READ,
+<br>
+
+NCAI_WATCHPOINT_WRITE,
+<br>
+
+NCAI_WATCHPOINT_ACCESS
+<br>
+} ncaiWatchpointMode;
+</code></p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">data_addr - the starting address of memory block to watch.
+ <li class="indent">len - the length in bytes of the memory block.
+ <li class="indent">mode - the mode to watch.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_DUPLICATE - the designated watchpoint is already set.
+</ul>
+
+<p><code>
+ncaiError JNICALL ClearWatchpoint
+<br>
+
+(ncaiEnv* env, void* data_addr);
+</code></p>
+
+<p>Clear a watchpoint starting at the given address data_addr.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">data_addr - the starting address of watching memory block.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_NOT_FOUND - the designated watchpoint is not found.
+</ul>
+
+<p><code>
+ncaiError JNICALL SetStepMode
+<br>
+
+(ncaiEnv* env, ncaiThread thread, ncaiStepMode mode);
+</code></p>
+
+<p>Set the step mode for the given thread. If thread is NULL, the mode is set for all the known threads.</p>
+
+<p class="indent"><code>
+typedef enum {
+<br>
+
+NCAI_STEP_OFF,
+<br>
+
+NCAI_STEP_INTO,
+<br>
+
+NCAI_STEP_OVER,
+<br>
+
+NCAI_STEP_OUT
+<br>
+} ncaiStepMode;
+</code></p>
+
+<p>NCAI_STEP_OFF disables generating step events for the given thread, NCAI_STEP_INTO
+enables generating step event for each CPU instruction,
+NCAI_STEP_OVER enables generating step event for each CPU instruction
+skipping function calls, NCAI_STEP_OUT disables generating step
+event untill the function returns.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to control.
+ <li class="indent">mode - the mode to set.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_ILLEGAL_ARGUMENT - mode is not valid.
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+</ul>
+
+<p><code>
+ncaiError JNICALL NotifyFramePop
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* frame_address);
+</code></p>
+
+<p>Set a trigger to notify when the frame of the given address is popped from the given thread stack.</p>
+
+<p class="indent">Parameters:</p>
+<ul>
+ <li class="indent">thread - the thread to watch.
+ <li class="indent">frame_addr - the address of frame to watch.
+</ul>
+
+<p class="indent">Errors:</p>
+<ul>
+ <li class="indent">NCAI_ERROR_INVALID_THREAD - thread is not a valid ncaiThread.
+ <li class="indent">NCAI_ERROR_THREAD_NOT_ALIVE - the thread is not alive.
+ <li class="indent">NCAI_ERROR_NOT_FOUND - the designated frame is not found.
+</ul>
+
+
+
+<h2><a name="1.16. Event Callbacks"></a>Event Callbacks</h2>
+
+<p>The following callbacks are called from within an appropriate application thread
+and are not queued by the VM.</p>
+
+<p><code>
+void JNICALL ThreadStart
+<br>
+
+(ncaiEnv* env, ncaiThread thread);
+</code></p>
+
+<p>This callback is invoked when the thread is about to enter its initial method.</p>
+
+<p><code>
+void JNICALL ThreadEnd
+<br>
+
+(ncaiEnv* env, ncaiThread thread);
+</code></p>
+
+<p>This callback is invoked just after the thread exits its initial method.</p>
+
+<p><code>
+void JNICALL Step
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr);
+</code></p>
+
+<p>This callback is invoked when the native thread specified in SetStepMode
+request reaches a new native instruction address according to the
+specified step mode.</p>
+
+
+<p><code>
+void JNICALL Breakpoint
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr);
+</code></p>
+
+<p>
+This callback is invoked when the native thread
+specified in SetBreakpoint request reaches the specified native
+instruction address.</p>
+
+<p><code>
+void JNICALL Watchpoint
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* code_addr, void* data_addr);
+</code></p>
+
+<p>
+This callback is invoked when the native thread
+specified in SetWatchpoint request accesses the specified native data
+address according to the specified watchpoint mode.</p>
+
+<p><code>
+void JNICALL Signal
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr, jint signal, jboolean is_internal, jboolean* is_handled);
+</code></p>
+
+<p>
+This callback is invoked when OS notifies the VM
+process about a raised signal. is_internal indicates whether the VM
+raises the signal for internal use. is_handled is in/out flag which
+indicates whether the VM will handle the signal or not. The actual
+set of possible signals depends on platform.</p>
+
+<p><code>
+void JNICALL Exception
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr, void* exception);
+</code></p>
+
+<p>This callback is invoked when C++ exception is thrown. <i>TBD</i>.</p>
+
+<p><code>
+void JNICALL ModuleLoad
+<br>
+
+(ncaiEnv* env, ncaiThread thread, ncaiModule module);
+</code></p>
+
+<p>This callback is invoked when the VM process loads an executable module.</p>
+
+<p><code>
+void JNICALL ModuleUnload
+<br>
+
+(ncaiEnv* env, ncaiThread thread, ncaiModule module);
+</code></p>
+
+<p>This callback is invoked when the VM process is about to unload an executable module.</p>
+
+<p><code>
+void JNICALL MethodEntry
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr);
+</code></p>
+
+<p>This callback is invoked when the thread is about to enter a method.</p>
+
+<p><code>
+void JNICALL MethodExit
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr);
+</code></p>
+
+<p>This callback is invoked when the thread is about to exit a method.</p>
+
+<p><code>
+void JNICALL FramePop
+<br>
+
+(ncaiEnv* env, ncaiThread thread, void* addr);
+</code></p>
+
+<p>This callback is invoked when the thread is about to exit a frame
+specified in NotifyFramePop request.</p>
+
+<p><code>
+void JNICALL ConsoleInput
+<br>
+
+(ncaiEnv* env, char** message);
+</code></p>
+
+<p> This callback is invoked when the VM process tries to read data from standard input. <i>TBD</i>.</p>
+
+<p><code>
+void JNICALL ConsoleOutput
+<br>
+
+(ncaiEnv* env, char* message);
+</code></p>
+
+<p>This callback is invoked when the VM process is about to write a message to standard output. <i>TBD</i>.</p>
+
+<p><code>
+void JNICALL DebugMessage
+<br>
+
+(ncaiEnv* env, char* message);
+</code></p>
+
+<p>This callback is invoked when the VM process sends a debug message. <i>TBD</i>.</p>
+
+
+
+<h2><a name="1.17. Error codes"></a>Error codes</h2>
+
+<p>The following is a list of possible error codes which can be returned by
+NCAI functions. <i>Universal errors</i> can be returned by any
+function and so they are not specified in the above function error
+lists. On the contrary <i>function specific errors</i> can be
+returned only by the functions which include them in the function
+errors specification.</p>
+
+
+<h3><a name="1.17.1. Universal errors"></a>Universal errors</h3>
+
+<p>
+NCAI_ERROR_NONE
+<br>
+<span class="indent">Indicates a successful completion of the function.</span>
+</p>
+
+<p>
+NCAI_ERROR_NULL_POINTER
+<br>
+<span class="indent">A pointer argument is equal to 0 which is not acceptable for the function.</span>
+</p>
+
+<p>NCAI_ERROR_OUT_OF_MEMORY
+<br>
+<span class="indent">Not enough allocatable memory available to process the function.</span>
+</p>
+
+<p>NCAI_ERROR_ACCESS_DENIED
+<br>
+<span class="indent">Access is denied.</span>
+</p>
+
+<p>NCAI_ERROR_UNATTACHED_THREAD
+<br>
+<span class="indent">The calling thread is not attached to the VM.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_ENVIRONMENT
+<br>
+<span class="indent">The NCAI environment is not valid.</span>
+</p>
+
+<p>NCAI_ERROR_INTERNAL
+<br>
+<span class="indent">An unexpected internal error.</span>
+</p>
+
+<p>NCAI_ERROR_ILLEGAL_ARGUMENT
+<br>
+<span class="indent">Illegal value of argument.</span>
+</p>
+
+
+<h3><a name="1.17.2. Function specific errors"></a>Function specific errors</h3>
+
+<p>NCAI_ERROR_NOT_AVAILABLE
+<br>
+<span class="indent">Function is not implemented.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_MODULE
+<br>
+<span class="indent">The module specified by argument is not a valid ncaiModule.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_METHOD
+<br>
+<span class="indent">The method specified by argument is not a valid jmethodID.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_LOCATION
+<br>
+<span class="indent">The location specified by argument is not a valid location.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_ADDRESS
+<br>
+<span class="indent">The address specified by argument is not valid.</span>
+</p>
+
+<p>NCAI_ERROR_INVALID_THREAD
+<br>
+<span class="indent">The thread specified by argument is not a valid ncaiThread.</span>
+</p>
+
+<p>NCAI_ERROR_THREAD_SUSPENDED
+<br>
+<span class="indent">The thread specified by argument is suspended.</span>
+</p>
+
+<p>NCAI_ERROR_THREAD_NOT_SUSPENDED
+<br>
+<span class="indent">The thread specified by argument is not suspended.</span>
+</p>
+
+<p>NCAI_ERROR_THREAD_NOT_ALIVE
+<br>
+<span class="indent">The thread specified by argument is not alive.</span>
+</p>
+
+<p>NCAI_ERROR_INTERPRETER_USED
+<br>
+<span class="indent">VM was started in interpreter mode.</span>
+</p>
+
+<p>NCAI_ERROR_NOT_COMPILED
+<br>
+<span class="indent">The method is not compiled yet.</span>
+</p>
+
+<p>NCAI_ERROR_DUPLICATE
+<br>
+<span class="indent">The designated breakpoint is already set.</span>
+</p>
+
+<p>NCAI_ERROR_NOT_FOUND
+<br>
+<span class="indent">The designated breakpoint is not found.</span>
+</p>
+
+
+
+<h2><a name="1.18. Appendix 1. Priorities"></a>Appendix 1. Priorities</h2>
+
+<p>The following table reflects our view on implementation priorities.</p>
+
+<table width=450 border="1" bordercolor="#000000" cellpadding="3" cellspacing="0">
+ <col width="40%">
+ <col width="16%">
+ <col width="24%">
+ <col width="20%">
+ <tr>
+ <td class="header">
+ Function Name
+ <td class="header">
+ Priority
+ <td class="header">
+ Comments
+ <td class="header">
+ Capability
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Modules
+ </tr>
+ <tr>
+ <td>GetAllLoadedModules
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetModuleInfo
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetModuleClassLoader
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ <B>Methods
+ </tr>
+ <tr>
+ <td>IsMethodCompiled
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetMethodLocation
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>FindJavaMethod
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetBytecodeLocation
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetNativeLocation
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Threads
+ </tr>
+ <tr>
+ <td>GetAllThreads
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetThreadInfo
+ <td>Medium
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetThreadHandle
+ <td>Medium
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetThreadObject
+ <td>Medium
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>SuspendThread
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ResumeThread
+ <td>High
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>TerminateThread
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetThreadState
+ <td>Medium
+ <td><i>TBD</i>
+ <td>Required
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Frames
+ </tr>
+ <tr>
+ <td>GetFrameCount
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetStackTrace
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Registers
+ </tr>
+ <tr>
+ <td>GetRegisterCount
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetRegisterInfo
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetRegisterValue
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>SetRegisterValue
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Memory
+ </tr>
+ <tr>
+ <td>ReadMemory
+ <td>High
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>WriteMemory
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Signals
+ </tr>
+ <tr>
+ <td>GetSignalCount
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>GetSignalInfo
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Miscellaneous
+ </tr>
+ <tr>
+ <td>GetJvmtiEnv
+ <td>Low
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetVersion
+ <td>Low
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetErrorName
+ <td>Low
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Capabilities
+ </tr>
+ <tr>
+ <td>GetPotentialCapabilities
+ <td>Medium
+ <td><i>TBD</i>
+ <td>Required
+ </tr>
+ <tr>
+ <td>AddCapabilities
+ <td>Medium
+ <td><i>TBD</i>
+ <td>Required
+ </tr>
+ <tr>
+ <td>RelinquishCapabilities
+ <td>Medium
+ <td><i>TBD</i>
+ <td>Required
+ </tr>
+ <tr>
+ <td>GetCapabilities
+ <td>Medium
+ <td><i>TBD</i>
+ <td>Required
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Event Management
+ </tr>
+ <tr>
+ <td>GetEventCallbacks
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>SetEventCallbacks
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>SetEventNotificationMode
+ <td>High
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>SetBreakpoint
+ <td>High
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ClearBreakpoint
+ <td>High
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>SetWatchpoint
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ClearWatchpoint
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>SetStepMode
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>NotifyFramePop
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td colspan="4" class="bold">
+ Event Callbacks
+ </tr>
+ <tr>
+ <td>ThreadStart
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ThreadEnd
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>Step
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>Breakpoint
+ <td>High
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>Watchpoint
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>Signal
+ <td>Medium
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>Exception
+ <td>Low
+ <td><i>TBD</i>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ModuleLoad
+ <td>Medium
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>ModuleUnload
+ <td>Medium
+ <td>
+ <td>Required
+ </tr>
+ <tr>
+ <td>MethodEntry
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>MethodExit
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>FramePop
+ <td>Low
+ <td>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ConsoleInput
+ <td>Low
+ <td><i>TBD</i>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>ConsoleOutput
+ <td>Low
+ <td><i>TBD</i>
+ <td>Optional
+ </tr>
+ <tr>
+ <td>DebugMessage
+ <td>Low
+ <td><i>TBD</i>
+ <td>Optional
+ </tr>
+</table>
+
+
+</BODY>
+</HTML>
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/NCAI.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/README
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/README?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/README (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/README Wed Nov 21 08:29:40 2007
@@ -0,0 +1,119 @@
+
+NCAI (Native Code Access Interface)
+--------------------------------------
+
+This directory contains the source code of Native Code Access Interface
+(NCAI) implementation in the VM core component, which is the important part of
+NCAI implementation. Additionally, NCAI involves other components, such as
+the thread manager (TM) and the interpreter.
+
+
+Implementation notes
+------------------------
+
+This section describes differences between the current NCAI implementation and
+the NCAI interface description (see NCAI.html document).
+
+Notes are divided into functional groups, as in NCAI interface description.
+
+General
+-------
+1. NCAI interface is not fully implemented now. Unimplemented features
+are listed below.
+2. Most features are implemented for IA-32 architecture only.
+
+Threads
+-------
+1. In the current NCAI implementation, threads are only TM threads.
+The GetAllThreads() function returns only threads attached to the thread
+manager, including Java threads, JVMTI agent threads, VM special threads
+or native threads attached to VM with the AttachCurrentThread() function.
+Native threads created using OS API and not attached to the VM are not
+reported.
+
+2. The thread list obtained with GetAllThreads() is not preserved until
+the next GetAllThreads() call, as specified in the interface description.
+That is, the GetThreadInfo() function can return NCAI_ERROR_THREAD_NOT_ALIVE
+if the corresponding thread was terminated after the last call to
+GetAllThreads() where thread handle was obtained.
+
+3. The NCAI suspend mechanism makes use of the suspend count: user code can
+suspend a thread many times but must resume it the same number of times.
+Therefore, a call to SuspendThread() never returns NCAI_ERROR_THREAD_SUSPENDED,
+as specified in the NCAI interface description.
+
+Frames
+------
+Stack walking algorithms for GetStackTrace() and GetFrameCount() functions
+are heuristic: these functions can return a partial stack trace if the stack
+walking algorithm is unable to unwind the stack any more, especially for code
+compiled with optimizations.
+
+Registers
+---------
+Functions GetRegisterValue() and SetRegisterValue() operate with register
+context saved while executing SuspendThread(). Thus, these functions work only
+for suspended threads and not for threads that are in a breakpoint or a step
+callback.
+
+Capabilities
+------------
+Capabilities are not implemented in the current version. All implemented
+features are enabled.
+
+Single Step
+------------
+Single stepping uses disassembling to predict the following instructions.
+Unlike JITted code that uses limited set of instructions, native code generated
+by common compilers may contain any instructions allowed in particular processor
+architecture. Thus the decoder used for disassembling should be extended to
+the whole set of processor instructions.
+Currently the decoder is extended with most frequently used instructions, but
+it does not cover the whole IA-32 instruction set. Therefore some errors may
+occur during single stepping through the native code if the decoder meets
+an unrecognized processor instruction.
+
+Event Callbacks
+---------------
+1. The signal callback can be called when VM is stopped, which imposes certain
+restrictions on event handler code: the event handler must not use JNI
+and JVMTI functions except in special cases (see GarbageCollectionStart and
+GarbageCollectionFinish events in JVMTI spec.)
+
+2. Although GetAllLoadedModules() returns all modules loaded into the VM process,
+ModuleLoad() and ModuleUnload() callbacks are called only for modules loaded by
+VM itself, which are JNI libraries loaded by Java code, including VM-internal
+JNI libraries.
+
+
+Unimplemented features
+--------------------------
+
+The list of unimplemented functions:
+
+GetModuleClassLoader
+FindJavaMethod
+GetBytcodeLocation
+GetThreadState
+GetVersion
+GetErrorName
+GetPotentialCapabilities
+GetCapabilities
+AddCapabilities
+RelinquishCapabilities
+SetWatchpoint
+ClearWatchpoint
+NotifyFramePop
+
+The list of unimplemented event callbacks:
+
+ThreadStart
+ThreadEnd
+Watchpoint
+Exception
+MethodEntry
+MethodExit
+FramePop
+ConsoleInput
+ConsoleOutput
+DebugMessage
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/README
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai.cpp?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai.cpp Wed Nov 21 08:29:40 2007
@@ -0,0 +1,208 @@
+/**
+ * @author Intel, Petr Ivanov
+ * @version $Revision$
+ */
+
+#define LOG_DOMAIN "ncai"
+#include "cxxlog.h"
+#include "jvmti_internal.h"
+#include "suspend_checker.h"
+#include "environment.h"
+#include "jvmti_break_intf.h"
+#include "ncai_direct.h"
+#include "ncai_internal.h"
+
+#include "ncai.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// Stubs for functions which are not implemented yet
+// FIXME: Possibly will be not needed after Capabilities implementation
+static ncaiError JNICALL ncaiGetModuleClassLoaderStub(ncaiEnv*,ncaiModule,jobject*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiFindJavaMethodStub(ncaiEnv*,void*,jmethodID*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetBytcodeLocationStub(ncaiEnv* env, void* address, jmethodID* method, jlocation* location_ptr)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetThreadStateStub(ncaiEnv*,ncaiThread,jint*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetVersionStub(ncaiEnv*,jint*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetErrorNameStub(ncaiEnv*,ncaiError,const char**)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetPotentialCapabilitiesStub(ncaiEnv*,ncaiCapabilities*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiGetCapabilitiesStub(ncaiEnv*,ncaiCapabilities*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiAddCapabilitiesStub(ncaiEnv*,ncaiCapabilities*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiRelinquishCapabilitiesStub(ncaiEnv*,ncaiCapabilities*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiSetWatchpointStub(ncaiEnv*,void*,size_t,ncaiWatchpointMode)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiClearWatchpointStub(ncaiEnv*,void*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+static ncaiError JNICALL ncaiNotifyFramePopStub(ncaiEnv*,ncaiThread,void*)
+{ return NCAI_ERROR_NOT_AVAILABLE; }
+
+// Function table
+const struct _ncai ncai_table =
+{
+ ncaiGetAllLoadedModules,
+ ncaiGetModuleInfo,
+ ncaiGetModuleClassLoaderStub, //ncaiGetModuleClassLoader,
+ ncaiIsMethodCompiled,
+ ncaiGetMethodLocation,
+ ncaiFindJavaMethodStub, //ncaiFindJavaMethod,
+ ncaiGetBytcodeLocationStub, //ncaiGetBytcodeLocation,
+ ncaiGetNativeLocation,
+ ncaiGetAllThreads,
+ ncaiGetThreadInfo,
+ ncaiGetThreadHandle,
+ ncaiGetThreadObject,
+ ncaiSuspendThread,
+ ncaiResumeThread,
+ ncaiTerminateThread,
+ ncaiGetThreadStateStub, //ncaiGetThreadState,
+ ncaiGetFrameCount,
+ ncaiGetStackTrace,
+ ncaiGetRegisterCount,
+ ncaiGetRegisterInfo,
+ ncaiGetRegisterValue,
+ ncaiSetRegisterValue,
+ ncaiReadMemory,
+ ncaiWriteMemory,
+ ncaiGetSignalCount,
+ ncaiGetSignalInfo,
+ ncaiGetJvmtiEnv,
+ ncaiGetVersionStub, //ncaiGetVersion,
+ ncaiGetErrorNameStub, //ncaiGetErrorName,
+ ncaiGetPotentialCapabilitiesStub, //ncaiGetPotentialCapabilities,
+ ncaiGetCapabilitiesStub, //ncaiGetCapabilities,
+ ncaiAddCapabilitiesStub, //ncaiAddCapabilities,
+ ncaiRelinquishCapabilitiesStub, //ncaiRelinquishCapabilities,
+ ncaiGetEventCallbacks,
+ ncaiSetEventCallbacks,
+ ncaiSetEventNotificationMode,
+ ncaiSetBreakpoint,
+ ncaiClearBreakpoint,
+ ncaiSetWatchpointStub, //ncaiSetWatchpoint,
+ ncaiClearWatchpointStub, //ncaiClearWatchpoint,
+ ncaiSetStepMode,
+ ncaiNotifyFramePopStub, //ncaiNotifyFramePop,
+};
+
+jvmtiError create_ncai_environment(jvmtiEnv* jvmti_env, NCAIEnv** penv)
+{
+ TRACE2("jvmti.ncai", "create_ncai_environment called");
+
+ TIEnv *ti_env = (TIEnv *)jvmti_env;
+ NCAIEnv *newenv;
+ jvmtiError error_code;
+
+ error_code = _allocate(sizeof(NCAIEnv), (unsigned char**)&newenv);
+ if (error_code != JVMTI_ERROR_NONE)
+ {
+ *penv = NULL;
+ return error_code;
+ }
+
+ newenv->functions = &ncai_table;
+ newenv->ti_env = ti_env;
+ newenv->modules = NULL;
+ ti_env->ncai_env = newenv;
+ memset(&newenv->event_table, 0, sizeof(ncaiEventCallbacks));
+ memset(&newenv->global_events, 0, sizeof(newenv->global_events));
+ memset(&newenv->event_threads, 0, sizeof(newenv->event_threads));
+
+ newenv->env_lock = new Lock_Manager();
+ assert(newenv->env_lock);
+
+ // Acquire interface for breakpoint handling
+ newenv->brpt_intf =
+ VM_Global_State::loader_env->TI->vm_brpt->new_intf(ti_env,
+ ncai_process_breakpoint_event, PRIORITY_NCAI_BREAKPOINT, false);
+ assert(newenv->brpt_intf);
+
+ *penv = newenv;
+ TRACE2("jvmti.ncai", "New NCAI environment created: " << newenv);
+ return JVMTI_ERROR_NONE;
+}
+
+
+jvmtiError JNICALL jvmtiGetNCAIEnvironment(jvmtiEnv* jvmti_env, ...)
+{
+ TRACE2("jvmti.ncai", "GetNCAIEnvironment called");
+ SuspendEnabledChecker sec;
+
+ va_list args;
+ va_start(args, jvmti_env);
+ // GetExtensionEnv function has following prototype:
+ // GetExtensionEnv(jvmtiEnv* jvmti_env, void** ncai_env_ptr, jint version);
+ NCAIEnv** penv = (NCAIEnv**)va_arg(args, void**);
+ jint version = (jint)va_arg(args, jint);
+ va_end(args);
+
+ if (penv == NULL)
+ return JVMTI_ERROR_NULL_POINTER;
+
+ jint vmajor = (version & NCAI_VERSION_MASK_MAJOR) >> NCAI_VERSION_SHIFT_MAJOR;
+ jint vminor = (version & NCAI_VERSION_MASK_MINOR) >> NCAI_VERSION_SHIFT_MINOR;
+ jint vmicro = (version & NCAI_VERSION_MASK_MICRO) >> NCAI_VERSION_SHIFT_MICRO;
+ if (vmajor > NCAI_VERSION_MAJOR ||
+ vminor > NCAI_VERSION_MINOR ||
+ vmicro > NCAI_VERSION_MICRO)
+ {
+ *penv = NULL;
+ return JVMTI_ERROR_NOT_AVAILABLE;
+ }
+
+ GlobalNCAI* ncai = VM_Global_State::loader_env->NCAI;
+
+ TIEnv* ti_env = (TIEnv*)jvmti_env;
+ if (ti_env->ncai_env != NULL)
+ {
+ *penv = ti_env->ncai_env;
+ ncai->enabled = true;
+ return JVMTI_ERROR_NONE;
+ }
+
+ jvmtiError err = create_ncai_environment(jvmti_env, penv);
+
+ if (err == JVMTI_ERROR_NONE)
+ ncai->enabled = true;
+
+ return err;
+}
+
+ncaiError JNICALL ncaiGetJvmtiEnv(ncaiEnv *env, jvmtiEnv** jvmti_env_ptr)
+{
+ if (env == NULL)
+ return NCAI_ERROR_INVALID_ENVIRONMENT;
+
+ if (jvmti_env_ptr == NULL)
+ return NCAI_ERROR_NULL_POINTER;
+
+ *jvmti_env_ptr = (jvmtiEnv*)((NCAIEnv*)env)->ti_env;
+
+ return NCAI_ERROR_NONE;
+}
+
+GlobalNCAI::GlobalNCAI():
+ enabled(false),
+ modules(NULL),
+ step_enabled(false),
+ step_mode(NCAI_STEP_INTO)
+{
+}
+
+GlobalNCAI::~GlobalNCAI()
+{
+ // Clean modules list
+ clean_all_modules(&modules);
+}
+
+bool GlobalNCAI::isEnabled()
+{
+ return VM_Global_State::loader_env->NCAI &&
+ VM_Global_State::loader_env->NCAI->enabled;
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_break.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_break.cpp?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_break.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_break.cpp Wed Nov 21 08:29:40 2007
@@ -0,0 +1,152 @@
+/**
+ * @author Ilya Berezhniuk
+ * @version $Revision$
+ */
+
+//#include <memory.h>
+//#include <string.h>
+//#include <stdio.h>
+
+#define LOG_DOMAIN "ncai.break"
+#include "cxxlog.h"
+#include "suspend_checker.h"
+#include "jvmti_break_intf.h"
+
+#include "ncai_utils.h"
+#include "ncai_direct.h"
+#include "ncai_internal.h"
+
+
+// Callback function for NCAI breakpoint processing
+bool ncai_process_breakpoint_event(TIEnv *env, const VMBreakPoint* bp,
+ const POINTER_SIZE_INT data)
+{
+ TRACE2("ncai.break", "BREAKPOINT occured, location = " << bp->addr);
+
+ VM_thread* vm_thread = p_TLS_vmthread;
+ if (!vm_thread)
+ return false;
+
+ jvmti_thread_t jvmti_thread = &vm_thread->jvmti_thread;
+
+ // This check works for current thread only
+ if (jvmti_thread->flag_ncai_handler) // Recursion
+ return true;
+
+ jvmti_thread->flag_ncai_handler = true;
+
+ NCAIEnv* ncai_env = env->ncai_env;
+ void* addr = (void*)bp->addr;
+
+ bool suspend_enabled = hythread_is_suspend_enabled();
+
+ if (!suspend_enabled)
+ hythread_suspend_enable();
+
+ hythread_t hythread = hythread_self();
+ ncaiThread thread = reinterpret_cast<ncaiThread>(hythread);
+
+ ncaiBreakpoint func =
+ (ncaiBreakpoint)ncai_env->get_event_callback(NCAI_EVENT_BREAKPOINT);
+
+ if (NULL != func)
+ {
+ if (ncai_env->global_events[NCAI_EVENT_BREAKPOINT - NCAI_MIN_EVENT_TYPE_VAL])
+ {
+ TRACE2("ncai.break", "Calling global breakpoint callback, address = " << addr);
+
+ func((ncaiEnv*)ncai_env, thread, addr);
+
+ TRACE2("ncai.break", "Finished global breakpoint callback, address = " << addr);
+ }
+ else
+ {
+
+ ncaiEventThread* next_et;
+ ncaiEventThread* first_et =
+ ncai_env->event_threads[NCAI_EVENT_BREAKPOINT - NCAI_MIN_EVENT_TYPE_VAL];
+
+ for (ncaiEventThread* et = first_et; NULL != et; et = next_et)
+ {
+ next_et = et->next;
+
+ if (et->thread == thread)
+ {
+ TRACE2("ncai.break", "Calling local breakpoint callback, address = " << addr);
+
+ func((ncaiEnv*)ncai_env, thread, addr);
+
+ TRACE2("ncai.break", "Finished local breakpoint callback, address = " << addr);
+ }
+
+ et = next_et;
+ }
+ }
+ }
+
+ if (!suspend_enabled)
+ hythread_suspend_disable();
+
+ jvmti_thread->flag_ncai_handler = false;
+ return true;
+}
+
+
+ncaiError JNICALL
+ncaiSetBreakpoint(ncaiEnv *env, void* code_addr)
+{
+ TRACE2("ncai.break", "SetBreakpoint called");
+ SuspendEnabledChecker sec;
+
+ if (env == NULL)
+ return NCAI_ERROR_INVALID_ENVIRONMENT;
+
+ if (code_addr == NULL)
+ return NCAI_ERROR_INVALID_ADDRESS;
+
+ NCAIEnv *p_env = (NCAIEnv*)env;
+ VMBreakInterface* brpt_intf = p_env->brpt_intf;
+ VMBreakPoints *vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
+ LMAutoUnlock lock(vm_breaks->get_lock());
+
+ VMBreakPointRef* bp_ref = brpt_intf->find_reference(code_addr);
+
+ if (NULL != bp_ref)
+ return NCAI_ERROR_DUPLICATE;
+
+ if (!brpt_intf->add_reference(code_addr, 0))
+ return NCAI_ERROR_INTERNAL;
+
+ TRACE2("ncai.break", "SetBreakpoint is successfull");
+ return NCAI_ERROR_NONE;
+}
+
+
+ncaiError JNICALL
+ncaiClearBreakpoint(ncaiEnv *env, void* code_addr)
+{
+ TRACE2("ncai.break", "ClearBreakpoint called");
+ SuspendEnabledChecker sec;
+
+ if (env == NULL)
+ return NCAI_ERROR_INVALID_ENVIRONMENT;
+
+ if (code_addr == NULL)
+ return NCAI_ERROR_INVALID_ADDRESS;
+
+ NCAIEnv *p_env = (NCAIEnv*)env;
+ VMBreakInterface* brpt_intf = p_env->brpt_intf;
+ VMBreakPoints *vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
+ LMAutoUnlock lock(vm_breaks->get_lock());
+
+ VMBreakPointRef* bp_ref = brpt_intf->find_reference(code_addr);
+
+ if (NULL == bp_ref)
+ return NCAI_ERROR_NOT_FOUND;
+
+ if (!brpt_intf->remove_reference(bp_ref))
+ return NCAI_ERROR_INTERNAL;
+
+ TRACE2("ncai.break", "ClearBreakpoint is successfull");
+ return NCAI_ERROR_NONE;
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_break.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_event.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_event.cpp?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_event.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_event.cpp Wed Nov 21 08:29:40 2007
@@ -0,0 +1,359 @@
+/**
+ * @author Intel, Petr Ivanov
+ * @version $Revision$
+ */
+
+/**
+ * NCAI event management
+ *
+ */
+
+#define LOG_DOMAIN "ncai.events"
+#include "cxxlog.h"
+
+#include "suspend_checker.h"
+#include "thread_generic.h"
+#include "environment.h"
+#include "jvmti_internal.h"
+#include "jvmti_break_intf.h"
+#include "open/ncai_thread.h"
+#include "ncai_direct.h"
+#include "ncai_internal.h"
+#include "ncai_utils.h"
+
+
+static ncaiError ncai_add_event_to_thread(ncaiEnv *, ncaiEventKind, ncaiThread);
+static void ncai_remove_event_from_thread(ncaiEnv *, ncaiEventKind, ncaiThread);
+static void ncai_add_event_to_global(ncaiEnv *, ncaiEventKind);
+static void ncai_remove_event_from_global(ncaiEnv *, ncaiEventKind);
+static ncaiError ncai_check_start_single_step(NCAIEnv* env);
+static ncaiError ncai_check_stop_single_step(NCAIEnv* env);
+
+/*
+ * Set Event Callbacks
+ *
+ * Set the functions to be called for each event.
+ *
+ */
+
+ncaiError JNICALL
+ncaiSetEventCallbacks(ncaiEnv* env,
+ ncaiEventCallbacks* callbacks,
+ size_t size)
+{
+ TRACE2("ncai.events", "SetEventCallbacks called");
+ SuspendEnabledChecker sec;
+
+ if (size <= 0)
+ return NCAI_ERROR_ILLEGAL_ARGUMENT;
+
+ if (callbacks != NULL)
+ memcpy(&(((NCAIEnv*)env)->event_table), callbacks, sizeof(ncaiEventCallbacks));
+ else
+ memset(&(((NCAIEnv*)env)->event_table), 0, sizeof(ncaiEventCallbacks));
+
+ return NCAI_ERROR_NONE;
+}
+
+/*
+ * Set Event Callbacks
+ *
+ * Get the list od functions to be called for each event.
+ *
+ */
+ncaiError JNICALL
+ncaiGetEventCallbacks(ncaiEnv* env,
+ ncaiEventCallbacks* callbacks,
+ size_t size)
+{
+ TRACE2("ncai.events", "GetEventCallbacks called");
+ SuspendEnabledChecker sec;
+
+ if (size <= 0)
+ return NCAI_ERROR_ILLEGAL_ARGUMENT;
+
+ if (callbacks == NULL)
+ return NCAI_ERROR_NULL_POINTER;
+
+ memcpy(callbacks, &(((NCAIEnv*)env)->event_table), sizeof(ncaiEventCallbacks));
+
+ return NCAI_ERROR_NONE;
+}
+
+/*
+ * Set Event Notification Mode
+ *
+ * Control the generation of events.
+ */
+ncaiError JNICALL
+ncaiSetEventNotificationMode(ncaiEnv* env,
+ ncaiEventMode mode,
+ ncaiEventKind event_type,
+ ncaiThread event_thread)
+{
+ TRACE2("ncai.event", "SetEventNotificationMode called," <<
+ "event type = " << event_type << " mode = " << mode);
+ SuspendEnabledChecker sec;
+
+ if (mode == NCAI_ENABLE)
+ {
+ if (event_thread == NULL)
+ ncai_add_event_to_global(env, event_type);
+ else
+ {
+ ncaiError result = ncai_add_event_to_thread(env, event_type, event_thread);
+ if (result != NCAI_ERROR_NONE)
+ return result;
+ }
+
+ if (event_type == NCAI_EVENT_STEP)
+ {
+ ncaiError result = ncai_check_start_single_step((NCAIEnv*)env);
+
+ if (result != NCAI_ERROR_NONE)
+ return result;
+ }
+ }
+ else if (mode == NCAI_DISABLE)
+ {
+ if (event_thread == NULL)
+ ncai_remove_event_from_global(env, event_type);
+ else
+ ncai_remove_event_from_thread(env, event_type, event_thread);
+
+ if (event_type == NCAI_EVENT_STEP)
+ {
+ ncaiError result = ncai_check_stop_single_step((NCAIEnv*)env);
+
+ if (result != NCAI_ERROR_NONE)
+ return result;
+ }
+ }
+ else
+ {
+ return NCAI_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ return NCAI_ERROR_NONE;
+}
+
+/*
+ * Set Step Mode for given thread
+ * If thread is NULL, set mode for all known threads
+ */
+ncaiError JNICALL
+ncaiSetStepMode(ncaiEnv* env,
+ ncaiThread thread,
+ ncaiStepMode mode)
+{
+ TRACE2("ncai.event", "SetStepMode called," <<
+ "thread = " << thread << " mode = " << mode);
+ SuspendEnabledChecker sec;
+
+ if (mode < NCAI_STEP_OFF || mode > NCAI_STEP_OUT)
+ return NCAI_ERROR_ILLEGAL_ARGUMENT;
+
+ GlobalNCAI* ncai = VM_Global_State::loader_env->NCAI;
+ hythread_t hythread = reinterpret_cast<hythread_t>(thread);
+ VMBreakPoints* vm_brpt = ((NCAIEnv*)env)->ti_env->vm->vm_env->TI->vm_brpt;
+ vm_thread_t vm_thread = jthread_get_vm_thread(hythread);
+
+ assert(vm_thread);
+ if (vm_thread == NULL)
+ return NCAI_ERROR_INTERNAL;
+
+ jvmti_thread_t jvmti_thread = &vm_thread->jvmti_thread;
+
+ LMAutoUnlock lock(vm_brpt->get_lock());
+
+ if (thread)
+ {
+ ncai_check_alloc_ss_data(jvmti_thread);
+ jvmti_thread->ncai_ss->use_local_mode = true;
+ jvmti_thread->ncai_ss->step_mode = mode;
+ jvmti_thread->ncai_ss->flag_out = false;
+ return NCAI_ERROR_NONE;
+ }
+
+ ncaiThread* threads;
+ jint thread_count;
+
+ ncaiError err = ncaiGetAllThreads((ncaiEnv*)env, &thread_count, &threads);
+
+ if (err != NCAI_ERROR_NONE)
+ return err;
+
+ assert(thread_count > 0);
+
+ for (jint i = 0; i < thread_count; i++)
+ {
+ hythread = (hythread_t)threads[i];
+ vm_thread = jthread_get_vm_thread(hythread);
+
+ if (!vm_thread)
+ continue;
+
+ ncai_check_alloc_ss_data(&vm_thread->jvmti_thread);
+ vm_thread->jvmti_thread.ncai_ss->use_local_mode = false;
+ vm_thread->jvmti_thread.ncai_ss->flag_out = false;
+ }
+
+ ncai->step_mode = mode;
+
+ return NCAI_ERROR_NONE;
+}
+
+
+//////////////////////
+// Helper Functions
+//////////////////////
+
+// Must be called under breakpoint lock
+ncaiStepMode ncai_get_thread_ss_mode(jvmti_thread_t jvmti_thread)
+{
+ assert(jvmti_thread->ncai_ss);
+
+ if (jvmti_thread->ncai_ss->use_local_mode)
+ return jvmti_thread->ncai_ss->step_mode;
+
+ return VM_Global_State::loader_env->NCAI->step_mode;
+}
+
+ncaiError ncai_add_event_to_thread(ncaiEnv *env, ncaiEventKind event_type,
+ ncaiThread event_thread)
+{
+ NCAIEnv *p_env = (NCAIEnv *)env;
+ ncaiEventThread *et =p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL];
+
+ // Find out if this environment is already registered
+ // on this thread on this event type
+ while (et != NULL)
+ {
+ if (et->thread == event_thread)
+ return NCAI_ERROR_NONE;
+
+ et = et->next;
+ }
+
+ ncaiEventThread *newet;
+ newet = (ncaiEventThread *) ncai_alloc(sizeof(ncaiEventThread));
+
+ if (newet == NULL)
+ return NCAI_ERROR_OUT_OF_MEMORY;
+
+ newet->thread = event_thread;
+
+ LMAutoUnlock aulock(p_env->env_lock); //ncai env general lock
+
+ newet->next = p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL];
+ p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL] = newet;
+ return NCAI_ERROR_NONE;
+}
+
+void ncai_remove_event_from_thread(ncaiEnv *env, ncaiEventKind event_type,
+ ncaiThread event_thread)
+{
+ NCAIEnv *p_env = (NCAIEnv *)env;
+ ncaiEventThread *et =
+ p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL];
+
+ LMAutoUnlock aulock(p_env->env_lock); //ncai env general lock
+
+ // Address of 'next' in previous list item or address of list root
+ // Is a place where current->next must be placed when removing item
+ ncaiEventThread **plast_next = &(p_env->event_threads[event_type - NCAI_MIN_EVENT_TYPE_VAL]);
+
+ // Find out if this environment is already registered
+ // on this thread on this event type
+ for (ncaiEventThread* current = et; current != NULL; current = current->next)
+ {
+ if (current->thread == event_thread)
+ {
+ *plast_next = current->next;
+ ncai_free(current);
+ return;
+ }
+ plast_next = ¤t->next;
+ }
+}
+
+void ncai_add_event_to_global(ncaiEnv *env, ncaiEventKind event_type)
+{
+ NCAIEnv *p_env = (NCAIEnv *)env;
+ p_env->global_events[event_type - NCAI_MIN_EVENT_TYPE_VAL] = true;
+}
+
+void ncai_remove_event_from_global(ncaiEnv *env, ncaiEventKind event_type)
+{
+ NCAIEnv *p_env = (NCAIEnv *)env;
+ p_env->global_events[event_type - NCAI_MIN_EVENT_TYPE_VAL] = false;
+}
+
+static ncaiError ncai_check_start_single_step(NCAIEnv* env)
+{
+ if (env->ti_env->vm->vm_env->NCAI->step_enabled)
+ return NCAI_ERROR_NONE;
+
+ return ncai_start_single_step(env);
+}
+
+static ncaiError ncai_check_stop_single_step(NCAIEnv* env)
+{
+ DebugUtilsTI* ti = env->ti_env->vm->vm_env->TI;
+ GlobalNCAI* ncai = env->ti_env->vm->vm_env->NCAI;
+
+ if (!ncai->step_enabled)
+ return NCAI_ERROR_NONE;
+
+ // Check that no environment has SingleStep enabled
+ LMAutoUnlock lock(&ti->TIenvs_lock);
+ bool disable = true;
+
+ for (TIEnv *ti_env = ti->getEnvironments(); ti_env;
+ ti_env = ti_env->next)
+ {
+ if (!ti_env->ncai_env)
+ continue;
+
+ if (ti_env->ncai_env->global_events[NCAI_EVENT_STEP - NCAI_MIN_EVENT_TYPE_VAL] ||
+ ti_env->ncai_env->event_threads[NCAI_EVENT_STEP - NCAI_MIN_EVENT_TYPE_VAL])
+ {
+ disable = false;
+ break;
+ }
+ }
+
+ return disable ? ncai_stop_single_step(env) : NCAI_ERROR_NONE;
+}
+
+void ncai_report_method_entry(jmethodID method)
+{
+ GlobalNCAI* ncai = VM_Global_State::loader_env->NCAI;
+
+ if (!GlobalNCAI::isEnabled())
+ return;
+
+ assert(method);
+
+ Method* m = reinterpret_cast<Method*>(method);
+ bool is_native = m->is_native();
+
+ if (is_native && ncai->step_enabled)
+ ncai_step_native_method_entry(m);
+}
+
+void ncai_report_method_exit(jmethodID method, jboolean exc_popped, jvalue ret_val)
+{
+ GlobalNCAI* ncai = VM_Global_State::loader_env->NCAI;
+
+ if (!GlobalNCAI::isEnabled())
+ return;
+
+ assert(method);
+
+ Method* m = reinterpret_cast<Method*>(method);
+ bool is_native = m->is_native();
+
+ if (is_native && ncai->step_enabled)
+ ncai_step_native_method_exit(m);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_event.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp?rev=597138&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp Wed Nov 21 08:29:40 2007
@@ -0,0 +1,168 @@
+/**
+ * @author Petr Ivanov
+ * @version $Revision$
+ */
+#define LOG_DOMAIN "ncai.memory"
+#include "cxxlog.h"
+#include "jvmti_break_intf.h"
+#include "environment.h"
+#include "jvmti_internal.h"
+#include "ncai_direct.h"
+#include "ncai_internal.h"
+
+
+struct BreakListItem
+{
+ VMBreakPoint* bp;
+ BreakListItem* next;
+};
+
+struct RewriteArray
+{
+ BreakListItem* array;
+ BreakListItem* list;
+ size_t size;
+ size_t count;
+};
+
+static void add_rewrite_address(RewriteArray* prwa, VMBreakPoint* bp);
+
+
+ncaiError JNICALL ncaiReadMemory(ncaiEnv* env,
+ void* addr, size_t size, void* buf)
+{
+ TRACE2("ncai.memory", "ReadMemory called");
+
+ if (!env)
+ return NCAI_ERROR_INVALID_ENVIRONMENT;
+
+ ncaiError err = ncai_read_memory(addr, size, buf);
+
+ if (err != NCAI_ERROR_NONE)
+ return err;
+
+ // Restore bytes changed by JVMTI/NCAI breakpoints
+ VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
+ LMAutoUnlock lock(vm_breaks->get_lock());
+
+ void* end_addr = (char*)addr + size;
+ jbyte* cbuf = (jbyte*)buf;
+
+ for (VMBreakPoint* cur = vm_breaks->get_first_breakpoint(); cur;
+ cur = vm_breaks->get_next_breakpoint(cur))
+ {
+ if (cur->addr >= addr && cur->addr < end_addr)
+ {
+ size_t offset = (size_t)cur->addr - (size_t)addr;
+ cbuf[offset] = cur->saved_byte;
+ }
+ }
+
+ return NCAI_ERROR_NONE;
+}
+
+ncaiError JNICALL ncaiWriteMemory(ncaiEnv* env,
+ void* addr, size_t size, void* buf)
+{
+ TRACE2("ncai.memory", "WriteMemory called");
+
+ if (!env)
+ return NCAI_ERROR_INVALID_ENVIRONMENT;
+
+ VMBreakPoints* vm_breaks = VM_Global_State::loader_env->TI->vm_brpt;
+ LMAutoUnlock lock(vm_breaks->get_lock());
+
+ jbyte* end_addr = (jbyte*)addr + size;
+ VMBreakPoint* cur;
+ size_t rewrite_count = 0;
+
+ // Count addresses in given range
+ for (cur = vm_breaks->get_first_breakpoint(); cur;
+ cur = vm_breaks->get_next_breakpoint(cur))
+ {
+ if (cur->addr >= addr && cur->addr < end_addr)
+ ++rewrite_count;
+ }
+
+ // Simple case: there are no breakpoints in specified address range
+ if (rewrite_count == 0)
+ return ncai_write_memory(addr, size, buf);
+
+ // Allocate array for address sorting
+ RewriteArray rwa;
+ rwa.array = (BreakListItem*)STD_MALLOC(rewrite_count*sizeof(BreakListItem));
+
+ if (!rwa.array)
+ return NCAI_ERROR_OUT_OF_MEMORY;
+
+ memset(rwa.array, 0, rewrite_count*sizeof(BreakListItem));
+ rwa.list = NULL;
+ rwa.size = rewrite_count;
+ rwa.count = 0;
+
+ // Add matching addresses to sorted list
+ for (cur = vm_breaks->get_first_breakpoint(); cur;
+ cur = vm_breaks->get_next_breakpoint(cur))
+ {
+ if (cur->addr >= addr && cur->addr < end_addr)
+ add_rewrite_address(&rwa, cur);
+ }
+
+ // Write memory
+ size_t remain = size;
+ BreakListItem* cur_bla = rwa.list;
+ assert(cur_bla);
+ jbyte* cbuf = (jbyte*)buf;
+ jbyte* cur_addr = (jbyte*)addr;
+ ncaiError err = NCAI_ERROR_NONE;
+
+ while (remain)
+ {
+ if (!cur_bla || cur_bla->bp->addr > cur_addr)
+ { // Write buffer to memory
+ size_t offset = (size_t)cur_addr - (size_t)addr;
+ size_t chunk_size = cur_bla ? ((jbyte*)cur_bla->bp->addr - cur_addr)
+ : (end_addr - cur_addr);
+ err = ncai_write_memory(cur_addr, chunk_size, cbuf + offset);
+
+ if (err != NCAI_ERROR_NONE)
+ break;
+
+ cur_addr += chunk_size;
+ remain -= chunk_size;
+ }
+
+ if (cur_bla)
+ { // Write byte from buffer to 'saved_byte' field in breakpoint
+ assert(cur_addr == cur_bla->bp->addr);
+
+ size_t offset = (size_t)cur_addr - (size_t)addr;
+ cur_bla->bp->saved_byte = cbuf[offset];
+ cur_bla = cur_bla->next;
+ ++cur_addr;
+ --remain;
+ }
+ }
+
+ STD_FREE(rwa.array);
+ return err;
+}
+
+// Adding sorted item into rewrite list
+static void add_rewrite_address(RewriteArray* prwa, VMBreakPoint* bp)
+{
+ assert(prwa && prwa->array && prwa->size && bp);
+
+ BreakListItem** pcur = &prwa->list;
+
+ // Look for place for insertion
+ while (*pcur && (*pcur)->bp->addr < bp->addr)
+ pcur = &((*pcur)->next);
+
+ BreakListItem* freeitem = prwa->array + prwa->count++;
+ assert(prwa->count <= prwa->size);
+
+ freeitem->next = *pcur;
+ *pcur = freeitem;
+ freeitem->bp = bp;
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/ncai/ncai_memory.cpp
------------------------------------------------------------------------------
svn:eol-style = native