1 /*
   2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 #include <stdio.h>
  24 #include <string.h>
  25 #include <jvmti.h>
  26 #include "agent_common.h"
  27 
  28 #include "nsk_tools.h"
  29 #include "JVMTITools.h"
  30 #include "jvmti_tools.h"
  31 #include "jni_tools.h"
  32 
  33 extern "C" {
  34 
  35 #define FOO 1
  36 #define WRAPPED_FOO 2
  37 
  38 /* ============================================================================= */
  39 
  40 JNIEXPORT jint JNICALL
  41 Java_nsk_jvmti_SetNativeMethodPrefix_AutomaticResolution1_foo (
  42         JNIEnv *jni
  43         , jclass klass
  44     )
  45 {
  46     NSK_DISPLAY0(" >>> AutomaticResolution1.foo()\n");
  47     return FOO;
  48 }
  49 
  50 /* ============================================================================= */
  51 
  52 JNIEXPORT jint JNICALL
  53 Java_nsk_jvmti_SetNativeMethodPrefix_AutomaticResolution1_wrapped_1foo (
  54         JNIEnv *jni
  55         , jclass klass
  56     )
  57 {
  58     NSK_DISPLAY0(" >>> AutomaticResolution1.wrapped_foo()\n");
  59     return WRAPPED_FOO;
  60 }
  61 
  62 /* ============================================================================= */
  63 
  64 JNIEXPORT jint JNICALL
  65 Java_nsk_jvmti_SetNativeMethodPrefix_AutomaticResolution2_foo (
  66         JNIEnv *jni
  67         , jclass klass
  68     )
  69 {
  70     NSK_DISPLAY0(" >>> AutomaticResolution2.foo()\n");
  71     return FOO;
  72 }
  73 
  74 /* ============================================================================= */
  75 
  76 JNIEXPORT jint JNICALL
  77 Java_nsk_jvmti_SetNativeMethodPrefix_AutomaticResolution3_foo (
  78         JNIEnv *jni
  79         , jclass klass
  80     )
  81 {
  82     NSK_DISPLAY0(" >>> AutomaticResolution3.foo()\n");
  83     return FOO;
  84 }
  85 /* ============================================================================= */
  86 
  87 JNIEXPORT jint JNICALL foo (JNIEnv *jni, jclass klass)
  88 {
  89     NSK_DISPLAY0(" >>> ::foo()\n");
  90     return FOO;
  91 }
  92 
  93 /* ============================================================================= */
  94 
  95 JNIEXPORT jint JNICALL wrapped_foo (JNIEnv *jni, jclass klass)
  96 {
  97     NSK_DISPLAY0(" >>> ::wrapped_foo()\n");
  98     return WRAPPED_FOO;
  99 }
 100 
 101 /* ============================================================================= */
 102 
 103 #define METHODS_COUNT 2
 104 static const void *METHODS [METHODS_COUNT] = {
 105     (void *) &foo,
 106     (void *) &wrapped_foo,
 107 };
 108 
 109 /* ============================================================================= */
 110 
 111 static jvmtiEnv *jvmti = NULL;
 112 
 113 /* ============================================================================= */
 114 
 115 JNIEXPORT jboolean JNICALL
 116 Java_nsk_jvmti_SetNativeMethodPrefix_Binder_setMethodPrefix (
 117         JNIEnv *jni
 118         , jclass klass
 119         , jstring prefix
 120         )
 121 {
 122     jboolean result = JNI_TRUE;
 123     char *str = NULL;
 124 
 125     if (prefix != NULL) {
 126         if (!NSK_VERIFY((str = (char *) jni->GetStringUTFChars(prefix, 0)) != NULL))
 127         { result = JNI_FALSE; goto finally; }
 128     }
 129 
 130     if (!NSK_JVMTI_VERIFY(jvmti->SetNativeMethodPrefix(str)))
 131     { result = JNI_FALSE; goto finally; }
 132 
 133     if (str != NULL) {
 134         NSK_DISPLAY1("New PREFIX is set: %s\n"
 135                 , str
 136                 );
 137     } else {
 138         NSK_DISPLAY0("Old PREFIX is reset\n");
 139     }
 140 
 141 finally:
 142     if (str != NULL) {
 143         jni->ReleaseStringUTFChars(prefix, str);
 144     }
 145 
 146     return JNI_TRUE;
 147 }
 148 
 149 /* ============================================================================= */
 150 
 151 JNIEXPORT jboolean JNICALL
 152 Java_nsk_jvmti_SetNativeMethodPrefix_Binder_setMultiplePrefixes (
 153         JNIEnv *jni
 154         , jclass klass
 155         , jstring prefix
 156         )
 157 {
 158     jboolean result = JNI_TRUE;
 159     char *str = NULL;
 160 
 161     if (prefix != NULL) {
 162         if (!NSK_VERIFY((str = (char *) jni->GetStringUTFChars(prefix, 0)) != NULL))
 163         { result = JNI_FALSE; goto finally; }
 164 
 165         if (!NSK_JVMTI_VERIFY(jvmti->SetNativeMethodPrefixes(1, (char **) &str)))
 166         { result = JNI_FALSE; goto finally; }
 167 
 168         NSK_DISPLAY1("MultiplePrefixes: New PREFIX is set: %s\n"
 169                 , str
 170                 );
 171     } else {
 172         char* prefixes[1];
 173         prefixes[0] = NULL;
 174 
 175         if (!NSK_JVMTI_VERIFY(jvmti->SetNativeMethodPrefixes(0, (char **)&prefixes)))
 176         { result = JNI_FALSE; goto finally; }
 177 
 178         NSK_DISPLAY0("Old PREFIX is reset\n");
 179     }
 180 
 181 finally:
 182     if (str != NULL) {
 183         jni->ReleaseStringUTFChars(prefix, str);
 184     }
 185 
 186     return JNI_TRUE;
 187 }
 188 
 189 /* ============================================================================= */
 190 
 191 JNIEXPORT jboolean JNICALL
 192 Java_nsk_jvmti_SetNativeMethodPrefix_Binder_registerMethod (
 193         JNIEnv *jni
 194         , jclass klass
 195         , jclass bound_klass
 196         , jstring method_name_obj
 197         , jstring method_sig_obj
 198         , jint native_method_number
 199         )
 200 {
 201     JNINativeMethod method;
 202     jboolean result = JNI_FALSE;
 203 
 204     if (native_method_number < 0 || native_method_number >= METHODS_COUNT) {
 205         NSK_DISPLAY2("Method index is out of the bound: %d of %d"
 206                 , native_method_number
 207                 , METHODS_COUNT
 208                 );
 209         return JNI_FALSE;
 210     }
 211 
 212     if (!NSK_VERIFY((method.name = (char *) jni->GetStringUTFChars(method_name_obj, 0)) != NULL)) {
 213         goto finally;
 214     }
 215 
 216     if (!NSK_VERIFY((method.signature = (char *) jni->GetStringUTFChars(method_sig_obj, 0)) != NULL)) {
 217         goto finally;
 218     }
 219 
 220     method.fnPtr = (void *) METHODS[native_method_number];
 221 
 222     NSK_DISPLAY2(">>>> Register native method: %s %s\n"
 223             , method.name
 224             , method.signature
 225             );
 226 
 227     if (jni->RegisterNatives(bound_klass, (const JNINativeMethod*) &method, 1) != 0)
 228     {
 229         if (jni->ExceptionOccurred() != NULL) {
 230             jni->ExceptionClear();
 231         }
 232 
 233         goto finally;
 234     }
 235 
 236     NSK_DISPLAY0("<<<< Finished native method registration\n");
 237 
 238     result = JNI_TRUE;
 239 finally:
 240     if (method.name != NULL) {
 241         jni->ReleaseStringUTFChars(method_name_obj, method.name);
 242     }
 243 
 244     if (method.signature != NULL) {
 245         jni->ReleaseStringUTFChars(method_sig_obj, method.signature);
 246     }
 247 
 248     return result;
 249 }
 250 
 251 /* ============================================================================= */
 252 
 253 /* Agent initialization procedure */
 254 #ifdef STATIC_BUILD
 255 JNIEXPORT jint JNICALL Agent_OnLoad_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 256     return Agent_Initialize(jvm, options, reserved);
 257 }
 258 JNIEXPORT jint JNICALL Agent_OnAttach_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 259     return Agent_Initialize(jvm, options, reserved);
 260 }
 261 JNIEXPORT jint JNI_OnLoad_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 262     return JNI_VERSION_1_8;
 263 }
 264 #endif
 265 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved)
 266 {
 267     jvmtiCapabilities caps;
 268 
 269     if (!NSK_VERIFY(
 270                 nsk_jvmti_parseOptions(options)
 271                 )
 272        )
 273         return JNI_ERR;
 274 
 275     if (!NSK_VERIFY(
 276                 (jvmti = nsk_jvmti_createJVMTIEnv(vm, reserved)) != NULL
 277                 )
 278        )
 279         return JNI_ERR;
 280 
 281     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
 282         return JNI_ERR;
 283 
 284     // Register all necessary JVM capabilities
 285     caps.can_set_native_method_prefix = 1;
 286 
 287     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 288         return JNI_ERR;
 289 
 290     return JNI_OK;
 291 }
 292 
 293 }