1 /*
  2  * Copyright (c) 2004, 2024, 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 
 24 #include <string.h>
 25 #include "jvmti.h"
 26 #include "agent_common.hpp"
 27 #include "ExceptionCheckingJniEnv.hpp"
 28 #include "jni_tools.hpp"
 29 #include "jvmti_tools.hpp"
 30 
 31 extern "C" {
 32 
 33 /* scaffold objects */
 34 static jlong timeout = 0;
 35 
 36 #define PATH_TO_NEW_BYTECODE "pathToNewByteCode"
 37 #define TESTED_CLASS_NAME "java/lang/Object"
 38 
 39 static jint newClassSize;
 40 static unsigned char* newClassBytes;
 41 
 42 static jvmtiClassDefinition classDef;
 43 
 44 /* ============================================================================= */
 45 
 46 int readNewBytecode(jvmtiEnv* jvmti) {
 47 
 48     char filename[256];
 49     FILE *bytecode;
 50     const char *pathToByteCode = nsk_jvmti_findOptionValue(PATH_TO_NEW_BYTECODE);
 51     jint read_bytes;
 52 
 53     if (pathToByteCode)
 54         snprintf(filename, sizeof(filename), "%s/%s/%s.class",
 55                     pathToByteCode, "newclass02", TESTED_CLASS_NAME);
 56     else
 57         snprintf(filename, sizeof(filename), "%s/%s.class",
 58                     "newclass02", TESTED_CLASS_NAME);
 59 
 60     NSK_DISPLAY1("Reading new bytecode for java.lang.Object\n\tfile name: %s\n",
 61                         filename);
 62 
 63     bytecode = fopen(filename, "rb");
 64     if (bytecode == nullptr) {
 65         NSK_COMPLAIN0("error opening file\n");
 66         return NSK_FALSE;
 67     }
 68 
 69     fseek(bytecode, 0, SEEK_END);
 70     classDef.class_byte_count = ftell(bytecode);
 71     rewind(bytecode);
 72 
 73     if (!NSK_JVMTI_VERIFY(jvmti->Allocate(classDef.class_byte_count, &newClassBytes))) {
 74         NSK_COMPLAIN0("buffer couldn't be allocated\n");
 75         return NSK_FALSE;
 76     }
 77     classDef.class_bytes = newClassBytes;
 78     read_bytes = (jint) fread(newClassBytes, 1,
 79                             classDef.class_byte_count, bytecode);
 80     fclose(bytecode);
 81     if (read_bytes != classDef.class_byte_count) {
 82         NSK_COMPLAIN0("error reading file\n");
 83         return NSK_FALSE;
 84     }
 85 
 86     return NSK_TRUE;
 87 }
 88 
 89 /* ============================================================================= */
 90 
 91 /** Agent algorithm. */
 92 static void JNICALL
 93 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 94 
 95     ExceptionCheckingJniEnvPtr ec_jni(jni);
 96     /*Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4*/
 97     NSK_DISPLAY0("Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4\n");
 98     if (!nsk_jvmti_waitForSync(timeout))
 99         return;
100 
101     NSK_DISPLAY1("Find class: %s\n", TESTED_CLASS_NAME);
102     classDef.klass = ec_jni->FindClass(TESTED_CLASS_NAME, TRACE_JNI_CALL);
103     classDef.klass = (jclass) ec_jni->NewGlobalRef(classDef.klass, TRACE_JNI_CALL);
104 
105     NSK_DISPLAY0("Redfine class with new byte code\n");
106     NSK_DISPLAY3("class definition:\n\t0x%p, 0x%p:%d\n",
107                     classDef.klass,
108                     classDef.class_bytes,
109                     classDef.class_byte_count);
110     if (nsk_getVerboseMode()) {
111         nsk_printHexBytes("   ", 16, classDef.class_byte_count,
112                                 classDef.class_bytes);
113     }
114     if (!NSK_JVMTI_VERIFY(jvmti->RedefineClasses(1, &classDef))) {
115         nsk_jvmti_setFailStatus();
116         return;
117     }
118 
119     ec_jni->DeleteGlobalRef(classDef.klass, TRACE_JNI_CALL);
120 
121     if (!nsk_jvmti_resumeSync())
122         return;
123 }
124 
125 /* ============================================================================= */
126 
127 /** Agent library initialization. */
128 #ifdef STATIC_BUILD
129 JNIEXPORT jint JNICALL Agent_OnLoad_bi04t002(JavaVM *jvm, char *options, void *reserved) {
130     return Agent_Initialize(jvm, options, reserved);
131 }
132 JNIEXPORT jint JNICALL Agent_OnAttach_bi04t002(JavaVM *jvm, char *options, void *reserved) {
133     return Agent_Initialize(jvm, options, reserved);
134 }
135 JNIEXPORT jint JNI_OnLoad_bi04t002(JavaVM *jvm, char *options, void *reserved) {
136     return JNI_VERSION_1_8;
137 }
138 #endif
139 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
140     jvmtiEnv *jvmti = nullptr;
141 
142     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
143         return JNI_ERR;
144 
145     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
146 
147     jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
148     if (!NSK_VERIFY(jvmti != nullptr))
149         return JNI_ERR;
150 
151     {
152         jvmtiCapabilities caps;
153         memset(&caps, 0, sizeof(caps));
154 
155         caps.can_redefine_classes = 1;
156         caps.can_redefine_any_class = 1;
157         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
158             return JNI_ERR;
159     }
160 
161     if (!NSK_VERIFY(readNewBytecode(jvmti)))
162         return JNI_ERR;
163 
164     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, nullptr)))
165         return JNI_ERR;
166 
167     return JNI_OK;
168 }
169 
170 /* ============================================================================= */
171 
172 
173 }