blob: cd09e2cc403aef6ab590c558c872c09876ae38da [file] [log] [blame]
jlanuti6f30d402007-04-18 19:54:42 +00001#include <jvmpi.h>
2#include <stdio.h>
3#include <stdlib.h>
4
5static JVMPI_Interface *jvmpi_interface;
6static struct methodref *mrefs;
7static int msize = 0;
8static struct classref *crefs;
9static int csize = 0;
10static FILE *outputFile;
11static char *include;
12static char *exclude;
13
14int memSize;
15int i;
16int j;
17
18struct methodref
19{
20 jmethodID id;
21 char *name;
22 char *signature;
23 int classid;
24};
25
26struct classref
27{
28 char *name;
29};
30
31void addClassref(char *classname)
32{
33 memSize = sizeof(struct classref);
34 if (csize == 0)
35 crefs = (struct classref *)malloc(memSize);
36 else
37 crefs = (struct classref *)realloc(crefs, memSize * (csize + 1));
38 (crefs + csize)->name = (char *)malloc(strlen(classname) + 1);
39 strcpy((crefs + csize)->name, classname);
40 csize++;
41}
42
43void addMethodref(jmethodID id, char *name, char *signature, int classid)
44{
45 memSize = sizeof(struct methodref);
46 if (msize == 0)
47 mrefs = (struct methodref *)malloc(memSize);
48 else
49 mrefs = (struct methodref *)realloc(mrefs, memSize * (msize + 1));
50
51 for (j = 0; j < msize; j++)
52 {
53 if ((mrefs + j)->id > id)
54 {
55 break;
56 }
57 }
58 if (j != msize)
59 {
60 memmove((mrefs + j + 1), (mrefs + j), memSize * (msize - j));
61 }
62 (mrefs + j)->name = (char *)malloc(strlen(name) + 1);
63 (mrefs + j)->signature = (char *)malloc(strlen(signature) + 1);
64 (mrefs + j)->id = id;
65 strcpy((mrefs + j)->name, name);
66 strcpy((mrefs + j)->signature, signature);
67 (mrefs + j)->classid = classid;
68 msize++;
69 /*
70 (mrefs + msize)->name = (char *)malloc(strlen(name) + 1);
71 (mrefs + msize)->signature = (char *)malloc(strlen(signature) + 1);
72 (mrefs + msize)->id = id;
73 strcpy((mrefs + msize)->name, name);
74 strcpy((mrefs + msize)->signature, signature);
75 (mrefs + msize)->classid = classid;
76 msize++;
77 */
78}
79
80int lower;
81int upper;
82int middle;
83jmethodID lowerid;
84jmethodID upperid;
85jmethodID middleid;
86
87void addMethodID(jmethodID id)
88{
89 if (msize < 1)
90 return;
91 lower = 0;
92 upper = msize - 1;
93 lowerid = (mrefs + lower)->id;
94 upperid = (mrefs + upper)->id;
95 while (lowerid < id && id < upperid && (upper - lower) > 1)
96 {
97 middle = ((upper - lower) / 2) + lower;
98 middleid = (mrefs + middle)->id;
99 if (middleid > id)
100 {
101 upper = middle;
102 upperid = middleid;
103 }
104 else if (middleid < id)
105 {
106 lower = middle;
107 lowerid = middleid;
108 }
109 else
110 {
111 upper = middle;
112 upperid = middleid;
113 break;
114 }
115 }
116 if (lowerid == id)
117 middle = lower;
118 else if (upperid == id)
119 middle = upper;
120 else
121 middle = -1;
122 if (middle != -1)
123 {
124 fputs((crefs + (mrefs + middle)->classid)->name, outputFile);
125 fputs("#", outputFile);
126 fputs((mrefs + middle)->name, outputFile);
127 fputs("#", outputFile);
128 fputs((mrefs + middle)->signature, outputFile);
129 fputs(" ", outputFile);
130 if (middle != (msize - 1))
131 memmove((mrefs + middle), (mrefs + middle + 1), sizeof(struct methodref) * (msize - (middle + 1)));
132 msize--;
133 return;
134 }
135 /*
136 for (i = 0; i < msize; i++)
137 {
138 if ((mrefs + i)->id == id)
139 {
140 fputs((crefs + (mrefs + i)->classid)->name, outputFile);
141 fputs("#", outputFile);
142 fputs((mrefs + i)->name, outputFile);
143 fputs("#", outputFile);
144 fputs((mrefs + i)->signature, outputFile);
145 fputs(" ", outputFile);
146 memmove((mrefs + i), (mrefs + i + 1), sizeof(struct methodref) * (msize - (i + 1)));
147 msize--;
148 return;
149 }
150 }
151 */
152}
153
154void notifyEvent(JVMPI_Event *event)
155{
156 switch(event->event_type)
157 {
158 case JVMPI_EVENT_CLASS_LOAD:
159 if (strstr(event->u.class_load.class_name, include) != NULL && (exclude == NULL || strstr(event->u.class_load.class_name, exclude) == NULL))
160 {
161 addClassref((char *)event->u.class_load.class_name);
162 for (i = 0; i < event->u.class_load.num_methods; i++)
163 {
164 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);
165 }
166 }
167 break;
168 case JVMPI_EVENT_METHOD_ENTRY:
169 addMethodID(event->u.method.method_id);
170 break;
171 case JVMPI_EVENT_JVM_SHUT_DOWN:
172 fclose(outputFile);
173 break;
174 }
175}
176
177JNIEXPORT jint JNICALL
178JVM_OnLoad(JavaVM *jvm, char *options, void *reserved)
179{
180 if ((*jvm)->GetEnv(jvm, (void **)&jvmpi_interface, JVMPI_VERSION_1) < 0)
181 return JNI_ERR;
182 outputFile = fopen(getenv("apiagent_output"), "a");
183 include = getenv("apiagent_include");
184 exclude = getenv("apiagent_exclude");
185 if (outputFile != NULL && include != NULL)
186 {
187 jvmpi_interface->NotifyEvent = notifyEvent;
188 jvmpi_interface->EnableEvent(JVMPI_EVENT_CLASS_LOAD, NULL);
189 jvmpi_interface->EnableEvent(JVMPI_EVENT_METHOD_ENTRY, NULL);
190 jvmpi_interface->EnableEvent(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
191 }
192 return JNI_OK;
193}