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 2006/11/24 14:10:27 UTC

svn commit: r478866 - in /harmony/enhanced/drlvm/trunk: build/make/ build/make/targets/ vm/tests/jvmti/Breakpoint1/ vm/tests/jvmti/SingleStep1/

Author: gshimansky
Date: Fri Nov 24 05:10:26 2006
New Revision: 478866

URL: http://svn.apache.org/viewvc?view=rev&rev=478866
Log:
Applied HARMONY-2293 [drlvm][jvmti] New tests for JVMTI: Breakpoint & SingleStep

New tests passed on ubuntu, fedora and windows 2003 server


Added:
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/Breakpoint1.java
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.cpp
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.h
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/breakpoint.cpp
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/SingleStep1.java
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.cpp
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.h
    harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/singlestep.cpp
Modified:
    harmony/enhanced/drlvm/trunk/build/make/   (props changed)
    harmony/enhanced/drlvm/trunk/build/make/targets/jvmti.test.xml

Propchange: harmony/enhanced/drlvm/trunk/build/make/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Fri Nov 24 05:10:26 2006
@@ -1 +1,2 @@
 tmp
+junit*.properties

Modified: harmony/enhanced/drlvm/trunk/build/make/targets/jvmti.test.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/build/make/targets/jvmti.test.xml?view=diff&rev=478866&r1=478865&r2=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/build/make/targets/jvmti.test.xml (original)
+++ harmony/enhanced/drlvm/trunk/build/make/targets/jvmti.test.xml Fri Nov 24 05:10:26 2006
@@ -78,6 +78,9 @@
                     <select os="lnx">
                         <linkerarg value="-lstdc++" />
                     </select>
