Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 16153 invoked from network); 24 Nov 2006 13:11:05 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 24 Nov 2006 13:11:05 -0000 Received: (qmail 14208 invoked by uid 500); 24 Nov 2006 13:11:15 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 14185 invoked by uid 500); 24 Nov 2006 13:11:14 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 14176 invoked by uid 99); 24 Nov 2006 13:11:14 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Nov 2006 05:11:14 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Nov 2006 05:11:03 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 4D7F41A9846; Fri, 24 Nov 2006 05:10:28 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r478866 - in /harmony/enhanced/drlvm/trunk: build/make/ build/make/targets/ vm/tests/jvmti/Breakpoint1/ vm/tests/jvmti/SingleStep1/ Date: Fri, 24 Nov 2006 13:10:27 -0000 To: commits@harmony.apache.org From: gshimansky@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061124131028.4D7F41A9846@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 @@ + 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 +#include +#include +#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 +#include +#include +#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; +}