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