1 /*
2  * Copyright (c) 2003, 2017, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * Copyright 2003 Wily Technology, Inc.
28  */
29 
30 #ifndef _JPLISAGENT_H_
31 #define _JPLISAGENT_H_
32 
33 #include    <jni.h>
34 #include    <jvmti.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 /*
41  *  The JPLISAgent manages the initialization all of the Java programming language Agents.
42  *  It also supports the native method bridge between the JPLIS and the JVMTI.
43  *  It maintains a single JVMTI Env that all JPL agents share.
44  *  It parses command line requests and creates individual Java agents.
45  */
46 
47 
48 /*
49  *  Forward definitions
50  */
51 struct  _JPLISAgent;
52 
53 typedef struct _JPLISAgent        JPLISAgent;
54 typedef struct _JPLISEnvironment  JPLISEnvironment;
55 
56 
57 /* constants for class names and methods names and such
58     these all must stay in sync with Java code & interfaces
59 */
60 #define JPLIS_INSTRUMENTIMPL_CLASSNAME                      "sun/instrument/InstrumentationImpl"
61 #define JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODNAME         "<init>"
62 #define JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODSIGNATURE    "(JZZ)V"
63 #define JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODNAME      "loadClassAndCallPremain"
64 #define JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V"
65 #define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODNAME      "loadClassAndCallAgentmain"
66 #define JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE "(Ljava/lang/String;Ljava/lang/String;)V"
67 #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME           "transform"
68 #define JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE      \
69     "(Ljava/lang/Module;Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B"
70 
71 
72 /*
73  *  Error messages
74  */
75 #define JPLIS_ERRORMESSAGE_CANNOTSTART              "processing of -javaagent failed"
76 
77 
78 /*
79  *  Our initialization errors
80  */
81 typedef enum {
82   JPLIS_INIT_ERROR_NONE,
83   JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT,
84   JPLIS_INIT_ERROR_FAILURE,
85   JPLIS_INIT_ERROR_ALLOCATION_FAILURE,
86   JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED
87 } JPLISInitializationError;
88 
89 
90 struct _JPLISEnvironment {
91     jvmtiEnv *              mJVMTIEnv;              /* the JVM TI environment */
92     JPLISAgent *            mAgent;                 /* corresponding agent */
93     jboolean                mIsRetransformer;       /* indicates if special environment */
94 };
95 
96 struct _JPLISAgent {
97     JavaVM *                mJVM;                   /* handle to the JVM */
98     JPLISEnvironment        mNormalEnvironment;     /* for every thing but retransform stuff */
99     JPLISEnvironment        mRetransformEnvironment;/* for retransform stuff only */
100     jobject                 mInstrumentationImpl;   /* handle to the Instrumentation instance */
101     jmethodID               mPremainCaller;         /* method on the InstrumentationImpl that does the premain stuff (cached to save lots of lookups) */
102     jmethodID               mAgentmainCaller;       /* method on the InstrumentationImpl for agents loaded via attach mechanism */
103     jmethodID               mTransform;             /* method on the InstrumentationImpl that does the class file transform */
104     jboolean                mRedefineAvailable;     /* cached answer to "does this agent support redefine" */
105     jboolean                mRedefineAdded;         /* indicates if can_redefine_classes capability has been added */
106     jboolean                mNativeMethodPrefixAvailable; /* cached answer to "does this agent support prefixing" */
107     jboolean                mNativeMethodPrefixAdded;     /* indicates if can_set_native_method_prefix capability has been added */
108     char const *            mAgentClassName;        /* agent class name */
109     char const *            mOptionsString;         /* -javaagent options string */
110     const char *            mJarfile;               /* agent jar file name */
111 };
112 
113 /*
114  * JVMTI event handlers
115  */
116 
117 /* VMInit event handler. Installed during OnLoad, then removed during VMInit. */
118 extern void JNICALL
119 eventHandlerVMInit( jvmtiEnv *      jvmtienv,
120                     JNIEnv *        jnienv,
121                     jthread         thread);
122 
123 /*
124  * ClassFileLoadHook event handler.
125  * Enabled when the first transformer is added;
126  * Disabled when the last transformer is removed.
127  */
128 extern void JNICALL
129 eventHandlerClassFileLoadHook(  jvmtiEnv *              jvmtienv,
130                                 JNIEnv *                jnienv,
131                                 jclass                  class_being_redefined,
132                                 jobject                 loader,
133                                 const char*             name,
134                                 jobject                 protectionDomain,
135                                 jint                    class_data_len,
136                                 const unsigned char*    class_data,
137                                 jint*                   new_class_data_len,
138                                 unsigned char**         new_class_data);
139 
140 /*
141  * Main entry points for the JPLIS JVMTI agent code
142  */
143 
144 /* looks up the  environment instance. returns null if there isn't one */
145 extern JPLISEnvironment *
146 getJPLISEnvironment(jvmtiEnv * jvmtienv);
147 
148 /*  Creates a new JPLIS agent.
149  *  Returns error if the agent cannot be created and initialized.
150  *  The JPLISAgent* pointed to by agent_ptr is set to the new broker,
151  *  or NULL if an error has occurred.
152  */
153 extern JPLISInitializationError
154 createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr);
155 
156 /* Adds can_redefine_classes capability */
157 extern void
158 addRedefineClassesCapability(JPLISAgent * agent);
159 
160 /* Add the can_set_native_method_prefix capability */
161 extern void
162 addNativeMethodPrefixCapability(JPLISAgent * agent);
163 
164 /* Add the can_maintain_original_method_order capability (for testing) */
165 extern void
166 addOriginalMethodOrderCapability(JPLISAgent * agent);
167 
168 
169 /* Our JPLIS agent is paralleled by a Java InstrumentationImpl instance.
170  * This routine uses JNI to create and initialized the Java instance.
171  * Returns true if it succeeds, false otherwise.
172  */
173 extern jboolean
174 createInstrumentationImpl( JNIEnv *        jnienv,
175                            JPLISAgent *    agent);
176 
177 
178 /* during OnLoad phase (command line parsing)
179  *  record the parameters of -javaagent
180  */
181 extern JPLISInitializationError
182 recordCommandLineData(  JPLISAgent *    agent,
183                         const char *    agentClass,
184                         const char *    optionsString );
185 
186 /* Swaps the start phase event handlers out and the live phase event handlers in.
187  * Also used in attach to enabled live phase event handlers.
188  * Returns true if it succeeds, false otherwise.
189  */
190 extern jboolean
191 setLivePhaseEventHandlers(  JPLISAgent * agent);
192 
193 /* Loads the Java agent according to the already processed command line. For each,
194  * loads the Java agent class, then calls the premain method.
195  * Returns true if all Java agent classes are loaded and all premain methods complete with no exceptions,
196  * false otherwise.
197  */
198 extern jboolean
199 startJavaAgent( JPLISAgent *    agent,
200                 JNIEnv *        jnienv,
201                 const char *    classname,
202                 const char *    optionsString,
203                 jmethodID       agentMainMethod);
204 
205 
206 /* during VMInit processing
207  *  this is how the invocation engine (callback wrapper) tells us to start up all the javaagents
208  */
209 extern jboolean
210 processJavaStart(   JPLISAgent *    agent,
211                     JNIEnv *        jnienv);
212 
213 /* on an ongoing basis,
214  *  this is how the invocation engine (callback wrapper) tells us to process a class file
215  */
216 extern void
217 transformClassFile(             JPLISAgent *            agent,
218                                 JNIEnv *                jnienv,
219                                 jobject                 loader,
220                                 const char*             name,
221                                 jclass                  classBeingRedefined,
222                                 jobject                 protectionDomain,
223                                 jint                    class_data_len,
224                                 const unsigned char*    class_data,
225                                 jint*                   new_class_data_len,
226                                 unsigned char**         new_class_data,
227                                 jboolean                is_retransformer);
228 
229 /* on an ongoing basis,
230  *  Return the environment with the retransformation capability.
231  *  Create it if it doesn't exist.
232  */
233 extern jvmtiEnv *
234 retransformableEnvironment(JPLISAgent * agent);
235 
236 /* on an ongoing basis,
237  *  these are implementations of the Instrumentation services.
238  *  Most are simple covers for JVMTI access services. These are the guts of the InstrumentationImpl
239  *  native methods.
240  */
241 extern jboolean
242 isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz);
243 
244 extern jboolean
245 isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent);
246 
247 extern void
248 setHasTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
249 
250 extern void
251 setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
252 
253 extern void
254 retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes);
255 
256 extern void
257 redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions);
258 
259 extern jobjectArray
260 getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent);
261 
262 extern jobjectArray
263 getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader);
264 
265 extern jlong
266 getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize);
267 
268 extern void
269 appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader);
270 
271 extern void
272 setNativeMethodPrefixes(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray prefixArray,
273                         jboolean isRetransformable);
274 
275 #define jvmti(a) a->mNormalEnvironment.mJVMTIEnv
276 
277 /*
278  * A set of macros for insulating the JLI method callers from
279  * JVMTI_ERROR_WRONG_PHASE return codes.
280  */
281 
282 /* for a JLI method where "blob" is executed before simply returning */
283 #define check_phase_blob_ret(ret, blob)      \
284     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
285         blob;                                \
286         return;                              \
287     }
288 
289 /* for a JLI method where simply returning is benign */
290 #define check_phase_ret(ret)                 \
291     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
292         return;                              \
293     }
294 
295 /* for a JLI method where returning zero (0) is benign */
296 #define check_phase_ret_0(ret)               \
297     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
298         return 0;                            \
299     }
300 
301 /* for a JLI method where returning one (1) is benign */
302 #define check_phase_ret_1(ret)               \
303     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
304         return 1;                            \
305     }
306 
307 /* for a case where a specific "blob" must be returned */
308 #define check_phase_ret_blob(ret, blob)      \
309     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
310         return (blob);                       \
311     }
312 
313 /* for a JLI method where returning false is benign */
314 #define check_phase_ret_false(ret)           \
315     if ((ret) == JVMTI_ERROR_WRONG_PHASE) {  \
316         return (jboolean) 0;                 \
317     }
318 
319 #ifdef __cplusplus
320 } /* extern "C" */
321 #endif /* __cplusplus */
322 
323 
324 #endif
325