1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
24 #include <sys/utsname.h>
25 #include <sys/param.h>
35 collect::check_target (int argc
, char **argv
)
42 int tindex
= targ_index
;
47 /* now check the executable */
48 nargs
= argc
- targ_index
;
49 Exec_status rv
= check_executable (argv
[targ_index
]);
53 njargs
= cc
->get_java_arg_cnt ();
54 arglist
= (char **) calloc (nargs
+ 5 + njargs
, sizeof (char *));
55 jargs
= cc
->get_java_args ();
57 // store the first argument -- target name
59 arglist
[ret
++] = argv
[tindex
++];
60 if (cc
->get_java_mode () == 1)
62 // add any user-specified -J (Java) arguments
63 int length
= (int) strlen (argv
[targ_index
]);
65 if ((length
>= 6) && strcmp (&argv
[targ_index
][length
- 5], NTXT ("/java")) == 0)
67 else if ((length
== 4) && strcmp (&argv
[targ_index
][0], NTXT ("java")) == 0)
69 if (njargs
!= 0 && is_java
)
71 next
= strtok_r (jargs
, NTXT (" \t"), lasts
);
72 arglist
[ret
++] = next
;
75 next
= strtok_r (NULL
, NTXT (" \t"), lasts
);
78 arglist
[ret
++] = next
;
83 // copy the rest of the arguments
84 for (int i
= 1; i
< nargs
; i
++)
85 arglist
[ret
++] = argv
[tindex
++];
89 // Preface the user-supplied argument list with
90 // the path to the java, the collector invocation,
91 // any -J java arguments provided, and "-jar".
92 ccret
= cc
->set_java_mode (NTXT ("on"));
98 njargs
= cc
->get_java_arg_cnt ();
99 arglist
= (char **) calloc (nargs
+ 5 + njargs
, sizeof (char *));
100 jargs
= cc
->get_java_args ();
104 exit (1); // message was written
107 // add any user-specified Java arguments
110 next
= strtok_r (jargs
, NTXT (" \t"), lasts
);
111 arglist
[ret
++] = next
;
114 next
= strtok_r (NULL
, NTXT (" \t"), lasts
);
117 arglist
[ret
++] = next
;
120 arglist
[ret
++] = NTXT ("-jar");
121 for (int i
= 0; i
< nargs
; i
++)
122 arglist
[ret
++] = argv
[tindex
++];
125 case EXEC_IS_CLASSCLASS
:
126 // remove the .class from the name
127 ret
= (int) strlen (argv
[targ_index
]);
128 argv
[targ_index
][ret
- 6] = 0;
130 // now fall through to the EXEC_IS_CLASS case
132 // Preface the user-supplied argument list with
133 // the path to the java, the collector invocation,
134 // and any -J java arguments provided.
135 ccret
= cc
->set_java_mode (NTXT ("on"));
141 jargs
= cc
->get_java_args ();
142 njargs
= cc
->get_java_arg_cnt ();
143 arglist
= (char **) calloc (nargs
+ 4 + njargs
, sizeof (char *));
147 exit (1); // message was written
150 // add any user-specified Java arguments
153 next
= strtok_r (jargs
, NTXT (" \t"), lasts
);
154 arglist
[ret
++] = next
;
157 next
= strtok_r (NULL
, NTXT (" \t"), lasts
);
160 arglist
[ret
++] = next
;
164 // copy the remaining arguments to the new list
165 for (int i
= 0; i
< nargs
; i
++)
166 arglist
[ret
++] = argv
[tindex
++];
169 case EXEC_ELF_NOSHARE
:
172 case EXEC_ELF_HEADER
:
178 /* something wrong; write a message */
179 char *errstr
= status_str (rv
, argv
[targ_index
]);
182 dbe_write (2, "%s", errstr
);
187 cc
->set_target (arglist
[0]);
189 /* check the experiment */
191 ccret
= cc
->check_expt (&ccwarn
);
194 writeStr (2, ccwarn
);
202 /* check if java, to see if -j flag was given */
203 if ((basename
= strrchr (arglist
[0], '/')) == NULL
)
204 basename
= arglist
[0];
207 if (strcmp (basename
, NTXT ("java")) == 0)
209 /* the target's name is java; was java flag set? */
210 if ((jseen_global
== 0) && (cc
->get_java_mode () == 0))
212 char *cret
= cc
->set_java_mode (NTXT ("on"));
223 collect::check_executable (char *target_name
)
225 char target_path
[MAXPATHLEN
];
226 struct stat64 statbuf
;
227 if (target_name
== NULL
) // not set, but assume caller knows what it's doing
229 if (getenv ("GPROFNG_SKIP_VALIDATION")) // don't check target
232 // see if target exists and is not a directory
233 if ((dbe_stat (target_name
, &statbuf
) == 0) && ((statbuf
.st_mode
& S_IFMT
) != S_IFDIR
))
235 // target is found, check for access as executable
236 if (access (target_name
, X_OK
) != 0)
238 // not an executable, check for jar or class file
239 int i
= (int) strlen (target_name
);
240 if ((i
>= 5) && strcmp (&target_name
[i
- 4], NTXT (".jar")) == 0)
242 // could be a jar file
243 // XXXX -- need better check for real jar file
244 cc
->set_java_mode ("on");
247 if ((i
>= 7) && strcmp (&target_name
[i
- 6], NTXT (".class")) == 0)
249 // could be a class file
250 // XXXX -- need better check for real class file
251 cc
->set_java_mode (NTXT ("on"));
252 return EXEC_IS_CLASSCLASS
;
254 // not a jar or class file, return not an executable
255 return EXEC_NOT_EXEC
;
257 else // found, and it is executable. set the path to it
258 snprintf (target_path
, sizeof (target_path
), NTXT ("%s"), target_name
);
262 // not found, look on path
263 char *exe_name
= get_realpath (target_name
);
264 if (access (exe_name
, X_OK
) == 0)
266 // target can't be located
267 // one last attempt: append .class to name, and see if we can find it
268 snprintf (target_path
, sizeof (target_path
), NTXT ("%s.class"), target_name
);
269 if (dbe_stat (target_path
, &statbuf
) == 0)
272 if ((statbuf
.st_mode
& S_IFMT
) == S_IFDIR
)
274 // this is a directory; that won't do.
277 // say it's a class file
278 cc
->set_java_mode (NTXT ("on"));
279 return EXEC_IS_CLASS
;
281 return EXEC_NOT_FOUND
;
283 snprintf (target_path
, sizeof (target_path
), NTXT ("%s"), exe_name
);
287 // target_path is now the purported executable
288 // check for ELF library out of date
289 if (Elf::elf_version (EV_CURRENT
) == EV_NONE
)
291 Elf
*elf
= Elf::elf_begin (target_path
);
294 // do not by pass checking architectural match
295 collect::Exec_status exec_stat
= check_executable_arch (elf
);
296 if (exec_stat
!= EXEC_OK
)
306 collect::check_executable_arch (Elf
*elf
)
308 Elf_Internal_Ehdr
*ehdrp
= elf
->elf_getehdr ();
310 return EXEC_ELF_HEADER
;
311 unsigned short machine
= ehdrp
->e_machine
;
326 // now figure out if the platform can run it
327 struct utsname unbuf
;
328 int r
= uname (&unbuf
);
329 if (r
== 0 && unbuf
.machine
&& strstr (unbuf
.machine
, "_64") == NULL
)
330 // machine can not run 64 bits, but this code is 64-bit
331 return EXEC_ELF_ARCH
;
342 return EXEC_ELF_ARCH
;
345 // now check if target was built with shared libraries
347 for (unsigned cnt
= 0; cnt
< ehdrp
->e_phnum
; cnt
++)
349 Elf_Internal_Phdr
*phdrp
= elf
->get_phdr (cnt
);
350 if (phdrp
&& phdrp
->p_type
== PT_DYNAMIC
)
358 // target is not a dynamic executable or shared object;
360 return EXEC_ELF_NOSHARE
;
366 collect::status_str (Exec_status rv
, char *target_name
)
373 case EXEC_IS_CLASSCLASS
:
374 // supported flavors -- no error message
376 case EXEC_ELF_NOSHARE
:
377 return dbe_sprintf (GTXT ("Target executable `%s' must be built with shared libraries\n"), target_name
);
379 return dbe_sprintf (GTXT ("Can't open target executable `%s'\n"), target_name
);
381 return strdup (GTXT ("Internal error: Not a working version of ELF library\n"));
382 case EXEC_ELF_HEADER
:
383 return dbe_sprintf (GTXT ("Target `%s' is not a valid ELF executable\n"), target_name
);
385 return dbe_sprintf (GTXT ("Target architecture of executable `%s' is not supported on this machine\n"), target_name
);
387 return dbe_sprintf (GTXT ("Target `%s' is a directory, not an executable\n"), target_name
);
389 return dbe_sprintf (GTXT ("Target `%s' is not executable\n"), target_name
);
391 return dbe_sprintf (GTXT ("Target `%s' not found\n"), target_name
);
397 collect::find_java (void)
399 char buf
[MAXPATHLEN
];
401 Exec_status rv
= EXEC_OK
;
403 // first see if the user entered a -j argument
404 var
= cc
->get_java_path ();
407 snprintf (buf
, sizeof (buf
), NTXT ("%s/bin/java"), var
);
408 java_how
= NTXT ("-j");
409 rv
= check_executable (buf
);
412 if (java_how
== NULL
)
414 var
= getenv (NTXT ("JDK_HOME"));
415 if ((var
!= NULL
) && (strlen (var
) > 0))
417 snprintf (buf
, sizeof (buf
), NTXT ("%s/bin/java"), var
);
418 java_how
= NTXT ("JDK_HOME");
419 rv
= check_executable (buf
);
422 // then try JAVA_PATH
423 if (java_how
== NULL
)
425 var
= getenv (NTXT ("JAVA_PATH"));
426 if ((var
!= NULL
) && (strlen (var
) > 0))
428 snprintf (buf
, sizeof (buf
), NTXT ("%s/bin/java"), var
);
429 java_how
= NTXT ("JAVA_PATH");
430 rv
= check_executable (buf
);
433 // try the user's path
434 if (java_how
== NULL
)
436 snprintf (buf
, sizeof (buf
), NTXT ("java"));
437 rv
= check_executable (buf
);
439 java_how
= NTXT ("PATH");
441 // finally, just try /usr/java -- system default
442 if (java_how
== NULL
)
444 snprintf (buf
, sizeof (buf
), NTXT ("/usr/java/bin/java"));
445 rv
= check_executable (buf
);
446 java_how
= NTXT ("/usr/java/bin/java");
449 // we now have a nominal path to java, and how we chose it
450 // and we have rv set to the check_executable return
454 java_path
= strdup (buf
);
456 dbe_write (2, GTXT ("Path to `%s' (set from %s) used for Java profiling\n"),
457 java_path
, java_how
);
458 return ( strdup (buf
));
460 dbe_write (2, GTXT ("Path to `%s' (set from %s) does not point to a JVM executable\n"),
468 collect::validate_config (int how
)
470 if (getenv (NTXT ("GPROFNG_SKIP_VALIDATION")) != NULL
)
472 char *cmd
= dbe_sprintf (NTXT ("%s/perftools_validate"), run_dir
);
473 if (access (cmd
, X_OK
) != 0)
476 dbe_write (2, GTXT ("WARNING: Unable to validate system: `%s' could not be executed\n"), cmd
);
479 char *quiet
= how
== 0 ? NTXT ("") : NTXT ("-q"); // check collection, verbosely
481 if (cc
->get_java_default () == 0 && java_path
)
482 buf
= dbe_sprintf (NTXT ("%s -c -j %s -H \"%s\" %s"), cmd
, java_path
, java_how
, quiet
);
483 else // not java mode -- don't check the java version
484 buf
= dbe_sprintf (NTXT ("%s -c %s"), cmd
, quiet
);
487 /* now run the command */
488 int ret
= system (buf
);
489 int status
= WEXITSTATUS (ret
);
490 if ((status
& 0x1) != 0)
491 dbe_write (2, GTXT ("WARNING: Data collection may fail: system is not properly configured or is unsupported.\n"));
492 if ((status
& 0x2) != 0)
493 dbe_write (2, GTXT ("WARNING: Java data collection may fail: J2SE[tm] version is unsupported.\n"));
498 collect::validate_java (const char *jvm
, const char *jhow
, int q
)
500 char *cmd
= dbe_sprintf (NTXT ("%s/perftools_ckjava"), run_dir
);
501 if (access (cmd
, X_OK
) != 0)
503 dbe_write (2, GTXT ("WARNING: Unable to validate Java: `%s' could not be executed\n"), cmd
);
506 char *buf
= dbe_sprintf (NTXT ("%s -j %s -H \"%s\" %s"), cmd
, jvm
, jhow
,
507 (q
== 1 ? "-q" : ""));
510 /* now run the command */
511 int ret
= system (buf
);
512 int status
= WEXITSTATUS (ret
);
514 dbe_write (2, GTXT ("WARNING: Java data collection may fail: J2SE[tm] version is unsupported.\n"));