|
1 /* |
|
2 * Copyright (c) 2008, 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 <string.h> |
|
24 #include <stdlib.h> |
|
25 #include <jvmti_aod.h> |
|
26 |
|
27 #ifdef __cplusplus |
|
28 extern "C" { |
|
29 #endif |
|
30 |
|
31 void nsk_jvmti_aod_disableEventAndFinish(const char* agentName, jvmtiEvent event, int success, jvmtiEnv *jvmti, JNIEnv* jni) { |
|
32 if (!nsk_jvmti_aod_disableEvent(jvmti, event)) |
|
33 success = 0; |
|
34 |
|
35 nsk_aod_agentFinished(jni, agentName, success); |
|
36 } |
|
37 |
|
38 void nsk_jvmti_aod_disableEventsAndFinish(const char* agentName, jvmtiEvent events[], int eventsNumber, int success, jvmtiEnv *jvmti, JNIEnv* jni) { |
|
39 if (!nsk_jvmti_aod_disableEvents(jvmti, events, eventsNumber)) |
|
40 success = 0; |
|
41 |
|
42 nsk_aod_agentFinished(jni, agentName, success); |
|
43 } |
|
44 |
|
45 /* |
|
46 * Work with agent options |
|
47 */ |
|
48 |
|
49 struct { |
|
50 jvmtiEnv *jvmti; |
|
51 Options *options; |
|
52 } multiagentsOptions[MAX_MULTIPLE_AGENTS]; |
|
53 |
|
54 static volatile int multiagentsCount = 0; |
|
55 |
|
56 int nsk_jvmti_aod_addMultiagentsOptions(jvmtiEnv *jvmti, Options *options) { |
|
57 if (multiagentsCount >= MAX_MULTIPLE_AGENTS) { |
|
58 NSK_COMPLAIN1("To many agents, max agents count is %d\n", MAX_MULTIPLE_AGENTS); |
|
59 return NSK_FALSE; |
|
60 } |
|
61 |
|
62 multiagentsOptions[multiagentsCount].jvmti = jvmti; |
|
63 multiagentsOptions[multiagentsCount].options = options; |
|
64 multiagentsCount++; |
|
65 |
|
66 NSK_DISPLAY3("Options for agent %s were added (jvmtiEnv: %p, agentsCount: %d)\n", |
|
67 nsk_aod_getOptionValue(options, NSK_AOD_AGENT_NAME_OPTION), |
|
68 jvmti, |
|
69 multiagentsCount); |
|
70 |
|
71 return NSK_TRUE; |
|
72 } |
|
73 |
|
74 Options* nsk_jvmti_aod_getMultiagentsOptions(jvmtiEnv *jvmti) { |
|
75 int i; |
|
76 for (i = 0; i < multiagentsCount; i++) { |
|
77 if (multiagentsOptions[i].jvmti == jvmti) { |
|
78 return multiagentsOptions[i].options; |
|
79 } |
|
80 } |
|
81 |
|
82 NSK_COMPLAIN1("Options for jvmtiEnv %p weren't found\n", jvmti); |
|
83 |
|
84 return NULL; |
|
85 } |
|
86 |
|
87 /* |
|
88 * Auxiliary functions |
|
89 */ |
|
90 |
|
91 void nsk_jvmti_aod_deallocate(jvmtiEnv *jvmti, unsigned char* mem) { |
|
92 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate, jvmti, mem))) { |
|
93 NSK_COMPLAIN0("Deallocate failed\n"); |
|
94 |
|
95 /* |
|
96 * if deallocate fails it isn't critical and test execution can continue without problems, |
|
97 * just call nsk_aod_internal_error to inform framework about this error |
|
98 */ |
|
99 nsk_aod_internal_error(); |
|
100 } |
|
101 } |
|
102 |
|
103 int nsk_jvmti_aod_getClassName(jvmtiEnv *jvmti, jclass klass, char classNameBuffer[]) { |
|
104 char* className; |
|
105 |
|
106 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature, jvmti, klass, &className, NULL))) { |
|
107 NSK_COMPLAIN0("Failed to get class name\n"); |
|
108 classNameBuffer[0] = '\0'; |
|
109 return NSK_FALSE; |
|
110 } else { |
|
111 strcpy(classNameBuffer, className); |
|
112 |
|
113 nsk_jvmti_aod_deallocate(jvmti, (unsigned char*)className); |
|
114 |
|
115 return NSK_TRUE; |
|
116 } |
|
117 } |
|
118 |
|
119 int nsk_jvmti_aod_getThreadName(jvmtiEnv * jvmti, jthread thread, char threadNameBuffer[]) { |
|
120 jvmtiThreadInfo info; |
|
121 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadInfo, jvmti, thread, &info))){ |
|
122 NSK_COMPLAIN0("Failed to get thread info\n"); |
|
123 threadNameBuffer[0] = '\0'; |
|
124 return NSK_FALSE; |
|
125 } else { |
|
126 strcpy(threadNameBuffer, info.name); |
|
127 |
|
128 nsk_jvmti_aod_deallocate(jvmti, (unsigned char*)info.name); |
|
129 |
|
130 return NSK_TRUE; |
|
131 } |
|
132 } |
|
133 |
|
134 // events enabling/disabling |
|
135 |
|
136 int nsk_jvmti_aod_disableEvents(jvmtiEnv* jvmti, jvmtiEvent events[], int eventsNumber) { |
|
137 int i; |
|
138 int status = NSK_TRUE; |
|
139 |
|
140 for (i = 0; i < eventsNumber; i++) { |
|
141 if (!nsk_jvmti_aod_disableEvent(jvmti, events[i])) { |
|
142 status = NSK_FALSE; |
|
143 } |
|
144 } |
|
145 |
|
146 return status; |
|
147 } |
|
148 |
|
149 int nsk_jvmti_aod_enableEvents(jvmtiEnv* jvmti, jvmtiEvent events[], int eventsNumber) { |
|
150 int i; |
|
151 for (i = 0; i < eventsNumber; i++) { |
|
152 if (!nsk_jvmti_aod_enableEvent(jvmti, events[i])) |
|
153 return NSK_FALSE; |
|
154 } |
|
155 |
|
156 return NSK_TRUE; |
|
157 } |
|
158 |
|
159 // java threads creation |
|
160 |
|
161 jthread nsk_jvmti_aod_createThread(JNIEnv *jni) { |
|
162 jclass klass ; |
|
163 jmethodID threadConstructor; |
|
164 jthread thread; |
|
165 |
|
166 if (!NSK_JNI_VERIFY(jni, |
|
167 (klass = NSK_CPP_STUB2(FindClass, jni, "java/lang/Thread")) != NULL )) { |
|
168 NSK_COMPLAIN0("Failed to get the java.lang.Thread class\n"); |
|
169 return NULL; |
|
170 } |
|
171 if (!NSK_JNI_VERIFY(jni, |
|
172 (threadConstructor = NSK_CPP_STUB4(GetMethodID, jni, klass, "<init>", "()V") ) != NULL )) { |
|
173 NSK_COMPLAIN0("Failed to get java.lang.Thread constructor\n"); |
|
174 return NULL; |
|
175 } |
|
176 |
|
177 if (!NSK_JNI_VERIFY (jni, |
|
178 (thread = NSK_CPP_STUB4(NewObject, jni, klass, threadConstructor, NULL)) != NULL ) ) { |
|
179 NSK_COMPLAIN0("Failed to create Thread object\n"); |
|
180 return NULL; |
|
181 } |
|
182 |
|
183 if (!NSK_JNI_VERIFY(jni, (thread = |
|
184 NSK_CPP_STUB2(NewGlobalRef, jni, thread)) != NULL)) { |
|
185 NSK_COMPLAIN0("Failed to create global reference\n"); |
|
186 return NULL; |
|
187 } |
|
188 |
|
189 return thread; |
|
190 } |
|
191 |
|
192 jthread nsk_jvmti_aod_createThreadWithName(JNIEnv *jni, char* threadName) { |
|
193 jclass klass ; |
|
194 jmethodID threadConstructor; |
|
195 jthread thread; |
|
196 jstring threadNameString; |
|
197 |
|
198 if (!NSK_JNI_VERIFY(jni, (threadNameString = |
|
199 NSK_CPP_STUB2(NewStringUTF, jni, threadName)) != NULL)) |
|
200 return NULL; |
|
201 |
|
202 if (!NSK_JNI_VERIFY(jni, |
|
203 (klass = NSK_CPP_STUB2(FindClass, jni, "java/lang/Thread")) != NULL )) { |
|
204 NSK_COMPLAIN0("Failed to get the java.lang.Thread class\n"); |
|
205 return NULL; |
|
206 } |
|
207 if (!NSK_JNI_VERIFY(jni, |
|
208 (threadConstructor = NSK_CPP_STUB4(GetMethodID, jni, klass, "<init>", "(Ljava/lang/String;)V") ) != NULL )) { |
|
209 NSK_COMPLAIN0("Failed to get java.lang.Thread constructor\n"); |
|
210 return NULL; |
|
211 } |
|
212 |
|
213 if (!NSK_JNI_VERIFY(jni, |
|
214 (thread = NSK_CPP_STUB4(NewObject, jni, klass, threadConstructor, threadNameString)) != NULL ) ) { |
|
215 NSK_COMPLAIN0("Failed to create Thread object\n"); |
|
216 return NULL; |
|
217 } |
|
218 |
|
219 if (!NSK_JNI_VERIFY(jni, (thread = |
|
220 NSK_CPP_STUB2(NewGlobalRef, jni, thread)) != NULL)) { |
|
221 NSK_COMPLAIN0("Failed to create global reference\n"); |
|
222 return NULL; |
|
223 } |
|
224 |
|
225 return thread; |
|
226 } |
|
227 |
|
228 // class redefinition |
|
229 |
|
230 int nsk_jvmti_aod_redefineClass( |
|
231 Options * options, |
|
232 jvmtiEnv * jvmti, |
|
233 jclass classToRedefine, |
|
234 const char * fileName) { |
|
235 |
|
236 if (!nsk_aod_optionSpecified(options, PATH_TO_NEW_BYTE_CODE_OPTION)) { |
|
237 NSK_COMPLAIN1("Option '%s' isn't specified\n", PATH_TO_NEW_BYTE_CODE_OPTION); |
|
238 return NSK_FALSE; |
|
239 } |
|
240 if (fileName == NULL) { |
|
241 NSK_COMPLAIN0("File name is NULL\n"); |
|
242 return NSK_FALSE; |
|
243 } |
|
244 { |
|
245 char file [1024]; |
|
246 |
|
247 sprintf(file,"%s/%s.class", |
|
248 nsk_aod_getOptionValue(options, PATH_TO_NEW_BYTE_CODE_OPTION), |
|
249 fileName); |
|
250 NSK_DISPLAY1("File with new bytecode: '%s'\n", file); |
|
251 |
|
252 { |
|
253 FILE *bytecode; |
|
254 unsigned char * classBytes; |
|
255 jvmtiError error; |
|
256 jint size; |
|
257 |
|
258 bytecode = fopen(file, "rb"); |
|
259 error= JVMTI_ERROR_NONE; |
|
260 if ( bytecode == NULL ) { |
|
261 NSK_COMPLAIN1("Error opening file '%s'\n", file); |
|
262 return NSK_FALSE; |
|
263 } |
|
264 |
|
265 NSK_DISPLAY1("Opening file '%s' \n", file); |
|
266 fseek(bytecode, 0, SEEK_END); |
|
267 size = ftell(bytecode); |
|
268 NSK_DISPLAY1("File size= %ld\n", ftell(bytecode)); |
|
269 rewind(bytecode); |
|
270 error = (*jvmti)->Allocate(jvmti, size, &classBytes); |
|
271 if ( error != JVMTI_ERROR_NONE) { |
|
272 NSK_DISPLAY1("Failed to create memory %s\n", TranslateError(error)); |
|
273 return NSK_FALSE; |
|
274 } |
|
275 |
|
276 if ( ((jint) fread( classBytes, 1, size, bytecode )) != size ) { |
|
277 NSK_COMPLAIN0("Failed to read all the bytes, could be less or more\n"); |
|
278 fclose(bytecode); |
|
279 return NSK_FALSE; |
|
280 } else { |
|
281 NSK_DISPLAY0("File read completely \n"); |
|
282 } |
|
283 fclose(bytecode); |
|
284 { |
|
285 jvmtiClassDefinition classDef; |
|
286 classDef.klass = classToRedefine; |
|
287 classDef.class_byte_count= size; |
|
288 classDef.class_bytes = classBytes; |
|
289 NSK_DISPLAY0("Redefining\n"); |
|
290 error = (*jvmti)->RedefineClasses(jvmti, 1, &classDef); |
|
291 if ( error != JVMTI_ERROR_NONE ) { |
|
292 NSK_DISPLAY1("# error occured while redefining %s ", |
|
293 TranslateError(error) ); |
|
294 return NSK_FALSE; |
|
295 } |
|
296 } |
|
297 } |
|
298 } |
|
299 return NSK_TRUE; |
|
300 } |
|
301 |
|
302 // capabilities |
|
303 |
|
304 void printCapabilities(jvmtiCapabilities caps) { |
|
305 #define printCap(name) NSK_DISPLAY1(#name ": %d\n", caps.name) |
|
306 |
|
307 printCap(can_tag_objects); |
|
308 printCap(can_generate_field_modification_events); |
|
309 printCap(can_generate_field_access_events); |
|
310 printCap(can_get_bytecodes); |
|
311 printCap(can_get_synthetic_attribute); |
|
312 printCap(can_get_owned_monitor_info); |
|
313 printCap(can_get_current_contended_monitor); |
|
314 printCap(can_get_monitor_info); |
|
315 printCap(can_pop_frame); |
|
316 printCap(can_redefine_classes); |
|
317 printCap(can_signal_thread); |
|
318 printCap(can_get_source_file_name); |
|
319 printCap(can_get_line_numbers); |
|
320 printCap(can_get_source_debug_extension); |
|
321 printCap(can_access_local_variables); |
|
322 printCap(can_maintain_original_method_order); |
|
323 printCap(can_generate_single_step_events); |
|
324 printCap(can_generate_exception_events); |
|
325 printCap(can_generate_frame_pop_events); |
|
326 printCap(can_generate_breakpoint_events); |
|
327 printCap(can_suspend); |
|
328 printCap(can_redefine_any_class); |
|
329 printCap(can_get_current_thread_cpu_time); |
|
330 printCap(can_get_thread_cpu_time); |
|
331 printCap(can_generate_method_entry_events); |
|
332 printCap(can_generate_method_exit_events); |
|
333 printCap(can_generate_all_class_hook_events); |
|
334 printCap(can_generate_compiled_method_load_events); |
|
335 printCap(can_generate_monitor_events); |
|
336 printCap(can_generate_vm_object_alloc_events); |
|
337 printCap(can_generate_native_method_bind_events); |
|
338 printCap(can_generate_garbage_collection_events); |
|
339 printCap(can_generate_object_free_events); |
|
340 printCap(can_force_early_return); |
|
341 printCap(can_get_owned_monitor_stack_depth_info); |
|
342 printCap(can_get_constant_pool); |
|
343 printCap(can_set_native_method_prefix); |
|
344 printCap(can_retransform_classes); |
|
345 printCap(can_retransform_any_class); |
|
346 |
|
347 #undef printCap |
|
348 } |
|
349 |
|
350 #ifdef __cplusplus |
|
351 } |
|
352 #endif |