1 /*
2 Copyright (c) 1998--2006 Benhur Stein
3
4 This file is part of Paj�.
5
6 Paj� is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
10
11 Paj� is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with Paj�; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
19 */
20
21
22 //////////////////////////////////////////////////
23 /* Author: Geovani Ricardo Wiedenhoft */
24 /* Email: grw@inf.ufsm.br */
25 //////////////////////////////////////////////////
26
27
28 #include "JRastro.h"
29
30 /*Global agente, contem a JVMTI, monitores, ...*/
31 globalAgent *gagent;
32 /*Identifica as capacidades da JVM*/
33 jvmtiCapabilities capabilities;
34 /*Seta as funcoes para retorno dos eventos*/
35 jvmtiEventCallbacks callbacks;
36
37 /*Identificador(contador) das threads*/
38 long threadId = 1;
39 /*Identificador da thread main == Identificador da JVM*/
40 long jrst_mainThread;
41 /*Somador aleatorio, obtido pelo tempo*/
42 long adder;
43
44 /*Nome do arquivo com as opcoes dos eventos a serem selecionados*/
45 char eventsOptionName[MAX_NAME_OPTIONS];
46 /*Nome do arquivo com as opcoes das classes e metodos a serem selecionados*/
47 char methodsOptionName[MAX_NAME_OPTIONS];
48
49 /*Variavel para indicar se sera rastreados os eventos monitorados*/
50 bool traces = true;
51 /*Variavel para setar se todos as classes e metodos serao rastreados*/
52 bool tracesAll = false;
53 /*Variavel para indicar se os metodos serao rastreados*/
54 bool methodsTrace = false;
55 /*Variavel para indicar se a alocacao e liberacao de memoria sera rastreado*/
56 bool memoryTrace = false;
57
58 /*Indica se ja ocorreu a inicializacao da JVM*/
59 bool initialized = false;
60
61 /*Hash com as classes a serem redefinidas*/
62 hash_t h_class;
63 /*Hash com as opcoes, classes e metodos*/
64 hash_t h_options;
65
66 /*Buffers*/
67 rst_buffer_t *ptr_loader = NULL;
68 rst_buffer_t *ptr_monitor = NULL;
69 rst_buffer_t *ptr_new_array = NULL;
70
71
72 /*--------------------------------------------------
73 * void JNICALL jrst_event_VMStart(jvmtiEnv *jvmtiLocate, JNIEnv* jniEnv)
74 * {
75 * //jrst_enter_critical_section(GET_JVMTI());
76 *
77 * //jrst_exit_critical_section(GET_JVMTI());
78 * }
79 *--------------------------------------------------*/
80
81 /*--------------------------------------------------
82 * //////////////////////////////////////////////////////////////////////////////
83 * / *const jniNativeInterface *original_jni_Functions;
84 * const jniNativeInterface *redirected_jni_Functions;
85 * int my_global_ref_count = 0;
86 *
87 * jobject MyNewGlobalRef(JNIEnv *jniEnv, jobject obj)
88 * {
89 * ++my_global_ref_count;
90 * printf("count=[%d] aqui...\n",my_global_ref_count);
91 * return original_jni_Functions->NewGlobalRef(jniEnv, obj);
92 * }
93 *
94 * //////////////////////////////////////////////////////////////////////////////
95 * void jrst_JNI_function_interception(void)
96 * {
97 * jvmtiError err;
98 * printf("aqui...\n");
99 * err = (*GET_JVMTI())->GetJNIFunctionTable(GET_JVMTI(), &original_jni_Functions);
100 * if (err != JVMTI_ERROR_NONE) {
101 * exit(1);
102 * //die();
103 * }
104 * err = (*GET_JVMTI())->GetJNIFunctionTable(GET_JVMTI(), &redirected_jni_Functions);
105 * if (err != JVMTI_ERROR_NONE) {
106 * exit(1);
107 * //die();
108 * }
109 * redirected_jni_Functions->NewGlobalRef = MyNewGlobalRef;
110 * err = (*GET_JVMTI())->SetJNIFunctionTable(GET_JVMTI(), redirected_jni_Functions);
111 * if (err != JVMTI_ERROR_NONE) {
112 * exit(1);
113 * //die();
114 * }
115 * }
116 * * /
117 *
118 * //////////////////////////////////////////////////////////////////////////////
119 *--------------------------------------------------*/
120 //unsigned class_number=0;
121 static int class_number = 0;
122
123
jrst_event_ClassFileLoadHook(jvmtiEnv * jvmtiLocate,JNIEnv * jniEnv,jclass class_being_redefined,jobject loader,const char * name,jobject protection_domain,jint class_data_len,const unsigned char * class_data,jint * new_class_data_len,unsigned char ** new_class_data)124 void JNICALL jrst_event_ClassFileLoadHook(jvmtiEnv *jvmtiLocate, JNIEnv *jniEnv, jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain, jint class_data_len, const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data)
125 {
126 jrst_enter_critical_section(jvmtiLocate, gagent->monitor);
127
128
129 if(initialized == false){
130
131 //if(jrst_trace_class((char *)name) == false || strcmp(name, "java/lang/ClassLoader") == 0 || strcmp(name, "java/util/Vector") == 0 || strcmp(name, "java/lang/CharacterDataLatin1") == 0 || strcmp(name, "java/lang/System") == 0 || strcmp(name, "java/lang/Character") == 0 || strcmp(name, "java/util/HashMap") == 0){
132 if(jrst_trace_class((char *)name) == false){
133 class_number++;
134 jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
135 return;
136 }
137
138 jvmtiClassDefinition definition;
139 definition.class_byte_count = class_data_len;
140 definition.class_bytes = class_data;
141
142 hash_insert(&h_class, (hash_key_t)name, (hash_data_t)&definition);
143
144 jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
145 return;
146 }
147
148 jvmtiError err;
149 int system_class = 0;
150 unsigned char *new_file_image = NULL;
151 long new_file_len = 0;
152
153
154 if(class_being_redefined == NULL){
155 //if(jrst_trace_class((char *)name) == false || strcmp(name,"org/lsc/JRastro/Instru") == 0 || strcmp(name,"sun/misc/GC") == 0 || strcmp(name, "java/lang/Math") == 0){
156 if(jrst_trace_class((char *)name) == false || strcmp(name,"org/lsc/JRastro/Instru") == 0){
157 class_number++;
158 jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
159 return;
160 }
161 }else{
162 system_class = 1;
163 }
164
165 //Registro do identificador e nome da classe
166 trace_event_class_load(class_number, (char*)name);
167
168 // printf("Classe name=[%s] class_number=[%d]\n",name,class_number);
169
170 // if(!methodsTrace){
171 // jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
172 // return;
173 // }
174
175 java_crw_demo(class_number,
176 name,
177 class_data,
178 class_data_len,
179 system_class,
180 &new_file_image,
181 &new_file_len,
182 &jrst_trace_methods
183 );
184
185 if(new_file_len > 0){
186 unsigned char *jvmti_space;
187 err = (*jvmtiLocate)->Allocate(jvmtiLocate,(jlong)new_file_len, &jvmti_space);
188 jrst_check_error(jvmtiLocate, err, "Cannot Allocate memory");
189
190 (void)memcpy((void*)jvmti_space, (void *)new_file_image, (int)new_file_len);
191 *new_class_data_len = (jint)new_file_len;
192 *new_class_data = jvmti_space;
193
194 }
195 class_number++;
196
197 jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
198 }
199
200
201 //////////////////////////////////////////////////////////////////////////////
202 /*Evento de inicializacao da JVM*/
jrst_event_VMInit(jvmtiEnv * jvmtiLocate,JNIEnv * jniEnv,jthread thread)203 void JNICALL jrst_event_VMInit(jvmtiEnv *jvmtiLocate, JNIEnv *jniEnv, jthread thread)
204 {
205 jrst_enter_critical_section(jvmtiLocate, gagent->monitor);
206
207 char name[MAX_NAME_THREAD];
208
209 /*------------------------------------------------*/
210 /*Obtencao do numero aleatorio para somar com os threadId*/
211 struct timeval rt;
212 gettimeofday(&rt,NULL);
213 adder = (long)rt.tv_usec;
214 /*------------------------------------------------*/
215 jrst_mainThread = threadId + adder;
216 /*--------------------------------------------------
217 * if(name != NULL){
218 * printf("VMInit thread name=[%s]\n",name);
219 * }
220 *--------------------------------------------------*/
221
222 /*Funcao que abilita as opcoes dos eventos*/
223 jrst_read_events_enable(jvmtiLocate);
224
225 jvmtiError error;
226 jint class_count_ptr;
227 jclass *classes_ptr;
228 jvmtiClassDefinition definitions[300];
229 hash_data_t *class = NULL;
230 int count=0;
231 int i;
232
233 error = (*jvmtiLocate)->GetLoadedClasses(jvmtiLocate, &class_count_ptr, &classes_ptr);
234 jrst_check_error(jvmtiLocate, error, "Cannot Get Loaded Classes");
235
236 for(i=0; i < class_count_ptr; i++){
237
238 char *signature_ptr;
239 char *generic_ptr;
240 int size = 0;
241 char *tmp;
242
243 error = (*jvmtiLocate)->GetClassSignature(jvmtiLocate, classes_ptr[i], &signature_ptr, &generic_ptr);
244 jrst_check_error(jvmtiLocate, error, "Cannot Get Class Signature");
245
246 /*Tirar da signature o caracter 'L'*/
247 tmp = (char *)signature_ptr + 1;
248 /* -1 Pois comeca em 0 o vetor*/
249 size = strlen(tmp) - 1;
250 /*Tira da signature o caracter ';'*/
251 tmp[size] = '\0';
252
253 class = hash_locate(&h_class, (hash_key_t)tmp);
254
255 if(class != NULL){
256 definitions[count] = **(jvmtiClassDefinition **)class;
257 definitions[count].klass = classes_ptr[i];
258 count++;
259
260 }
261
262 error=(*jvmtiLocate)->Deallocate(jvmtiLocate, (unsigned char*)signature_ptr);
263 jrst_check_error(jvmtiLocate, error, "Cannot deallocate memory");
264 error=(*jvmtiLocate)->Deallocate(jvmtiLocate, (unsigned char*)generic_ptr);
265 jrst_check_error(jvmtiLocate, error, "Cannot deallocate memory");
266 }
267
268 initialized = true;
269
270 error=(*jvmtiLocate)->RedefineClasses(jvmtiLocate, count, definitions);
271 jrst_check_error(jvmtiLocate, error, "Redefine Classes");
272
273 error=(*jvmtiLocate)->Deallocate(jvmtiLocate, (unsigned char*)classes_ptr);
274 jrst_check_error(jvmtiLocate, error, "Cannot deallocate memory");
275
276 jrst_get_thread_name(jvmtiLocate, thread, name, MAX_NAME_THREAD);
277
278 trace_initialize(jvmtiLocate, thread, name);
279
280 if(traces){
281 jrst_threads(jvmtiLocate);
282 }
283
284 jrst_exit_critical_section(jvmtiLocate, gagent->monitor);
285 }
286
287
288 //////////////////////////////////////////////////////////////////////////////
289 /*--------------------------------------------------
290 * void JNICALL jrst_event_VMDeath(jvmtiEnv *jvmtiLocate, JNIEnv *jniEnv)
291 * {
292 * jrst_enter_critical_section(jvmtiLocate);
293 *
294 * printf("VM Death event\n");
295 *
296 * jrst_exit_critical_section(jvmtiLocate);
297 * }
298 *--------------------------------------------------*/
299
300 //////////////////////////////////////////////////////////////////////////////
jrst_set_capabilities()301 void jrst_set_capabilities()
302 {
303 jvmtiError error;
304
305 (void)memset(&capabilities, 0, sizeof(capabilities));
306
307 /*Abilitar as abilidades que se deseja monitorar*/
308 error = (*GET_JVMTI())->GetPotentialCapabilities(GET_JVMTI(), &capabilities);
309 jrst_check_error(GET_JVMTI(), error, "Cannot Get Potential Capabilities");
310
311 /*Verificacao de capacidades*/
312 if(capabilities.can_signal_thread != 1 ||
313 capabilities.can_get_owned_monitor_info != 1 ||
314 capabilities.can_generate_exception_events != 1 ||
315 capabilities.can_generate_frame_pop_events != 1 ||
316 capabilities.can_generate_method_entry_events != 1 ||
317 capabilities.can_generate_method_exit_events != 1 ||
318 capabilities.can_generate_vm_object_alloc_events != 1 ||
319 capabilities.can_generate_object_free_events != 1 ||
320 capabilities.can_get_current_thread_cpu_time != 1 ||
321 capabilities.can_get_thread_cpu_time != 1 ||
322 capabilities.can_access_local_variables != 1 ||
323 capabilities.can_generate_compiled_method_load_events != 1 ||
324 capabilities.can_maintain_original_method_order != 1 ||
325 capabilities.can_generate_monitor_events != 1 ||
326 capabilities.can_generate_garbage_collection_events != 1 ||
327 capabilities.can_generate_all_class_hook_events != 1){
328
329 printf("JVMTI_ERROR: Cannot get capabilities\n");
330 exit(1);
331 }
332
333 error=(*GET_JVMTI())->AddCapabilities(GET_JVMTI(), &capabilities);
334 jrst_check_error(GET_JVMTI(), error, "Cannot Enable JVMTI capabilities");
335
336 }
337
jrst_set_funcs()338 void jrst_set_funcs()
339 {
340 jvmtiError error;
341
342 (void)memset(&callbacks, 0, sizeof(callbacks));
343
344 /*Abilitar as funcoes que serao chamadas*/
345 callbacks.VMInit = &jrst_event_VMInit;
346 callbacks.ClassFileLoadHook = &jrst_event_ClassFileLoadHook;
347 callbacks.ThreadStart = &jrst_event_thread_start;
348 callbacks.ThreadEnd = &jrst_event_thread_end;
349 /*callbacks.VMObjectAlloc = &jrst_event_VMObject_alloc;*/
350 callbacks.ObjectFree = &jrst_event_object_free;
351 callbacks.GarbageCollectionStart = &jrst_event_garbage_collection_start;
352 callbacks.GarbageCollectionFinish = &jrst_event_garbage_collection_finish;
353 callbacks.Exception = &jrst_event_exception;
354 /*callbacks.ExceptionCatch = &jrst_event_exception_catch;*/
355 callbacks.FramePop = &jrst_event_frame_pop;
356 callbacks.MonitorContendedEnter = &jrst_monitor_contended_enter;
357 callbacks.MonitorContendedEntered = &jrst_monitor_contended_entered;
358 callbacks.MonitorWait = &jrst_monitor_wait;
359 callbacks.MonitorWaited = &jrst_monitor_waited;
360 /*callbacks.VMStart = &jrst_event_VMStart;*/
361 /*callbacks.VMDeath = &jrst_event_VMDeath;*/
362
363
364 error=(*GET_JVMTI())->SetEventCallbacks(GET_JVMTI(), &callbacks,(jint)sizeof(callbacks));
365 jrst_check_error(GET_JVMTI(), error, "Cannot set JVMTI callbacks");
366 }
367
jrst_init()368 void jrst_init()
369 {
370 jvmtiError error;
371
372 /*Abilita as funcoes JVMTI_EVENT_CLASS_FILE_LOAD_HOOK e JVMTI_EVENT_VM_INIT*/
373
374 error=(*GET_JVMTI())->SetEventNotificationMode(GET_JVMTI(), JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
375 jrst_check_error(GET_JVMTI(), error, "Cannot set event notification <JVMTI_EVENT_CLASS_FILE_LOAD_HOOK>");
376
377 error=(*GET_JVMTI())->SetEventNotificationMode(GET_JVMTI(), JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, (jthread)NULL);
378 jrst_check_error(GET_JVMTI(), error, "Cannot set event notification <JVMTI_EVENT_VM_INIT>");
379
380 /* error=(*GET_JVMTI())->SetEventNotificationMode(GET_JVMTI(), JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, (jthread)NULL);
381 jrst_check_error(GET_JVMTI(), error, "Cannot set event notification <JVMTI_EVENT_VM_DEATH>");
382
383 error=(*GET_JVMTI())->SetEventNotificationMode(GET_JVMTI(), JVMTI_ENABLE, JVMTI_EVENT_VM_START, (jthread)NULL);
384 jrst_check_error(GET_JVMTI(), error, "Cannot set event notification <JVMTI_EVENT_VM_START>");
385 */
386
387 }
388
jrst_create_monitor()389 void jrst_create_monitor()
390 {
391 jvmtiError error;
392
393 /*Criacao dos monitores*/
394 error=(*GET_JVMTI())->CreateRawMonitor(GET_JVMTI(), "agent", &(gagent->monitor));
395 jrst_check_error(GET_JVMTI(), error, "Cannot create raw monitor");
396
397 error=(*GET_JVMTI())->CreateRawMonitor(GET_JVMTI(), "thread", &(gagent->monitor_thread));
398 jrst_check_error(GET_JVMTI(), error, "Cannot create raw monitor");
399
400 error=(*GET_JVMTI())->CreateRawMonitor(GET_JVMTI(), "buffer", &(gagent->monitor_buffer));
401 jrst_check_error(GET_JVMTI(), error, "Cannot create raw monitor");
402
403 error=(*GET_JVMTI())->CreateRawMonitor(GET_JVMTI(), "newArray", &(gagent->monitor_new_array));
404 jrst_check_error(GET_JVMTI(), error, "Cannot create raw monitor");
405
406 error=(*GET_JVMTI())->CreateRawMonitor(GET_JVMTI(), "tag", &(gagent->monitor_tag));
407 jrst_check_error(GET_JVMTI(), error, "Cannot create raw monitor");
408
409 }
410
Agent_OnLoad(JavaVM * jvm,char * options,void * reserved)411 JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
412 {
413 jint ret;
414
415 printf("[JRastro] Loading Agent_Onload...\n");
416
417 hash_initialize(&h_options, hash_value_string, hash_copy_string, hash_key_cmp_string, hash_destroy_string_list);
418 hash_initialize(&h_class, hash_value_string, hash_copy_string_data, hash_key_cmp_string, hash_destroy_string_data);
419
420 gagent = (globalAgent *) malloc(sizeof(globalAgent));
421
422 ret=(*jvm)->GetEnv(jvm, (void **)&gagent->jvmti, JVMTI_VERSION_1_0);
423 if(ret != JNI_OK || gagent->jvmti == NULL){
424 printf("ERROR: Unable to access JVMTI Version 1 (0x%x),"
425 " is your J2SE a 1.5 or newer version?"
426 " JNIEnv's GetEnv() returned %d\n",
427 JVMTI_VERSION_1, ret);
428 exit(1);
429 }
430
431
432 /*Le nomes dos arquivos "opcoes"*/
433 jrst_read_names_options(options);
434
435 /*Funcao que abilita os methodos a serem rastreados*/
436 jrst_read_class_methods_enable();
437
438 jrst_set_capabilities();
439
440 jrst_set_funcs();
441
442 jrst_init();
443
444 jrst_create_monitor();
445
446 return JNI_OK;
447
448 }
449
450
451 //////////////////////////////////////////////////////////////////////////////
Agent_OnUnload(JavaVM * vm)452 JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
453 {
454 //printf("Loading Agent_OnUnload ........");
455 //extern int count;
456 hash_finalize(&h_options);
457 hash_finalize(&h_class);
458
459 if(traces){
460 rst_flush_all();
461 }
462 printf("[JRastro] ................OK\n");
463 }
464
465