LCOV - code coverage report
Current view: top level - gcc - collect-utils.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 71.2 % 111 79
Test Date: 2024-12-21 13:15:12 Functions: 75.0 % 8 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Utility functions used by tools like collect2 and lto-wrapper.
       2                 :             :    Copyright (C) 2009-2024 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : #include "config.h"
      21                 :             : #include "system.h"
      22                 :             : #include "coretypes.h"
      23                 :             : #include "intl.h"
      24                 :             : #include "diagnostic.h"
      25                 :             : #include "obstack.h"
      26                 :             : #include "opts.h"
      27                 :             : #include "options.h"
      28                 :             : #include "simple-object.h"
      29                 :             : #include "lto-section-names.h"
      30                 :             : #include "collect-utils.h"
      31                 :             : 
      32                 :             : static char *response_file;
      33                 :             : 
      34                 :             : bool debug;
      35                 :             : bool verbose;
      36                 :             : bool save_temps;
      37                 :             : const char *dumppfx;
      38                 :             : 
      39                 :             : 
      40                 :             : /* Notify user of a non-error.  */
      41                 :             : void
      42                 :           0 : notice (const char *cmsgid, ...)
      43                 :             : {
      44                 :           0 :   va_list ap;
      45                 :             : 
      46                 :           0 :   va_start (ap, cmsgid);
      47                 :           0 :   vfprintf (stderr, _(cmsgid), ap);
      48                 :           0 :   va_end (ap);
      49                 :           0 : }
      50                 :             : 
      51                 :             : void
      52                 :           0 : fatal_signal (int signum)
      53                 :             : {
      54                 :           0 :   signal (signum, SIG_DFL);
      55                 :           0 :   utils_cleanup (true);
      56                 :             :   /* Get the same signal again, this time not handled,
      57                 :             :      so its normal effect occurs.  */
      58                 :           0 :   kill (getpid (), signum);
      59                 :           0 : }
      60                 :             : 
      61                 :             : /* Setup the signal handlers for the utils. */
      62                 :             : void
      63                 :      105687 : setup_signals (void)
      64                 :             : {
      65                 :             : #ifdef SIGQUIT
      66                 :      105687 :   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
      67                 :      105687 :     signal (SIGQUIT, fatal_signal);
      68                 :             : #endif
      69                 :      105687 :   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
      70                 :      105682 :     signal (SIGINT, fatal_signal);
      71                 :             : #ifdef SIGALRM
      72                 :      105687 :   if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
      73                 :      105687 :     signal (SIGALRM, fatal_signal);
      74                 :             : #endif
      75                 :             : #ifdef SIGHUP
      76                 :      105687 :   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
      77                 :        2423 :     signal (SIGHUP, fatal_signal);
      78                 :             : #endif
      79                 :      105687 :   if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
      80                 :      105687 :     signal (SIGSEGV, fatal_signal);
      81                 :      105687 :   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
      82                 :      105687 :     signal (SIGTERM, fatal_signal);
      83                 :             : #ifdef SIGPIPE
      84                 :      105687 :   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
      85                 :      105687 :     signal (SIGPIPE, fatal_signal);
      86                 :             : #endif
      87                 :             : #ifdef SIGBUS
      88                 :      105687 :   if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
      89                 :      105687 :     signal (SIGBUS, fatal_signal);
      90                 :             : #endif
      91                 :             : #ifdef SIGCHLD
      92                 :             :   /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
      93                 :             :      receive the signal.  A different setting is inheritable */
      94                 :      105687 :   signal (SIGCHLD, SIG_DFL);
      95                 :             : #endif
      96                 :      105687 : }
      97                 :             : 
      98                 :             : /* Wait for a process to finish, and exit if a nonzero status is found.  */
      99                 :             : 
     100                 :             : int
     101                 :      122850 : collect_wait (const char *prog, struct pex_obj *pex)
     102                 :             : {
     103                 :      122850 :   int status;
     104                 :             : 
     105                 :      122850 :   if (!pex_get_status (pex, 1, &status))
     106                 :           0 :     fatal_error (input_location, "cannot get program status: %m");
     107                 :      122850 :   pex_free (pex);
     108                 :             : 
     109                 :      122850 :   if (response_file && !save_temps)
     110                 :             :     {
     111                 :       13073 :       unlink (response_file);
     112                 :       13073 :       response_file = NULL;
     113                 :             :     }
     114                 :             : 
     115                 :      122850 :   if (status)
     116                 :             :     {
     117                 :         124 :       if (WIFSIGNALED (status))
     118                 :             :         {
     119                 :           0 :           int sig = WTERMSIG (status);
     120                 :           0 :           fatal_error (input_location, "%s terminated with signal %d [%s]%s",
     121                 :             :                        prog, sig, strsignal (sig),
     122                 :           0 :                        WCOREDUMP (status) ? ", core dumped" : "");
     123                 :             :         }
     124                 :             : 
     125                 :         124 :       if (WIFEXITED (status))
     126                 :         124 :         return WEXITSTATUS (status);
     127                 :             :     }
     128                 :             :   return 0;
     129                 :             : }
     130                 :             : 
     131                 :             : void
     132                 :       30189 : do_wait (const char *prog, struct pex_obj *pex)
     133                 :             : {
     134                 :       30189 :   int ret = collect_wait (prog, pex);
     135                 :       30189 :   if (ret != 0)
     136                 :           0 :     fatal_error (input_location, "%s returned %d exit status", prog, ret);
     137                 :       30189 : }
     138                 :             : 
     139                 :             : 
     140                 :             : /* Execute a program, and wait for the reply.  */
     141                 :             : 
     142                 :             : struct pex_obj *
     143                 :      122850 : collect_execute (const char *prog, char **argv, const char *outname,
     144                 :             :                  const char *errname, int flags, bool use_atfile,
     145                 :             :                  const char *atsuffix)
     146                 :             : {
     147                 :      122850 :   struct pex_obj *pex;
     148                 :      122850 :   const char *errmsg;
     149                 :      122850 :   int err;
     150                 :      122850 :   char *response_arg = NULL;
     151                 :      122850 :   char *response_argv[3];
     152                 :             : 
     153                 :      122850 :   if (use_atfile && argv[0] != NULL)
     154                 :             :     {
     155                 :             :       /* If using @file arguments, create a temporary file and put the
     156                 :             :          contents of argv into it.  Then change argv to an array corresponding
     157                 :             :          to a single argument @FILE, where FILE is the temporary filename.  */
     158                 :             : 
     159                 :       13112 :       char **current_argv = argv + 1;
     160                 :       13112 :       char *argv0 = argv[0];
     161                 :       13112 :       int status;
     162                 :       13112 :       FILE *f;
     163                 :             : 
     164                 :             :       /* Note: we assume argv contains at least one element; this is
     165                 :             :          checked above.  */
     166                 :             : 
     167                 :       13112 :       if (!save_temps || !atsuffix || !dumppfx)
     168                 :       13073 :         response_file = make_temp_file ("");
     169                 :             :       else
     170                 :          39 :         response_file = concat (dumppfx, atsuffix, NULL);
     171                 :             : 
     172                 :       13112 :       f = fopen (response_file, "w");
     173                 :             : 
     174                 :       13112 :       if (f == NULL)
     175                 :           0 :         fatal_error (input_location, "could not open response file %s",
     176                 :             :                      response_file);
     177                 :             : 
     178                 :       13112 :       status = writeargv (current_argv, f);
     179                 :             : 
     180                 :       13112 :       if (status)
     181                 :           0 :         fatal_error (input_location, "could not write to response file %s",
     182                 :             :                      response_file);
     183                 :             : 
     184                 :       13112 :       status = fclose (f);
     185                 :             : 
     186                 :       13112 :       if (EOF == status)
     187                 :           0 :         fatal_error (input_location, "could not close response file %s",
     188                 :             :                      response_file);
     189                 :             : 
     190                 :       13112 :       response_arg = concat ("@", response_file, NULL);
     191                 :       13112 :       response_argv[0] = argv0;
     192                 :       13112 :       response_argv[1] = response_arg;
     193                 :       13112 :       response_argv[2] = NULL;
     194                 :             : 
     195                 :       13112 :       argv = response_argv;
     196                 :             :     }
     197                 :             : 
     198                 :      122850 :   if (verbose || debug)
     199                 :             :     {
     200                 :           0 :       char **p_argv;
     201                 :           0 :       const char *str;
     202                 :             : 
     203                 :           0 :       if (argv[0])
     204                 :           0 :         fprintf (stderr, "%s", argv[0]);
     205                 :             :       else
     206                 :           0 :         notice ("[cannot find %s]", prog);
     207                 :             : 
     208                 :           0 :       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
     209                 :           0 :         fprintf (stderr, " %s", str);
     210                 :             : 
     211                 :           0 :       fprintf (stderr, "\n");
     212                 :             :     }
     213                 :             : 
     214                 :      122850 :   fflush (stdout);
     215                 :      122850 :   fflush (stderr);
     216                 :             : 
     217                 :             :   /* If we cannot find a program we need, complain error.  Do this here
     218                 :             :      since we might not end up needing something that we could not find.  */
     219                 :             : 
     220                 :      122850 :   if (argv[0] == 0)
     221                 :           0 :     fatal_error (input_location, "cannot find %qs", prog);
     222                 :             : 
     223                 :      122850 :   pex = pex_init (0, "collect2", NULL);
     224                 :      122850 :   if (pex == NULL)
     225                 :             :     fatal_error (input_location, "%<pex_init%> failed: %m");
     226                 :             : 
     227                 :      122850 :   errmsg = pex_run (pex, flags, argv[0], argv, outname,
     228                 :             :                     errname, &err);
     229                 :      122850 :   if (errmsg != NULL)
     230                 :             :     {
     231                 :           0 :       if (err != 0)
     232                 :             :         {
     233                 :           0 :           errno = err;
     234                 :           0 :           fatal_error (input_location, "%s: %m", _(errmsg));
     235                 :             :         }
     236                 :             :       else
     237                 :           0 :         fatal_error (input_location, errmsg);
     238                 :             :     }
     239                 :             : 
     240                 :      122850 :   free (response_arg);
     241                 :             : 
     242                 :      122850 :   return pex;
     243                 :             : }
     244                 :             : 
     245                 :             : void
     246                 :       17269 : fork_execute (const char *prog, char **argv, bool use_atfile,
     247                 :             :               const char *atsuffix)
     248                 :             : {
     249                 :       17269 :   struct pex_obj *pex;
     250                 :             : 
     251                 :       17269 :   pex = collect_execute (prog, argv, NULL, NULL,
     252                 :             :                          PEX_LAST | PEX_SEARCH, use_atfile, atsuffix);
     253                 :       17269 :   do_wait (prog, pex);
     254                 :       17269 : }
     255                 :             : 
     256                 :             : /* Delete tempfiles.  */
     257                 :             : 
     258                 :             : void
     259                 :       13026 : utils_cleanup (bool from_signal)
     260                 :             : {
     261                 :       13026 :   static bool cleanup_done = false;
     262                 :             : 
     263                 :       13026 :   if (cleanup_done)
     264                 :             :     return;
     265                 :             : 
     266                 :             :   /* Setting cleanup_done prevents an infinite loop if one of the
     267                 :             :      calls to maybe_unlink fails. */
     268                 :       13026 :   cleanup_done = true;
     269                 :             : 
     270                 :       13026 :   tool_cleanup (from_signal);
     271                 :             : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.