Bug Summary

File:jdk/src/java.base/unix/native/libjli/java_md.c
Warning:line 301, column 9
Value stored to 'argc' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name java_md.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjli -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjli -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.base -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused -Wno-unused-function -Wno-implicit-fallthrough -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjli/java_md.c
1/*
2 * Copyright (c) 1998, 2020, 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
40
41#define JVM_DLL"libjvm.so" "libjvm.so"
42#define JAVA_DLL"libjava.so" "libjava.so"
43#ifdef AIX
44#define LD_LIBRARY_PATH"LD_LIBRARY_PATH" "LIBPATH"
45#else
46#define LD_LIBRARY_PATH"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
74 * $RPATH/$ORIGIN baked into the shared libraries at compile time. Therefore,
75 * in most cases, the launcher will only exec, if the data models are
76 * mismatched, and will not set any environment variables, regardless of the
77 * data models.
78 *
79 * However, if the environment contains a LD_LIBRARY_PATH, this will cause the
80 * launcher to inspect the LD_LIBRARY_PATH. The launcher will check
81 * a. if the LD_LIBRARY_PATH's first component is the path to the desired
82 * libjvm.so
83 * b. if any other libjvm.so is found in any of the paths.
84 * If case b is true, then the launcher will set the LD_LIBRARY_PATH to the
85 * desired JRE and reexec, in order to propagate the environment.
86 *
87 * Main
88 * (incoming argv)
89 * |
90 * \|/
91 * CreateExecutionEnvironment
92 * (determines desired data model)
93 * |
94 * |
95 * \|/
96 * Have Desired Model ? --> NO --> Exit(with error)
97 * |
98 * |
99 * \|/
100 * YES
101 * |
102 * |
103 * \|/
104 * CheckJvmType
105 * (removes -client, -server, etc.)
106 * |
107 * |
108 * \|/
109 * TranslateDashJArgs...
110 * (Prepare to pass args to vm)
111 * |
112 * |
113 * \|/
114 * ParseArguments
115 * |
116 * |
117 * \|/
118 * RequiresSetenv
119 * Is LD_LIBRARY_PATH
120 * and friends set ? --> NO --> Continue
121 * YES
122 * |
123 * |
124 * \|/
125 * Path is desired JRE ? YES --> Continue
126 * NO
127 * |
128 * |
129 * \|/
130 * Paths have well known
131 * jvm paths ? --> NO --> Error/Exit
132 * YES
133 * |
134 * |
135 * \|/
136 * Does libjvm.so exist
137 * in any of them ? --> NO --> Continue
138 * YES
139 * |
140 * |
141 * \|/
142 * Set the LD_LIBRARY_PATH
143 * |
144 * |
145 * \|/
146 * Re-exec
147 * |
148 * |
149 * \|/
150 * Main
151 */
152
153/* Store the name of the executable once computed */
154static char *execname = NULL((void*)0);
155
156/*
157 * execname accessor from other parts of platform dependent logic
158 */
159const char *
160GetExecName() {
161 return execname;
162}
163
164#ifdef SETENV_REQUIRED
165static jboolean
166JvmExists(const char *path) {
167 char tmp[PATH_MAX4096 + 1];
168 struct stat statbuf;
169 JLI_Snprintf(tmp, PATH_MAX, "%s/%s", path, JVM_DLL)__builtin___snprintf_chk (tmp, 4096, 2 - 1, __builtin_object_size
(tmp, 2 > 1), "%s/%s", path, "libjvm.so")
;
170 if (stat(tmp, &statbuf) == 0) {
171 return JNI_TRUE1;
172 }
173 return JNI_FALSE0;
174}
175/*
176 * contains a lib/{server,client}/libjvm.so ?
177 */
178static jboolean
179ContainsLibJVM(const char *env) {
180 /* the usual suspects */
181 char clientPattern[] = "lib/client";
182 char serverPattern[] = "lib/server";
183 char *envpath;
184 char *path;
185 char* save_ptr = NULL((void*)0);
186 jboolean clientPatternFound;
187 jboolean serverPatternFound;
188
189 /* fastest path */
190 if (env == NULL((void*)0)) {
191 return JNI_FALSE0;
192 }
193
194 /* to optimize for time, test if any of our usual suspects are present. */
195 clientPatternFound = JLI_StrStr(env, clientPattern)strstr((env), (clientPattern)) != NULL((void*)0);
196 serverPatternFound = JLI_StrStr(env, serverPattern)strstr((env), (serverPattern)) != NULL((void*)0);
197 if (clientPatternFound == JNI_FALSE0 && serverPatternFound == JNI_FALSE0) {
198 return JNI_FALSE0;
199 }
200
201 /*
202 * we have a suspicious path component, check if it contains a libjvm.so
203 */
204 envpath = JLI_StringDup(env);
205 for (path = strtok_r(envpath, ":", &save_ptr); path != NULL((void*)0); path = strtok_r(NULL((void*)0), ":", &save_ptr)) {
206 if (clientPatternFound && JLI_StrStr(path, clientPattern)strstr((path), (clientPattern)) != NULL((void*)0)) {
207 if (JvmExists(path)) {
208 JLI_MemFree(envpath);
209 return JNI_TRUE1;
210 }
211 }
212 if (serverPatternFound && JLI_StrStr(path, serverPattern)strstr((path), (serverPattern)) != NULL((void*)0)) {
213 if (JvmExists(path)) {
214 JLI_MemFree(envpath);
215 return JNI_TRUE1;
216 }
217 }
218 }
219 JLI_MemFree(envpath);
220 return JNI_FALSE0;
221}
222
223/*
224 * Test whether the environment variable needs to be set, see flowchart.
225 */
226static jboolean
227RequiresSetenv(const char *jvmpath) {
228 char jpath[PATH_MAX4096 + 1];
229 char *llp;
230 char *dmllp = NULL((void*)0);
231 char *p; /* a utility pointer */
232
233#ifdef MUSL_LIBC
234 /*
235 * The musl library loader requires LD_LIBRARY_PATH to be set in order
236 * to correctly resolve the dependency libjava.so has on libjvm.so.
237 */
238 return JNI_TRUE1;
239#endif
240
241#ifdef AIX
242 /* We always have to set the LIBPATH on AIX because ld doesn't support $ORIGIN. */
243 return JNI_TRUE1;
244#endif
245
246 llp = getenv("LD_LIBRARY_PATH");
247 /* no environment variable is a good environment variable */
248 if (llp == NULL((void*)0) && dmllp == NULL((void*)0)) {
249 return JNI_FALSE0;
250 }
251#ifdef __linux1
252 /*
253 * On linux, if a binary is running as sgid or suid, glibc sets
254 * LD_LIBRARY_PATH to the empty string for security purposes. (In contrast,
255 * on Solaris the LD_LIBRARY_PATH variable for a privileged binary does not
256 * lose its settings; but the dynamic linker does apply more scrutiny to the
257 * path.) The launcher uses the value of LD_LIBRARY_PATH to prevent an exec
258 * loop, here and further downstream. Therefore, if we are running sgid or
259 * suid, this function's setting of LD_LIBRARY_PATH will be ineffective and
260 * we should case a return from the calling function. Getting the right
261 * libraries will be handled by the RPATH. In reality, this check is
262 * redundant, as the previous check for a non-null LD_LIBRARY_PATH will
263 * return back to the calling function forthwith, it is left here to safe
264 * guard against any changes, in the glibc's existing security policy.
265 */
266 if ((getgid() != getegid()) || (getuid() != geteuid())) {
267 return JNI_FALSE0;
268 }
269#endif /* __linux */
270
271 /*
272 * Prevent recursions. Since LD_LIBRARY_PATH is the one which will be set by
273 * previous versions of the JRE, thus it is the only path that matters here.
274 * So we check to see if the desired JRE is set.
275 */
276 JLI_StrNCpy(jpath, jvmpath, PATH_MAX)strncpy((jpath), (jvmpath), (4096));
277 p = JLI_StrRChr(jpath, '/')strrchr((jpath), ('/'));
278 *p = '\0';
279 if (llp != NULL((void*)0) && JLI_StrNCmp(llp, jpath, JLI_StrLen(jpath))strncmp((llp), (jpath), (strlen((jpath)))) == 0) {
280 return JNI_FALSE0;
281 }
282
283 /* scrutinize all the paths further */
284 if (llp != NULL((void*)0) && ContainsLibJVM(llp)) {
285 return JNI_TRUE1;
286 }
287 if (dmllp != NULL((void*)0) && ContainsLibJVM(dmllp)) {
288 return JNI_TRUE1;
289 }
290 return JNI_FALSE0;
291}
292#endif /* SETENV_REQUIRED */
293
294void
295CreateExecutionEnvironment(int *pargc, char ***pargv,
296 char jrepath[], jint so_jrepath,
297 char jvmpath[], jint so_jvmpath,
298 char jvmcfg[], jint so_jvmcfg) {
299
300 char * jvmtype = NULL((void*)0);
301 int argc = *pargc;
Value stored to 'argc' during its initialization is never read
302 char **argv = *pargv;
303
304#ifdef SETENV_REQUIRED
305 jboolean mustsetenv = JNI_FALSE0;
306 char *runpath = NULL((void*)0); /* existing effective LD_LIBRARY_PATH setting */
307 char* new_runpath = NULL((void*)0); /* desired new LD_LIBRARY_PATH string */
308 char* newpath = NULL((void*)0); /* path on new LD_LIBRARY_PATH */
309 char* lastslash = NULL((void*)0);
310 char** newenvp = NULL((void*)0); /* current environment */
311 size_t new_runpath_size;
312#endif /* SETENV_REQUIRED */
313
314 /* Compute/set the name of the executable */
315 SetExecname(*pargv);
316
317 /* Check to see if the jvmpath exists */
318 /* Find out where the JRE is that we will be using. */
319 if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE0)) {
320 JLI_ReportErrorMessage(JRE_ERROR1"Error: Could not find Java SE Runtime Environment.");
321 exit(2);
322 }
323 JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",__builtin___snprintf_chk (jvmcfg, so_jvmcfg, 2 - 1, __builtin_object_size
(jvmcfg, 2 > 1), "%s%slib%sjvm.cfg", jrepath, "/", "/")
324 jrepath, FILESEP, FILESEP)__builtin___snprintf_chk (jvmcfg, so_jvmcfg, 2 - 1, __builtin_object_size
(jvmcfg, 2 > 1), "%s%slib%sjvm.cfg", jrepath, "/", "/")
;
325 /* Find the specified JVM type */
326 if (ReadKnownVMs(jvmcfg, JNI_FALSE0) < 1) {
327 JLI_ReportErrorMessage(CFG_ERROR7"Error: no known VMs. (check for corrupt jvm.cfg file)");
328 exit(1);
329 }
330
331 jvmpath[0] = '\0';
332 jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE0);
333 if (JLI_StrCmp(jvmtype, "ERROR")strcmp((jvmtype), ("ERROR")) == 0) {
334 JLI_ReportErrorMessage(CFG_ERROR9"Error: could not determine JVM type.");
335 exit(4);
336 }
337
338 if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) {
339 JLI_ReportErrorMessage(CFG_ERROR8"Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components.", jvmtype, jvmpath);
340 exit(4);
341 }
342 /*
343 * we seem to have everything we need, so without further ado
344 * we return back, otherwise proceed to set the environment.
345 */
346#ifdef SETENV_REQUIRED
347 mustsetenv = RequiresSetenv(jvmpath);
348 JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE");
349
350 if (mustsetenv == JNI_FALSE0) {
351 return;
352 }
353#else
354 return;
355#endif /* SETENV_REQUIRED */
356
357#ifdef SETENV_REQUIRED
358 if (mustsetenv) {
359 /*
360 * We will set the LD_LIBRARY_PATH as follows:
361 *
362 * o $JVMPATH (directory portion only)
363 * o $JRE/lib
364 * o $JRE/../lib
365 *
366 * followed by the user's previous effective LD_LIBRARY_PATH, if
367 * any.
368 */
369
370 runpath = getenv(LD_LIBRARY_PATH"LD_LIBRARY_PATH");
371
372 /* runpath contains current effective LD_LIBRARY_PATH setting */
373 { /* New scope to declare local variable */
374 char *new_jvmpath = JLI_StringDup(jvmpath);
375 new_runpath_size = ((runpath != NULL((void*)0)) ? JLI_StrLen(runpath)strlen((runpath)) : 0) +
376 2 * JLI_StrLen(jrepath)strlen((jrepath)) +
377 JLI_StrLen(new_jvmpath)strlen((new_jvmpath)) + 52;
378 new_runpath = JLI_MemAlloc(new_runpath_size);
379 newpath = new_runpath + JLI_StrLen(LD_LIBRARY_PATH "=")strlen(("LD_LIBRARY_PATH" "="));
380
381
382 /*
383 * Create desired LD_LIBRARY_PATH value for target data model.
384 */
385 {
386 /* remove the name of the .so from the JVM path */
387 lastslash = JLI_StrRChr(new_jvmpath, '/')strrchr((new_jvmpath), ('/'));
388 if (lastslash)
389 *lastslash = '\0';
390
391 sprintf(new_runpath, LD_LIBRARY_PATH "="__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
392 "%s:"__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
393 "%s/lib:"__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
394 "%s/../lib",__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
395 new_jvmpath,__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
396 jrepath,__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
397 jrepath__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
398 )__builtin___sprintf_chk (new_runpath, 2 - 1, __builtin_object_size
(new_runpath, 2 > 1), "LD_LIBRARY_PATH" "=" "%s:" "%s/lib:"
"%s/../lib", new_jvmpath, jrepath, jrepath)
;
399
400 JLI_MemFree(new_jvmpath);
401
402 /*
403 * Check to make sure that the prefix of the current path is the
404 * desired environment variable setting, though the RequiresSetenv
405 * checks if the desired runpath exists, this logic does a more
406 * comprehensive check.
407 */
408 if (runpath != NULL((void*)0) &&
409 JLI_StrNCmp(newpath, runpath, JLI_StrLen(newpath))strncmp((newpath), (runpath), (strlen((newpath)))) == 0 &&
410 (runpath[JLI_StrLen(newpath)strlen((newpath))] == 0 ||
411 runpath[JLI_StrLen(newpath)strlen((newpath))] == ':')) {
412 JLI_MemFree(new_runpath);
413 return;
414 }
415 }
416 }
417
418 /*
419 * Place the desired environment setting onto the prefix of
420 * LD_LIBRARY_PATH. Note that this prevents any possible infinite
421 * loop of execv() because we test for the prefix, above.
422 */
423 if (runpath != 0) {
424 /* ensure storage for runpath + colon + NULL */
425 if ((JLI_StrLen(runpath)strlen((runpath)) + 1 + 1) > new_runpath_size) {
426 JLI_ReportErrorMessageSys(JRE_ERROR11"Error: Path length exceeds maximum length (PATH_MAX)");
427 exit(1);
428 }
429 JLI_StrCat(new_runpath, ":")strcat((new_runpath), (":"));
430 JLI_StrCat(new_runpath, runpath)strcat((new_runpath), (runpath));
431 }
432
433 if (putenv(new_runpath) != 0) {
434 /* problem allocating memory; LD_LIBRARY_PATH not set properly */
435 exit(1);
436 }
437
438 /*
439 * Unix systems document that they look at LD_LIBRARY_PATH only
440 * once at startup, so we have to re-exec the current executable
441 * to get the changed environment variable to have an effect.
442 */
443
444 newenvp = environ;
445 }
446#endif /* SETENV_REQUIRED */
447 {
448 char *newexec = execname;
449 JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
450 (void) fflush(stdoutstdout);
451 (void) fflush(stderrstderr);
452#ifdef SETENV_REQUIRED
453 if (mustsetenv) {
454 execve(newexec, argv, newenvp);
455 } else {
456 execv(newexec, argv);
457 }
458#else /* !SETENV_REQUIRED */
459 execv(newexec, argv);
460#endif /* SETENV_REQUIRED */
461 JLI_ReportErrorMessageSys(JRE_ERROR4"Error: trying to exec %s.\nCheck if file exists and permissions are set correctly.", newexec);
462 }
463 exit(1);
464}
465
466
467static jboolean
468GetJVMPath(const char *jrepath, const char *jvmtype,
469 char *jvmpath, jint jvmpathsize)
470{
471 struct stat s;
472
473 if (JLI_StrChr(jvmtype, '/')strchr((jvmtype), ('/'))) {
474 JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype)__builtin___snprintf_chk (jvmpath, jvmpathsize, 2 - 1, __builtin_object_size
(jvmpath, 2 > 1), "%s/" "libjvm.so", jvmtype)
;
475 } else {
476 JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/" JVM_DLL, jrepath, jvmtype)__builtin___snprintf_chk (jvmpath, jvmpathsize, 2 - 1, __builtin_object_size
(jvmpath, 2 > 1), "%s/lib/%s/" "libjvm.so", jrepath, jvmtype
)
;
477 }
478
479 JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
480
481 if (stat(jvmpath, &s) == 0) {
482 JLI_TraceLauncher("yes.\n");
483 return JNI_TRUE1;
484 } else {
485 JLI_TraceLauncher("no.\n");
486 return JNI_FALSE0;
487 }
488}
489
490/*
491 * Find path to JRE based on .exe's location or registry settings.
492 */
493static jboolean
494GetJREPath(char *path, jint pathsize, jboolean speculative)
495{
496 char libjava[MAXPATHLEN4096];
497 struct stat s;
498
499 if (GetApplicationHome(path, pathsize)) {
500 /* Is JRE co-located with the application? */
501 JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path)__builtin___snprintf_chk (libjava, sizeof(libjava), 2 - 1, __builtin_object_size
(libjava, 2 > 1), "%s/lib/" "libjava.so", path)
;
502 if (access(libjava, F_OK0) == 0) {
503 JLI_TraceLauncher("JRE path is %s\n", path);
504 return JNI_TRUE1;
505 }
506 /* ensure storage for path + /jre + NULL */
507 if ((JLI_StrLen(path)strlen((path)) + 4 + 1) > (size_t) pathsize) {
508 JLI_TraceLauncher("Insufficient space to store JRE path\n");
509 return JNI_FALSE0;
510 }
511 /* Does the app ship a private JRE in <apphome>/jre directory? */
512 JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path)__builtin___snprintf_chk (libjava, sizeof(libjava), 2 - 1, __builtin_object_size
(libjava, 2 > 1), "%s/jre/lib/" "libjava.so", path)
;
513 if (access(libjava, F_OK0) == 0) {
514 JLI_StrCat(path, "/jre")strcat((path), ("/jre"));
515 JLI_TraceLauncher("JRE path is %s\n", path);
516 return JNI_TRUE1;
517 }
518 }
519
520 if (GetApplicationHomeFromDll(path, pathsize)) {
521 JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path)__builtin___snprintf_chk (libjava, sizeof(libjava), 2 - 1, __builtin_object_size
(libjava, 2 > 1), "%s/lib/" "libjava.so", path)
;
522 if (stat(libjava, &s) == 0) {
523 JLI_TraceLauncher("JRE path is %s\n", path);
524 return JNI_TRUE1;
525 }
526 }
527
528 if (!speculative)
529 JLI_ReportErrorMessage(JRE_ERROR8"Error: could not find " JAVA_DLL"libjava.so");
530 return JNI_FALSE0;
531}
532
533jboolean
534LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
535{
536 void *libjvm;
537
538 JLI_TraceLauncher("JVM path is %s\n", jvmpath);
539
540 libjvm = dlopen(jvmpath, RTLD_NOW0x00002 + RTLD_GLOBAL0x00100);
541 if (libjvm == NULL((void*)0)) {
542 JLI_ReportErrorMessage(DLL_ERROR1"Error: dl failure on line %d", __LINE__542);
543 JLI_ReportErrorMessage(DLL_ERROR2"Error: failed %s, because %s", jvmpath, dlerror());
544 return JNI_FALSE0;
545 }
546
547 ifn->CreateJavaVM = (CreateJavaVM_t)
548 dlsym(libjvm, "JNI_CreateJavaVM");
549 if (ifn->CreateJavaVM == NULL((void*)0)) {
550 JLI_ReportErrorMessage(DLL_ERROR2"Error: failed %s, because %s", jvmpath, dlerror());
551 return JNI_FALSE0;
552 }
553
554 ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t)
555 dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs");
556 if (ifn->GetDefaultJavaVMInitArgs == NULL((void*)0)) {
557 JLI_ReportErrorMessage(DLL_ERROR2"Error: failed %s, because %s", jvmpath, dlerror());
558 return JNI_FALSE0;
559 }
560
561 ifn->GetCreatedJavaVMs = (GetCreatedJavaVMs_t)
562 dlsym(libjvm, "JNI_GetCreatedJavaVMs");
563 if (ifn->GetCreatedJavaVMs == NULL((void*)0)) {
564 JLI_ReportErrorMessage(DLL_ERROR2"Error: failed %s, because %s", jvmpath, dlerror());
565 return JNI_FALSE0;
566 }
567
568 return JNI_TRUE1;
569}
570
571/*
572 * Compute the name of the executable
573 *
574 * In order to re-exec securely we need the absolute path of the
575 * executable. On Solaris getexecname(3c) may not return an absolute
576 * path so we use dladdr to get the filename of the executable and
577 * then use realpath to derive an absolute path. From Solaris 9
578 * onwards the filename returned in DL_info structure from dladdr is
579 * an absolute pathname so technically realpath isn't required.
580 * On Linux we read the executable name from /proc/self/exe.
581 * As a fallback, and for platforms other than Solaris and Linux,
582 * we use FindExecName to compute the executable name.
583 */
584const char*
585SetExecname(char **argv)
586{
587 char* exec_path = NULL((void*)0);
588#if defined(__linux__1)
589 {
590 const char* self = "/proc/self/exe";
591 char buf[PATH_MAX4096+1];
592 int len = readlink(self, buf, PATH_MAX4096);
593 if (len >= 0) {
594 buf[len] = '\0'; /* readlink(2) doesn't NUL terminate */
595 exec_path = JLI_StringDup(buf);
596 }
597 }
598#else /* !__linux__ */
599 {
600 /* Not implemented */
601 }
602#endif
603
604 if (exec_path == NULL((void*)0)) {
605 exec_path = FindExecName(argv[0]);
606 }
607 execname = exec_path;
608 return exec_path;
609}
610
611/* --- Splash Screen shared library support --- */
612static const char* SPLASHSCREEN_SO = JNI_LIB_NAME("splashscreen")"lib" "splashscreen" ".so";
613static void* hSplashLib = NULL((void*)0);
614
615void* SplashProcAddress(const char* name) {
616 if (!hSplashLib) {
617 int ret;
618 char jrePath[MAXPATHLEN4096];
619 char splashPath[MAXPATHLEN4096];
620
621 if (!GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE0)) {
622 JLI_ReportErrorMessage(JRE_ERROR1"Error: Could not find Java SE Runtime Environment.");
623 return NULL((void*)0);
624 }
625 ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s",__builtin___snprintf_chk (splashPath, sizeof(splashPath), 2 -
1, __builtin_object_size (splashPath, 2 > 1), "%s/lib/%s"
, jrePath, SPLASHSCREEN_SO)
626 jrePath, SPLASHSCREEN_SO)__builtin___snprintf_chk (splashPath, sizeof(splashPath), 2 -
1, __builtin_object_size (splashPath, 2 > 1), "%s/lib/%s"
, jrePath, SPLASHSCREEN_SO)
;
627
628 if (ret >= (int) sizeof(splashPath)) {
629 JLI_ReportErrorMessage(JRE_ERROR11"Error: Path length exceeds maximum length (PATH_MAX)");
630 return NULL((void*)0);
631 }
632 if (ret < 0) {
633 JLI_ReportErrorMessage(JRE_ERROR13"Error: String processing operation failed");
634 return NULL((void*)0);
635 }
636 hSplashLib = dlopen(splashPath, RTLD_LAZY0x00001 | RTLD_GLOBAL0x00100);
637 JLI_TraceLauncher("Info: loaded %s\n", splashPath);
638 }
639 if (hSplashLib) {
640 void* sym = dlsym(hSplashLib, name);
641 return sym;
642 } else {
643 return NULL((void*)0);
644 }
645}
646
647/*
648 * Signature adapter for pthread_create() or thr_create().
649 */
650static void* ThreadJavaMain(void* args) {
651 return (void*)(intptr_t)JavaMain(args);
652}
653
654/*
655 * Block current thread and continue execution in a new thread.
656 */
657int
658CallJavaMainInNewThread(jlong stack_size, void* args) {
659 int rslt;
660 pthread_t tid;
661 pthread_attr_t attr;
662 pthread_attr_init(&attr);
663 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLEPTHREAD_CREATE_JOINABLE);
664
665 if (stack_size > 0) {
666 pthread_attr_setstacksize(&attr, stack_size);
667 }
668 pthread_attr_setguardsize(&attr, 0); // no pthread guard page on java threads
669
670 if (pthread_create(&tid, &attr, ThreadJavaMain, args) == 0) {
671 void* tmp;
672 pthread_join(tid, &tmp);
673 rslt = (int)(intptr_t)tmp;
674 } else {
675 /*
676 * Continue execution in current thread if for some reason (e.g. out of
677 * memory/LWP) a new thread can't be created. This will likely fail
678 * later in JavaMain as JNI_CreateJavaVM needs to create quite a
679 * few new threads, anyway, just give it a try..
680 */
681 rslt = JavaMain(args);
682 }
683
684 pthread_attr_destroy(&attr);
685 return rslt;
686}
687
688/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
689#define MAX_PID_STR_SZ20 20
690
691int
692JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
693 int argc, char **argv,
694 int mode, char *what, int ret)
695{
696 ShowSplashScreen();
697 return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
698}
699
700void
701PostJVMInit(JNIEnv *env, jclass mainClass, JavaVM *vm)
702{
703 // stubbed out for windows and *nixes.
704}
705
706void
707RegisterThread()
708{
709 // stubbed out for windows and *nixes.
710}
711
712/*
713 * on unix, we return a false to indicate this option is not applicable
714 */
715jboolean
716ProcessPlatformOption(const char *arg)
717{
718 return JNI_FALSE0;
719}