blob: 36304d251e003930feb287f296c3da997023bcbc [file] [log] [blame]
/**
* @author Valentin Al. Sitnick
*
*/
#ifndef _UTILS_H_
#define _UTILS_H_
#ifdef LINUX
#include <unistd.h>
#else
#include <windows.h>
#endif
#include "jvmti.h"
#include "events.h"
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define FREE_TINFO jvmti_env->Deallocate((unsigned char*)(tinfo.name));
#define FREE_TLIST jvmti_env->Deallocate((unsigned char*)(threads));
#define FREE_CLIST jvmti_env->Deallocate((unsigned char*)(classes));
#define FREE_MLIST jvmti_env->Deallocate((unsigned char*)(methods));
#define FREE_FLIST jvmti_env->Deallocate((unsigned char*)(fids));
#define FREE_VARIABLE_TABLE_EL \
jvmti_env->Deallocate((unsigned char*)table[i].name); \
jvmti_env->Deallocate((unsigned char*)table[i].signature); \
jvmti_env->Deallocate((unsigned char*)table[i].generic_signature);
#define FREE_VARIABLE_TABLE \
jvmti_env->Deallocate((unsigned char*)table);
#define FREE_METHOD_NAME_OUT \
jvmti_env->Deallocate((unsigned char*)name); \
jvmti_env->Deallocate((unsigned char*)sign); \
jvmti_env->Deallocate((unsigned char*)generic);
/***************************************************************************/
#define AGENT_JVMTI_ENV_INIT { \
/* initialization of JVMTI environment */ \
{ \
jint res = JNI_OK; \
\
res = vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); \
\
if (res != JNI_OK) { \
printf ("Failure of initialization of JVMTI environment: %d\n", \
(int)res); \
return res; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_JAVA_LIB_PATH_WINDOWS { \
/* adding .dll & .so directories to "java.library.path" */ \
{ \
results[0] = jvmti->SetSystemProperty( \
"java.library.path", ".\\dll\\."); \
if (results[0] != JVMTI_ERROR_NONE) { \
printf("Failure of adding library path : %d \n", results[0]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_JAVA_LIB_PATH_LINUX { \
/* adding .dll & .so directories to "java.library.path" */ \
{ \
results[0] = jvmti->SetSystemProperty( \
"java.library.path", "./so"); \
if (results[0] != JVMTI_ERROR_NONE) { \
printf("Failure of adding library path : %d \n", results[0]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_CAPABILITIES_INIT { \
/* initialization of needed capabilities and calbacks */ \
{ \
results[1] = jvmti->GetPotentialCapabilities(&possible_caps); \
results[2] = jvmti->AddCapabilities(&possible_caps); \
\
if ((results[1] != JVMTI_ERROR_NONE) || \
(results[2] != JVMTI_ERROR_NONE)) { \
printf("Failure of adding capabilities : pot=%d add=%d \n", \
results[1], \
results[2]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_CALLBACK_EXCEPTION_INIT { \
/* events enabling */ \
{ \
jvmtiEvent events[] = { JVMTI_EVENT_EXCEPTION }; \
\
memset(&callbacks, 0, sizeof(callbacks)); \
callbacks.Exception = callbackException; \
\
results[3] = \
jvmti->SetEventNotificationMode( \
JVMTI_ENABLE, events[0], NULL); \
\
if (results[3] != JVMTI_ERROR_NONE) { \
printf("Failure of enabling event: %d\n", results[3]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_CALLBACK_VMINIT_INIT { \
/* events enabling */ \
{ \
jvmtiEvent events[] = { JVMTI_EVENT_VM_INIT }; \
\
memset(&callbacks, 0, sizeof(callbacks)); \
callbacks.VMInit = callbackVMInit; \
\
results[3] = \
jvmti->SetEventNotificationMode( \
JVMTI_ENABLE, events[0], NULL); \
\
if (results[3] != JVMTI_ERROR_NONE) { \
printf("Failure of enabling event: %d\n", results[3]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_CALLBACK_THREAD_START_INIT { \
/* events enabling */ \
{ \
jvmtiEvent events[] = { JVMTI_EVENT_THREAD_START }; \
\
memset(&callbacks, 0, sizeof(callbacks)); \
callbacks.ThreadStart = callbackThreadStart; \
\
results[3] = \
jvmti->SetEventNotificationMode( \
JVMTI_ENABLE, events[0], NULL); \
\
if (results[3] != JVMTI_ERROR_NONE) { \
printf("Failure of enabling event: %d\n", results[3]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_SET_CALLBACK_THRD_START_INIT { \
/* events enabling */ \
{ \
jvmtiEvent events[] = { JVMTI_EVENT_THREAD_START }; \
\
memset(&callbacks, 0, sizeof(callbacks)); \
callbacks.ThreadStart = callbackThreadStart; \
\
results[3] = \
jvmti->SetEventNotificationMode( \
JVMTI_ENABLE, events[0], NULL); \
\
if (results[3] != JVMTI_ERROR_NONE) { \
printf("Failure of enabling event: %d\n", results[3]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define AGENT_JVMTI_CALLBACKS_INIT { \
/* set event callbacks */ \
{ \
results[7] = \
jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); \
if (results[7] != JVMTI_ERROR_NONE) { \
printf("Failure of setting event callbacks: %d\n", \
results[7]); \
return JNI_ERR; \
} \
} \
}
/***************************************************************************/
#define START_TEST_CHECK \
jint test_start = 0; \
jvmtiPhase phase; \
jvmtiThreadInfo tinfo; \
\
if (jvmti_env->GetPhase(&phase) == JVMTI_ERROR_NONE) \
{ \
if (phase == JVMTI_PHASE_LIVE) \
{ \
test_start = 1; \
} \
} \
\
if (test_start) \
{ \
test_start = 0; \
\
if (jvmti_env->GetThreadInfo(thread, &tinfo) \
== JVMTI_ERROR_NONE) \
{ \
if (!strcmp(tinfo.name, "agent")) \
{ \
test_start = 1; \
} \
} \
}
/***************************************************************************/
#define CHECK_BEFORE_START() \
jvmtiPhase phase; \
bool test_can_be_started = false; \
\
if (jvmti_env->GetPhase(&phase) == JVMTI_ERROR_NONE) \
{ \
if (phase == JVMTI_PHASE_LIVE) \
{ \
jvmtiThreadInfo tinfo ; \
\
if (jvmti_env->GetThreadInfo(thread, &tinfo) \
== JVMTI_ERROR_NONE) \
{ \
if (!strcmp(tinfo.name, "agent")) \
{ \
test_can_be_started = true; \
} \
} \
\
FREE_TINFO; \
} \
}
/***************************************************************************/
#define GET_CURRENT_JCLASS_AND_SPECIAL_METHOD_ID() \
{ \
jint ccount; \
jclass cc = NULL; \
jclass* classes; \
jvmtiError r_get_classes = \
jvmti_env->GetLoadedClasses(&ccount, &classes); \
\
if (r_get_classes == JVMTI_ERROR_NONE) \
{ \
for (int i = 0; i < ccount; i++) \
{ \
char* s; \
char* g; \
jvmtiError r_get_class_sign = \
jvmti_env->GetClassSignature(classes[i], &s, &g); \
\
if (r_get_class_sign == JVMTI_ERROR_NONE) \
{ \
if (!strcmp(s, filename)) \
{ \
cc = classes[i]; \
break; \
} \
} \
} \
} \
else \
{ \
printf(" FAILED \n\terror during GetLoadedClasses"); \
return; \
} \
if (cc) \
{ \
jint mcount; \
jmethodID* methods; \
jvmtiError r = jvmti_env->GetClassMethods(cc, &mcount, &methods); \
if (r == JVMTI_ERROR_NONE) \
{ \
for (int i = 0; i < mcount; i++) \
{ \
char* name; \
char* signature; \
char* generic; \
if (jvmti_env->GetMethodName(methods[i], &name, &signature,\
&generic) == JVMTI_ERROR_NONE) \
{ \
if (!strcmp(name, "special_method")) \
{ \
method = methods[i]; \
break; \
} \
} \
} \
} \
} \
if (!cc || !method) \
{ \
printf(" FAILED\n\tError during class or method definition\n class = %x, method = %x\n ",\
cc, method); \
return; \
} \
}
/***************************************************************************/
#define GET_CURRENT_JCLASS() \
{ \
jint ccount; \
jclass cc = NULL; \
jclass* classes; \
jvmtiError r_get_classes = \
jvmti_env->GetLoadedClasses(&ccount, &classes); \
\
if (r_get_classes == JVMTI_ERROR_NONE) \
{ \
for (int i = 0; i < ccount; i++) \
{ \
char* s; \
char* g; \
jvmtiError r_get_class_sign = \
jvmti_env->GetClassSignature(classes[i], &s, &g); \
\
if (r_get_class_sign == JVMTI_ERROR_NONE) \
{ \
if (!strcmp(s, filename)) \
{ \
cc = classes[i]; \
break; \
} \
} \
} \
} \
else \
{ \
printf(" FAILED \n\terror during GetLoadedClasses"); \
return; \
} \
\
if (!cc) \
{ \
printf(" FAILED\n\tError during class definition\n class = %x", \
cc); \
return; \
} \
\
clazz = cc; \
}
/***************************************************************************/
#define GET_NEEDED_FID() \
\
if (jvmti_env->GetClassFields(clazz, &fcount, &fids) == JVMTI_ERROR_NONE) \
{ \
for (int i = 0; i < fcount; i++) \
{ \
char* field_name; \
char* field_signature; \
char* field_generic; \
\
if (jvmti_env->GetFieldName(clazz, fids[i], &field_name, \
&field_signature, &field_generic) == JVMTI_ERROR_NONE) \
{ \
if (!strcmp(field_name, "special_field")) \
{ \
if (!strcmp(field_signature, "Z")) \
{ \
fid = fids[i]; \
break; \
} \
} \
} \
} \
}
/***************************************************************************/
void thread_state_output_as_string(long state);
void class_status_output_as_string(long status);
void print_capabilities(jvmtiCapabilities c, const char* name);
int cmp_caps_and_output_results(jvmtiCapabilities c1,
jvmtiCapabilities c2, const char* name1, const char* name2);
void make_caps_zero(jvmtiCapabilities* c1);
void make_caps_set_all(jvmtiCapabilities* c1);
/***************************************************************************/
#define CAPABILITY_TURN_OFF(cap) \
{ \
jvmtiCapabilities zero_caps; \
jvmtiError result; \
make_caps_zero(&zero_caps); \
zero_caps.cap = 1; \
result = jvmti->RelinquishCapabilities(&zero_caps); \
if (result != JVMTI_ERROR_NONE) \
{ \
fprintf(stderr, \
"Error during RelinquishCapabilities. Test Stopped\n"); \
fflush(stderr); \
return JNI_ERR; \
} \
} \
/***************************************************************************/
#define CAPABILITY_TURN_OFF_VOID(cap) \
{ \
jvmtiCapabilities zero_caps; \
jvmtiError result; \
make_caps_zero(&zero_caps); \
zero_caps.cap = 1; \
result = jvmti_env->RelinquishCapabilities(&zero_caps); \
if (result != JVMTI_ERROR_NONE) \
{ \
fprintf(stderr, \
"Error during RelinquishCapabilities. Test Stopped\n"); \
fflush(stderr); \
return; \
} \
} \
/***************************************************************************/
#define CAPABILITY_CHECK() \
{ \
jvmtiCapabilities full_caps; \
jvmtiCapabilities caps; \
make_caps_set_all(&full_caps); \
result = jvmti_env->GetCapabilities(&caps); \
if (result != JVMTI_ERROR_NONE) \
{ \
fprintf(stderr, \
"Error during GetCapabilities. Test Stopped\n"); \
fflush(stderr); \
return; \
} \
int diff = cmp_caps_and_output_results(full_caps, caps, \
"potential", "current"); \
} \
/***************************************************************************/
#define SPP_NONE 0
#define SPP_ONLOAD_ONLY 1
#define SPP_ONLOAD_AND_LIVE 2
#define SPP_START_AND_LIVE 3
#define SPP_LIVE_ONLY 4
#define DEBUG_OUT 0
bool check_phase_debug(jvmtiEnv* jvmti_env, int phase_param, bool is_debug);
bool check_phase_and_method_debug(jvmtiEnv* jvmti_env, jmethodID method, int phase_param,
const char* exp_name, bool is_debug);
bool check_phase_and_thread_debug(jvmtiEnv* jvmti_env, jthread thread, int phase_param,
const char* exp_name, bool is_debug);
jthread create_not_alive_thread(JNIEnv* jni_env, jvmtiEnv* jvmti_env);
bool is_needed_field_found(jvmtiEnv* jvmti_env, const char* filename, const char* fieldname,
jclass* myclass, jfieldID* myfield, bool is_debug);
void func_for_callback_VMDeath(JNIEnv* jni_env, jvmtiEnv* jvmti_env,
const char* test_case_name, bool test, bool util);
jint func_for_Agent_OnLoad(JavaVM *vm, char *options, void *reserved, Callbacks* callbacks,
jvmtiEvent* events, jint size, const char* test_case_name, bool is_debug);
jint func_for_Agent_OnLoad_JVMTI(JavaVM *vm, char *options, void *reserved, Callbacks* callbacks,
jvmtiEvent* events, jint size, const char* test_case_name, bool is_debug, jvmtiEnv** jvmti_env);
//////////////////////////////////////////////////////////////////////////
const char* get_jvmti_eror_text(jvmtiError);
#endif /* _UTILS_H_ */