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(
 127                 (str = (char *) NSK_CPP_STUB3(
 128                               GetStringUTFChars
 129                               , jni
 130                               , prefix
 131                               , 0
 132                          )
 133                     ) != NULL
 134                 )
 135            )
 136         { result = JNI_FALSE; goto finally; }
 137     }
 138 
 139     if (!NSK_JVMTI_VERIFY(
 140                 NSK_CPP_STUB2(
 141                     SetNativeMethodPrefix
 142                     , jvmti
 143                     , str
 144                     )
 145                 )
 146        )
 147     { result = JNI_FALSE; goto finally; }
 148 
 149     if (str != NULL) {
 150         NSK_DISPLAY1("New PREFIX is set: %s\n"
 151                 , str
 152                 );
 153     } else {
 154         NSK_DISPLAY0("Old PREFIX is reset\n");
 155     }
 156 
 157 finally:
 158     if (str != NULL) {
 159         jni->ReleaseStringUTFChars(prefix, str);
 160     }
 161 
 162     return JNI_TRUE;
 163 }
 164 
 165 /* ============================================================================= */
 166 
 167 JNIEXPORT jboolean JNICALL
 168 Java_nsk_jvmti_SetNativeMethodPrefix_Binder_setMultiplePrefixes (
 169         JNIEnv *jni
 170         , jclass klass
 171         , jstring prefix
 172         )
 173 {
 174     jboolean result = JNI_TRUE;
 175     char *str = NULL;
 176 
 177     if (prefix != NULL) {
 178         if (!NSK_VERIFY(
 179                 (str = (char *) NSK_CPP_STUB3(
 180                               GetStringUTFChars
 181                               , jni
 182                               , prefix
 183                               , 0
 184                          )
 185                     ) != NULL
 186                 )
 187            )
 188         { result = JNI_FALSE; goto finally; }
 189 
 190         if (!NSK_JVMTI_VERIFY(
 191                     NSK_CPP_STUB3(
 192                         SetNativeMethodPrefixes
 193                         , jvmti
 194                         , 1
 195                         , (char **) &str
 196                         )
 197                     )
 198            )
 199         { result = JNI_FALSE; goto finally; }
 200 
 201         NSK_DISPLAY1("MultiplePrefixes: New PREFIX is set: %s\n"
 202                 , str
 203                 );
 204     } else {
 205         char* prefixes[1];
 206         prefixes[0] = NULL;
 207 
 208         if (!NSK_JVMTI_VERIFY(
 209                     NSK_CPP_STUB3(
 210                         SetNativeMethodPrefixes
 211                         , jvmti
 212                         , 0
 213                         , (char **)&prefixes
 214                         )
 215                     )
 216            )
 217         { result = JNI_FALSE; goto finally; }
 218 
 219         NSK_DISPLAY0("Old PREFIX is reset\n");
 220     }
 221 
 222 finally:
 223     if (str != NULL) {
 224         jni->ReleaseStringUTFChars(prefix, str);
 225     }
 226 
 227     return JNI_TRUE;
 228 }
 229 
 230 /* ============================================================================= */
 231 
 232 JNIEXPORT jboolean JNICALL
 233 Java_nsk_jvmti_SetNativeMethodPrefix_Binder_registerMethod (
 234         JNIEnv *jni
 235         , jclass klass
 236         , jclass bound_klass
 237         , jstring method_name_obj
 238         , jstring method_sig_obj
 239         , jint native_method_number
 240         )
 241 {
 242     JNINativeMethod method;
 243     jboolean result = JNI_FALSE;
 244 
 245     if (native_method_number < 0 || native_method_number >= METHODS_COUNT) {
 246         NSK_DISPLAY2("Method index is out of the bound: %d of %d"
 247                 , native_method_number
 248                 , METHODS_COUNT
 249                 );
 250         return JNI_FALSE;
 251     }
 252 
 253     if (!NSK_VERIFY(
 254             (method.name =
 255                 (char *) NSK_CPP_STUB3(
 256                      GetStringUTFChars
 257                      , jni
 258                      , method_name_obj
 259                      , 0
 260                     )
 261             ) != NULL
 262             )
 263        )
 264     {
 265         goto finally;
 266     }
 267 
 268     if (!NSK_VERIFY(
 269             (method.signature =
 270                     (char *) NSK_CPP_STUB3(
 271                          GetStringUTFChars
 272                          , jni
 273                          , method_sig_obj
 274                          , 0
 275                     )
 276             ) != NULL
 277             )
 278        )
 279     {
 280         goto finally;
 281     }
 282 
 283     method.fnPtr = (void *) METHODS[native_method_number];
 284 
 285     NSK_DISPLAY2(">>>> Register native method: %s %s\n"
 286             , method.name
 287             , method.signature
 288             );
 289 
 290     if (jni->RegisterNatives(bound_klass, (const JNINativeMethod*) &method, 1) != 0)
 291     {
 292         if (jni->ExceptionOccurred() != NULL) {
 293             jni->ExceptionClear();
 294         }
 295 
 296         goto finally;
 297     }
 298 
 299     NSK_DISPLAY0("<<<< Finished native method registration\n");
 300 
 301     result = JNI_TRUE;
 302 finally:
 303     if (method.name != NULL) {
 304         jni->ReleaseStringUTFChars(method_name_obj, method.name);
 305     }
 306 
 307     if (method.signature != NULL) {
 308         jni->ReleaseStringUTFChars(method_sig_obj, method.signature);
 309     }
 310 
 311     return result;
 312 }
 313 
 314 /* ============================================================================= */
 315 
 316 /* Agent initialization procedure */
 317 #ifdef STATIC_BUILD
 318 JNIEXPORT jint JNICALL Agent_OnLoad_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 319     return Agent_Initialize(jvm, options, reserved);
 320 }
 321 JNIEXPORT jint JNICALL Agent_OnAttach_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 322     return Agent_Initialize(jvm, options, reserved);
 323 }
 324 JNIEXPORT jint JNI_OnLoad_SetNativeMethodPrefix001(JavaVM *jvm, char *options, void *reserved) {
 325     return JNI_VERSION_1_8;
 326 }
 327 #endif
 328 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved)
 329 {
 330     jvmtiCapabilities caps;
 331 
 332     if (!NSK_VERIFY(
 333                 nsk_jvmti_parseOptions(options)
 334                 )
 335        )
 336         return JNI_ERR;
 337 
 338     if (!NSK_VERIFY(
 339                 (jvmti = nsk_jvmti_createJVMTIEnv(vm, reserved)) != NULL
 340                 )
 341        )
 342         return JNI_ERR;
 343 
 344     if (!NSK_JVMTI_VERIFY(
 345                 NSK_CPP_STUB2(
 346                     GetCapabilities
 347                     , jvmti
 348                     , &caps)
 349                 )
 350        )
 351         return JNI_ERR;
 352 
 353     // Register all necessary JVM capabilities
 354     caps.can_set_native_method_prefix = 1;
 355 
 356     if (!NSK_JVMTI_VERIFY(
 357                 NSK_CPP_STUB2(
 358                     AddCapabilities
 359                     , jvmti
 360                     , &caps)
 361                 )
 362        )
 363         return JNI_ERR;
 364 
 365     return JNI_OK;
 366 }
 367 
 368 }