author | chegar |
Tue, 22 Mar 2016 10:43:19 +0000 | |
changeset 36709 | f9f252088afa |
parent 25859 | 3317bb8137f4 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
14342
8435a30053c1
7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents:
10292
diff
changeset
|
2 |
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
* |
|
5506 | 15 |
* - Neither the name of Oracle nor the names of its |
2 | 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 |
||
10292
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
32 |
/* |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
33 |
* This source code is provided to illustrate the usage of a given feature |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
34 |
* or technique and has been deliberately simplified. Additional steps |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
35 |
* required for a production-quality application, such as security checks, |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
36 |
* input validation and proper error handling, might not be present in |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
37 |
* this sample code. |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
38 |
*/ |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
39 |
|
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
40 |
|
2 | 41 |
#include <agent_util.h> |
42 |
||
43 |
/* ------------------------------------------------------------------- */ |
|
44 |
/* Generic C utility functions */ |
|
45 |
||
46 |
/* Send message to stdout or whatever the data output location is */ |
|
47 |
void |
|
48 |
stdout_message(const char * format, ...) |
|
49 |
{ |
|
50 |
va_list ap; |
|
51 |
||
52 |
va_start(ap, format); |
|
53 |
(void)vfprintf(stdout, format, ap); |
|
54 |
va_end(ap); |
|
55 |
} |
|
56 |
||
57 |
/* Send message to stderr or whatever the error output location is and exit */ |
|
58 |
void |
|
59 |
fatal_error(const char * format, ...) |
|
60 |
{ |
|
61 |
va_list ap; |
|
62 |
||
63 |
va_start(ap, format); |
|
64 |
(void)vfprintf(stderr, format, ap); |
|
65 |
(void)fflush(stderr); |
|
66 |
va_end(ap); |
|
67 |
exit(3); |
|
68 |
} |
|
69 |
||
70 |
/* Get a token from a string (strtok is not MT-safe) |
|
71 |
* str String to scan |
|
72 |
* seps Separation characters |
|
73 |
* buf Place to put results |
|
74 |
* max Size of buf |
|
75 |
* Returns NULL if no token available or can't do the scan. |
|
76 |
*/ |
|
77 |
char * |
|
78 |
get_token(char *str, char *seps, char *buf, int max) |
|
79 |
{ |
|
80 |
int len; |
|
81 |
||
82 |
buf[0] = 0; |
|
83 |
if ( str==NULL || str[0]==0 ) { |
|
84 |
return NULL; |
|
85 |
} |
|
86 |
str += strspn(str, seps); |
|
87 |
if ( str[0]==0 ) { |
|
88 |
return NULL; |
|
89 |
} |
|
90 |
len = (int)strcspn(str, seps); |
|
91 |
if ( len >= max ) { |
|
92 |
return NULL; |
|
93 |
} |
|
94 |
(void)strncpy(buf, str, len); |
|
95 |
buf[len] = 0; |
|
96 |
return str+len; |
|
97 |
} |
|
98 |
||
99 |
/* Determines if a class/method is specified by a list item |
|
100 |
* item String that represents a pattern to match |
|
101 |
* If it starts with a '*', then any class is allowed |
|
102 |
* If it ends with a '*', then any method is allowed |
|
103 |
* cname Class name, e.g. "java.lang.Object" |
|
104 |
* mname Method name, e.g. "<init>" |
|
105 |
* Returns 1(true) or 0(false). |
|
106 |
*/ |
|
107 |
static int |
|
108 |
covered_by_list_item(char *item, char *cname, char *mname) |
|
109 |
{ |
|
110 |
int len; |
|
111 |
||
112 |
len = (int)strlen(item); |
|
113 |
if ( item[0]=='*' ) { |
|
114 |
if ( strncmp(mname, item+1, len-1)==0 ) { |
|
115 |
return 1; |
|
116 |
} |
|
117 |
} else if ( item[len-1]=='*' ) { |
|
118 |
if ( strncmp(cname, item, len-1)==0 ) { |
|
119 |
return 1; |
|
120 |
} |
|
121 |
} else { |
|
122 |
int cname_len; |
|
123 |
||
124 |
cname_len = (int)strlen(cname); |
|
125 |
if ( strncmp(cname, item, (len>cname_len?cname_len:len))==0 ) { |
|
126 |
if ( cname_len >= len ) { |
|
127 |
/* No method name supplied in item, we must have matched */ |
|
128 |
return 1; |
|
129 |
} else { |
|
130 |
int mname_len; |
|
131 |
||
132 |
mname_len = (int)strlen(mname); |
|
133 |
item += cname_len+1; |
|
134 |
len -= cname_len+1; |
|
135 |
if ( strncmp(mname, item, (len>mname_len?mname_len:len))==0 ) { |
|
136 |
return 1; |
|
137 |
} |
|
138 |
} |
|
139 |
} |
|
140 |
} |
|
141 |
return 0; |
|
142 |
} |
|
143 |
||
144 |
/* Determines if a class/method is specified by this list |
|
145 |
* list String of comma separated pattern items |
|
146 |
* cname Class name, e.g. "java.lang.Object" |
|
147 |
* mname Method name, e.g. "<init>" |
|
148 |
* Returns 1(true) or 0(false). |
|
149 |
*/ |
|
150 |
static int |
|
151 |
covered_by_list(char *list, char *cname, char *mname) |
|
152 |
{ |
|
153 |
char token[1024]; |
|
154 |
char *next; |
|
155 |
||
156 |
if ( list[0] == 0 ) { |
|
157 |
return 0; |
|
158 |
} |
|
159 |
||
160 |
next = get_token(list, ",", token, sizeof(token)); |
|
161 |
while ( next != NULL ) { |
|
162 |
if ( covered_by_list_item(token, cname, mname) ) { |
|
163 |
return 1; |
|
164 |
} |
|
165 |
next = get_token(next, ",", token, sizeof(token)); |
|
166 |
} |
|
167 |
return 0; |
|
168 |
} |
|
169 |
||
170 |
/* Determines which class and methods we are interested in |
|
171 |
* cname Class name, e.g. "java.lang.Object" |
|
172 |
* mname Method name, e.g. "<init>" |
|
173 |
* include_list Empty or an explicit list for inclusion |
|
174 |
* exclude_list Empty or an explicit list for exclusion |
|
175 |
* Returns 1(true) or 0(false). |
|
176 |
*/ |
|
177 |
int |
|
178 |
interested(char *cname, char *mname, char *include_list, char *exclude_list) |
|
179 |
{ |
|
180 |
if ( exclude_list!=NULL && exclude_list[0]!=0 && |
|
181 |
covered_by_list(exclude_list, cname, mname) ) { |
|
182 |
return 0; |
|
183 |
} |
|
184 |
if ( include_list!=NULL && include_list[0]!=0 && |
|
185 |
!covered_by_list(include_list, cname, mname) ) { |
|
186 |
return 0; |
|
187 |
} |
|
188 |
return 1; |
|
189 |
} |
|
190 |
||
191 |
/* ------------------------------------------------------------------- */ |
|
192 |
/* Generic JVMTI utility functions */ |
|
193 |
||
194 |
/* Every JVMTI interface returns an error code, which should be checked |
|
195 |
* to avoid any cascading errors down the line. |
|
196 |
* The interface GetErrorName() returns the actual enumeration constant |
|
197 |
* name, making the error messages much easier to understand. |
|
198 |
*/ |
|
199 |
void |
|
200 |
check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str) |
|
201 |
{ |
|
202 |
if ( errnum != JVMTI_ERROR_NONE ) { |
|
203 |
char *errnum_str; |
|
204 |
||
205 |
errnum_str = NULL; |
|
206 |
(void)(*jvmti)->GetErrorName(jvmti, errnum, &errnum_str); |
|
207 |
||
208 |
fatal_error("ERROR: JVMTI: %d(%s): %s\n", errnum, |
|
209 |
(errnum_str==NULL?"Unknown":errnum_str), |
|
210 |
(str==NULL?"":str)); |
|
211 |
} |
|
212 |
} |
|
213 |
||
214 |
/* All memory allocated by JVMTI must be freed by the JVMTI Deallocate |
|
215 |
* interface. |
|
216 |
*/ |
|
217 |
void |
|
218 |
deallocate(jvmtiEnv *jvmti, void *ptr) |
|
219 |
{ |
|
220 |
jvmtiError error; |
|
221 |
||
222 |
error = (*jvmti)->Deallocate(jvmti, ptr); |
|
223 |
check_jvmti_error(jvmti, error, "Cannot deallocate memory"); |
|
224 |
} |
|
225 |
||
226 |
/* Allocation of JVMTI managed memory */ |
|
227 |
void * |
|
228 |
allocate(jvmtiEnv *jvmti, jint len) |
|
229 |
{ |
|
230 |
jvmtiError error; |
|
231 |
void *ptr; |
|
232 |
||
233 |
error = (*jvmti)->Allocate(jvmti, len, (unsigned char **)&ptr); |
|
234 |
check_jvmti_error(jvmti, error, "Cannot allocate memory"); |
|
235 |
return ptr; |
|
236 |
} |
|
237 |
||
238 |
/* Add demo jar file to boot class path (the BCI Tracker class must be |
|
239 |
* in the boot classpath) |
|
240 |
* |
|
241 |
* WARNING: This code assumes that the jar file can be found at one of: |
|
242 |
* ${JAVA_HOME}/demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar |
|
243 |
* ${JAVA_HOME}/../demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar |
|
244 |
* where JAVA_HOME may refer to the jre directory. |
|
245 |
* Both these values are added to the boot classpath. |
|
246 |
* These locations are only true for these demos, installed |
|
247 |
* in the JDK area. Platform specific code could be used to |
|
248 |
* find the location of the DLL or .so library, and construct a |
|
249 |
* path name to the jar file, relative to the library location. |
|
250 |
*/ |
|
251 |
void |
|
252 |
add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name) |
|
253 |
{ |
|
254 |
jvmtiError error; |
|
255 |
char *file_sep; |
|
256 |
int max_len; |
|
257 |
char *java_home; |
|
258 |
char jar_path[FILENAME_MAX+1]; |
|
259 |
||
260 |
java_home = NULL; |
|
261 |
error = (*jvmti)->GetSystemProperty(jvmti, "java.home", &java_home); |
|
262 |
check_jvmti_error(jvmti, error, "Cannot get java.home property value"); |
|
263 |
if ( java_home == NULL || java_home[0] == 0 ) { |
|
264 |
fatal_error("ERROR: Java home not found\n"); |
|
265 |
} |
|
266 |
||
267 |
#ifdef WIN32 |
|
268 |
file_sep = "\\"; |
|
269 |
#else |
|
270 |
file_sep = "/"; |
|
271 |
#endif |
|
272 |
||
273 |
max_len = (int)(strlen(java_home) + strlen(demo_name)*2 + |
|
274 |
strlen(file_sep)*5 + |
|
275 |
16 /* ".." "demo" "jvmti" ".jar" NULL */ ); |
|
276 |
if ( max_len > (int)sizeof(jar_path) ) { |
|
277 |
fatal_error("ERROR: Path to jar file too long\n"); |
|
278 |
} |
|
279 |
(void)strcpy(jar_path, java_home); |
|
280 |
(void)strcat(jar_path, file_sep); |
|
281 |
(void)strcat(jar_path, "demo"); |
|
282 |
(void)strcat(jar_path, file_sep); |
|
283 |
(void)strcat(jar_path, "jvmti"); |
|
284 |
(void)strcat(jar_path, file_sep); |
|
285 |
(void)strcat(jar_path, demo_name); |
|
286 |
(void)strcat(jar_path, file_sep); |
|
287 |
(void)strcat(jar_path, demo_name); |
|
288 |
(void)strcat(jar_path, ".jar"); |
|
289 |
error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path); |
|
290 |
check_jvmti_error(jvmti, error, "Cannot add to boot classpath"); |
|
291 |
||
292 |
(void)strcpy(jar_path, java_home); |
|
293 |
(void)strcat(jar_path, file_sep); |
|
294 |
(void)strcat(jar_path, ".."); |
|
295 |
(void)strcat(jar_path, file_sep); |
|
296 |
(void)strcat(jar_path, "demo"); |
|
297 |
(void)strcat(jar_path, file_sep); |
|
298 |
(void)strcat(jar_path, "jvmti"); |
|
299 |
(void)strcat(jar_path, file_sep); |
|
300 |
(void)strcat(jar_path, demo_name); |
|
301 |
(void)strcat(jar_path, file_sep); |
|
302 |
(void)strcat(jar_path, demo_name); |
|
303 |
(void)strcat(jar_path, ".jar"); |
|
304 |
||
305 |
error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path); |
|
306 |
check_jvmti_error(jvmti, error, "Cannot add to boot classpath"); |
|
307 |
} |
|
308 |
||
309 |
/* ------------------------------------------------------------------- */ |