< prev index next >

src/java.base/unix/native/libjli/java_md_solinux.c

Print this page
rev 59105 : imported patch corelibs


  34 #include <stdlib.h>
  35 #include <sys/stat.h>
  36 #include <unistd.h>
  37 #include <sys/types.h>
  38 #include "manifest_info.h"
  39 
  40 
  41 #define JVM_DLL "libjvm.so"
  42 #define JAVA_DLL "libjava.so"
  43 #ifdef AIX
  44 #define LD_LIBRARY_PATH "LIBPATH"
  45 #else
  46 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
  47 #endif
  48 
  49 /* help jettison the LD_LIBRARY_PATH settings in the future */
  50 #ifndef SETENV_REQUIRED
  51 #define SETENV_REQUIRED
  52 #endif
  53 
  54 #ifdef __solaris__
  55 #  include <sys/systeminfo.h>
  56 #  include <sys/elf.h>
  57 #  include <stdio.h>
  58 #endif
  59 
  60 /*
  61  * Flowchart of launcher execs and options processing on unix
  62  *
  63  * The selection of the proper vm shared library to open depends on
  64  * several classes of command line options, including vm "flavor"
  65  * options (-client, -server).
  66  * The vm selection options are not passed to the running
  67  * virtual machine; they must be screened out by the launcher.
  68  *
  69  * The version specification (if any) is processed first by the
  70  * platform independent routine SelectVersion.  This may result in
  71  * the exec of the specified launcher version.
  72  *
  73  * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the
  74  * desired data model path, regardless if data models matched or not. The
  75  * launcher subsequently exec'ed the desired executable, in order to make the
  76  * LD_LIBRARY_PATH path available, for the runtime linker.
  77  *
  78  * Now, in most cases,the launcher will dlopen the target libjvm.so. All
  79  * required libraries are loaded by the runtime linker, using the


 225     JLI_MemFree(envpath);
 226     return JNI_FALSE;
 227 }
 228 
 229 /*
 230  * Test whether the environment variable needs to be set, see flowchart.
 231  */
 232 static jboolean
 233 RequiresSetenv(const char *jvmpath) {
 234     char jpath[PATH_MAX + 1];
 235     char *llp;
 236     char *dmllp = NULL;
 237     char *p; /* a utility pointer */
 238 
 239 #ifdef AIX
 240     /* We always have to set the LIBPATH on AIX because ld doesn't support $ORIGIN. */
 241     return JNI_TRUE;
 242 #endif
 243 
 244     llp = getenv("LD_LIBRARY_PATH");
 245 #ifdef __solaris__
 246     dmllp = getenv("LD_LIBRARY_PATH_64");
 247 #endif /* __solaris__ */
 248     /* no environment variable is a good environment variable */
 249     if (llp == NULL && dmllp == NULL) {
 250         return JNI_FALSE;
 251     }
 252 #ifdef __linux
 253     /*
 254      * On linux, if a binary is running as sgid or suid, glibc sets
 255      * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast,
 256      * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not
 257      * lose its settings; but the dynamic linker does apply more scrutiny to the
 258      * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec
 259      * loop, here and further downstream. Therefore, if we are running sgid or
 260      * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and
 261      * we should case a return from the calling function.  Getting the right
 262      * libraries will be handled by the RPATH. In reality, this check is
 263      * redundant, as the previous check for a non-null LD_LIBRARY_PATH will
 264      * return back to the calling function forthwith, it is left here to safe
 265      * guard against any changes, in the glibc's existing security policy.
 266      */
 267     if ((getgid() != getegid()) || (getuid() != geteuid())) {


 287     }
 288     if (dmllp != NULL && ContainsLibJVM(dmllp)) {
 289         return JNI_TRUE;
 290     }
 291     return JNI_FALSE;
 292 }
 293 #endif /* SETENV_REQUIRED */
 294 
 295 void
 296 CreateExecutionEnvironment(int *pargc, char ***pargv,
 297                            char jrepath[], jint so_jrepath,
 298                            char jvmpath[], jint so_jvmpath,
 299                            char jvmcfg[],  jint so_jvmcfg) {
 300 
 301     char * jvmtype = NULL;
 302     int argc = *pargc;
 303     char **argv = *pargv;
 304 
 305 #ifdef SETENV_REQUIRED
 306     jboolean mustsetenv = JNI_FALSE;
 307 #ifdef __solaris__
 308     char *llp64 = NULL; /* existing LD_LIBRARY_PATH_64 setting */
 309 #endif // __solaris__
 310     char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */
 311     char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
 312     char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
 313     char* lastslash = NULL;
 314     char** newenvp = NULL; /* current environment */
 315     size_t new_runpath_size;
 316 #endif  /* SETENV_REQUIRED */
 317 
 318     /* Compute/set the name of the executable */
 319     SetExecname(*pargv);
 320 
 321     /* Check to see if the jvmpath exists */
 322     /* Find out where the JRE is that we will be using. */
 323     if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE)) {
 324         JLI_ReportErrorMessage(JRE_ERROR1);
 325         exit(2);
 326     }
 327     JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
 328             jrepath, FILESEP, FILESEP);
 329     /* Find the specified JVM type */


 354     if (mustsetenv == JNI_FALSE) {
 355         return;
 356     }
 357 #else
 358     return;
 359 #endif /* SETENV_REQUIRED */
 360 
 361 #ifdef SETENV_REQUIRED
 362     if (mustsetenv) {
 363         /*
 364          * We will set the LD_LIBRARY_PATH as follows:
 365          *
 366          *     o          $JVMPATH (directory portion only)
 367          *     o          $JRE/lib
 368          *     o          $JRE/../lib
 369          *
 370          * followed by the user's previous effective LD_LIBRARY_PATH, if
 371          * any.
 372          */
 373 
 374 #ifdef __solaris__
 375         llp64 = getenv("LD_LIBRARY_PATH_64");
 376         runpath = (llp64 == NULL) ? getenv(LD_LIBRARY_PATH) : llp64;
 377 #else
 378         runpath = getenv(LD_LIBRARY_PATH);
 379 #endif /* __solaris__ */
 380 
 381         /* runpath contains current effective LD_LIBRARY_PATH setting */
 382         { /* New scope to declare local variable */
 383             char *new_jvmpath = JLI_StringDup(jvmpath);
 384             new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
 385                     2 * JLI_StrLen(jrepath) +
 386                     JLI_StrLen(new_jvmpath) + 52;
 387             new_runpath = JLI_MemAlloc(new_runpath_size);
 388             newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "=");
 389 
 390 
 391             /*
 392              * Create desired LD_LIBRARY_PATH value for target data model.
 393              */
 394             {
 395                 /* remove the name of the .so from the JVM path */
 396                 lastslash = JLI_StrRChr(new_jvmpath, '/');
 397                 if (lastslash)
 398                     *lastslash = '\0';
 399 


 432         if (runpath != 0) {
 433             /* ensure storage for runpath + colon + NULL */
 434             if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) {
 435                 JLI_ReportErrorMessageSys(JRE_ERROR11);
 436                 exit(1);
 437             }
 438             JLI_StrCat(new_runpath, ":");
 439             JLI_StrCat(new_runpath, runpath);
 440         }
 441 
 442         if (putenv(new_runpath) != 0) {
 443             /* problem allocating memory; LD_LIBRARY_PATH not set properly */
 444             exit(1);
 445         }
 446 
 447         /*
 448          * Unix systems document that they look at LD_LIBRARY_PATH only
 449          * once at startup, so we have to re-exec the current executable
 450          * to get the changed environment variable to have an effect.
 451          */
 452 #ifdef __solaris__
 453         /*
 454          * new LD_LIBRARY_PATH took over for LD_LIBRARY_PATH_64
 455          */
 456         if (llp64 != NULL) {
 457             UnsetEnv("LD_LIBRARY_PATH_64");
 458         }
 459 #endif // __solaris__
 460 
 461         newenvp = environ;
 462     }
 463 #endif /* SETENV_REQUIRED */
 464     {
 465         char *newexec = execname;
 466         JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
 467         (void) fflush(stdout);
 468         (void) fflush(stderr);
 469 #ifdef SETENV_REQUIRED
 470         if (mustsetenv) {
 471             execve(newexec, argv, newenvp);
 472         } else {
 473             execv(newexec, argv);
 474         }
 475 #else /* !SETENV_REQUIRED */
 476         execv(newexec, argv);
 477 #endif /* SETENV_REQUIRED */
 478         JLI_ReportErrorMessageSys(JRE_ERROR4, newexec);
 479     }


 539         if (stat(libjava, &s) == 0) {
 540             JLI_TraceLauncher("JRE path is %s\n", path);
 541             return JNI_TRUE;
 542         }
 543     }
 544 
 545     if (!speculative)
 546       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
 547     return JNI_FALSE;
 548 }
 549 
 550 jboolean
 551 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
 552 {
 553     void *libjvm;
 554 
 555     JLI_TraceLauncher("JVM path is %s\n", jvmpath);
 556 
 557     libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
 558     if (libjvm == NULL) {
 559 #if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
 560       FILE * fp;
 561       Elf32_Ehdr elf_head;
 562       int count;
 563       int location;
 564 
 565       fp = fopen(jvmpath, "r");
 566       if (fp == NULL) {
 567         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 568         return JNI_FALSE;
 569       }
 570 
 571       /* read in elf header */
 572       count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
 573       fclose(fp);
 574       if (count < 1) {
 575         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 576         return JNI_FALSE;
 577       }
 578 
 579       /*
 580        * Check for running a server vm (compiled with -xarch=v8plus)
 581        * on a stock v8 processor.  In this case, the machine type in
 582        * the elf header would not be included the architecture list
 583        * provided by the isalist command, which is turn is gotten from
 584        * sysinfo.  This case cannot occur on 64-bit hardware and thus
 585        * does not have to be checked for in binaries with an LP64 data
 586        * model.
 587        */
 588       if (elf_head.e_machine == EM_SPARC32PLUS) {
 589         char buf[257];  /* recommended buffer size from sysinfo man
 590                            page */
 591         long length;
 592         char* location;
 593 
 594         length = sysinfo(SI_ISALIST, buf, 257);
 595         if (length > 0) {
 596             location = JLI_StrStr(buf, "sparcv8plus ");
 597           if (location == NULL) {
 598             JLI_ReportErrorMessage(JVM_ERROR3);
 599             return JNI_FALSE;
 600           }
 601         }
 602       }
 603 #endif
 604         JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
 605         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 606         return JNI_FALSE;
 607     }
 608 
 609     ifn->CreateJavaVM = (CreateJavaVM_t)
 610         dlsym(libjvm, "JNI_CreateJavaVM");
 611     if (ifn->CreateJavaVM == NULL) {
 612         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 613         return JNI_FALSE;
 614     }
 615 
 616     ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
 617         dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
 618     if (ifn->GetDefaultJavaVMInitArgs == NULL) {
 619         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 620         return JNI_FALSE;
 621     }
 622 
 623     ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)


 630     return JNI_TRUE;
 631 }
 632 
 633 /*
 634  * Compute the name of the executable
 635  *
 636  * In order to re-exec securely we need the absolute path of the
 637  * executable. On Solaris getexecname(3c) may not return an absolute
 638  * path so we use dladdr to get the filename of the executable and
 639  * then use realpath to derive an absolute path. From Solaris 9
 640  * onwards the filename returned in DL_info structure from dladdr is
 641  * an absolute pathname so technically realpath isn't required.
 642  * On Linux we read the executable name from /proc/self/exe.
 643  * As a fallback, and for platforms other than Solaris and Linux,
 644  * we use FindExecName to compute the executable name.
 645  */
 646 const char*
 647 SetExecname(char **argv)
 648 {
 649     char* exec_path = NULL;
 650 #if defined(__solaris__)
 651     {
 652         Dl_info dlinfo;
 653         int (*fptr)();
 654 
 655         fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
 656         if (fptr == NULL) {
 657             JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
 658             return JNI_FALSE;
 659         }
 660 
 661         if (dladdr((void*)fptr, &dlinfo)) {
 662             char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
 663             if (resolved != NULL) {
 664                 exec_path = realpath(dlinfo.dli_fname, resolved);
 665                 if (exec_path == NULL) {
 666                     JLI_MemFree(resolved);
 667                 }
 668             }
 669         }
 670     }
 671 #elif defined(__linux__)
 672     {
 673         const char* self = "/proc/self/exe";
 674         char buf[PATH_MAX+1];
 675         int len = readlink(self, buf, PATH_MAX);
 676         if (len >= 0) {
 677             buf[len] = '\0';            /* readlink(2) doesn't NUL terminate */
 678             exec_path = JLI_StringDup(buf);
 679         }
 680     }
 681 #else /* !__solaris__ && !__linux__ */
 682     {
 683         /* Not implemented */
 684     }
 685 #endif
 686 
 687     if (exec_path == NULL) {
 688         exec_path = FindExecName(argv[0]);
 689     }
 690     execname = exec_path;
 691     return exec_path;
 692 }
 693 
 694 /* --- Splash Screen shared library support --- */
 695 static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen");
 696 static void* hSplashLib = NULL;
 697 
 698 void* SplashProcAddress(const char* name) {
 699     if (!hSplashLib) {
 700         int ret;
 701         char jrePath[MAXPATHLEN];


 723         void* sym = dlsym(hSplashLib, name);
 724         return sym;
 725     } else {
 726         return NULL;
 727     }
 728 }
 729 
 730 /*
 731  * Signature adapter for pthread_create() or thr_create().
 732  */
 733 static void* ThreadJavaMain(void* args) {
 734     return (void*)(intptr_t)JavaMain(args);
 735 }
 736 
 737 /*
 738  * Block current thread and continue execution in a new thread.
 739  */
 740 int
 741 CallJavaMainInNewThread(jlong stack_size, void* args) {
 742     int rslt;
 743 #ifndef __solaris__
 744     pthread_t tid;
 745     pthread_attr_t attr;
 746     pthread_attr_init(&attr);
 747     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 748 
 749     if (stack_size > 0) {
 750         pthread_attr_setstacksize(&attr, stack_size);
 751     }
 752     pthread_attr_setguardsize(&attr, 0); // no pthread guard page on java threads
 753 
 754     if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
 755         void* tmp;
 756         pthread_join(tid, &tmp);
 757         rslt = (int)(intptr_t)tmp;
 758     } else {
 759        /*
 760         * Continue execution in current thread if for some reason (e.g. out of
 761         * memory/LWP)  a new thread can't be created. This will likely fail
 762         * later in JavaMain as JNI_CreateJavaVM needs to create quite a
 763         * few new threads, anyway, just give it a try..
 764         */
 765         rslt = JavaMain(args);
 766     }
 767 
 768     pthread_attr_destroy(&attr);
 769 #else /* __solaris__ */
 770     thread_t tid;
 771     long flags = 0;
 772     if (thr_create(NULL, stack_size, ThreadJavaMain, args, flags, &tid) == 0) {
 773         void* tmp;
 774         thr_join(tid, NULL, &tmp);
 775         rslt = (int)(intptr_t)tmp;
 776     } else {
 777         /* See above. Continue in current thread if thr_create() failed */
 778         rslt = JavaMain(args);
 779     }
 780 #endif /* !__solaris__ */
 781     return rslt;
 782 }
 783 
 784 /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
 785 #define MAX_PID_STR_SZ   20
 786 
 787 int
 788 JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
 789         int argc, char **argv,
 790         int mode, char *what, int ret)
 791 {
 792     ShowSplashScreen();
 793     return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
 794 }
 795 
 796 void
 797 PostJVMInit(JNIEnv *env, jclass mainClass, JavaVM *vm)
 798 {
 799     // stubbed out for windows and *nixes.
 800 }
 801 
 802 void
 803 RegisterThread()
 804 {
 805     // stubbed out for windows and *nixes.
 806 }
 807 
 808 /*
 809  * on unix, we return a false to indicate this option is not applicable
 810  */
 811 jboolean
 812 ProcessPlatformOption(const char *arg)
 813 {
 814     return JNI_FALSE;
 815 }
 816 
 817 #ifndef __solaris__
 818 
 819 /*
 820  * Provide a CounterGet() implementation based on gettimeofday() which
 821  * is universally available, even though it may not be 'high resolution'
 822  * compared to platforms that provide gethrtime() (like Solaris). It is
 823  * also subject to time-of-day changes, but alternatives may not be
 824  * known to be available at either build time or run time.
 825  */
 826 uint64_t CounterGet() {
 827     uint64_t result = 0;
 828     struct timeval tv;
 829     if (gettimeofday(&tv, NULL) != -1) {
 830         result = 1000000LL * (uint64_t)tv.tv_sec;
 831         result += (uint64_t)tv.tv_usec;
 832     }
 833     return result;
 834 }
 835 
 836 #endif // !__solaris__


  34 #include <stdlib.h>
  35 #include <sys/stat.h>
  36 #include <unistd.h>
  37 #include <sys/types.h>
  38 #include "manifest_info.h"
  39 
  40 
  41 #define JVM_DLL "libjvm.so"
  42 #define JAVA_DLL "libjava.so"
  43 #ifdef AIX
  44 #define LD_LIBRARY_PATH "LIBPATH"
  45 #else
  46 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
  47 #endif
  48 
  49 /* help jettison the LD_LIBRARY_PATH settings in the future */
  50 #ifndef SETENV_REQUIRED
  51 #define SETENV_REQUIRED
  52 #endif
  53 






  54 /*
  55  * Flowchart of launcher execs and options processing on unix
  56  *
  57  * The selection of the proper vm shared library to open depends on
  58  * several classes of command line options, including vm "flavor"
  59  * options (-client, -server).
  60  * The vm selection options are not passed to the running
  61  * virtual machine; they must be screened out by the launcher.
  62  *
  63  * The version specification (if any) is processed first by the
  64  * platform independent routine SelectVersion.  This may result in
  65  * the exec of the specified launcher version.
  66  *
  67  * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the
  68  * desired data model path, regardless if data models matched or not. The
  69  * launcher subsequently exec'ed the desired executable, in order to make the
  70  * LD_LIBRARY_PATH path available, for the runtime linker.
  71  *
  72  * Now, in most cases,the launcher will dlopen the target libjvm.so. All
  73  * required libraries are loaded by the runtime linker, using the


 219     JLI_MemFree(envpath);
 220     return JNI_FALSE;
 221 }
 222 
 223 /*
 224  * Test whether the environment variable needs to be set, see flowchart.
 225  */
 226 static jboolean
 227 RequiresSetenv(const char *jvmpath) {
 228     char jpath[PATH_MAX + 1];
 229     char *llp;
 230     char *dmllp = NULL;
 231     char *p; /* a utility pointer */
 232 
 233 #ifdef AIX
 234     /* We always have to set the LIBPATH on AIX because ld doesn't support $ORIGIN. */
 235     return JNI_TRUE;
 236 #endif
 237 
 238     llp = getenv("LD_LIBRARY_PATH");



 239     /* no environment variable is a good environment variable */
 240     if (llp == NULL && dmllp == NULL) {
 241         return JNI_FALSE;
 242     }
 243 #ifdef __linux
 244     /*
 245      * On linux, if a binary is running as sgid or suid, glibc sets
 246      * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast,
 247      * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not
 248      * lose its settings; but the dynamic linker does apply more scrutiny to the
 249      * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec
 250      * loop, here and further downstream. Therefore, if we are running sgid or
 251      * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and
 252      * we should case a return from the calling function.  Getting the right
 253      * libraries will be handled by the RPATH. In reality, this check is
 254      * redundant, as the previous check for a non-null LD_LIBRARY_PATH will
 255      * return back to the calling function forthwith, it is left here to safe
 256      * guard against any changes, in the glibc's existing security policy.
 257      */
 258     if ((getgid() != getegid()) || (getuid() != geteuid())) {


 278     }
 279     if (dmllp != NULL && ContainsLibJVM(dmllp)) {
 280         return JNI_TRUE;
 281     }
 282     return JNI_FALSE;
 283 }
 284 #endif /* SETENV_REQUIRED */
 285 
 286 void
 287 CreateExecutionEnvironment(int *pargc, char ***pargv,
 288                            char jrepath[], jint so_jrepath,
 289                            char jvmpath[], jint so_jvmpath,
 290                            char jvmcfg[],  jint so_jvmcfg) {
 291 
 292     char * jvmtype = NULL;
 293     int argc = *pargc;
 294     char **argv = *pargv;
 295 
 296 #ifdef SETENV_REQUIRED
 297     jboolean mustsetenv = JNI_FALSE;



 298     char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */
 299     char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
 300     char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
 301     char* lastslash = NULL;
 302     char** newenvp = NULL; /* current environment */
 303     size_t new_runpath_size;
 304 #endif  /* SETENV_REQUIRED */
 305 
 306     /* Compute/set the name of the executable */
 307     SetExecname(*pargv);
 308 
 309     /* Check to see if the jvmpath exists */
 310     /* Find out where the JRE is that we will be using. */
 311     if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE)) {
 312         JLI_ReportErrorMessage(JRE_ERROR1);
 313         exit(2);
 314     }
 315     JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
 316             jrepath, FILESEP, FILESEP);
 317     /* Find the specified JVM type */


 342     if (mustsetenv == JNI_FALSE) {
 343         return;
 344     }
 345 #else
 346     return;
 347 #endif /* SETENV_REQUIRED */
 348 
 349 #ifdef SETENV_REQUIRED
 350     if (mustsetenv) {
 351         /*
 352          * We will set the LD_LIBRARY_PATH as follows:
 353          *
 354          *     o          $JVMPATH (directory portion only)
 355          *     o          $JRE/lib
 356          *     o          $JRE/../lib
 357          *
 358          * followed by the user's previous effective LD_LIBRARY_PATH, if
 359          * any.
 360          */
 361 




 362         runpath = getenv(LD_LIBRARY_PATH);

 363 
 364         /* runpath contains current effective LD_LIBRARY_PATH setting */
 365         { /* New scope to declare local variable */
 366             char *new_jvmpath = JLI_StringDup(jvmpath);
 367             new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
 368                     2 * JLI_StrLen(jrepath) +
 369                     JLI_StrLen(new_jvmpath) + 52;
 370             new_runpath = JLI_MemAlloc(new_runpath_size);
 371             newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "=");
 372 
 373 
 374             /*
 375              * Create desired LD_LIBRARY_PATH value for target data model.
 376              */
 377             {
 378                 /* remove the name of the .so from the JVM path */
 379                 lastslash = JLI_StrRChr(new_jvmpath, '/');
 380                 if (lastslash)
 381                     *lastslash = '\0';
 382 


 415         if (runpath != 0) {
 416             /* ensure storage for runpath + colon + NULL */
 417             if ((JLI_StrLen(runpath) + 1 + 1) > new_runpath_size) {
 418                 JLI_ReportErrorMessageSys(JRE_ERROR11);
 419                 exit(1);
 420             }
 421             JLI_StrCat(new_runpath, ":");
 422             JLI_StrCat(new_runpath, runpath);
 423         }
 424 
 425         if (putenv(new_runpath) != 0) {
 426             /* problem allocating memory; LD_LIBRARY_PATH not set properly */
 427             exit(1);
 428         }
 429 
 430         /*
 431          * Unix systems document that they look at LD_LIBRARY_PATH only
 432          * once at startup, so we have to re-exec the current executable
 433          * to get the changed environment variable to have an effect.
 434          */








 435 
 436         newenvp = environ;
 437     }
 438 #endif /* SETENV_REQUIRED */
 439     {
 440         char *newexec = execname;
 441         JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
 442         (void) fflush(stdout);
 443         (void) fflush(stderr);
 444 #ifdef SETENV_REQUIRED
 445         if (mustsetenv) {
 446             execve(newexec, argv, newenvp);
 447         } else {
 448             execv(newexec, argv);
 449         }
 450 #else /* !SETENV_REQUIRED */
 451         execv(newexec, argv);
 452 #endif /* SETENV_REQUIRED */
 453         JLI_ReportErrorMessageSys(JRE_ERROR4, newexec);
 454     }


 514         if (stat(libjava, &s) == 0) {
 515             JLI_TraceLauncher("JRE path is %s\n", path);
 516             return JNI_TRUE;
 517         }
 518     }
 519 
 520     if (!speculative)
 521       JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL);
 522     return JNI_FALSE;
 523 }
 524 
 525 jboolean
 526 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
 527 {
 528     void *libjvm;
 529 
 530     JLI_TraceLauncher("JVM path is %s\n", jvmpath);
 531 
 532     libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
 533     if (libjvm == NULL) {













































 534         JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
 535         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 536         return JNI_FALSE;
 537     }
 538 
 539     ifn->CreateJavaVM = (CreateJavaVM_t)
 540         dlsym(libjvm, "JNI_CreateJavaVM");
 541     if (ifn->CreateJavaVM == NULL) {
 542         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 543         return JNI_FALSE;
 544     }
 545 
 546     ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
 547         dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
 548     if (ifn->GetDefaultJavaVMInitArgs == NULL) {
 549         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
 550         return JNI_FALSE;
 551     }
 552 
 553     ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)


 560     return JNI_TRUE;
 561 }
 562 
 563 /*
 564  * Compute the name of the executable
 565  *
 566  * In order to re-exec securely we need the absolute path of the
 567  * executable. On Solaris getexecname(3c) may not return an absolute
 568  * path so we use dladdr to get the filename of the executable and
 569  * then use realpath to derive an absolute path. From Solaris 9
 570  * onwards the filename returned in DL_info structure from dladdr is
 571  * an absolute pathname so technically realpath isn't required.
 572  * On Linux we read the executable name from /proc/self/exe.
 573  * As a fallback, and for platforms other than Solaris and Linux,
 574  * we use FindExecName to compute the executable name.
 575  */
 576 const char*
 577 SetExecname(char **argv)
 578 {
 579     char* exec_path = NULL;
 580 #if defined(__linux__)





















 581     {
 582         const char* self = "/proc/self/exe";
 583         char buf[PATH_MAX+1];
 584         int len = readlink(self, buf, PATH_MAX);
 585         if (len >= 0) {
 586             buf[len] = '\0';            /* readlink(2) doesn't NUL terminate */
 587             exec_path = JLI_StringDup(buf);
 588         }
 589     }
 590 #else /* !__linux__ */
 591     {
 592         /* Not implemented */
 593     }
 594 #endif
 595 
 596     if (exec_path == NULL) {
 597         exec_path = FindExecName(argv[0]);
 598     }
 599     execname = exec_path;
 600     return exec_path;
 601 }
 602 
 603 /* --- Splash Screen shared library support --- */
 604 static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen");
 605 static void* hSplashLib = NULL;
 606 
 607 void* SplashProcAddress(const char* name) {
 608     if (!hSplashLib) {
 609         int ret;
 610         char jrePath[MAXPATHLEN];


 632         void* sym = dlsym(hSplashLib, name);
 633         return sym;
 634     } else {
 635         return NULL;
 636     }
 637 }
 638 
 639 /*
 640  * Signature adapter for pthread_create() or thr_create().
 641  */
 642 static void* ThreadJavaMain(void* args) {
 643     return (void*)(intptr_t)JavaMain(args);
 644 }
 645 
 646 /*
 647  * Block current thread and continue execution in a new thread.
 648  */
 649 int
 650 CallJavaMainInNewThread(jlong stack_size, void* args) {
 651     int rslt;

 652     pthread_t tid;
 653     pthread_attr_t attr;
 654     pthread_attr_init(&attr);
 655     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 656 
 657     if (stack_size > 0) {
 658         pthread_attr_setstacksize(&attr, stack_size);
 659     }
 660     pthread_attr_setguardsize(&attr, 0); // no pthread guard page on java threads
 661 
 662     if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
 663         void* tmp;
 664         pthread_join(tid, &tmp);
 665         rslt = (int)(intptr_t)tmp;
 666     } else {
 667        /*
 668         * Continue execution in current thread if for some reason (e.g. out of
 669         * memory/LWP)  a new thread can't be created. This will likely fail
 670         * later in JavaMain as JNI_CreateJavaVM needs to create quite a
 671         * few new threads, anyway, just give it a try..
 672         */
 673         rslt = JavaMain(args);
 674     }
 675 
 676     pthread_attr_destroy(&attr);












 677     return rslt;
 678 }
 679 
 680 /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
 681 #define MAX_PID_STR_SZ   20
 682 
 683 int
 684 JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
 685         int argc, char **argv,
 686         int mode, char *what, int ret)
 687 {
 688     ShowSplashScreen();
 689     return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
 690 }
 691 
 692 void
 693 PostJVMInit(JNIEnv *env, jclass mainClass, JavaVM *vm)
 694 {
 695     // stubbed out for windows and *nixes.
 696 }
 697 
 698 void
 699 RegisterThread()
 700 {
 701     // stubbed out for windows and *nixes.
 702 }
 703 
 704 /*
 705  * on unix, we return a false to indicate this option is not applicable
 706  */
 707 jboolean
 708 ProcessPlatformOption(const char *arg)
 709 {
 710     return JNI_FALSE;
 711 }
 712 


 713 /*
 714  * Provide a CounterGet() implementation based on gettimeofday() which
 715  * is universally available, even though it may not be 'high resolution'
 716  * compared to platforms that provide gethrtime() (like Solaris). It is
 717  * also subject to time-of-day changes, but alternatives may not be
 718  * known to be available at either build time or run time.
 719  */
 720 uint64_t CounterGet() {
 721     uint64_t result = 0;
 722     struct timeval tv;
 723     if (gettimeofday(&tv, NULL) != -1) {
 724         result = 1000000LL * (uint64_t)tv.tv_sec;
 725         result += (uint64_t)tv.tv_usec;
 726     }
 727     return result;
 728 }


< prev index next >