blob: cd09e2cc403aef6ab590c558c872c09876ae38da [file] [log] [blame]
#include <jvmpi.h>
#include <stdio.h>
#include <stdlib.h>
static JVMPI_Interface *jvmpi_interface;
static struct methodref *mrefs;
static int msize = 0;
static struct classref *crefs;
static int csize = 0;
static FILE *outputFile;
static char *include;
static char *exclude;
int memSize;
int i;
int j;
struct methodref
{
jmethodID id;
char *name;
char *signature;
int classid;
};
struct classref
{
char *name;
};
void addClassref(char *classname)
{
memSize = sizeof(struct classref);
if (csize == 0)
crefs = (struct classref *)malloc(memSize);
else
crefs = (struct classref *)realloc(crefs, memSize * (csize + 1));
(crefs + csize)->name = (char *)malloc(strlen(classname) + 1);
strcpy((crefs + csize)->name, classname);
csize++;
}
void addMethodref(jmethodID id, char *name, char *signature, int classid)
{
memSize = sizeof(struct methodref);
if (msize == 0)
mrefs = (struct methodref *)malloc(memSize);
else
mrefs = (struct methodref *)realloc(mrefs, memSize * (msize + 1));
for (j = 0; j < msize; j++)
{
if ((mrefs + j)->id > id)
{
break;
}
}
if (j != msize)
{
memmove((mrefs + j + 1), (mrefs + j), memSize * (msize - j));
}
(mrefs + j)->name = (char *)malloc(strlen(name) + 1);
(mrefs + j)->signature = (char *)malloc(strlen(signature) + 1);
(mrefs + j)->id = id;
strcpy((mrefs + j)->name, name);
strcpy((mrefs + j)->signature, signature);
(mrefs + j)->classid = classid;
msize++;
/*
(mrefs + msize)->name = (char *)malloc(strlen(name) + 1);
(mrefs + msize)->signature = (char *)malloc(strlen(signature) + 1);
(mrefs + msize)->id = id;
strcpy((mrefs + msize)->name, name);
strcpy((mrefs + msize)->signature, signature);
(mrefs + msize)->classid = classid;
msize++;
*/
}
int lower;
int upper;
int middle;
jmethodID lowerid;
jmethodID upperid;
jmethodID middleid;
void addMethodID(jmethodID id)
{
if (msize < 1)
return;
lower = 0;
upper = msize - 1;
lowerid = (mrefs + lower)->id;
upperid = (mrefs + upper)->id;
while (lowerid < id && id < upperid && (upper - lower) > 1)
{
middle = ((upper - lower) / 2) + lower;
middleid = (mrefs + middle)->id;
if (middleid > id)
{
upper = middle;
upperid = middleid;
}
else if (middleid < id)
{
lower = middle;
lowerid = middleid;
}
else
{
upper = middle;
upperid = middleid;
break;
}
}
if (lowerid == id)
middle = lower;
else if (upperid == id)
middle = upper;
else
middle = -1;
if (middle != -1)
{
fputs((crefs + (mrefs + middle)->classid)->name, outputFile);
fputs("#", outputFile);
fputs((mrefs + middle)->name, outputFile);
fputs("#", outputFile);
fputs((mrefs + middle)->signature, outputFile);
fputs(" ", outputFile);
if (middle != (msize - 1))
memmove((mrefs + middle), (mrefs + middle + 1), sizeof(struct methodref) * (msize - (middle + 1)));
msize--;
return;
}
/*
for (i = 0; i < msize; i++)
{
if ((mrefs + i)->id == id)
{
fputs((crefs + (mrefs + i)->classid)->name, outputFile);
fputs("#", outputFile);
fputs((mrefs + i)->name, outputFile);
fputs("#", outputFile);
fputs((mrefs + i)->signature, outputFile);
fputs(" ", outputFile);
memmove((mrefs + i), (mrefs + i + 1), sizeof(struct methodref) * (msize - (i + 1)));
msize--;
return;
}
}
*/
}
void notifyEvent(JVMPI_Event *event)
{
switch(event->event_type)
{
case JVMPI_EVENT_CLASS_LOAD:
if (strstr(event->u.class_load.class_name, include) != NULL && (exclude == NULL || strstr(event->u.class_load.class_name, exclude) == NULL))
{
addClassref((char *)event->u.class_load.class_name);
for (i = 0; i < event->u.class_load.num_methods; i++)
{
addMethodref(event->u.class_load.methods[i].method_id, (char *)event->u.class_load.methods[i].method_name, (char *)event->u.class_load.methods[i].method_signature, csize - 1);
}
}
break;
case JVMPI_EVENT_METHOD_ENTRY:
addMethodID(event->u.method.method_id);
break;
case JVMPI_EVENT_JVM_SHUT_DOWN:
fclose(outputFile);
break;
}
}
JNIEXPORT jint JNICALL
JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
{
if ((*jvm)->GetEnv(jvm, (void **)&jvmpi_interface, JVMPI_VERSION_1) < 0)
return JNI_ERR;
outputFile = fopen(getenv("apiagent_output"), "a");
include = getenv("apiagent_include");
exclude = getenv("apiagent_exclude");
if (outputFile != NULL && include != NULL)
{
jvmpi_interface->NotifyEvent = notifyEvent;
jvmpi_interface->EnableEvent(JVMPI_EVENT_CLASS_LOAD, NULL);
jvmpi_interface->EnableEvent(JVMPI_EVENT_METHOD_ENTRY, NULL);
jvmpi_interface->EnableEvent(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
}
return JNI_OK;
}