blob: 369a09442babf570190b1e1d58ba1223a6b8888d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <agent_util.h>
33
34/* ------------------------------------------------------------------- */
35/* Generic C utility functions */
36
37/* Send message to stdout or whatever the data output location is */
38void
39stdout_message(const char * format, ...)
40{
41 va_list ap;
42
43 va_start(ap, format);
44 (void)vfprintf(stdout, format, ap);
45 va_end(ap);
46}
47
48/* Send message to stderr or whatever the error output location is and exit */
49void
50fatal_error(const char * format, ...)
51{
52 va_list ap;
53
54 va_start(ap, format);
55 (void)vfprintf(stderr, format, ap);
56 (void)fflush(stderr);
57 va_end(ap);
58 exit(3);
59}
60
61/* Get a token from a string (strtok is not MT-safe)
62 * str String to scan
63 * seps Separation characters
64 * buf Place to put results
65 * max Size of buf
66 * Returns NULL if no token available or can't do the scan.
67 */
68char *
69get_token(char *str, char *seps, char *buf, int max)
70{
71 int len;
72
73 buf[0] = 0;
74 if ( str==NULL || str[0]==0 ) {
75 return NULL;
76 }
77 str += strspn(str, seps);
78 if ( str[0]==0 ) {
79 return NULL;
80 }
81 len = (int)strcspn(str, seps);
82 if ( len >= max ) {
83 return NULL;
84 }
85 (void)strncpy(buf, str, len);
86 buf[len] = 0;
87 return str+len;
88}
89
90/* Determines if a class/method is specified by a list item
91 * item String that represents a pattern to match
92 * If it starts with a '*', then any class is allowed
93 * If it ends with a '*', then any method is allowed
94 * cname Class name, e.g. "java.lang.Object"
95 * mname Method name, e.g. "<init>"
96 * Returns 1(true) or 0(false).
97 */
98static int
99covered_by_list_item(char *item, char *cname, char *mname)
100{
101 int len;
102
103 len = (int)strlen(item);
104 if ( item[0]=='*' ) {
105 if ( strncmp(mname, item+1, len-1)==0 ) {
106 return 1;
107 }
108 } else if ( item[len-1]=='*' ) {
109 if ( strncmp(cname, item, len-1)==0 ) {
110 return 1;
111 }
112 } else {
113 int cname_len;
114
115 cname_len = (int)strlen(cname);
116 if ( strncmp(cname, item, (len>cname_len?cname_len:len))==0 ) {
117 if ( cname_len >= len ) {
118 /* No method name supplied in item, we must have matched */
119 return 1;
120 } else {
121 int mname_len;
122
123 mname_len = (int)strlen(mname);
124 item += cname_len+1;
125 len -= cname_len+1;
126 if ( strncmp(mname, item, (len>mname_len?mname_len:len))==0 ) {
127 return 1;
128 }
129 }
130 }
131 }
132 return 0;
133}
134
135/* Determines if a class/method is specified by this list
136 * list String of comma separated pattern items
137 * cname Class name, e.g. "java.lang.Object"
138 * mname Method name, e.g. "<init>"
139 * Returns 1(true) or 0(false).
140 */
141static int
142covered_by_list(char *list, char *cname, char *mname)
143{
144 char token[1024];
145 char *next;
146
147 if ( list[0] == 0 ) {
148 return 0;
149 }
150
151 next = get_token(list, ",", token, sizeof(token));
152 while ( next != NULL ) {
153 if ( covered_by_list_item(token, cname, mname) ) {
154 return 1;
155 }
156 next = get_token(next, ",", token, sizeof(token));
157 }
158 return 0;
159}
160
161/* Determines which class and methods we are interested in
162 * cname Class name, e.g. "java.lang.Object"
163 * mname Method name, e.g. "<init>"
164 * include_list Empty or an explicit list for inclusion
165 * exclude_list Empty or an explicit list for exclusion
166 * Returns 1(true) or 0(false).
167 */
168int
169interested(char *cname, char *mname, char *include_list, char *exclude_list)
170{
171 if ( exclude_list!=NULL && exclude_list[0]!=0 &&
172 covered_by_list(exclude_list, cname, mname) ) {
173 return 0;
174 }
175 if ( include_list!=NULL && include_list[0]!=0 &&
176 !covered_by_list(include_list, cname, mname) ) {
177 return 0;
178 }
179 return 1;
180}
181
182/* ------------------------------------------------------------------- */
183/* Generic JVMTI utility functions */
184
185/* Every JVMTI interface returns an error code, which should be checked
186 * to avoid any cascading errors down the line.
187 * The interface GetErrorName() returns the actual enumeration constant
188 * name, making the error messages much easier to understand.
189 */
190void
191check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str)
192{
193 if ( errnum != JVMTI_ERROR_NONE ) {
194 char *errnum_str;
195
196 errnum_str = NULL;
197 (void)(*jvmti)->GetErrorName(jvmti, errnum, &errnum_str);
198
199 fatal_error("ERROR: JVMTI: %d(%s): %s\n", errnum,
200 (errnum_str==NULL?"Unknown":errnum_str),
201 (str==NULL?"":str));
202 }
203}
204
205/* All memory allocated by JVMTI must be freed by the JVMTI Deallocate
206 * interface.
207 */
208void
209deallocate(jvmtiEnv *jvmti, void *ptr)
210{
211 jvmtiError error;
212
213 error = (*jvmti)->Deallocate(jvmti, ptr);
214 check_jvmti_error(jvmti, error, "Cannot deallocate memory");
215}
216
217/* Allocation of JVMTI managed memory */
218void *
219allocate(jvmtiEnv *jvmti, jint len)
220{
221 jvmtiError error;
222 void *ptr;
223
224 error = (*jvmti)->Allocate(jvmti, len, (unsigned char **)&ptr);
225 check_jvmti_error(jvmti, error, "Cannot allocate memory");
226 return ptr;
227}
228
229/* Add demo jar file to boot class path (the BCI Tracker class must be
230 * in the boot classpath)
231 *
232 * WARNING: This code assumes that the jar file can be found at one of:
233 * ${JAVA_HOME}/demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar
234 * ${JAVA_HOME}/../demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar
235 * where JAVA_HOME may refer to the jre directory.
236 * Both these values are added to the boot classpath.
237 * These locations are only true for these demos, installed
238 * in the JDK area. Platform specific code could be used to
239 * find the location of the DLL or .so library, and construct a
240 * path name to the jar file, relative to the library location.
241 */
242void
243add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name)
244{
245 jvmtiError error;
246 char *file_sep;
247 int max_len;
248 char *java_home;
249 char jar_path[FILENAME_MAX+1];
250
251 java_home = NULL;
252 error = (*jvmti)->GetSystemProperty(jvmti, "java.home", &java_home);
253 check_jvmti_error(jvmti, error, "Cannot get java.home property value");
254 if ( java_home == NULL || java_home[0] == 0 ) {
255 fatal_error("ERROR: Java home not found\n");
256 }
257
258#ifdef WIN32
259 file_sep = "\\";
260#else
261 file_sep = "/";
262#endif
263
264 max_len = (int)(strlen(java_home) + strlen(demo_name)*2 +
265 strlen(file_sep)*5 +
266 16 /* ".." "demo" "jvmti" ".jar" NULL */ );
267 if ( max_len > (int)sizeof(jar_path) ) {
268 fatal_error("ERROR: Path to jar file too long\n");
269 }
270 (void)strcpy(jar_path, java_home);
271 (void)strcat(jar_path, file_sep);
272 (void)strcat(jar_path, "demo");
273 (void)strcat(jar_path, file_sep);
274 (void)strcat(jar_path, "jvmti");
275 (void)strcat(jar_path, file_sep);
276 (void)strcat(jar_path, demo_name);
277 (void)strcat(jar_path, file_sep);
278 (void)strcat(jar_path, demo_name);
279 (void)strcat(jar_path, ".jar");
280 error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);
281 check_jvmti_error(jvmti, error, "Cannot add to boot classpath");
282
283 (void)strcpy(jar_path, java_home);
284 (void)strcat(jar_path, file_sep);
285 (void)strcat(jar_path, "..");
286 (void)strcat(jar_path, file_sep);
287 (void)strcat(jar_path, "demo");
288 (void)strcat(jar_path, file_sep);
289 (void)strcat(jar_path, "jvmti");
290 (void)strcat(jar_path, file_sep);
291 (void)strcat(jar_path, demo_name);
292 (void)strcat(jar_path, file_sep);
293 (void)strcat(jar_path, demo_name);
294 (void)strcat(jar_path, ".jar");
295
296 error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);
297 check_jvmti_error(jvmti, error, "Cannot add to boot classpath");
298}
299
300/* ------------------------------------------------------------------- */