src/solaris/demo/jvmti/hprof/hprof_md.c

Print this page
rev 7983 : 8024854: Basic changes and files to build the class library on AIX
Contributed-by: luchsh@linux.vnet.ibm.com, spoole@linux.vnet.ibm.com, thomas.stuefe@sap.com
Reviewed-by:
   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