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 }
231 return res;
232 }
233
234 /* Time of day in milli-seconds */
235 static jlong
236 md_timeofday(void)
237 {
238 struct timeval tv;
239
240 if ( gettimeofday(&tv, (void *)0) != 0 ) {
241 return (jlong)0; /* EOVERFLOW ? */
242 }
243 /*LINTED*/
244 return ((jlong)tv.tv_sec * (jlong)1000) + (jlong)(tv.tv_usec / 1000);
245 }
246
247 /* Hi-res timer in micro-seconds */
248 jlong
249 md_get_microsecs(void)
250 {
251 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
252 return (jlong)(md_timeofday() * (jlong)1000); /* Milli to micro */
253 #else
254 return (jlong)(gethrtime()/(hrtime_t)1000); /* Nano seconds to micro seconds */
255 #endif
256 }
257
258 /* Time of day in milli-seconds */
259 jlong
260 md_get_timemillis(void)
261 {
262 return md_timeofday();
263 }
264
265 /* Current CPU hi-res CPU time used */
266 jlong
267 md_get_thread_cpu_timemillis(void)
268 {
269 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
270 return md_timeofday();
271 #else
272 return (jlong)(gethrvtime()/1000); /* Nano seconds to milli seconds */
273 #endif
274 }
275
276 void
277 md_get_prelude_path(char *path, int path_len, char *filename)
278 {
279 void *addr;
280 char libdir[FILENAME_MAX+1];
281 Dl_info dlinfo;
282
283 libdir[0] = 0;
284 #if defined(LINUX) || defined(_ALLBSD_SOURCE)
285 addr = (void*)&Agent_OnLoad;
286 #else
287 /* Just using &Agent_OnLoad will get the first external symbol with
288 * this name in the first .so, which may not be libhprof.so.
289 * On Solaris we can actually ask for the address of our Agent_OnLoad.
290 */
291 addr = dlsym(RTLD_SELF, "Agent_OnLoad");
292 /* Just in case the above didn't work (missing linker patch?). */
293 if ( addr == NULL ) {
294 addr = (void*)&Agent_OnLoad;
295 }
296 #endif
297
298 /* Use dladdr() to get the full path to libhprof.so, which we use to find
299 * the prelude file.
300 */
301 dlinfo.dli_fname = NULL;
302 (void)dladdr(addr, &dlinfo);
303 if ( dlinfo.dli_fname != NULL ) {
304 char * lastSlash;
435 }
436 return result;
437 }
438
439 /* Unload this library */
440 void
441 md_unload_library(void *handle)
442 {
443 (void)dlclose(handle);
444 }
445
446 /* Find an entry point inside this library (return NULL if not found) */
447 void *
448 md_find_library_entry(void *handle, const char *name)
449 {
450 void * sym;
451
452 sym = dlsym(handle, name);
453 return sym;
454 }
|
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
69 #ifdef AIX
70 /* SAPJVM */
71 #include <sys/ldr.h>
72 #include <errno.h>
73 typedef struct {
74 const char *dli_fname;
75 void *dli_fbase;
76 const char *dli_sname;
77 void *dli_saddr;
78 } Dl_info;
79
80 static int dladdr(void *addr, Dl_info *info);
81 #endif /* AIX */
82
83 int
84 md_getpid(void)
85 {
86 static int pid = -1;
87
88 if ( pid >= 0 ) {
89 return pid;
90 }
91 pid = getpid();
92 return pid;
93 }
94
95 void
96 md_sleep(unsigned seconds)
97 {
98 sleep(seconds);
99 }
100
101 void
102 md_init(void)
103 {
104 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
105 /* No Hi-Res timer option? */
106 #else
107 if ( gdata->micro_state_accounting ) {
108 char proc_ctl_fn[48];
109 int procfd;
110
111 /* Turn on micro state accounting, once per process */
112 (void)md_snprintf(proc_ctl_fn, sizeof(proc_ctl_fn),
113 "/proc/%d/ctl", md_getpid());
114
115 procfd = open(proc_ctl_fn, O_WRONLY);
116 if (procfd >= 0) {
117 long ctl_op[2];
118
119 ctl_op[0] = PCSET;
120 ctl_op[1] = PR_MSACCT;
121 (void)write(procfd, ctl_op, sizeof(ctl_op));
122 (void)close(procfd);
123 }
124 }
246 return res;
247 }
248
249 /* Time of day in milli-seconds */
250 static jlong
251 md_timeofday(void)
252 {
253 struct timeval tv;
254
255 if ( gettimeofday(&tv, (void *)0) != 0 ) {
256 return (jlong)0; /* EOVERFLOW ? */
257 }
258 /*LINTED*/
259 return ((jlong)tv.tv_sec * (jlong)1000) + (jlong)(tv.tv_usec / 1000);
260 }
261
262 /* Hi-res timer in micro-seconds */
263 jlong
264 md_get_microsecs(void)
265 {
266 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
267 return (jlong)(md_timeofday() * (jlong)1000); /* Milli to micro */
268 #else
269 return (jlong)(gethrtime()/(hrtime_t)1000); /* Nano seconds to micro seconds */
270 #endif
271 }
272
273 /* Time of day in milli-seconds */
274 jlong
275 md_get_timemillis(void)
276 {
277 return md_timeofday();
278 }
279
280 /* Current CPU hi-res CPU time used */
281 jlong
282 md_get_thread_cpu_timemillis(void)
283 {
284 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
285 return md_timeofday();
286 #else
287 return (jlong)(gethrvtime()/1000); /* Nano seconds to milli seconds */
288 #endif
289 }
290
291 void
292 md_get_prelude_path(char *path, int path_len, char *filename)
293 {
294 void *addr;
295 char libdir[FILENAME_MAX+1];
296 Dl_info dlinfo;
297
298 libdir[0] = 0;
299 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(AIX)
300 addr = (void*)&Agent_OnLoad;
301 #else
302 /* Just using &Agent_OnLoad will get the first external symbol with
303 * this name in the first .so, which may not be libhprof.so.
304 * On Solaris we can actually ask for the address of our Agent_OnLoad.
305 */
306 addr = dlsym(RTLD_SELF, "Agent_OnLoad");
307 /* Just in case the above didn't work (missing linker patch?). */
308 if ( addr == NULL ) {
309 addr = (void*)&Agent_OnLoad;
310 }
311 #endif
312
313 /* Use dladdr() to get the full path to libhprof.so, which we use to find
314 * the prelude file.
315 */
316 dlinfo.dli_fname = NULL;
317 (void)dladdr(addr, &dlinfo);
318 if ( dlinfo.dli_fname != NULL ) {
319 char * lastSlash;
450 }
451 return result;
452 }
453
454 /* Unload this library */
455 void
456 md_unload_library(void *handle)
457 {
458 (void)dlclose(handle);
459 }
460
461 /* Find an entry point inside this library (return NULL if not found) */
462 void *
463 md_find_library_entry(void *handle, const char *name)
464 {
465 void * sym;
466
467 sym = dlsym(handle, name);
468 return sym;
469 }
470
471 #ifdef AIX
472
473 /* SAPJVM:
474 * workaround for the missing dladdr */
475 static unsigned char dladdr_buffer[0x4000];
476
477 static void fill_dll_info(void) {
478 int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer));
479 if (rc == -1) {
480 fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno));
481 fflush(stderr);
482 }
483 }
484
485 static int dladdr_dont_reload(void* addr, Dl_info* info) {
486 const struct ld_info* p = (struct ld_info*) dladdr_buffer;
487 info->dli_fbase = 0; info->dli_fname = 0;
488 info->dli_sname = 0; info->dli_saddr = 0;
489 for (;;) {
490 if (addr >= p->ldinfo_textorg &&
491 addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
492 info->dli_fname = p->ldinfo_filename;
493 info->dli_fbase = p->ldinfo_textorg;
494 return 1; /* [sic] */
495 }
496 if (!p->ldinfo_next) {
497 break;
498 }
499 p = (struct ld_info*)(((char*)p) + p->ldinfo_next);
500 }
501 return 0; /* [sic] */
502 }
503
504 static int dladdr(void *addr, Dl_info *info) {
505 static int loaded = 0;
506 if (!loaded) {
507 fill_dll_info();
508 loaded = 1;
509 }
510 if (!addr) {
511 return 0; /* [sic] */
512 }
513 /* Address cuold be AIX function descriptor? */
514 void* const addr0 = *( (void**) addr );
515 int rc = dladdr_dont_reload(addr, info);
516 if (rc == 0) {
517 rc = dladdr_dont_reload(addr0, info);
518 if (rc == 0) { /* [sic] */
519 fill_dll_info(); /* refill, maybe loadquery info is outdated */
520 rc = dladdr_dont_reload(addr, info);
521 if (rc == 0) {
522 rc = dladdr_dont_reload(addr0, info);
523 }
524 }
525 }
526 return rc;
527 }
528
529 #endif /* AIX */
|