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
37extern "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 */
51struct _JPLISAgent;
52
53typedef struct _JPLISAgent JPLISAgent;
54typedef 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 */
81typedef 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
90struct _JPLISEnvironment {
91 jvmtiEnv * mJVMTIEnv; /* the JVM TI environment */
92 JPLISAgent * mAgent; /* corresponding agent */
93 jboolean mIsRetransformer; /* indicates if special environment */
94};
95
96struct _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. */
118extern void JNICALL
119eventHandlerVMInit( 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 */
128extern void JNICALL
129eventHandlerClassFileLoadHook( 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 */
145extern JPLISEnvironment *
146getJPLISEnvironment(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 */
153extern JPLISInitializationError
154createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr);
155
156/* Adds can_redefine_classes capability */
157extern void
158addRedefineClassesCapability(JPLISAgent * agent);
159
160/* Add the can_set_native_method_prefix capability */
161extern void
162addNativeMethodPrefixCapability(JPLISAgent * agent);
163
164/* Add the can_maintain_original_method_order capability (for testing) */
165extern void
166addOriginalMethodOrderCapability(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 */
173extern jboolean
174createInstrumentationImpl( JNIEnv * jnienv,
175 JPLISAgent * agent);
176
177
178/* during OnLoad phase (command line parsing)
179 * record the parameters of -javaagent
180 */
181extern JPLISInitializationError
182recordCommandLineData( 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 */
190extern jboolean
191setLivePhaseEventHandlers( 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 */
198extern jboolean
199startJavaAgent( 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 */
209extern jboolean
210processJavaStart( 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 */
216extern void
217transformClassFile( 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 */
233extern jvmtiEnv *
234retransformableEnvironment(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 */
241extern jboolean
242isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz);
243
244extern jboolean
245isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent);
246
247extern void
248setHasTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
249
250extern void
251setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
252
253extern void
254retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes);
255
256extern void
257redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions);
258
259extern jobjectArray
260getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent);
261
262extern jobjectArray
263getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader);
264
265extern jlong
266getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize);
267
268extern void
269appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader);
270
271extern void
272setNativeMethodPrefixes(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