1 /*
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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 Oracle 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
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 /*
33 * This source code is provided to illustrate the usage of a given feature
34 * or technique and has been deliberately simplified. Additional steps
35 * required for a production-quality application, such as security checks,
36 * input validation and proper error handling, might not be present in
37 * this sample code.
38 */
39
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44
45 #if !defined(LINUX) && !defined(_ALLBSD_SOURCE)
46 #include <procfs.h>
47 #endif
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sys/socket.h>
53 #include <sys/errno.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <dlfcn.h>
57 #include <sys/time.h>
58
59 #include <netdb.h>
60 #include <netinet/in.h>
61 #include <sys/param.h>
62 #include <time.h>
63
64 #include "jni.h"
65 #include "jvm_md.h"
66 #include "hprof.h"
67
68 int
69 md_getpid(void)
70 {
71 static int pid = -1;
72
73 if ( pid >= 0 ) {
74 return pid;
75 }
76 pid = getpid();
77 return pid;
78 }
79
80 void
81 md_sleep(unsigned seconds)
82 {
83 sleep(seconds);
84 }
85
86 void
87 md_init(void)
88 {
89 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
90 /* No Hi-Res timer option? */
91 #else
92 if ( gdata->micro_state_accounting ) {
93 char proc_ctl_fn[48];
94 int procfd;
95
96 /* Turn on micro state accounting, once per process */
97 (void)md_snprintf(proc_ctl_fn, sizeof(proc_ctl_fn),
98 "/proc/%d/ctl", md_getpid());
99
100 procfd = open(proc_ctl_fn, O_WRONLY);
101 if (procfd >= 0) {
102 long ctl_op[2];
103
104 ctl_op[0] = PCSET;
105 ctl_op[1] = PR_MSACCT;
106 (void)write(procfd, ctl_op, sizeof(ctl_op));
107 (void)close(procfd);
108 }
109 }
236 return res;
237 }
238
239 /* Time of day in milli-seconds */
240 static jlong
241 md_timeofday(void)
242 {
243 struct timeval tv;
244
245 if ( gettimeofday(&tv, (void *)0) != 0 ) {
246 return (jlong)0; /* EOVERFLOW ? */
247 }
248 /*LINTED*/
249 return ((jlong)tv.tv_sec * (jlong)1000) + (jlong)(tv.tv_usec / 1000);
250 }
251
252 /* Hi-res timer in micro-seconds */
253 jlong
254 md_get_microsecs(void)
255 {
256 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
257 return (jlong)(md_timeofday() * (jlong)1000); /* Milli to micro */
258 #else
259 return (jlong)(gethrtime()/(hrtime_t)1000); /* Nano seconds to micro seconds */
260 #endif
261 }
262
263 /* Time of day in milli-seconds */
264 jlong
265 md_get_timemillis(void)
266 {
267 return md_timeofday();
268 }
269
270 /* Current CPU hi-res CPU time used */
271 jlong
272 md_get_thread_cpu_timemillis(void)
273 {
274 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
275 return md_timeofday();
276 #else
277 return (jlong)(gethrvtime()/1000); /* Nano seconds to milli seconds */
278 #endif
279 }
280
281 void
282 md_get_prelude_path(char *path, int path_len, char *filename)
283 {
284 void *addr;
285 char libdir[FILENAME_MAX+1];
286 Dl_info dlinfo;
287
288 libdir[0] = 0;
289 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
290 addr = (void*)&Agent_OnLoad;
291 #else
292 /* Just using &Agent_OnLoad will get the first external symbol with
293 * this name in the first .so, which may not be libhprof.so.
294 * On Solaris we can actually ask for the address of our Agent_OnLoad.
295 */
296 addr = dlsym(RTLD_SELF, "Agent_OnLoad");
297 /* Just in case the above didn't work (missing linker patch?). */
298 if ( addr == NULL ) {
299 addr = (void*)&Agent_OnLoad;
300 }
301 #endif
302
303 /* Use dladdr() to get the full path to libhprof.so, which we use to find
304 * the prelude file.
305 */
306 dlinfo.dli_fname = NULL;
307 (void)dladdr(addr, &dlinfo);
308 if ( dlinfo.dli_fname != NULL ) {
309 char * lastSlash;
440 }
441 return result;
442 }
443
444 /* Unload this library */
445 void
446 md_unload_library(void *handle)
447 {
448 (void)dlclose(handle);
449 }
450
451 /* Find an entry point inside this library (return NULL if not found) */
452 void *
453 md_find_library_entry(void *handle, const char *name)
454 {
455 void * sym;
456
457 sym = dlsym(handle, name);
458 return sym;
459 }
|
1 /*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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 Oracle 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
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 /*
33 * This source code is provided to illustrate the usage of a given feature
34 * or technique and has been deliberately simplified. Additional steps
35 * required for a production-quality application, such as security checks,
36 * input validation and proper error handling, might not be present in
37 * this sample code.
38 */
39
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44
45 #if !defined(LINUX) && !defined(_ALLBSD_SOURCE) && !defined(AIX)
46 #include <procfs.h>
47 #endif
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sys/socket.h>
53 #include <sys/errno.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <dlfcn.h>
57 #include <sys/time.h>
58
59 #include <netdb.h>
60 #include <netinet/in.h>
61 #include <sys/param.h>
62 #include <time.h>
63
64 #include "jni.h"
65 #include "jvm_md.h"
66 #include "hprof.h"
67
68 #ifdef AIX
69 /* AIX does not provide the 'dladdr' function so we have to implement it ourselves (see below)
70 * It's derived from the HotSpot implementation under hotspot/src/os/aix/vm/porting_aix.{hpp,cpp}.
71 */
72 #include <sys/ldr.h>
73 #include <errno.h>
74 typedef struct {
75 const char *dli_fname; /* file path of loaded library */
76 void *dli_fbase; /* doesn't make sence on AIX */
77 const char *dli_sname; /* symbol name; "" if not known */
78 void *dli_saddr; /* address of *entry* of function; not function descriptor; */
79 } Dl_info;
80
81 static int dladdr(void *addr, Dl_info *info);
82 #endif
83
84 int
85 md_getpid(void)
86 {
87 static int pid = -1;
88
89 if ( pid >= 0 ) {
90 return pid;
91 }
92 pid = getpid();
93 return pid;
94 }
95
96 void
97 md_sleep(unsigned seconds)
98 {
99 sleep(seconds);
100 }
101
102 void
103 md_init(void)
104 {
105 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
106 /* No Hi-Res timer option? */
107 #else
108 if ( gdata->micro_state_accounting ) {
109 char proc_ctl_fn[48];
110 int procfd;
111
112 /* Turn on micro state accounting, once per process */
113 (void)md_snprintf(proc_ctl_fn, sizeof(proc_ctl_fn),
114 "/proc/%d/ctl", md_getpid());
115
116 procfd = open(proc_ctl_fn, O_WRONLY);
117 if (procfd >= 0) {
118 long ctl_op[2];
119
120 ctl_op[0] = PCSET;
121 ctl_op[1] = PR_MSACCT;
122 (void)write(procfd, ctl_op, sizeof(ctl_op));
123 (void)close(procfd);
124 }
125 }
252 return res;
253 }
254
255 /* Time of day in milli-seconds */
256 static jlong
257 md_timeofday(void)
258 {
259 struct timeval tv;
260
261 if ( gettimeofday(&tv, (void *)0) != 0 ) {
262 return (jlong)0; /* EOVERFLOW ? */
263 }
264 /*LINTED*/
265 return ((jlong)tv.tv_sec * (jlong)1000) + (jlong)(tv.tv_usec / 1000);
266 }
267
268 /* Hi-res timer in micro-seconds */
269 jlong
270 md_get_microsecs(void)
271 {
272 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
273 return (jlong)(md_timeofday() * (jlong)1000); /* Milli to micro */
274 #else
275 return (jlong)(gethrtime()/(hrtime_t)1000); /* Nano seconds to micro seconds */
276 #endif
277 }
278
279 /* Time of day in milli-seconds */
280 jlong
281 md_get_timemillis(void)
282 {
283 return md_timeofday();
284 }
285
286 /* Current CPU hi-res CPU time used */
287 jlong
288 md_get_thread_cpu_timemillis(void)
289 {
290 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
291 return md_timeofday();
292 #else
293 return (jlong)(gethrvtime()/1000); /* Nano seconds to milli seconds */
294 #endif
295 }
296
297 void
298 md_get_prelude_path(char *path, int path_len, char *filename)
299 {
300 void *addr;
301 char libdir[FILENAME_MAX+1];
302 Dl_info dlinfo;
303
304 libdir[0] = 0;
305 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
306 addr = (void*)&Agent_OnLoad;
307 #else
308 /* Just using &Agent_OnLoad will get the first external symbol with
309 * this name in the first .so, which may not be libhprof.so.
310 * On Solaris we can actually ask for the address of our Agent_OnLoad.
311 */
312 addr = dlsym(RTLD_SELF, "Agent_OnLoad");
313 /* Just in case the above didn't work (missing linker patch?). */
314 if ( addr == NULL ) {
315 addr = (void*)&Agent_OnLoad;
316 }
317 #endif
318
319 /* Use dladdr() to get the full path to libhprof.so, which we use to find
320 * the prelude file.
321 */
322 dlinfo.dli_fname = NULL;
323 (void)dladdr(addr, &dlinfo);
324 if ( dlinfo.dli_fname != NULL ) {
325 char * lastSlash;
456 }
457 return result;
458 }
459
460 /* Unload this library */
461 void
462 md_unload_library(void *handle)
463 {
464 (void)dlclose(handle);
465 }
466
467 /* Find an entry point inside this library (return NULL if not found) */
468 void *
469 md_find_library_entry(void *handle, const char *name)
470 {
471 void * sym;
472
473 sym = dlsym(handle, name);
474 return sym;
475 }
476
477 #ifdef AIX
478
479 /* workaround for the missing dladdr on AIX */
480 static unsigned char dladdr_buffer[0x4000];
481
482 static void fill_dll_info(void) {
483 int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer));
484 if (rc == -1) {
485 fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
486 fflush(stderr);
487 }
488 }
489
490 static int dladdr_dont_reload(void* addr, Dl_info* info) {
491 const struct ld_info* p = (struct ld_info*) dladdr_buffer;
492 info->dli_fbase = 0; info->dli_fname = 0;
493 info->dli_sname = 0; info->dli_saddr = 0;
494 for (;;) {
495 if (addr >= p->ldinfo_textorg &&
496 addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
497 info->dli_fname = p->ldinfo_filename;
498 info->dli_fbase = p->ldinfo_textorg;
499 return 1; /* [sic] */
500 }
501 if (!p->ldinfo_next) {
502 break;
503 }
504 p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
505 }
506 return 0; /* [sic] */
507 }
508
509 static int dladdr(void *addr, Dl_info *info) {
510 static int loaded = 0;
511 if (!loaded) {
512 fill_dll_info();
513 loaded = 1;
514 }
515 if (!addr) {
516 return 0; /* [sic] */
517 }
518 /* Address could be AIX function descriptor? */
519 void* const addr0 = *( (void**) addr );
520 int rc = dladdr_dont_reload(addr, info);
521 if (rc == 0) {
522 rc = dladdr_dont_reload(addr0, info);
523 if (rc == 0) { /* [sic] */
524 fill_dll_info(); /* refill, maybe loadquery info is outdated */
525 rc = dladdr_dont_reload(addr, info);
526 if (rc == 0) {
527 rc = dladdr_dont_reload(addr0, info);
528 }
529 }
530 }
531 return rc;
532 }
533
534 #endif /* AIX */
535
536
|