+                    <select os="win">
+                        <compilerarg value="/GX" />
+                    </select>
                     <fileset dir="@{directory}">
                         <include name="**/*.cpp" />
                     </fileset>

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/Breakpoint1.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/Breakpoint1.java?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/Breakpoint1.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/Breakpoint1.java Fri Nov 24 05:10:26 2006
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+package Breakpoint1;
+
+import junit.framework.TestCase;
+
+public class Breakpoint1 extends TestCase {
+    static boolean status = false;
+
+    static public void main(String args[]) {
+        Breakpoint1 instance = new Breakpoint1();
+        instance.test();
+        instance.test();
+        if(status) {
+            System.out.println("Test passed!");
+        } else {
+            System.out.println("Test failed!");
+        }
+        assertTrue(status);        
+        return;
+    }
+
+    public void test() {
+        /*
+         * Simple sequention of operations for
+         * creating breakpoints here.
+         */
+        int a = 2;
+        int b = a + 3;
+        int c = b + 4;
+        int d = c + 5;
+        int e = d + 6;
+        int f = e + 7;
+        int g = f + 9;
+        int h = g + 10;
+        int i = h + 11;
+        int j = i + 12;
+        assertTrue(status);
+        return;
+    }
+}
+
+

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.cpp?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.cpp Fri Nov 24 05:10:26 2006
@@ -0,0 +1,127 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#include "agent.h"
+
+#define CHECK_CAP(obtained, needed, jvmti_cap)              \
+    if(!obtained.jvmti_cap) {                               \
+    REPORT( "Cannot set capability: "#jvmti_cap );          \
+        return JNI_ERR;                                     \
+    }                                                       \
+    needed.jvmti_cap = 1;
+
+void JNICALL 
+agent_callback_MethodEntry( jvmtiEnv* jvmti_env,
+                            JNIEnv* jni_env,
+                            jthread thread,
+                            jmethodID method);
+
+void JNICALL
+agent_callback_Breakpoint( jvmtiEnv* jvmti_env,
+                           JNIEnv* jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location);
+
+static inline jint
+set_agent_capabilities(jvmtiEnv * jvmti_env)
+{
+    // get VM capabilities
+    jvmtiCapabilities vm_cap;
+    jvmtiError result = jvmti_env->GetPotentialCapabilities(&vm_cap);
+    if (result != JVMTI_ERROR_NONE) {
+        REPORT( "get potential capabilities" );
+        return JNI_ERR;
+    }
+
+    jvmtiCapabilities need_cap = {0};
+    CHECK_CAP(vm_cap, need_cap, can_generate_breakpoint_events);
+    CHECK_CAP(vm_cap, need_cap, can_generate_method_entry_events);
+    CHECK_CAP(vm_cap, need_cap, can_get_line_numbers);
+
+    result = jvmti_env->AddCapabilities(&need_cap);
+    if (result != JVMTI_ERROR_NONE) {
+        REPORT( "set needed capabilities" );
+        return JNI_ERR;
+    }
+    return JNI_OK;
+}
+
+static inline jint
+set_agent_events(jvmtiEnv * jvmti_env)
+{
+    jvmtiEventCallbacks callbacks;
+    memset(&callbacks, 0, sizeof(callbacks));
+
+    // set event callbacks
+    callbacks.MethodEntry = &agent_callback_MethodEntry;
+    callbacks.Breakpoint = &agent_callback_Breakpoint;
+    jvmtiError result = jvmti_env->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks));
+    if( result != JVMTI_ERROR_NONE ) {
+        REPORT("set events callbacks");
+        return JNI_ERR;
+    }
+
+    // set MethodEntry event
+    result = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, NULL);
+    if( result != JVMTI_ERROR_NONE ) {
+        REPORT("enable MethodEntry event");
+        return JNI_ERR;
+    }
+
+    // set Breakpoint event
+    result = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL);
+    if( result != JVMTI_ERROR_NONE ) {
+        REPORT("enable Breakpoint event");
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+{
+    // get JVMTI enviroment
+    jvmtiEnv * jvmti_env;
+    DEBUG("Getting JVMTI enviroment... ");
+    if( vm->GetEnv( (void**)&jvmti_env, JVMTI_VERSION_1_0) != JNI_OK ) {
+        REPORT( "get JVMTI enviroment" );
+        return JNI_OK;
+    }
+    DEBUG("done!");
+    
+    // set capabilities
+    DEBUG("Setting capabilities... ");
+    if( set_agent_capabilities(jvmti_env) != JNI_OK ) {
+        return JNI_OK;
+    }
+    DEBUG("done!");
+
+    // set events
+    DEBUG("Setting events... ");
+    if( set_agent_events(jvmti_env) != JNI_OK ) {
+        return JNI_OK;
+    }
+    DEBUG("done!");
+
+    return JNI_OK;
+}

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.h?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/agent.h Fri Nov 24 05:10:26 2006
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#ifndef _JVMTI_AGENT_H_
+#define _JVMTI_AGENT_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include "jvmti.h"
+
+#ifdef NDEBUG
+#define DEBUG(str)
+#else // NDEBUG
+#define DEBUG(str)      std::cout << "DEBUG: " << str << std::endl;
+#endif // NDEBUG
+
+#define REPORT(str)     std::cerr << "ERROR: " << str << std::endl;
+#define ERR_REPORT(str)                                 \
+    {                                                   \
+        std::cerr << "ERROR: " << str << std::endl;     \
+        error = true;                                   \
+    }
+
+#define CHECK_ERROR()   \
+    if(error) {         \
+        return;         \
+    }
+
+#endif // _JVMTI_AGENT_H_

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/breakpoint.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/breakpoint.cpp?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/breakpoint.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/Breakpoint1/breakpoint.cpp Fri Nov 24 05:10:26 2006
@@ -0,0 +1,233 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#include "agent.h"
+
+static jint lines[] = {50, 55};
+static bool error = false;
+
+static void
+set_test_success( jvmtiEnv* jvmti_env,
+                  JNIEnv* jni_env,
+                  jmethodID method)
+{
+    CHECK_ERROR();
+
+    DEBUG("Setting success == true... ");
+    jclass klass;
+    jvmtiError result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    jfieldID field = jni_env->GetStaticFieldID(klass, "status", "Z");
+    if( !field ) {
+        ERR_REPORT("get 'status' field");
+        return;
+    }
+    jni_env->SetStaticBooleanField(klass, field, JNI_TRUE);
+    DEBUG("done");
+    return;
+}
+
+void JNICALL 
+agent_callback_MethodEntry( jvmtiEnv* jvmti_env,
+                            JNIEnv* jni_env,
+                            jthread thread,
+                            jmethodID method)
+{
+    CHECK_ERROR();
+
+    char *name;
+    char *descr;
+    jvmtiError result = jvmti_env->GetMethodName(method, &name, &descr, NULL);
+    if( result != JVMTI_ERROR_NONE
+        || strcmp(name, "test") || strcmp(descr, "()V" ) )
+    {
+        return;
+    }
+    jclass klass;
+    result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    char *class_name;
+    result = jvmti_env->GetClassSignature(klass, &class_name, NULL);
+    if(result != JVMTI_ERROR_NONE
+        || strcmp(class_name, "LBreakpoint1/Breakpoint1;"))
+    {
+        ERR_REPORT("wrong MethodEntry callback");
+        return;
+    }
+    DEBUG("MethodEntry callback is called for Breakpoint1.Breakpoint1.test()");
+
+    DEBUG("Disabling MethodEntry event... ");
+    result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+        JVMTI_EVENT_METHOD_ENTRY, NULL);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("disable MethodEntry event");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Getting line number table...");
+    jvmtiLineNumberEntry *table;
+    jint number;
+    result = jvmti_env->GetLineNumberTable( method, &number, &table );
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get line number table");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Setting breakpoints... ");
+    for(int index = 0; index < 2; index++) {
+        bool is_set = false;
+        for(jint count = 0; count < number - 1; count++) {
+            if(lines[index] >= table[count].line_number
+                && lines[index] < table[count + 1].line_number )
+            {
+                is_set = true;
+                DEBUG("Setting breakpoint on line " << lines[index] << "...");
+                result = jvmti_env->SetBreakpoint(method, table[count].start_location);
+                if(result != JVMTI_ERROR_NONE) {
+                    ERR_REPORT("set breakpoint on line " << lines[index]);
+                    return;
+                }
+                DEBUG("done");
+                break;
+            }
+        }
+        if(!is_set) {
+            ERR_REPORT("set breakpoint on line " << lines[index]);
+            return;
+        }
+    }
+    DEBUG("Setting breakpoints... done");
+
+    DEBUG("Deallocating line number table... ");
+    result = jvmti_env->Deallocate((unsigned char*)table);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("Deallocate failed!");
+        return;
+    }
+    DEBUG("done");
+
+    return;
+}
+
+void JNICALL
+agent_callback_Breakpoint( jvmtiEnv* jvmti_env,
+                           JNIEnv* jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location)
+{
+    CHECK_ERROR();
+
+    char *name;
+    char *descr;
+    jvmtiError result = jvmti_env->GetMethodName(method, &name, &descr, NULL);
+    if( result != JVMTI_ERROR_NONE
+        || strcmp(name, "test") || strcmp(descr, "()V" ) )
+    {
+        return;
+    }
+    jclass klass;
+    result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    char *class_name;
+    result = jvmti_env->GetClassSignature(klass, &class_name, NULL);
+    if(result != JVMTI_ERROR_NONE
+        || strcmp(class_name, "LBreakpoint1/Breakpoint1;"))
+    {
+        ERR_REPORT("wrong Breakpoint callback");
+        return;
+    }
+    DEBUG("Breakpoint occupied in function Breakpoint1.Breakpoint1.test()");
+
+    DEBUG("Getting line number table...");
+    jvmtiLineNumberEntry *table;
+    jint number;
+    result = jvmti_env->GetLineNumberTable( method, &number, &table );
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get line number table");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Checking breakpoints...");
+    for(jint count = 0; count < number - 1; count++) {
+        if(location >= table[count].start_location
+            && location < table[count + 1].start_location)
+        {
+            DEBUG("Breakpoint on line " << table[count].line_number);
+            static bool is_occupied = false;
+            if( !is_occupied ) {
+                if( lines[0] == table[count].line_number ) {
+                    // the first breakpoint is occupied
+                    is_occupied = true;
+                    DEBUG("Clearing the first breakpoint...");
+                    result = jvmti_env->ClearBreakpoint(method, location);
+                    if(result != JVMTI_ERROR_NONE) {
+                        ERR_REPORT("clear breakpoint");
+                        return;
+                    }
+                    DEBUG("done");
+                    break;
+                } else {
+                    ERR_REPORT("wrong breakpoint callback");
+                    return;
+                }
+            } else {
+                if( lines[1] == table[count].line_number ) {
+                    // the second breakpoint is occupied
+                    DEBUG("Disabling Breakpoint event... ");
+                    result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                        JVMTI_EVENT_BREAKPOINT, NULL);
+                    if(result != JVMTI_ERROR_NONE) {
+                        ERR_REPORT("disable Breakpoint event");
+                        return;
+                    }
+                    DEBUG("done");
+                    set_test_success(jvmti_env, jni_env, method);
+                    break;
+                } else {
+                    ERR_REPORT("wrong breakpoint callback");
+                    return;
+                }
+            }
+        }
+    }
+
+    DEBUG("Deallocating line number table... ");
+    result = jvmti_env->Deallocate((unsigned char*)table);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("Deallocate failed!");
+        return;
+    }
+    DEBUG("done");
+    return;
+}

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/SingleStep1.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/SingleStep1.java?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/SingleStep1.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/SingleStep1.java Fri Nov 24 05:10:26 2006
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+package SingleStep1;
+
+import junit.framework.TestCase;
+
+public class SingleStep1 extends TestCase {
+
+    static boolean status = false;
+
+    public static void main(String[] args) {
+        new SingleStep1().test();
+        if (status) {
+            System.out.println("Test passed!");
+        } else {
+            System.out.println("Test failed!");
+        }
+        assertTrue(status);
+    }
+
+    public void test() {
+        // set the first breakpoint to the next line
+        Object obj = new Object();
+        int z = 10;
+        z = z * 2;
+        // set the second breakpoint to the next line
+        System.out.println("done: " + z + obj);
+        assertTrue(status);
+        return;
+    }
+}

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.cpp?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.cpp Fri Nov 24 05:10:26 2006
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#include "agent.h"
+
+#define CHECK_CAP(obtained, needed, jvmti_cap)              \
+    if(!obtained.jvmti_cap) {                               \
+    REPORT( "Cannot set capability: "#jvmti_cap );          \
+        return JNI_ERR;                                     \
+    }                                                       \
+    needed.jvmti_cap = 1;
+
+void JNICALL 
+agent_callback_MethodEntry( jvmtiEnv* jvmti_env,
+                            JNIEnv* jni_env,
+                            jthread thread,
+                            jmethodID method);
+
+void JNICALL
+agent_callback_Breakpoint( jvmtiEnv* jvmti_env,
+                           JNIEnv* jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location);
+
+void JNICALL 
+agent_callback_SingleStep( jvmtiEnv * jvmti_env,
+                           JNIEnv * jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location);
+
+static inline jint
+set_agent_capabilities(jvmtiEnv * jvmti_env)
+{
+    // get VM capabilities
+    jvmtiCapabilities vm_cap;
+    jvmtiError result = jvmti_env->GetPotentialCapabilities(&vm_cap);
+    if (result != JVMTI_ERROR_NONE) {
+        REPORT( "get potential capabilities" );
+        return JNI_ERR;
+    }
+
+    jvmtiCapabilities need_cap = {0};
+    CHECK_CAP(vm_cap, need_cap, can_generate_breakpoint_events);
+    CHECK_CAP(vm_cap, need_cap, can_generate_method_entry_events);
+    CHECK_CAP(vm_cap, need_cap, can_get_line_numbers);
+    CHECK_CAP(vm_cap, need_cap, can_generate_single_step_events);
+
+    result = jvmti_env->AddCapabilities(&need_cap);
+    if (result != JVMTI_ERROR_NONE) {
+        REPORT( "set needed capabilities" );
+        return JNI_ERR;
+    }
+    return JNI_OK;
+}
+
+static inline jint
+set_agent_events(jvmtiEnv * jvmti_env)
+{
+    jvmtiEventCallbacks callbacks;
+    memset(&callbacks, 0, sizeof(callbacks));
+
+    // set event callbacks
+    callbacks.MethodEntry = &agent_callback_MethodEntry;
+    callbacks.Breakpoint = &agent_callback_Breakpoint;
+    callbacks.SingleStep = &agent_callback_SingleStep;
+    jvmtiError result = jvmti_env->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks));
+    if( result != JVMTI_ERROR_NONE ) {
+        REPORT("set events callbacks");
+        return JNI_ERR;
+    }
+
+    // set MethodEntry event
+    result = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, NULL);
+    if( result != JVMTI_ERROR_NONE ) {
+        REPORT("enable MethodEntry event");
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+{
+    // get JVMTI enviroment
+    jvmtiEnv * jvmti_env;
+    DEBUG("Getting JVMTI enviroment... ");
+    if( vm->GetEnv( (void**)&jvmti_env, JVMTI_VERSION_1_0) != JNI_OK ) {
+        REPORT( "get JVMTI enviroment" );
+        return JNI_OK;
+    }
+    DEBUG("done!");
+    
+    // set capabilities
+    DEBUG("Setting capabilities... ");
+    if( set_agent_capabilities(jvmti_env) != JNI_OK ) {
+        return JNI_OK;
+    }
+    DEBUG("done!");
+
+    // set events
+    DEBUG("Setting events... ");
+    if( set_agent_events(jvmti_env) != JNI_OK ) {
+        return JNI_OK;
+    }
+    DEBUG("done!");
+
+    return JNI_OK;
+}

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.h?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/agent.h Fri Nov 24 05:10:26 2006
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#ifndef _JVMTI_AGENT_H_
+#define _JVMTI_AGENT_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include "jvmti.h"
+
+#ifdef NDEBUG
+#define DEBUG(str)
+#else // NDEBUG
+#define DEBUG(str)      std::cout << "DEBUG: " << str << std::endl;
+#endif // NDEBUG
+
+#define REPORT(str)     std::cerr << "ERROR: " << str << std::endl;
+#define ERR_REPORT(str)                                 \
+    {                                                   \
+        std::cerr << "ERROR: " << str << std::endl;     \
+        error = true;                                   \
+    }
+
+#define CHECK_ERROR()   \
+    if(error) {         \
+        return;         \
+    }
+
+#endif // _JVMTI_AGENT_H_

Added: harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/singlestep.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/singlestep.cpp?view=auto&rev=478866
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/singlestep.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/jvmti/SingleStep1/singlestep.cpp Fri Nov 24 05:10:26 2006
@@ -0,0 +1,332 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Pavel Rebriy
+ */
+
+#include "agent.h"
+
+static jint lines[] = {43, 47, 44};
+static bool stop_after_constructor = false;
+static bool error = false;
+
+static void
+set_test_success( jvmtiEnv* jvmti_env,
+                  JNIEnv* jni_env,
+                  jmethodID method)
+{
+    CHECK_ERROR();
+
+    DEBUG("Setting success == true... ");
+    jclass klass;
+    jvmtiError result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    jfieldID field = jni_env->GetStaticFieldID(klass, "status", "Z");
+    if( !field ) {
+        ERR_REPORT("get 'status' field");
+        return;
+    }
+    jni_env->SetStaticBooleanField(klass, field, JNI_TRUE);
+    DEBUG("done");
+    return;
+}
+
+void JNICALL 
+agent_callback_SingleStep( jvmtiEnv * jvmti_env,
+                           JNIEnv * jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location)
+{
+    CHECK_ERROR();
+
+    char *name;
+    char *descr;
+    jvmtiError result = jvmti_env->GetMethodName(method, &name, &descr, NULL);
+    if( result != JVMTI_ERROR_NONE
+        || strcmp(name, "test") || strcmp(descr, "()V" ) )
+    {
+        return;
+    }
+    jclass klass;
+    result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    char *class_name;
+    result = jvmti_env->GetClassSignature(klass, &class_name, NULL);
+    if(result != JVMTI_ERROR_NONE
+        || strcmp(class_name, "LSingleStep1/SingleStep1;"))
+    {
+        ERR_REPORT("wrong MethodEntry callback");
+        return;
+    }
+    DEBUG("SingleStep callback is called");
+
+    DEBUG("Getting line number table...");
+    jvmtiLineNumberEntry *table;
+    jint number;
+    result = jvmti_env->GetLineNumberTable( method, &number, &table );
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get line number table");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Checking SingleStep location...");
+    for(jint count = 0; count < number - 1; count++) {
+        if(location >= table[count].start_location
+            && location < table[count + 1].start_location)
+        {
+            DEBUG("SingleStep location is on line " << table[count].line_number);
+            if( lines[2] == table[count].line_number ) {
+                // SingleStep location is after new Object().
+                DEBUG("Disabling SingleStep event... ");
+                result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                    JVMTI_EVENT_SINGLE_STEP, NULL);
+                if(result != JVMTI_ERROR_NONE) {
+                    ERR_REPORT("disable SingleStep event");
+                    return;
+                }
+                DEBUG("done");
+                stop_after_constructor = true;
+            }
+            break;
+        }
+    }
+
+    DEBUG("Deallocating line number table... ");
+    result = jvmti_env->Deallocate((unsigned char*)table);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("deallocate line number");
+        return;
+    }
+    DEBUG("done");
+
+    return;
+}
+
+
+void JNICALL 
+agent_callback_MethodEntry( jvmtiEnv* jvmti_env,
+                            JNIEnv* jni_env,
+                            jthread thread,
+                            jmethodID method)
+{
+    CHECK_ERROR();
+
+    char *name;
+    char *descr;
+    jvmtiError result = jvmti_env->GetMethodName(method, &name, &descr, NULL);
+    if( result != JVMTI_ERROR_NONE
+        || strcmp(name, "test") || strcmp(descr, "()V" ) )
+    {
+        return;
+    }
+    jclass klass;
+    result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    char *class_name;
+    result = jvmti_env->GetClassSignature(klass, &class_name, NULL);
+    if(result != JVMTI_ERROR_NONE
+        || strcmp(class_name, "LSingleStep1/SingleStep1;"))
+    {
+        ERR_REPORT("wrong MethodEntry callback");
+        return;
+    }
+    DEBUG("MethodEntry callback is called for SingleStep1.SingleStep1.test()");
+
+    DEBUG("Disabling MethodEntry event... ");
+    result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+        JVMTI_EVENT_METHOD_ENTRY, NULL);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("disable MethodEntry event");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Enabling Breakpoint event... ");
+    result = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL);
+    if( result != JVMTI_ERROR_NONE ) {
+        ERR_REPORT("enable Breakpoint event");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Getting line number table...");
+    jvmtiLineNumberEntry *table;
+    jint number;
+    result = jvmti_env->GetLineNumberTable( method, &number, &table );
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get line number table");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Setting breakpoints... ");
+    for(int index = 0; index < 2; index++) {
+        bool is_set = false;
+        for(jint count = 0; count < number - 1; count++) {
+            if(lines[index] >= table[count].line_number
+                && lines[index] < table[count + 1].line_number )
+            {
+                is_set = true;
+                DEBUG("Setting breakpoint on line " << lines[index] << "...");
+                result = jvmti_env->SetBreakpoint(method, table[count].start_location);
+                if(result != JVMTI_ERROR_NONE) {
+                    ERR_REPORT("set breakpoint on line " << lines[index]);
+                    return;
+                }
+                DEBUG("done");
+                break;
+            }
+        }
+        if(!is_set) {
+            ERR_REPORT("set breakpoint on line " << lines[index]);
+            return;
+        }
+    }
+    DEBUG("Setting breakpoints... done");
+
+    DEBUG("Deallocating line number table... ");
+    result = jvmti_env->Deallocate((unsigned char*)table);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("deallocate line number");
+        return;
+    }
+    DEBUG("done");
+
+    return;
+}
+
+void JNICALL
+agent_callback_Breakpoint( jvmtiEnv* jvmti_env,
+                           JNIEnv* jni_env,
+                           jthread thread,
+                           jmethodID method,
+                           jlocation location)
+{
+    CHECK_ERROR();
+
+    char *name;
+    char *descr;
+    jvmtiError result = jvmti_env->GetMethodName(method, &name, &descr, NULL);
+    if( result != JVMTI_ERROR_NONE
+        || strcmp(name, "test") || strcmp(descr, "()V" ) )
+    {
+        return;
+    }
+    jclass klass;
+    result = jvmti_env->GetMethodDeclaringClass(method, &klass);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get method class");
+        return;
+    }
+    char *class_name;
+    result = jvmti_env->GetClassSignature(klass, &class_name, NULL);
+    if(result != JVMTI_ERROR_NONE
+        || strcmp(class_name, "LSingleStep1/SingleStep1;"))
+    {
+        ERR_REPORT("wrong Breakpoint callback");
+        return;
+    }
+    DEBUG("Breakpoint occupied in function SingleStep1.SingleStep1.test()");
+
+    DEBUG("Getting line number table...");
+    jvmtiLineNumberEntry *table;
+    jint number;
+    result = jvmti_env->GetLineNumberTable( method, &number, &table );
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("get line number table");
+        return;
+    }
+    DEBUG("done");
+
+    DEBUG("Checking breakpoints...");
+    for(jint count = 0; count < number - 1; count++) {
+        if(location >= table[count].start_location
+            && location < table[count + 1].start_location)
+        {
+            DEBUG("Breakpoint on line " << table[count].line_number);
+            static bool is_occupied = false;
+            if( !is_occupied ) {
+                if( lines[0] == table[count].line_number ) {
+                    // the first breakpoint is occupied
+                    is_occupied = true;
+                    DEBUG("Enabling SingleStep event... ");
+                    result = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
+                        JVMTI_EVENT_SINGLE_STEP, NULL);
+                    if(result != JVMTI_ERROR_NONE) {
+                        ERR_REPORT("enable SingleStep event");
+                        return;
+                    }
+                    DEBUG("done");
+                    break;
+                } else {
+                    ERR_REPORT("wrong breakpoint callback");
+                    return;
+                }
+            } else {
+                if( lines[1] == table[count].line_number ) {
+                    // the second breakpoint is occupied
+                    DEBUG("Disabling Breakpoint event... ");
+                    result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                        JVMTI_EVENT_BREAKPOINT, NULL);
+                    if(result != JVMTI_ERROR_NONE) {
+                        ERR_REPORT("disable Breakpoint event");
+                        return;
+                    }
+                    DEBUG("done");
+                    if(!stop_after_constructor) {
+                        DEBUG("Disabling SingleStep event... ");
+                        result = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
+                            JVMTI_EVENT_BREAKPOINT, NULL);
+                        if(result != JVMTI_ERROR_NONE) {
+                            ERR_REPORT("disable Breakpoint event");
+                            return;
+                        }
+                        DEBUG("done");
+                    } else {
+                        set_test_success(jvmti_env, jni_env, method);
+                    }
+                    break;
+                } else {
+                    ERR_REPORT("wrong breakpoint callback");
+                    return;
+                }
+            }
+        }
+    }
+
+    DEBUG("Deallocating line number table... ");
+    result = jvmti_env->Deallocate((unsigned char*)table);
+    if(result != JVMTI_ERROR_NONE) {
+        ERR_REPORT("deallocate line number");
+        return;
+    }
+    DEBUG("done");
+
+    return;
+}