1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "java.h" 27 #include "jvm_md.h" 28 #include <dirent.h> 29 #include <dlfcn.h> 30 #include <fcntl.h> 31 #include <inttypes.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <stdlib.h> 35 #include <sys/stat.h> 36 #include <unistd.h> 37 #include <sys/types.h> 38 #include "manifest_info.h" 39 #include "version_comp.h" 40 41 42 #define JVM_DLL "libjvm.so" 43 #define JAVA_DLL "libjava.so" 44 #define LD_LIBRARY_PATH "LD_LIBRARY_PATH" 45 46 /* help jettison the LD_LIBRARY_PATH settings in the future */ 47 #ifndef SETENV_REQUIRED 48 #define SETENV_REQUIRED 49 #endif 50 51 #ifdef __solaris__ 52 # ifndef LIBARCHNAME 53 # error "The macro LIBARCHNAME was not defined on the compile line" 54 # endif 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) and the data model options, -d32 and 66 * -d64, as well as a version specification which may have come from 67 * the command line or from the manifest of an executable jar file. 68 * The vm selection options are not passed to the running 69 * virtual machine; they must be screened out by the launcher. 70 * 71 * The version specification (if any) is processed first by the 72 * platform independent routine SelectVersion. This may result in 73 * the exec of the specified launcher version. 74 * 75 * Previously the launcher modified the LD_LIBRARY_PATH appropriately for the 76 * desired data model path, regardless if data models matched or not. The 77 * launcher subsequently exec'ed the desired executable, in order to make the 78 * LD_LIBRARY_PATH path available, for the runtime linker. 79 * 80 * Now, in most cases,the launcher will dlopen the target libjvm.so. All 81 * required libraries are loaded by the runtime linker, using the 82 * $RPATH/$ORIGIN baked into the shared libraries at compile time. Therefore, 83 * in most cases, the launcher will only exec, if the data models are 84 * mismatched, and will not set any environment variables, regardless of the 85 * data models. 86 * 87 * However, if the environment contains a LD_LIBRARY_PATH, this will cause the 88 * launcher to inspect the LD_LIBRARY_PATH. The launcher will check 89 * a. if the LD_LIBRARY_PATH's first component is the the path to the desired 90 * libjvm.so 91 * b. if any other libjvm.so is found in any of the paths. 92 * If case b is true, then the launcher will set the LD_LIBRARY_PATH to the 93 * desired JRE and reexec, in order to propagate the environment. 94 * 95 * Main 96 * (incoming argv) 97 * | 98 * \|/ 99 * SelectVersion 100 * (selects the JRE version, note: not data model) 101 * | 102 * \|/ 103 * CreateExecutionEnvironment 104 * (determines desired data model) 105 * | 106 * | 107 * \|/ 108 * Have Desired Model ? --> NO --> Exit(with error) 109 * | 110 * | 111 * \|/ 112 * YES 113 * | 114 * | 115 * \|/ 116 * CheckJvmType 117 * (removes -client, -server, etc.) 118 * | 119 * | 120 * \|/ 121 * TranslateDashJArgs... 122 * (Prepare to pass args to vm) 123 * | 124 * | 125 * \|/ 126 * ParseArguments 127 * (removes -d32 and -d64 if any, 128 * processes version options, 129 * creates argument list for vm, 130 * etc.) 131 * | 132 * | 133 * \|/ 134 * RequiresSetenv 135 * Is LD_LIBRARY_PATH 136 * and friends set ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main 137 * YES YES --> Continue 138 * | 139 * | 140 * \|/ 141 * Path is desired JRE ? YES --> Have Desired Model ? NO --> Re-exec --> Main 142 * NO YES --> Continue 143 * | 144 * | 145 * \|/ 146 * Paths have well known 147 * jvm paths ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main 148 * YES YES --> Continue 149 * | 150 * | 151 * \|/ 152 * Does libjvm.so exit 153 * in any of them ? --> NO --> Have Desired Model ? NO --> Re-exec --> Main 154 * YES YES --> Continue 155 * | 156 * | 157 * \|/ 158 * Set the LD_LIBRARY_PATH 159 * | 160 * | 161 * \|/ 162 * Re-exec 163 * | 164 * | 165 * \|/ 166 * Main 167 */ 168 169 /* Store the name of the executable once computed */ 170 static char *execname = NULL; 171 172 /* 173 * execname accessor from other parts of platform dependent logic 174 */ 175 const char * 176 GetExecName() { 177 return execname; 178 } 179 180 #ifdef SETENV_REQUIRED 181 static jboolean 182 JvmExists(const char *path) { 183 char tmp[PATH_MAX + 1]; 184 struct stat statbuf; 185 JLI_Snprintf(tmp, PATH_MAX, "%s/%s", path, JVM_DLL); 186 if (stat(tmp, &statbuf) == 0) { 187 return JNI_TRUE; 188 } 189 return JNI_FALSE; 190 } 191 /* 192 * contains a lib/$LIBARCHNAME/{server,client}/libjvm.so ? 193 */ 194 static jboolean 195 ContainsLibJVM(const char *env) { 196 char clientPattern[PATH_MAX + 1]; 197 char serverPattern[PATH_MAX + 1]; 198 char *envpath; 199 char *path; 200 jboolean clientPatternFound; 201 jboolean serverPatternFound; 202 203 /* fastest path */ 204 if (env == NULL) { 205 return JNI_FALSE; 206 } 207 208 /* the usual suspects */ 209 JLI_Snprintf(clientPattern, PATH_MAX, "lib/%s/client", LIBARCHNAME); 210 JLI_Snprintf(serverPattern, PATH_MAX, "lib/%s/server", LIBARCHNAME); 211 212 /* to optimize for time, test if any of our usual suspects are present. */ 213 clientPatternFound = JLI_StrStr(env, clientPattern) != NULL; 214 serverPatternFound = JLI_StrStr(env, serverPattern) != NULL; 215 if (clientPatternFound == JNI_FALSE && serverPatternFound == JNI_FALSE) { 216 return JNI_FALSE; 217 } 218 219 /* 220 * we have a suspicious path component, check if it contains a libjvm.so 221 */ 222 envpath = JLI_StringDup(env); 223 for (path = JLI_StrTok(envpath, ":"); path != NULL; path = JLI_StrTok(NULL, ":")) { 224 if (clientPatternFound && JLI_StrStr(path, clientPattern) != NULL) { 225 if (JvmExists(path)) { 226 JLI_MemFree(envpath); 227 return JNI_TRUE; 228 } 229 } 230 if (serverPatternFound && JLI_StrStr(path, serverPattern) != NULL) { 231 if (JvmExists(path)) { 232 JLI_MemFree(envpath); 233 return JNI_TRUE; 234 } 235 } 236 } 237 JLI_MemFree(envpath); 238 return JNI_FALSE; 239 } 240 241 /* 242 * Test whether the environment variable needs to be set, see flowchart. 243 */ 244 static jboolean 245 RequiresSetenv(const char *jvmpath) { 246 char jpath[PATH_MAX + 1]; 247 char *llp; 248 char *dmllp = NULL; 249 char *p; /* a utility pointer */ 250 251 llp = getenv("LD_LIBRARY_PATH"); 252 #ifdef __solaris__ 253 dmllp = getenv("LD_LIBRARY_PATH_64"); 254 #endif /* __solaris__ */ 255 /* no environment variable is a good environment variable */ 256 if (llp == NULL && dmllp == NULL) { 257 return JNI_FALSE; 258 } 259 #ifdef __linux 260 /* 261 * On linux, if a binary is running as sgid or suid, glibc sets 262 * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast, 263 * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not 264 * lose its settings; but the dynamic linker does apply more scrutiny to the 265 * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec 266 * loop, here and further downstream. Therefore, if we are running sgid or 267 * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and 268 * we should case a return from the calling function. Getting the right 269 * libraries will be handled by the RPATH. In reality, this check is 270 * redundant, as the previous check for a non-null LD_LIBRARY_PATH will 271 * return back to the calling function forthwith, it is left here to safe 272 * guard against any changes, in the glibc's existing security policy. 273 */ 274 if ((getgid() != getegid()) || (getuid() != geteuid())) { 275 return JNI_FALSE; 276 } 277 #endif /* __linux */ 278 279 /* 280 * Prevent recursions. Since LD_LIBRARY_PATH is the one which will be set by 281 * previous versions of the JRE, thus it is the only path that matters here. 282 * So we check to see if the desired JRE is set. 283 */ 284 JLI_StrNCpy(jpath, jvmpath, PATH_MAX); 285 p = JLI_StrRChr(jpath, '/'); 286 *p = '\0'; 287 if (llp != NULL && JLI_StrNCmp(llp, jpath, JLI_StrLen(jpath)) == 0) { 288 return JNI_FALSE; 289 } 290 291 /* scrutinize all the paths further */ 292 if (llp != NULL && ContainsLibJVM(llp)) { 293 return JNI_TRUE; 294 } 295 if (dmllp != NULL && ContainsLibJVM(dmllp)) { 296 return JNI_TRUE; 297 } 298 return JNI_FALSE; 299 } 300 #endif /* SETENV_REQUIRED */ 301 302 void 303 CreateExecutionEnvironment(int *pargc, char ***pargv, 304 char jrepath[], jint so_jrepath, 305 char jvmpath[], jint so_jvmpath, 306 char jvmcfg[], jint so_jvmcfg) { 307 /* 308 * First, determine if we are running the desired data model. If we 309 * are running the desired data model, all the error messages 310 * associated with calling GetJREPath, ReadKnownVMs, etc. should be 311 * output. However, if we are not running the desired data model, 312 * some of the errors should be suppressed since it is more 313 * informative to issue an error message based on whether or not the 314 * os/processor combination has dual mode capabilities. 315 */ 316 jboolean jvmpathExists; 317 318 /* Compute/set the name of the executable */ 319 SetExecname(*pargv); 320 321 /* Check data model flags, and exec process, if needed */ 322 { 323 char *arch = LIBARCHNAME; /* like sparc or sparcv9 */ 324 char * jvmtype = NULL; 325 int argc = *pargc; 326 char **argv = *pargv; 327 int running = CURRENT_DATA_MODEL; 328 /* 329 * As of jdk9, there is no support for dual mode operations, however 330 * for legacy error reporting purposes and until -d options are supported 331 * we need this. 332 */ 333 int wanted = running; 334 #ifdef SETENV_REQUIRED 335 jboolean mustsetenv = JNI_FALSE; 336 char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */ 337 char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ 338 char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ 339 char* lastslash = NULL; 340 char** newenvp = NULL; /* current environment */ 341 #ifdef __solaris__ 342 char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, 343 Solaris only */ 344 #endif /* __solaris__ */ 345 #endif /* SETENV_REQUIRED */ 346 347 char** newargv = NULL; 348 int newargc = 0; 349 350 /* 351 * Starting in 1.5, all unix platforms accept the -d32 and -d64 352 * options. On platforms where only one data-model is supported 353 * (e.g. ia-64 Linux), using the flag for the other data model is 354 * an error and will terminate the program. 355 */ 356 357 { /* open new scope to declare local variables */ 358 int i; 359 360 newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*)); 361 newargv[newargc++] = argv[0]; 362 363 /* scan for data model arguments and remove from argument list; 364 last occurrence determines desired data model */ 365 for (i=1; i < argc; i++) { 366 367 if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) { 368 wanted = 64; 369 continue; 370 } 371 if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) { 372 wanted = 32; 373 continue; 374 } 375 newargv[newargc++] = argv[i]; 376 377 if (IsJavaArgs()) { 378 if (argv[i][0] != '-') continue; 379 } else { 380 if (JLI_StrCmp(argv[i], "-classpath") == 0 || JLI_StrCmp(argv[i], "-cp") == 0) { 381 i++; 382 if (i >= argc) break; 383 newargv[newargc++] = argv[i]; 384 continue; 385 } 386 if (argv[i][0] != '-') { i++; break; } 387 } 388 } 389 390 /* copy rest of args [i .. argc) */ 391 while (i < argc) { 392 newargv[newargc++] = argv[i++]; 393 } 394 newargv[newargc] = NULL; 395 396 /* 397 * newargv has all proper arguments here 398 */ 399 400 argc = newargc; 401 argv = newargv; 402 } 403 404 /* If the data model is not changing, it is an error if the 405 jvmpath does not exist */ 406 if (wanted == running) { 407 /* Find out where the JRE is that we will be using. */ 408 if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { 409 JLI_ReportErrorMessage(JRE_ERROR1); 410 exit(2); 411 } 412 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg", 413 jrepath, FILESEP, FILESEP, arch, FILESEP); 414 /* Find the specified JVM type */ 415 if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) { 416 JLI_ReportErrorMessage(CFG_ERROR7); 417 exit(1); 418 } 419 420 jvmpath[0] = '\0'; 421 jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); 422 if (JLI_StrCmp(jvmtype, "ERROR") == 0) { 423 JLI_ReportErrorMessage(CFG_ERROR9); 424 exit(4); 425 } 426 427 if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, 0 )) { 428 JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath); 429 exit(4); 430 } 431 /* 432 * we seem to have everything we need, so without further ado 433 * we return back, otherwise proceed to set the environment. 434 */ 435 #ifdef SETENV_REQUIRED 436 mustsetenv = RequiresSetenv(jvmpath); 437 JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE"); 438 439 if (mustsetenv == JNI_FALSE) { 440 JLI_MemFree(newargv); 441 return; 442 } 443 #else 444 JLI_MemFree(newargv); 445 return; 446 #endif /* SETENV_REQUIRED */ 447 } else { /* do the same speculatively or exit */ 448 JLI_ReportErrorMessage(JRE_ERROR2, wanted); 449 exit(1); 450 } 451 #ifdef SETENV_REQUIRED 452 if (mustsetenv) { 453 /* 454 * We will set the LD_LIBRARY_PATH as follows: 455 * 456 * o $JVMPATH (directory portion only) 457 * o $JRE/lib/$LIBARCHNAME 458 * o $JRE/../lib/$LIBARCHNAME 459 * 460 * followed by the user's previous effective LD_LIBRARY_PATH, if 461 * any. 462 */ 463 464 #ifdef __solaris__ 465 /* 466 * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH 467 * variables: 468 * 469 * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if 470 * data-model specific variables are not set. 471 * 472 * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH 473 * for 64-bit binaries. 474 * The vm uses LD_LIBRARY_PATH to set the java.library.path system 475 * property. To shield the vm from the complication of multiple 476 * LD_LIBRARY_PATH variables, if the appropriate data model 477 * specific variable is set, we will act as if LD_LIBRARY_PATH had 478 * the value of the data model specific variant and the data model 479 * specific variant will be unset. Note that the variable for the 480 * *wanted* data model must be used (if it is set), not simply the 481 * current running data model. 482 */ 483 484 switch (wanted) { 485 case 0: 486 case 64: 487 dmpath = getenv("LD_LIBRARY_PATH_64"); 488 wanted = 64; 489 break; 490 491 default: 492 JLI_ReportErrorMessage(JRE_ERROR3, __LINE__); 493 exit(1); /* unknown value in wanted */ 494 break; 495 } 496 497 /* 498 * If dmpath is NULL, the relevant data model specific variable is 499 * not set and normal LD_LIBRARY_PATH should be used. 500 */ 501 if (dmpath == NULL) { 502 runpath = getenv("LD_LIBRARY_PATH"); 503 } else { 504 runpath = dmpath; 505 } 506 #else /* ! __solaris__ */ 507 /* 508 * If not on Solaris, assume only a single LD_LIBRARY_PATH 509 * variable. 510 */ 511 runpath = getenv("LD_LIBRARY_PATH"); 512 #endif /* __solaris__ */ 513 514 /* runpath contains current effective LD_LIBRARY_PATH setting */ 515 516 jvmpath = JLI_StringDup(jvmpath); 517 new_runpath = JLI_MemAlloc(((runpath != NULL) ? JLI_StrLen(runpath) : 0) + 518 2 * JLI_StrLen(jrepath) + 2 * JLI_StrLen(arch) + 519 JLI_StrLen(jvmpath) + 52); 520 newpath = new_runpath + JLI_StrLen("LD_LIBRARY_PATH="); 521 522 523 /* 524 * Create desired LD_LIBRARY_PATH value for target data model. 525 */ 526 { 527 /* remove the name of the .so from the JVM path */ 528 lastslash = JLI_StrRChr(jvmpath, '/'); 529 if (lastslash) 530 *lastslash = '\0'; 531 532 sprintf(new_runpath, "LD_LIBRARY_PATH=" 533 "%s:" 534 "%s/lib/%s:" 535 "%s/../lib/%s", 536 jvmpath, 537 jrepath, arch, 538 jrepath, arch 539 ); 540 541 542 /* 543 * Check to make sure that the prefix of the current path is the 544 * desired environment variable setting, though the RequiresSetenv 545 * checks if the desired runpath exists, this logic does a more 546 * comprehensive check. 547 */ 548 if (runpath != NULL && 549 JLI_StrNCmp(newpath, runpath, JLI_StrLen(newpath)) == 0 && 550 (runpath[JLI_StrLen(newpath)] == 0 || runpath[JLI_StrLen(newpath)] == ':') && 551 (running == wanted) /* data model does not have to be changed */ 552 #ifdef __solaris__ 553 && (dmpath == NULL) /* data model specific variables not set */ 554 #endif /* __solaris__ */ 555 ) { 556 JLI_MemFree(newargv); 557 JLI_MemFree(new_runpath); 558 return; 559 } 560 } 561 562 /* 563 * Place the desired environment setting onto the prefix of 564 * LD_LIBRARY_PATH. Note that this prevents any possible infinite 565 * loop of execv() because we test for the prefix, above. 566 */ 567 if (runpath != 0) { 568 JLI_StrCat(new_runpath, ":"); 569 JLI_StrCat(new_runpath, runpath); 570 } 571 572 if (putenv(new_runpath) != 0) { 573 exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set 574 properly */ 575 } 576 577 /* 578 * Unix systems document that they look at LD_LIBRARY_PATH only 579 * once at startup, so we have to re-exec the current executable 580 * to get the changed environment variable to have an effect. 581 */ 582 583 #ifdef __solaris__ 584 /* 585 * If dmpath is not NULL, remove the data model specific string 586 * in the environment for the exec'ed child. 587 */ 588 if (dmpath != NULL) 589 (void)UnsetEnv((wanted == 32) ? "LD_LIBRARY_PATH_32" : "LD_LIBRARY_PATH_64"); 590 #endif /* __solaris */ 591 592 newenvp = environ; 593 } 594 #endif /* SETENV_REQUIRED */ 595 { 596 char *newexec = execname; 597 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n"); 598 (void) fflush(stdout); 599 (void) fflush(stderr); 600 #ifdef SETENV_REQUIRED 601 if (mustsetenv) { 602 execve(newexec, argv, newenvp); 603 } else { 604 execv(newexec, argv); 605 } 606 #else /* !SETENV_REQUIRED */ 607 execv(newexec, argv); 608 #endif /* SETENV_REQUIRED */ 609 JLI_ReportErrorMessageSys(JRE_ERROR4, newexec); 610 } 611 exit(1); 612 } 613 } 614 615 /* 616 * On Solaris VM choosing is done by the launcher (java.c), 617 * bitsWanted is used by MacOSX, on Solaris and Linux this. 618 * parameter is unused. 619 */ 620 static jboolean 621 GetJVMPath(const char *jrepath, const char *jvmtype, 622 char *jvmpath, jint jvmpathsize, const char * arch, int bitsWanted) 623 { 624 struct stat s; 625 626 if (JLI_StrChr(jvmtype, '/')) { 627 JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype); 628 } else { 629 JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); 630 } 631 632 JLI_TraceLauncher("Does `%s' exist ... ", jvmpath); 633 634 if (stat(jvmpath, &s) == 0) { 635 JLI_TraceLauncher("yes.\n"); 636 return JNI_TRUE; 637 } else { 638 JLI_TraceLauncher("no.\n"); 639 return JNI_FALSE; 640 } 641 } 642 643 /* 644 * Find path to JRE based on .exe's location or registry settings. 645 */ 646 static jboolean 647 GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative) 648 { 649 char libjava[MAXPATHLEN]; 650 651 if (GetApplicationHome(path, pathsize)) { 652 /* Is JRE co-located with the application? */ 653 JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch); 654 if (access(libjava, F_OK) == 0) { 655 JLI_TraceLauncher("JRE path is %s\n", path); 656 return JNI_TRUE; 657 } 658 659 /* Does the app ship a private JRE in <apphome>/jre directory? */ 660 JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch); 661 if (access(libjava, F_OK) == 0) { 662 JLI_StrCat(path, "/jre"); 663 JLI_TraceLauncher("JRE path is %s\n", path); 664 return JNI_TRUE; 665 } 666 } 667 668 if (!speculative) 669 JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); 670 return JNI_FALSE; 671 } 672 673 jboolean 674 LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) 675 { 676 void *libjvm; 677 678 JLI_TraceLauncher("JVM path is %s\n", jvmpath); 679 680 libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); 681 if (libjvm == NULL) { 682 #if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */ 683 FILE * fp; 684 Elf32_Ehdr elf_head; 685 int count; 686 int location; 687 688 fp = fopen(jvmpath, "r"); 689 if (fp == NULL) { 690 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 691 return JNI_FALSE; 692 } 693 694 /* read in elf header */ 695 count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp); 696 fclose(fp); 697 if (count < 1) { 698 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 699 return JNI_FALSE; 700 } 701 702 /* 703 * Check for running a server vm (compiled with -xarch=v8plus) 704 * on a stock v8 processor. In this case, the machine type in 705 * the elf header would not be included the architecture list 706 * provided by the isalist command, which is turn is gotten from 707 * sysinfo. This case cannot occur on 64-bit hardware and thus 708 * does not have to be checked for in binaries with an LP64 data 709 * model. 710 */ 711 if (elf_head.e_machine == EM_SPARC32PLUS) { 712 char buf[257]; /* recommended buffer size from sysinfo man 713 page */ 714 long length; 715 char* location; 716 717 length = sysinfo(SI_ISALIST, buf, 257); 718 if (length > 0) { 719 location = JLI_StrStr(buf, "sparcv8plus "); 720 if (location == NULL) { 721 JLI_ReportErrorMessage(JVM_ERROR3); 722 return JNI_FALSE; 723 } 724 } 725 } 726 #endif 727 JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); 728 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 729 return JNI_FALSE; 730 } 731 732 ifn->CreateJavaVM = (CreateJavaVM_t) 733 dlsym(libjvm, "JNI_CreateJavaVM"); 734 if (ifn->CreateJavaVM == NULL) { 735 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 736 return JNI_FALSE; 737 } 738 739 ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) 740 dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); 741 if (ifn->GetDefaultJavaVMInitArgs == NULL) { 742 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 743 return JNI_FALSE; 744 } 745 746 ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t) 747 dlsym(libjvm, "JNI_GetCreatedJavaVMs"); 748 if (ifn->GetCreatedJavaVMs == NULL) { 749 JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); 750 return JNI_FALSE; 751 } 752 753 return JNI_TRUE; 754 } 755 756 /* 757 * Compute the name of the executable 758 * 759 * In order to re-exec securely we need the absolute path of the 760 * executable. On Solaris getexecname(3c) may not return an absolute 761 * path so we use dladdr to get the filename of the executable and 762 * then use realpath to derive an absolute path. From Solaris 9 763 * onwards the filename returned in DL_info structure from dladdr is 764 * an absolute pathname so technically realpath isn't required. 765 * On Linux we read the executable name from /proc/self/exe. 766 * As a fallback, and for platforms other than Solaris and Linux, 767 * we use FindExecName to compute the executable name. 768 */ 769 const char* 770 SetExecname(char **argv) 771 { 772 char* exec_path = NULL; 773 #if defined(__solaris__) 774 { 775 Dl_info dlinfo; 776 int (*fptr)(); 777 778 fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); 779 if (fptr == NULL) { 780 JLI_ReportErrorMessage(DLL_ERROR3, dlerror()); 781 return JNI_FALSE; 782 } 783 784 if (dladdr((void*)fptr, &dlinfo)) { 785 char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1); 786 if (resolved != NULL) { 787 exec_path = realpath(dlinfo.dli_fname, resolved); 788 if (exec_path == NULL) { 789 JLI_MemFree(resolved); 790 } 791 } 792 } 793 } 794 #elif defined(__linux__) 795 { 796 const char* self = "/proc/self/exe"; 797 char buf[PATH_MAX+1]; 798 int len = readlink(self, buf, PATH_MAX); 799 if (len >= 0) { 800 buf[len] = '\0'; /* readlink(2) doesn't NUL terminate */ 801 exec_path = JLI_StringDup(buf); 802 } 803 } 804 #else /* !__solaris__ && !__linux__ */ 805 { 806 /* Not implemented */ 807 } 808 #endif 809 810 if (exec_path == NULL) { 811 exec_path = FindExecName(argv[0]); 812 } 813 execname = exec_path; 814 return exec_path; 815 } 816 817 /* --- Splash Screen shared library support --- */ 818 static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen"); 819 static void* hSplashLib = NULL; 820 821 void* SplashProcAddress(const char* name) { 822 if (!hSplashLib) { 823 int ret; 824 char jrePath[MAXPATHLEN]; 825 char splashPath[MAXPATHLEN]; 826 827 if (!GetJREPath(jrePath, sizeof(jrePath), LIBARCHNAME, JNI_FALSE)) { 828 JLI_ReportErrorMessage(JRE_ERROR1); 829 return NULL; 830 } 831 ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s/%s", 832 jrePath, LIBARCHNAME, SPLASHSCREEN_SO); 833 834 if (ret >= (int) sizeof(splashPath)) { 835 JLI_ReportErrorMessage(JRE_ERROR11); 836 return NULL; 837 } 838 if (ret < 0) { 839 JLI_ReportErrorMessage(JRE_ERROR13); 840 return NULL; 841 } 842 hSplashLib = dlopen(splashPath, RTLD_LAZY | RTLD_GLOBAL); 843 JLI_TraceLauncher("Info: loaded %s\n", splashPath); 844 } 845 if (hSplashLib) { 846 void* sym = dlsym(hSplashLib, name); 847 return sym; 848 } else { 849 return NULL; 850 } 851 } 852 853 void SplashFreeLibrary() { 854 if (hSplashLib) { 855 dlclose(hSplashLib); 856 hSplashLib = NULL; 857 } 858 } 859 860 /* 861 * Block current thread and continue execution in a new thread 862 */ 863 int 864 ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { 865 int rslt; 866 #ifdef __linux__ 867 pthread_t tid; 868 pthread_attr_t attr; 869 pthread_attr_init(&attr); 870 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 871 872 if (stack_size > 0) { 873 pthread_attr_setstacksize(&attr, stack_size); 874 } 875 876 if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) { 877 void * tmp; 878 pthread_join(tid, &tmp); 879 rslt = (int)tmp; 880 } else { 881 /* 882 * Continue execution in current thread if for some reason (e.g. out of 883 * memory/LWP) a new thread can't be created. This will likely fail 884 * later in continuation as JNI_CreateJavaVM needs to create quite a 885 * few new threads, anyway, just give it a try.. 886 */ 887 rslt = continuation(args); 888 } 889 890 pthread_attr_destroy(&attr); 891 #else /* ! __linux__ */ 892 thread_t tid; 893 long flags = 0; 894 if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) { 895 void * tmp; 896 thr_join(tid, NULL, &tmp); 897 rslt = (int)tmp; 898 } else { 899 /* See above. Continue in current thread if thr_create() failed */ 900 rslt = continuation(args); 901 } 902 #endif /* __linux__ */ 903 return rslt; 904 } 905 906 /* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */ 907 #define MAX_PID_STR_SZ 20 908 909 void SetJavaLauncherPlatformProps() { 910 /* Linux only */ 911 #ifdef __linux__ 912 const char *substr = "-Dsun.java.launcher.pid="; 913 char *pid_prop_str = (char *)JLI_MemAlloc(JLI_StrLen(substr) + MAX_PID_STR_SZ + 1); 914 sprintf(pid_prop_str, "%s%d", substr, getpid()); 915 AddOption(pid_prop_str, NULL); 916 #endif /* __linux__ */ 917 } 918 919 int 920 JVMInit(InvocationFunctions* ifn, jlong threadStackSize, 921 int argc, char **argv, 922 int mode, char *what, int ret) 923 { 924 ShowSplashScreen(); 925 return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret); 926 } 927 928 void 929 PostJVMInit(JNIEnv *env, jstring mainClass, JavaVM *vm) 930 { 931 // stubbed out for windows and *nixes. 932 } 933 934 void 935 RegisterThread() 936 { 937 // stubbed out for windows and *nixes. 938 } 939 940 /* 941 * on unix, we return a false to indicate this option is not applicable 942 */ 943 jboolean 944 ProcessPlatformOption(const char *arg) 945 { 946 return JNI_FALSE; 947 }