LCOV - code coverage report
Current view: top level - gcc - gcov-io.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 180 206 87.4 %
Date: 2020-03-28 11:57:23 Functions: 24 28 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* File format for coverage information
       2                 :            :    Copyright (C) 1996-2020 Free Software Foundation, Inc.
       3                 :            :    Contributed by Bob Manson <manson@cygnus.com>.
       4                 :            :    Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
       5                 :            : 
       6                 :            : This file is part of GCC.
       7                 :            : 
       8                 :            : GCC is free software; you can redistribute it and/or modify it under
       9                 :            : the terms of the GNU General Public License as published by the Free
      10                 :            : Software Foundation; either version 3, or (at your option) any later
      11                 :            : version.
      12                 :            : 
      13                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16                 :            : for more details.
      17                 :            : 
      18                 :            : Under Section 7 of GPL version 3, you are granted additional
      19                 :            : permissions described in the GCC Runtime Library Exception, version
      20                 :            : 3.1, as published by the Free Software Foundation.
      21                 :            : 
      22                 :            : You should have received a copy of the GNU General Public License and
      23                 :            : a copy of the GCC Runtime Library Exception along with this program;
      24                 :            : see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      25                 :            : <http://www.gnu.org/licenses/>.  */
      26                 :            : 
      27                 :            : /* Routines declared in gcov-io.h.  This file should be #included by
      28                 :            :    another source file, after having #included gcov-io.h.  */
      29                 :            : 
      30                 :            : #if !IN_GCOV
      31                 :            : static void gcov_write_block (unsigned);
      32                 :            : static gcov_unsigned_t *gcov_write_words (unsigned);
      33                 :            : #endif
      34                 :            : static const gcov_unsigned_t *gcov_read_words (unsigned);
      35                 :            : #if !IN_LIBGCOV
      36                 :            : static void gcov_allocate (unsigned);
      37                 :            : #endif
      38                 :            : 
      39                 :            : /* Optimum number of gcov_unsigned_t's read from or written to disk.  */
      40                 :            : #define GCOV_BLOCK_SIZE (1 << 10)
      41                 :            : 
      42                 :            : struct gcov_var
      43                 :            : {
      44                 :            :   FILE *file;
      45                 :            :   gcov_position_t start;        /* Position of first byte of block */
      46                 :            :   unsigned offset;              /* Read/write position within the block.  */
      47                 :            :   unsigned length;              /* Read limit in the block.  */
      48                 :            :   unsigned overread;            /* Number of words overread.  */
      49                 :            :   int error;                    /* < 0 overflow, > 0 disk error.  */
      50                 :            :   int mode;                     /* < 0 writing, > 0 reading */
      51                 :            : #if IN_LIBGCOV
      52                 :            :   /* Holds one block plus 4 bytes, thus all coverage reads & writes
      53                 :            :      fit within this buffer and we always can transfer GCOV_BLOCK_SIZE
      54                 :            :      to and from the disk. libgcov never backtracks and only writes 4
      55                 :            :      or 8 byte objects.  */
      56                 :            :   gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1];
      57                 :            : #else
      58                 :            :   int endian;                   /* Swap endianness.  */
      59                 :            :   /* Holds a variable length block, as the compiler can write
      60                 :            :      strings and needs to backtrack.  */
      61                 :            :   size_t alloc;
      62                 :            :   gcov_unsigned_t *buffer;
      63                 :            : #endif
      64                 :            : } gcov_var;
      65                 :            : 
      66                 :            : /* Save the current position in the gcov file.  */
      67                 :            : /* We need to expose this function when compiling for gcov-tool.  */
      68                 :            : #ifndef IN_GCOV_TOOL
      69                 :            : static inline
      70                 :            : #endif
      71                 :            : gcov_position_t
      72                 :      11340 : gcov_position (void)
      73                 :            : {
      74                 :      11340 :   gcov_nonruntime_assert (gcov_var.mode > 0); 
      75                 :      11340 :   return gcov_var.start + gcov_var.offset;
      76                 :            : }
      77                 :            : 
      78                 :            : /* Return nonzero if the error flag is set.  */
      79                 :            : /* We need to expose this function when compiling for gcov-tool.  */
      80                 :            : #ifndef IN_GCOV_TOOL
      81                 :            : static inline
      82                 :            : #endif
      83                 :            : int
      84                 :      12794 : gcov_is_error (void)
      85                 :            : {
      86                 :      12794 :   return gcov_var.file ? gcov_var.error : 1;
      87                 :            : }
      88                 :            : 
      89                 :            : #if IN_LIBGCOV
      90                 :            : /* Move to beginning of file and initialize for writing.  */
      91                 :            : GCOV_LINKAGE inline void
      92                 :            : gcov_rewrite (void)
      93                 :            : {
      94                 :            :   gcov_var.mode = -1; 
      95                 :            :   gcov_var.start = 0;
      96                 :            :   gcov_var.offset = 0;
      97                 :            :   fseek (gcov_var.file, 0L, SEEK_SET);
      98                 :            : }
      99                 :            : #endif
     100                 :            : 
     101                 :      80776 : static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
     102                 :            : {
     103                 :            : #if !IN_LIBGCOV
     104                 :      80776 :   if (gcov_var.endian)
     105                 :            :     {
     106                 :          0 :       value = (value >> 16) | (value << 16);
     107                 :          0 :       value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff);
     108                 :            :     }
     109                 :            : #endif
     110                 :       9970 :   return value;
     111                 :            : }
     112                 :            : 
     113                 :            : /* Open a gcov file. NAME is the name of the file to open and MODE
     114                 :            :    indicates whether a new file should be created, or an existing file
     115                 :            :    opened. If MODE is >= 0 an existing file will be opened, if
     116                 :            :    possible, and if MODE is <= 0, a new file will be created. Use
     117                 :            :    MODE=0 to attempt to reopen an existing file and then fall back on
     118                 :            :    creating a new one.  If MODE > 0, the file will be opened in
     119                 :            :    read-only mode.  Otherwise it will be opened for modification.
     120                 :            :    Return zero on failure, non-zero on success.  */
     121                 :            : 
     122                 :            : GCOV_LINKAGE int
     123                 :            : #if IN_LIBGCOV
     124                 :            : gcov_open (const char *name)
     125                 :            : #else
     126                 :        539 : gcov_open (const char *name, int mode)
     127                 :            : #endif
     128                 :            : {
     129                 :            : #if IN_LIBGCOV
     130                 :            :   int mode = 0;
     131                 :            : #endif
     132                 :            : #if GCOV_LOCKED
     133                 :        539 :   struct flock s_flock;
     134                 :        539 :   int fd;
     135                 :            : 
     136                 :        539 :   s_flock.l_whence = SEEK_SET;
     137                 :        539 :   s_flock.l_start = 0;
     138                 :        539 :   s_flock.l_len = 0; /* Until EOF.  */
     139                 :        539 :   s_flock.l_pid = getpid ();
     140                 :            : #endif
     141                 :            : 
     142                 :        539 :   gcov_nonruntime_assert (!gcov_var.file);
     143                 :        539 :   gcov_var.start = 0;
     144                 :        539 :   gcov_var.offset = gcov_var.length = 0;
     145                 :        539 :   gcov_var.overread = -1u;
     146                 :        539 :   gcov_var.error = 0;
     147                 :            : #if !IN_LIBGCOV
     148                 :        539 :   gcov_var.endian = 0;
     149                 :            : #endif
     150                 :            : #if GCOV_LOCKED
     151                 :        539 :   if (mode > 0)
     152                 :            :     {
     153                 :            :       /* Read-only mode - acquire a read-lock.  */
     154                 :        397 :       s_flock.l_type = F_RDLCK;
     155                 :            :       /* pass mode (ignored) for compatibility */
     156                 :        397 :       fd = open (name, O_RDONLY, S_IRUSR | S_IWUSR);
     157                 :            :     }
     158                 :            :   else
     159                 :            :      {
     160                 :            :        /* Write mode - acquire a write-lock.  */
     161                 :        142 :        s_flock.l_type = F_WRLCK;
     162                 :            :        /* Truncate if force new mode.  */
     163                 :        142 :        fd = open (name, O_RDWR | O_CREAT | (mode < 0 ? O_TRUNC : 0), 0666);
     164                 :            :     }
     165                 :        539 :   if (fd < 0)
     166                 :            :     return 0;
     167                 :            : 
     168                 :        493 :   while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR)
     169                 :          0 :     continue;
     170                 :            : 
     171                 :        635 :   gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b");
     172                 :            : 
     173                 :        493 :   if (!gcov_var.file)
     174                 :            :     {
     175                 :          0 :       close (fd);
     176                 :          0 :       return 0;
     177                 :            :     }
     178                 :            : #else
     179                 :            :   if (mode >= 0)
     180                 :            :     /* Open an existing file.  */
     181                 :            :     gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b");
     182                 :            : 
     183                 :            :   if (gcov_var.file)
     184                 :            :     mode = 1;
     185                 :            :   else if (mode <= 0)
     186                 :            :     /* Create a new file.  */
     187                 :            :     gcov_var.file = fopen (name, "w+b");
     188                 :            : 
     189                 :            :   if (!gcov_var.file)
     190                 :            :     return 0;
     191                 :            : #endif
     192                 :            : 
     193                 :        493 :   gcov_var.mode = mode ? mode : 1;
     194                 :            : 
     195                 :        493 :   setbuf (gcov_var.file, (char *)0);
     196                 :            : 
     197                 :        493 :   return 1;
     198                 :            : }
     199                 :            : 
     200                 :            : /* Close the current gcov file. Flushes data to disk. Returns nonzero
     201                 :            :    on failure or error flag set.  */
     202                 :            : 
     203                 :            : GCOV_LINKAGE int
     204                 :        493 : gcov_close (void)
     205                 :            : {
     206                 :        493 :   if (gcov_var.file)
     207                 :            :     {
     208                 :            : #if !IN_GCOV
     209                 :        244 :       if (gcov_var.offset && gcov_var.mode < 0)
     210                 :        138 :         gcov_write_block (gcov_var.offset);
     211                 :            : #endif
     212                 :        493 :       fclose (gcov_var.file);
     213                 :        493 :       gcov_var.file = 0;
     214                 :        493 :       gcov_var.length = 0;
     215                 :            :     }
     216                 :            : #if !IN_LIBGCOV
     217                 :        493 :   free (gcov_var.buffer);
     218                 :        493 :   gcov_var.alloc = 0;
     219                 :        493 :   gcov_var.buffer = 0;
     220                 :            : #endif
     221                 :        493 :   gcov_var.mode = 0;
     222                 :        493 :   return gcov_var.error;
     223                 :            : }
     224                 :            : 
     225                 :            : #if !IN_LIBGCOV
     226                 :            : /* Check if MAGIC is EXPECTED. Use it to determine endianness of the
     227                 :            :    file. Returns +1 for same endian, -1 for other endian and zero for
     228                 :            :    not EXPECTED.  */
     229                 :            : 
     230                 :            : GCOV_LINKAGE int
     231                 :        351 : gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected)
     232                 :            : {
     233                 :        351 :   if (magic == expected)
     234                 :            :     return 1;
     235                 :          0 :   magic = (magic >> 16) | (magic << 16);
     236                 :          0 :   magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff);
     237                 :          0 :   if (magic == expected)
     238                 :            :     {
     239                 :          0 :       gcov_var.endian = 1;
     240                 :          0 :       return -1;
     241                 :            :     }
     242                 :            :   return 0;
     243                 :            : }
     244                 :            : #endif
     245                 :            : 
     246                 :            : #if !IN_LIBGCOV
     247                 :            : static void
     248                 :        493 : gcov_allocate (unsigned length)
     249                 :            : {
     250                 :        493 :   size_t new_size = gcov_var.alloc;
     251                 :            : 
     252                 :        493 :   if (!new_size)
     253                 :        493 :     new_size = GCOV_BLOCK_SIZE;
     254                 :        493 :   new_size += length;
     255                 :        493 :   new_size *= 2;
     256                 :            : 
     257                 :        493 :   gcov_var.alloc = new_size;
     258                 :        493 :   gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2);
     259                 :        493 : }
     260                 :            : #endif
     261                 :            : 
     262                 :            : #if !IN_GCOV
     263                 :            : /* Write out the current block, if needs be.  */
     264                 :            : 
     265                 :            : static void
     266                 :        247 : gcov_write_block (unsigned size)
     267                 :            : {
     268                 :        247 :   if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1)
     269                 :          0 :     gcov_var.error = 1;
     270                 :        247 :   gcov_var.start += size;
     271                 :        247 :   gcov_var.offset -= size;
     272                 :        247 : }
     273                 :            : 
     274                 :            : /* Allocate space to write BYTES bytes to the gcov file. Return a
     275                 :            :    pointer to those bytes, or NULL on failure.  */
     276                 :            : 
     277                 :            : static gcov_unsigned_t *
     278                 :      52801 : gcov_write_words (unsigned words)
     279                 :            : {
     280                 :      52801 :   gcov_unsigned_t *result;
     281                 :            : 
     282                 :      52801 :   gcov_nonruntime_assert (gcov_var.mode < 0);
     283                 :            : #if IN_LIBGCOV
     284                 :            :   if (gcov_var.offset >= GCOV_BLOCK_SIZE)
     285                 :            :     {
     286                 :            :       gcov_write_block (GCOV_BLOCK_SIZE);
     287                 :            :       if (gcov_var.offset)
     288                 :            :         {
     289                 :            :           memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
     290                 :            :         }
     291                 :            :     }
     292                 :            : #else
     293                 :      52801 :   if (gcov_var.offset + words > gcov_var.alloc)
     294                 :        142 :     gcov_allocate (gcov_var.offset + words);
     295                 :            : #endif
     296                 :      52801 :   result = &gcov_var.buffer[gcov_var.offset];
     297                 :      52801 :   gcov_var.offset += words;
     298                 :            : 
     299                 :      52801 :   return result;
     300                 :            : }
     301                 :            : 
     302                 :            : /* Write unsigned VALUE to coverage file.  Sets error flag
     303                 :            :    appropriately.  */
     304                 :            : 
     305                 :            : GCOV_LINKAGE void
     306                 :      36434 : gcov_write_unsigned (gcov_unsigned_t value)
     307                 :            : {
     308                 :      36434 :   gcov_unsigned_t *buffer = gcov_write_words (1);
     309                 :            : 
     310                 :      36434 :   buffer[0] = value;
     311                 :      36434 : }
     312                 :            : 
     313                 :            : /* Write counter VALUE to coverage file.  Sets error flag
     314                 :            :    appropriately.  */
     315                 :            : 
     316                 :            : #if IN_LIBGCOV
     317                 :            : GCOV_LINKAGE void
     318                 :            : gcov_write_counter (gcov_type value)
     319                 :            : {
     320                 :            :   gcov_unsigned_t *buffer = gcov_write_words (2);
     321                 :            : 
     322                 :            :   buffer[0] = (gcov_unsigned_t) value;
     323                 :            :   if (sizeof (value) > sizeof (gcov_unsigned_t))
     324                 :            :     buffer[1] = (gcov_unsigned_t) (value >> 32);
     325                 :            :   else
     326                 :            :     buffer[1] = 0;
     327                 :            : }
     328                 :            : #endif /* IN_LIBGCOV */
     329                 :            : 
     330                 :            : #if !IN_LIBGCOV
     331                 :            : /* Write STRING to coverage file.  Sets error flag on file
     332                 :            :    error, overflow flag on overflow */
     333                 :            : 
     334                 :            : GCOV_LINKAGE void
     335                 :       7782 : gcov_write_string (const char *string)
     336                 :            : {
     337                 :       7782 :   unsigned length = 0;
     338                 :       7782 :   unsigned alloc = 0;
     339                 :       7782 :   gcov_unsigned_t *buffer;
     340                 :            : 
     341                 :       7782 :   if (string)
     342                 :            :     {
     343                 :       4693 :       length = strlen (string);
     344                 :       4693 :       alloc = (length + 4) >> 2;
     345                 :            :     }
     346                 :            : 
     347                 :       7782 :   buffer = gcov_write_words (1 + alloc);
     348                 :            : 
     349                 :       7782 :   buffer[0] = alloc;
     350                 :            : 
     351                 :       7782 :   if (alloc > 0)
     352                 :            :     {
     353                 :       4693 :       buffer[alloc] = 0; /* place nul terminators.  */
     354                 :       4693 :       memcpy (&buffer[1], string, length);
     355                 :            :     }
     356                 :       7782 : }
     357                 :            : #endif
     358                 :            : 
     359                 :            : #if !IN_LIBGCOV
     360                 :            : /* Write FILENAME to coverage file.  Sets error flag on file
     361                 :            :    error, overflow flag on overflow */
     362                 :            : 
     363                 :            : GCOV_LINKAGE void
     364                 :       3824 : gcov_write_filename (const char *filename)
     365                 :            : {
     366                 :       3824 :   if (profile_abs_path_flag && filename && filename[0]
     367                 :          8 :       && !(IS_DIR_SEPARATOR (filename[0])
     368                 :            : #if HAVE_DOS_BASED_FILE_SYSTEM
     369                 :            :            || filename[1] == ':'
     370                 :            : #endif
     371                 :            :           ))
     372                 :            :     {
     373                 :          0 :       char *buf = getcwd (NULL, 0);
     374                 :          0 :       if (buf != NULL && buf[0])
     375                 :            :         {
     376                 :          0 :           size_t len = strlen (buf);
     377                 :          0 :           buf = (char*)xrealloc (buf, len + strlen (filename) + 2);
     378                 :          0 :           if (!IS_DIR_SEPARATOR (buf[len - 1]))
     379                 :          0 :             strcat (buf, "/");
     380                 :          0 :           strcat (buf, filename);
     381                 :          0 :           gcov_write_string (buf);
     382                 :          0 :           free (buf);
     383                 :          0 :           return;
     384                 :            :         }
     385                 :            :     }
     386                 :            : 
     387                 :       3824 :   gcov_write_string (filename);
     388                 :            : }
     389                 :            : #endif
     390                 :            : 
     391                 :            : #if !IN_LIBGCOV
     392                 :            : /* Write a tag TAG and reserve space for the record length. Return a
     393                 :            :    value to be used for gcov_write_length.  */
     394                 :            : 
     395                 :            : GCOV_LINKAGE gcov_position_t
     396                 :       8585 : gcov_write_tag (gcov_unsigned_t tag)
     397                 :            : {
     398                 :       8585 :   gcov_position_t result = gcov_var.start + gcov_var.offset;
     399                 :       8585 :   gcov_unsigned_t *buffer = gcov_write_words (2);
     400                 :            : 
     401                 :       8585 :   buffer[0] = tag;
     402                 :       8585 :   buffer[1] = 0;
     403                 :            : 
     404                 :       8585 :   return result;
     405                 :            : }
     406                 :            : 
     407                 :            : /* Write a record length using POSITION, which was returned by
     408                 :            :    gcov_write_tag.  The current file position is the end of the
     409                 :            :    record, and is restored before returning.  Returns nonzero on
     410                 :            :    overflow.  */
     411                 :            : 
     412                 :            : GCOV_LINKAGE void
     413                 :       8585 : gcov_write_length (gcov_position_t position)
     414                 :            : {
     415                 :       8585 :   unsigned offset;
     416                 :       8585 :   gcov_unsigned_t length;
     417                 :       8585 :   gcov_unsigned_t *buffer;
     418                 :            : 
     419                 :       8585 :   gcov_nonruntime_assert (gcov_var.mode < 0);
     420                 :       8585 :   gcov_nonruntime_assert (position + 2 <= gcov_var.start + gcov_var.offset);
     421                 :       8585 :   gcov_nonruntime_assert (position >= gcov_var.start);
     422                 :       8585 :   offset = position - gcov_var.start;
     423                 :       8585 :   length = gcov_var.offset - offset - 2;
     424                 :       8585 :   buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset];
     425                 :       8585 :   buffer[1] = length;
     426                 :       8585 :   if (gcov_var.offset >= GCOV_BLOCK_SIZE)
     427                 :        109 :     gcov_write_block (gcov_var.offset);
     428                 :       8585 : }
     429                 :            : 
     430                 :            : #else /* IN_LIBGCOV */
     431                 :            : 
     432                 :            : /* Write a tag TAG and length LENGTH.  */
     433                 :            : 
     434                 :            : GCOV_LINKAGE void
     435                 :            : gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
     436                 :            : {
     437                 :            :   gcov_unsigned_t *buffer = gcov_write_words (2);
     438                 :            : 
     439                 :            :   buffer[0] = tag;
     440                 :            :   buffer[1] = length;
     441                 :            : }
     442                 :            : 
     443                 :            : /* Write a summary structure to the gcov file.  Return nonzero on
     444                 :            :    overflow.  */
     445                 :            : 
     446                 :            : GCOV_LINKAGE void
     447                 :            : gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
     448                 :            : {
     449                 :            :   gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
     450                 :            :   gcov_write_unsigned (summary->runs);
     451                 :            :   gcov_write_unsigned (summary->sum_max);
     452                 :            : }
     453                 :            : 
     454                 :            : #endif /* IN_LIBGCOV */
     455                 :            : 
     456                 :            : #endif /*!IN_GCOV */
     457                 :            : 
     458                 :            : /* Return a pointer to read BYTES bytes from the gcov file. Returns
     459                 :            :    NULL on failure (read past EOF).  */
     460                 :            : 
     461                 :            : static const gcov_unsigned_t *
     462                 :      80521 : gcov_read_words (unsigned words)
     463                 :            : {
     464                 :      80521 :   const gcov_unsigned_t *result;
     465                 :      80521 :   unsigned excess = gcov_var.length - gcov_var.offset;
     466                 :            : 
     467                 :      80521 :   if (gcov_var.mode <= 0)
     468                 :            :     return NULL;
     469                 :            : 
     470                 :      80521 :   if (excess < words)
     471                 :            :     {
     472                 :        527 :       gcov_var.start += gcov_var.offset;
     473                 :        527 :       if (excess)
     474                 :            :         {
     475                 :            : #if IN_LIBGCOV
     476                 :            :           memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
     477                 :            : #else
     478                 :         32 :           memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset,
     479                 :         32 :                    excess * 4);
     480                 :            : #endif
     481                 :            :         }
     482                 :        527 :       gcov_var.offset = 0;
     483                 :        527 :       gcov_var.length = excess;
     484                 :            : #if IN_LIBGCOV
     485                 :            :       excess = GCOV_BLOCK_SIZE;
     486                 :            : #else
     487                 :        527 :       if (gcov_var.length + words > gcov_var.alloc)
     488                 :        351 :         gcov_allocate (gcov_var.length + words);
     489                 :        527 :       excess = gcov_var.alloc - gcov_var.length;
     490                 :            : #endif
     491                 :       1054 :       excess = fread (gcov_var.buffer + gcov_var.length,
     492                 :        527 :                       1, excess << 2, gcov_var.file) >> 2;
     493                 :        527 :       gcov_var.length += excess;
     494                 :        527 :       if (gcov_var.length < words)
     495                 :            :         {
     496                 :        129 :           gcov_var.overread += words - gcov_var.length;
     497                 :        129 :           gcov_var.length = 0;
     498                 :        129 :           return 0;
     499                 :            :         }
     500                 :            :     }
     501                 :      80392 :   result = &gcov_var.buffer[gcov_var.offset];
     502                 :      80392 :   gcov_var.offset += words;
     503                 :      80392 :   return result;
     504                 :            : }
     505                 :            : 
     506                 :            : /* Read unsigned value from a coverage file. Sets error flag on file
     507                 :            :    error, overflow flag on overflow */
     508                 :            : 
     509                 :            : GCOV_LINKAGE gcov_unsigned_t
     510                 :      70935 : gcov_read_unsigned (void)
     511                 :            : {
     512                 :      70935 :   gcov_unsigned_t value;
     513                 :      70935 :   const gcov_unsigned_t *buffer = gcov_read_words (1);
     514                 :            : 
     515                 :      70935 :   if (!buffer)
     516                 :            :     return 0;
     517                 :      70806 :   value = from_file (buffer[0]);
     518                 :            :   return value;
     519                 :            : }
     520                 :            : 
     521                 :            : /* Read counter value from a coverage file. Sets error flag on file
     522                 :            :    error, overflow flag on overflow */
     523                 :            : 
     524                 :            : GCOV_LINKAGE gcov_type
     525                 :       4985 : gcov_read_counter (void)
     526                 :            : {
     527                 :       4985 :   gcov_type value;
     528                 :       4985 :   const gcov_unsigned_t *buffer = gcov_read_words (2);
     529                 :            : 
     530                 :       4985 :   if (!buffer)
     531                 :            :     return 0;
     532                 :       4985 :   value = from_file (buffer[0]);
     533                 :       4985 :   if (sizeof (value) > sizeof (gcov_unsigned_t))
     534                 :       4985 :     value |= ((gcov_type) from_file (buffer[1])) << 32;
     535                 :            :   else if (buffer[1])
     536                 :            :     gcov_var.error = -1;
     537                 :            : 
     538                 :       4985 :   return value;
     539                 :            : }
     540                 :            : 
     541                 :            : /* Mangle filename path of BASE and output new allocated pointer with
     542                 :            :    mangled path.  */
     543                 :            : 
     544                 :            : char *
     545                 :          3 : mangle_path (char const *base)
     546                 :            : {
     547                 :            :   /* Convert '/' to '#', convert '..' to '^',
     548                 :            :      convert ':' to '~' on DOS based file system.  */
     549                 :          3 :   const char *probe;
     550                 :          3 :   char *buffer = (char *)xmalloc (strlen (base) + 1);
     551                 :          3 :   char *ptr = buffer;
     552                 :            : 
     553                 :            : #if HAVE_DOS_BASED_FILE_SYSTEM
     554                 :            :   if (base[0] && base[1] == ':')
     555                 :            :     {
     556                 :            :       ptr[0] = base[0];
     557                 :            :       ptr[1] = '~';
     558                 :            :       ptr += 2;
     559                 :            :       base += 2;
     560                 :            :     }
     561                 :            : #endif
     562                 :         42 :   for (; *base; base = probe)
     563                 :            :     {
     564                 :            :       size_t len;
     565                 :            : 
     566                 :        301 :       for (probe = base; *probe; probe++)
     567                 :        298 :         if (*probe == '/')
     568                 :            :           break;
     569                 :         39 :       len = probe - base;
     570                 :         39 :       if (len == 2 && base[0] == '.' && base[1] == '.')
     571                 :          0 :         *ptr++ = '^';
     572                 :            :       else
     573                 :            :         {
     574                 :         39 :           memcpy (ptr, base, len);
     575                 :         39 :           ptr += len;
     576                 :            :         }
     577                 :         39 :       if (*probe)
     578                 :            :         {
     579                 :         36 :           *ptr++ = '#';
     580                 :         36 :           probe++;
     581                 :            :         }
     582                 :            :     }
     583                 :            : 
     584                 :            :   /* Terminate the string.  */
     585                 :          3 :   *ptr = '\0';
     586                 :            : 
     587                 :          3 :   return buffer;
     588                 :            : }
     589                 :            : 
     590                 :            : /* We need to expose the below function when compiling for gcov-tool.  */
     591                 :            : 
     592                 :            : #if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
     593                 :            : /* Read string from coverage file. Returns a pointer to a static
     594                 :            :    buffer, or NULL on empty string. You must copy the string before
     595                 :            :    calling another gcov function.  */
     596                 :            : 
     597                 :            : GCOV_LINKAGE const char *
     598                 :       7653 : gcov_read_string (void)
     599                 :            : {
     600                 :       7653 :   unsigned length = gcov_read_unsigned ();
     601                 :            : 
     602                 :       7653 :   if (!length)
     603                 :            :     return 0;
     604                 :            : 
     605                 :       4601 :   return (const char *) gcov_read_words (length);
     606                 :            : }
     607                 :            : #endif
     608                 :            : 
     609                 :            : GCOV_LINKAGE void
     610                 :        120 : gcov_read_summary (struct gcov_summary *summary)
     611                 :            : {
     612                 :        120 :   summary->runs = gcov_read_unsigned ();
     613                 :        120 :   summary->sum_max = gcov_read_unsigned ();
     614                 :          0 : }
     615                 :            : 
     616                 :            : /* We need to expose the below function when compiling for gcov-tool.  */
     617                 :            : 
     618                 :            : #if !IN_LIBGCOV || defined (IN_GCOV_TOOL)
     619                 :            : /* Reset to a known position.  BASE should have been obtained from
     620                 :            :    gcov_position, LENGTH should be a record length.  */
     621                 :            : 
     622                 :            : GCOV_LINKAGE void
     623                 :      11340 : gcov_sync (gcov_position_t base, gcov_unsigned_t length)
     624                 :            : {
     625                 :      11340 :   gcov_nonruntime_assert (gcov_var.mode > 0);
     626                 :      11340 :   base += length;
     627                 :      11340 :   if (base - gcov_var.start <= gcov_var.length)
     628                 :      11340 :     gcov_var.offset = base - gcov_var.start;
     629                 :            :   else
     630                 :            :     {
     631                 :          0 :       gcov_var.offset = gcov_var.length = 0;
     632                 :          0 :       fseek (gcov_var.file, base << 2, SEEK_SET);
     633                 :          0 :       gcov_var.start = ftell (gcov_var.file) >> 2;
     634                 :            :     }
     635                 :      11340 : }
     636                 :            : #endif
     637                 :            : 
     638                 :            : #if IN_LIBGCOV
     639                 :            : /* Move to a given position in a gcov file.  */
     640                 :            : 
     641                 :            : GCOV_LINKAGE void
     642                 :            : gcov_seek (gcov_position_t base)
     643                 :            : {
     644                 :            :   if (gcov_var.offset)
     645                 :            :     gcov_write_block (gcov_var.offset);
     646                 :            :   fseek (gcov_var.file, base << 2, SEEK_SET);
     647                 :            :   gcov_var.start = ftell (gcov_var.file) >> 2;
     648                 :            : }
     649                 :            : #endif
     650                 :            : 
     651                 :            : #if IN_GCOV > 0
     652                 :            : /* Return the modification time of the current gcov file.  */
     653                 :            : 
     654                 :            : GCOV_LINKAGE time_t
     655                 :        129 : gcov_time (void)
     656                 :            : {
     657                 :        129 :   struct stat status;
     658                 :            : 
     659                 :        129 :   if (fstat (fileno (gcov_var.file), &status))
     660                 :            :     return 0;
     661                 :            :   else
     662                 :        129 :     return status.st_mtime;
     663                 :            : }
     664                 :            : #endif /* IN_GCOV */

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.