LCOV - code coverage report
Current view: top level - gcc - collect-utils.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 58 90 64.4 %
Date: 2020-04-04 11:58:09 Functions: 5 7 71.4 %
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-2020 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                 :            : 
      38                 :            : 
      39                 :            : /* Notify user of a non-error.  */
      40                 :            : void
      41                 :          0 : notice (const char *cmsgid, ...)
      42                 :            : {
      43                 :          0 :   va_list ap;
      44                 :            : 
      45                 :          0 :   va_start (ap, cmsgid);
      46                 :          0 :   vfprintf (stderr, _(cmsgid), ap);
      47                 :          0 :   va_end (ap);
      48                 :          0 : }
      49                 :            : 
      50                 :            : void
      51                 :          0 : fatal_signal (int signum)
      52                 :            : {
      53                 :          0 :   signal (signum, SIG_DFL);
      54                 :          0 :   utils_cleanup (true);
      55                 :            :   /* Get the same signal again, this time not handled,
      56                 :            :      so its normal effect occurs.  */
      57                 :          0 :   kill (getpid (), signum);
      58                 :          0 : }
      59                 :            : 
      60                 :            : /* Wait for a process to finish, and exit if a nonzero status is found.  */
      61                 :            : 
      62                 :            : int
      63                 :      93049 : collect_wait (const char *prog, struct pex_obj *pex)
      64                 :            : {
      65                 :      93049 :   int status;
      66                 :            : 
      67                 :      93049 :   if (!pex_get_status (pex, 1, &status))
      68                 :          0 :     fatal_error (input_location, "cannot get program status: %m");
      69                 :      93049 :   pex_free (pex);
      70                 :            : 
      71                 :      93049 :   if (response_file && !save_temps)
      72                 :            :     {
      73                 :      13967 :       unlink (response_file);
      74                 :      13967 :       response_file = NULL;
      75                 :            :     }
      76                 :            : 
      77                 :      93049 :   if (status)
      78                 :            :     {
      79                 :        127 :       if (WIFSIGNALED (status))
      80                 :            :         {
      81                 :          0 :           int sig = WTERMSIG (status);
      82                 :          0 :           fatal_error (input_location, "%s terminated with signal %d [%s]%s",
      83                 :            :                        prog, sig, strsignal (sig),
      84                 :          0 :                        WCOREDUMP (status) ? ", core dumped" : "");
      85                 :            :         }
      86                 :            : 
      87                 :        127 :       if (WIFEXITED (status))
      88                 :        127 :         return WEXITSTATUS (status);
      89                 :            :     }
      90                 :            :   return 0;
      91                 :            : }
      92                 :            : 
      93                 :            : void
      94                 :      21141 : do_wait (const char *prog, struct pex_obj *pex)
      95                 :            : {
      96                 :      21141 :   int ret = collect_wait (prog, pex);
      97                 :      21141 :   if (ret != 0)
      98                 :          0 :     fatal_error (input_location, "%s returned %d exit status", prog, ret);
      99                 :      21141 : }
     100                 :            : 
     101                 :            : 
     102                 :            : /* Execute a program, and wait for the reply.  */
     103                 :            : 
     104                 :            : struct pex_obj *
     105                 :      93049 : collect_execute (const char *prog, char **argv, const char *outname,
     106                 :            :                  const char *errname, int flags, bool use_atfile)
     107                 :            : {
     108                 :      93049 :   struct pex_obj *pex;
     109                 :      93049 :   const char *errmsg;
     110                 :      93049 :   int err;
     111                 :      93049 :   char *response_arg = NULL;
     112                 :      93049 :   char *response_argv[3];
     113                 :            : 
     114                 :      93049 :   if (use_atfile && argv[0] != NULL)
     115                 :            :     {
     116                 :            :       /* If using @file arguments, create a temporary file and put the
     117                 :            :          contents of argv into it.  Then change argv to an array corresponding
     118                 :            :          to a single argument @FILE, where FILE is the temporary filename.  */
     119                 :            : 
     120                 :      13969 :       char **current_argv = argv + 1;
     121                 :      13969 :       char *argv0 = argv[0];
     122                 :      13969 :       int status;
     123                 :      13969 :       FILE *f;
     124                 :            : 
     125                 :            :       /* Note: we assume argv contains at least one element; this is
     126                 :            :          checked above.  */
     127                 :            : 
     128                 :      13969 :       response_file = make_temp_file ("");
     129                 :            : 
     130                 :      13969 :       f = fopen (response_file, "w");
     131                 :            : 
     132                 :      13969 :       if (f == NULL)
     133                 :          0 :         fatal_error (input_location, "could not open response file %s",
     134                 :            :                      response_file);
     135                 :            : 
     136                 :      13969 :       status = writeargv (current_argv, f);
     137                 :            : 
     138                 :      13969 :       if (status)
     139                 :          0 :         fatal_error (input_location, "could not write to response file %s",
     140                 :            :                      response_file);
     141                 :            : 
     142                 :      13969 :       status = fclose (f);
     143                 :            : 
     144                 :      13969 :       if (EOF == status)
     145                 :          0 :         fatal_error (input_location, "could not close response file %s",
     146                 :            :                      response_file);
     147                 :            : 
     148                 :      13969 :       response_arg = concat ("@", response_file, NULL);
     149                 :      13969 :       response_argv[0] = argv0;
     150                 :      13969 :       response_argv[1] = response_arg;
     151                 :      13969 :       response_argv[2] = NULL;
     152                 :            : 
     153                 :      13969 :       argv = response_argv;
     154                 :            :     }
     155                 :            : 
     156                 :      93049 :   if (verbose || debug)
     157                 :            :     {
     158                 :          0 :       char **p_argv;
     159                 :          0 :       const char *str;
     160                 :            : 
     161                 :          0 :       if (argv[0])
     162                 :          0 :         fprintf (stderr, "%s", argv[0]);
     163                 :            :       else
     164                 :          0 :         notice ("[cannot find %s]", prog);
     165                 :            : 
     166                 :          0 :       for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++)
     167                 :          0 :         fprintf (stderr, " %s", str);
     168                 :            : 
     169                 :          0 :       fprintf (stderr, "\n");
     170                 :            :     }
     171                 :            : 
     172                 :      93049 :   fflush (stdout);
     173                 :      93049 :   fflush (stderr);
     174                 :            : 
     175                 :            :   /* If we cannot find a program we need, complain error.  Do this here
     176                 :            :      since we might not end up needing something that we could not find.  */
     177                 :            : 
     178                 :      93049 :   if (argv[0] == 0)
     179                 :          0 :     fatal_error (input_location, "cannot find %qs", prog);
     180                 :            : 
     181                 :      93049 :   pex = pex_init (0, "collect2", NULL);
     182                 :      93049 :   if (pex == NULL)
     183                 :            :     fatal_error (input_location, "%<pex_init%> failed: %m");
     184                 :            : 
     185                 :      93049 :   errmsg = pex_run (pex, flags, argv[0], argv, outname,
     186                 :            :                     errname, &err);
     187                 :      93049 :   if (errmsg != NULL)
     188                 :            :     {
     189                 :          0 :       if (err != 0)
     190                 :            :         {
     191                 :          0 :           errno = err;
     192                 :          0 :           fatal_error (input_location, "%s: %m", _(errmsg));
     193                 :            :         }
     194                 :            :       else
     195                 :          0 :         fatal_error (input_location, errmsg);
     196                 :            :     }
     197                 :            : 
     198                 :      93049 :   free (response_arg);
     199                 :            : 
     200                 :      93049 :   return pex;
     201                 :            : }
     202                 :            : 
     203                 :            : void
     204                 :      17546 : fork_execute (const char *prog, char **argv, bool use_atfile)
     205                 :            : {
     206                 :      17546 :   struct pex_obj *pex;
     207                 :            : 
     208                 :      17546 :   pex = collect_execute (prog, argv, NULL, NULL,
     209                 :            :                          PEX_LAST | PEX_SEARCH, use_atfile);
     210                 :      17546 :   do_wait (prog, pex);
     211                 :      17546 : }
     212                 :            : 
     213                 :            : /* Delete tempfiles.  */
     214                 :            : 
     215                 :            : void
     216                 :       8631 : utils_cleanup (bool from_signal)
     217                 :            : {
     218                 :       8631 :   static bool cleanup_done = false;
     219                 :            : 
     220                 :       8631 :   if (cleanup_done)
     221                 :            :     return;
     222                 :            : 
     223                 :            :   /* Setting cleanup_done prevents an infinite loop if one of the
     224                 :            :      calls to maybe_unlink fails. */
     225                 :       8631 :   cleanup_done = true;
     226                 :            : 
     227                 :       8631 :   tool_cleanup (from_signal);
     228                 :            : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.