Home | History | Annotate | Line # | Download | only in libgcc
libgcov-driver.c revision 1.1.1.6
      1      1.1  mrg /* Routines required for instrumenting a program.  */
      2      1.1  mrg /* Compile this one with gcc.  */
      3  1.1.1.6  mrg /* Copyright (C) 1989-2017 Free Software Foundation, Inc.
      4      1.1  mrg 
      5      1.1  mrg This file is part of GCC.
      6      1.1  mrg 
      7      1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      8      1.1  mrg the terms of the GNU General Public License as published by the Free
      9      1.1  mrg Software Foundation; either version 3, or (at your option) any later
     10      1.1  mrg version.
     11      1.1  mrg 
     12      1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13      1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14      1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15      1.1  mrg for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg #include "libgcov.h"
     27      1.1  mrg 
     28      1.1  mrg #if defined(inhibit_libc)
     29      1.1  mrg /* If libc and its header files are not available, provide dummy functions.  */
     30      1.1  mrg 
     31      1.1  mrg #if defined(L_gcov)
     32      1.1  mrg void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
     33      1.1  mrg #endif
     34      1.1  mrg 
     35      1.1  mrg #else /* inhibit_libc */
     36      1.1  mrg 
     37      1.1  mrg #include <string.h>
     38      1.1  mrg #if GCOV_LOCKED
     39      1.1  mrg #include <fcntl.h>
     40      1.1  mrg #include <errno.h>
     41      1.1  mrg #include <sys/stat.h>
     42      1.1  mrg #endif
     43      1.1  mrg 
     44      1.1  mrg #ifdef L_gcov
     45      1.1  mrg 
     46  1.1.1.4  mrg /* A utility function for outputting errors.  */
     47      1.1  mrg static int gcov_error (const char *, ...);
     48      1.1  mrg 
     49  1.1.1.4  mrg #if !IN_GCOV_TOOL
     50  1.1.1.4  mrg static void gcov_error_exit (void);
     51  1.1.1.4  mrg #endif
     52  1.1.1.4  mrg 
     53      1.1  mrg #include "gcov-io.c"
     54      1.1  mrg 
     55      1.1  mrg struct gcov_fn_buffer
     56      1.1  mrg {
     57      1.1  mrg   struct gcov_fn_buffer *next;
     58      1.1  mrg   unsigned fn_ix;
     59      1.1  mrg   struct gcov_fn_info info;
     60      1.1  mrg   /* note gcov_fn_info ends in a trailing array.  */
     61      1.1  mrg };
     62      1.1  mrg 
     63      1.1  mrg struct gcov_summary_buffer
     64      1.1  mrg {
     65      1.1  mrg   struct gcov_summary_buffer *next;
     66      1.1  mrg   struct gcov_summary summary;
     67      1.1  mrg };
     68      1.1  mrg 
     69      1.1  mrg /* A struct that bundles all the related information about the
     70      1.1  mrg    gcda filename.  */
     71      1.1  mrg 
     72      1.1  mrg struct gcov_filename
     73      1.1  mrg {
     74      1.1  mrg   char *filename;  /* filename buffer */
     75      1.1  mrg   size_t max_length;  /* maximum filename length */
     76      1.1  mrg   int strip; /* leading chars to strip from filename */
     77      1.1  mrg   size_t prefix; /* chars to prepend to filename */
     78      1.1  mrg };
     79      1.1  mrg 
     80      1.1  mrg static struct gcov_fn_buffer *
     81      1.1  mrg free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
     82      1.1  mrg               unsigned limit)
     83      1.1  mrg {
     84      1.1  mrg   struct gcov_fn_buffer *next;
     85      1.1  mrg   unsigned ix, n_ctr = 0;
     86      1.1  mrg 
     87      1.1  mrg   if (!buffer)
     88      1.1  mrg     return 0;
     89      1.1  mrg   next = buffer->next;
     90      1.1  mrg 
     91      1.1  mrg   for (ix = 0; ix != limit; ix++)
     92      1.1  mrg     if (gi_ptr->merge[ix])
     93      1.1  mrg       free (buffer->info.ctrs[n_ctr++].values);
     94      1.1  mrg   free (buffer);
     95      1.1  mrg   return next;
     96      1.1  mrg }
     97      1.1  mrg 
     98      1.1  mrg static struct gcov_fn_buffer **
     99      1.1  mrg buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
    100      1.1  mrg                 struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
    101      1.1  mrg {
    102      1.1  mrg   unsigned n_ctrs = 0, ix = 0;
    103      1.1  mrg   struct gcov_fn_buffer *fn_buffer;
    104      1.1  mrg   unsigned len;
    105      1.1  mrg 
    106      1.1  mrg   for (ix = GCOV_COUNTERS; ix--;)
    107      1.1  mrg     if (gi_ptr->merge[ix])
    108      1.1  mrg       n_ctrs++;
    109      1.1  mrg 
    110      1.1  mrg   len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
    111      1.1  mrg   fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
    112      1.1  mrg 
    113      1.1  mrg   if (!fn_buffer)
    114      1.1  mrg     goto fail;
    115      1.1  mrg 
    116      1.1  mrg   fn_buffer->next = 0;
    117      1.1  mrg   fn_buffer->fn_ix = fn_ix;
    118      1.1  mrg   fn_buffer->info.ident = gcov_read_unsigned ();
    119      1.1  mrg   fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
    120      1.1  mrg   fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
    121      1.1  mrg 
    122      1.1  mrg   for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
    123      1.1  mrg     {
    124      1.1  mrg       gcov_unsigned_t length;
    125      1.1  mrg       gcov_type *values;
    126      1.1  mrg 
    127      1.1  mrg       if (!gi_ptr->merge[ix])
    128      1.1  mrg         continue;
    129      1.1  mrg 
    130      1.1  mrg       if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
    131      1.1  mrg         {
    132      1.1  mrg           len = 0;
    133      1.1  mrg           goto fail;
    134      1.1  mrg         }
    135      1.1  mrg 
    136      1.1  mrg       length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
    137      1.1  mrg       len = length * sizeof (gcov_type);
    138      1.1  mrg       values = (gcov_type *) xmalloc (len);
    139      1.1  mrg       if (!values)
    140      1.1  mrg         goto fail;
    141      1.1  mrg 
    142      1.1  mrg       fn_buffer->info.ctrs[n_ctrs].num = length;
    143      1.1  mrg       fn_buffer->info.ctrs[n_ctrs].values = values;
    144      1.1  mrg 
    145      1.1  mrg       while (length--)
    146      1.1  mrg         *values++ = gcov_read_counter ();
    147      1.1  mrg       n_ctrs++;
    148      1.1  mrg     }
    149      1.1  mrg 
    150      1.1  mrg   *end_ptr = fn_buffer;
    151      1.1  mrg   return &fn_buffer->next;
    152      1.1  mrg 
    153      1.1  mrg fail:
    154      1.1  mrg   gcov_error ("profiling:%s:Function %u %s %u \n", filename, fn_ix,
    155      1.1  mrg               len ? "cannot allocate" : "counter mismatch", len ? len : ix);
    156      1.1  mrg 
    157      1.1  mrg   return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
    158      1.1  mrg }
    159      1.1  mrg 
    160      1.1  mrg /* Add an unsigned value to the current crc */
    161      1.1  mrg 
    162      1.1  mrg static gcov_unsigned_t
    163      1.1  mrg crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
    164      1.1  mrg {
    165      1.1  mrg   unsigned ix;
    166      1.1  mrg 
    167      1.1  mrg   for (ix = 32; ix--; value <<= 1)
    168      1.1  mrg     {
    169      1.1  mrg       unsigned feedback;
    170      1.1  mrg 
    171      1.1  mrg       feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
    172      1.1  mrg       crc32 <<= 1;
    173      1.1  mrg       crc32 ^= feedback;
    174      1.1  mrg     }
    175      1.1  mrg 
    176      1.1  mrg   return crc32;
    177      1.1  mrg }
    178      1.1  mrg 
    179      1.1  mrg /* Check if VERSION of the info block PTR matches libgcov one.
    180      1.1  mrg    Return 1 on success, or zero in case of versions mismatch.
    181      1.1  mrg    If FILENAME is not NULL, its value used for reporting purposes
    182      1.1  mrg    instead of value from the info block.  */
    183      1.1  mrg 
    184      1.1  mrg static int
    185      1.1  mrg gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
    186      1.1  mrg               const char *filename)
    187      1.1  mrg {
    188      1.1  mrg   if (version != GCOV_VERSION)
    189      1.1  mrg     {
    190      1.1  mrg       char v[4], e[4];
    191      1.1  mrg 
    192      1.1  mrg       GCOV_UNSIGNED2STRING (v, version);
    193      1.1  mrg       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
    194      1.1  mrg 
    195      1.1  mrg       gcov_error ("profiling:%s:Version mismatch - expected %.4s got %.4s\n",
    196      1.1  mrg                   filename? filename : ptr->filename, e, v);
    197      1.1  mrg       return 0;
    198      1.1  mrg     }
    199      1.1  mrg   return 1;
    200      1.1  mrg }
    201      1.1  mrg 
    202      1.1  mrg /* Insert counter VALUE into HISTOGRAM.  */
    203      1.1  mrg 
    204      1.1  mrg static void
    205      1.1  mrg gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
    206      1.1  mrg {
    207      1.1  mrg   unsigned i;
    208      1.1  mrg 
    209      1.1  mrg   i = gcov_histo_index(value);
    210      1.1  mrg   histogram[i].num_counters++;
    211      1.1  mrg   histogram[i].cum_value += value;
    212      1.1  mrg   if (value < histogram[i].min_value)
    213      1.1  mrg     histogram[i].min_value = value;
    214      1.1  mrg }
    215      1.1  mrg 
    216      1.1  mrg /* Computes a histogram of the arc counters to place in the summary SUM.  */
    217      1.1  mrg 
    218      1.1  mrg static void
    219      1.1  mrg gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
    220      1.1  mrg {
    221      1.1  mrg   struct gcov_info *gi_ptr;
    222      1.1  mrg   const struct gcov_fn_info *gfi_ptr;
    223      1.1  mrg   const struct gcov_ctr_info *ci_ptr;
    224      1.1  mrg   struct gcov_ctr_summary *cs_ptr;
    225      1.1  mrg   unsigned t_ix, f_ix, ctr_info_ix, ix;
    226      1.1  mrg   int h_ix;
    227      1.1  mrg 
    228      1.1  mrg   /* This currently only applies to arc counters.  */
    229      1.1  mrg   t_ix = GCOV_COUNTER_ARCS;
    230      1.1  mrg 
    231      1.1  mrg   /* First check if there are any counts recorded for this counter.  */
    232      1.1  mrg   cs_ptr = &(sum->ctrs[t_ix]);
    233      1.1  mrg   if (!cs_ptr->num)
    234      1.1  mrg     return;
    235      1.1  mrg 
    236      1.1  mrg   for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
    237      1.1  mrg     {
    238      1.1  mrg       cs_ptr->histogram[h_ix].num_counters = 0;
    239      1.1  mrg       cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
    240      1.1  mrg       cs_ptr->histogram[h_ix].cum_value = 0;
    241      1.1  mrg     }
    242      1.1  mrg 
    243      1.1  mrg   /* Walk through all the per-object structures and record each of
    244      1.1  mrg      the count values in histogram.  */
    245      1.1  mrg   for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
    246      1.1  mrg     {
    247      1.1  mrg       if (!gi_ptr->merge[t_ix])
    248      1.1  mrg         continue;
    249      1.1  mrg 
    250      1.1  mrg       /* Find the appropriate index into the gcov_ctr_info array
    251      1.1  mrg          for the counter we are currently working on based on the
    252      1.1  mrg          existence of the merge function pointer for this object.  */
    253      1.1  mrg       for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
    254      1.1  mrg         {
    255      1.1  mrg           if (gi_ptr->merge[ix])
    256      1.1  mrg             ctr_info_ix++;
    257      1.1  mrg         }
    258      1.1  mrg       for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
    259      1.1  mrg         {
    260      1.1  mrg           gfi_ptr = gi_ptr->functions[f_ix];
    261      1.1  mrg 
    262      1.1  mrg           if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    263      1.1  mrg             continue;
    264      1.1  mrg 
    265      1.1  mrg           ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
    266      1.1  mrg           for (ix = 0; ix < ci_ptr->num; ix++)
    267      1.1  mrg             gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
    268      1.1  mrg         }
    269      1.1  mrg     }
    270      1.1  mrg }
    271      1.1  mrg 
    272      1.1  mrg /* buffer for the fn_data from another program.  */
    273      1.1  mrg static struct gcov_fn_buffer *fn_buffer;
    274      1.1  mrg /* buffer for summary from other programs to be written out. */
    275      1.1  mrg static struct gcov_summary_buffer *sum_buffer;
    276      1.1  mrg 
    277      1.1  mrg /* This function computes the program level summary and the histo-gram.
    278      1.1  mrg    It computes and returns CRC32 and stored summary in THIS_PRG.
    279      1.1  mrg    Also determines the longest filename length of the info files.  */
    280      1.1  mrg 
    281      1.1  mrg #if !IN_GCOV_TOOL
    282      1.1  mrg static
    283      1.1  mrg #endif
    284      1.1  mrg gcov_unsigned_t
    285      1.1  mrg compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
    286      1.1  mrg 		 size_t *max_length)
    287      1.1  mrg {
    288      1.1  mrg   struct gcov_info *gi_ptr;
    289      1.1  mrg   const struct gcov_fn_info *gfi_ptr;
    290      1.1  mrg   struct gcov_ctr_summary *cs_ptr;
    291      1.1  mrg   const struct gcov_ctr_info *ci_ptr;
    292      1.1  mrg   int f_ix;
    293      1.1  mrg   unsigned t_ix;
    294      1.1  mrg   gcov_unsigned_t c_num;
    295      1.1  mrg   gcov_unsigned_t crc32 = 0;
    296      1.1  mrg 
    297      1.1  mrg   /* Find the totals for this execution.  */
    298      1.1  mrg   memset (this_prg, 0, sizeof (*this_prg));
    299      1.1  mrg   *max_length = 0;
    300      1.1  mrg   for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
    301      1.1  mrg     {
    302      1.1  mrg       size_t len = strlen (gi_ptr->filename);
    303      1.1  mrg       if (len > *max_length)
    304      1.1  mrg 	*max_length = len;
    305      1.1  mrg 
    306      1.1  mrg       crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
    307      1.1  mrg       crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
    308      1.1  mrg 
    309      1.1  mrg       for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
    310      1.1  mrg         {
    311      1.1  mrg           gfi_ptr = gi_ptr->functions[f_ix];
    312      1.1  mrg 
    313      1.1  mrg           if (gfi_ptr && gfi_ptr->key != gi_ptr)
    314      1.1  mrg             gfi_ptr = 0;
    315      1.1  mrg 
    316      1.1  mrg           crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
    317      1.1  mrg           crc32 = crc32_unsigned (crc32,
    318      1.1  mrg                                   gfi_ptr ? gfi_ptr->lineno_checksum : 0);
    319      1.1  mrg           if (!gfi_ptr)
    320      1.1  mrg             continue;
    321      1.1  mrg 
    322      1.1  mrg           ci_ptr = gfi_ptr->ctrs;
    323      1.1  mrg           for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
    324      1.1  mrg             {
    325      1.1  mrg               if (!gi_ptr->merge[t_ix])
    326      1.1  mrg                 continue;
    327      1.1  mrg 
    328      1.1  mrg               cs_ptr = &(this_prg->ctrs[t_ix]);
    329      1.1  mrg               cs_ptr->num += ci_ptr->num;
    330      1.1  mrg               crc32 = crc32_unsigned (crc32, ci_ptr->num);
    331      1.1  mrg 
    332      1.1  mrg               for (c_num = 0; c_num < ci_ptr->num; c_num++)
    333      1.1  mrg                 {
    334      1.1  mrg                   cs_ptr->sum_all += ci_ptr->values[c_num];
    335      1.1  mrg                   if (cs_ptr->run_max < ci_ptr->values[c_num])
    336      1.1  mrg                     cs_ptr->run_max = ci_ptr->values[c_num];
    337      1.1  mrg                 }
    338      1.1  mrg               ci_ptr++;
    339      1.1  mrg             }
    340      1.1  mrg         }
    341      1.1  mrg     }
    342      1.1  mrg   gcov_compute_histogram (list, this_prg);
    343      1.1  mrg   return crc32;
    344      1.1  mrg }
    345      1.1  mrg 
    346      1.1  mrg /* Including system dependent components. */
    347      1.1  mrg #include "libgcov-driver-system.c"
    348      1.1  mrg 
    349      1.1  mrg /* This function merges counters in GI_PTR to an existing gcda file.
    350      1.1  mrg    Return 0 on success.
    351      1.1  mrg    Return -1 on error. In this case, caller will goto read_fatal.  */
    352      1.1  mrg 
    353      1.1  mrg static int
    354      1.1  mrg merge_one_data (const char *filename,
    355      1.1  mrg 		struct gcov_info *gi_ptr,
    356      1.1  mrg 		struct gcov_summary *prg_p,
    357      1.1  mrg 		struct gcov_summary *this_prg,
    358      1.1  mrg 		gcov_position_t *summary_pos_p,
    359      1.1  mrg 		gcov_position_t *eof_pos_p,
    360      1.1  mrg 		gcov_unsigned_t crc32)
    361      1.1  mrg {
    362      1.1  mrg   gcov_unsigned_t tag, length;
    363      1.1  mrg   unsigned t_ix;
    364      1.1  mrg   int f_ix;
    365      1.1  mrg   int error = 0;
    366      1.1  mrg   struct gcov_fn_buffer **fn_tail = &fn_buffer;
    367      1.1  mrg   struct gcov_summary_buffer **sum_tail = &sum_buffer;
    368      1.1  mrg 
    369      1.1  mrg   length = gcov_read_unsigned ();
    370      1.1  mrg   if (!gcov_version (gi_ptr, length, filename))
    371      1.1  mrg     return -1;
    372      1.1  mrg 
    373      1.1  mrg   length = gcov_read_unsigned ();
    374      1.1  mrg   if (length != gi_ptr->stamp)
    375      1.1  mrg     /* Read from a different compilation. Overwrite the file.  */
    376      1.1  mrg     return 0;
    377      1.1  mrg 
    378      1.1  mrg   /* Look for program summary.  */
    379      1.1  mrg   for (f_ix = 0;;)
    380      1.1  mrg     {
    381      1.1  mrg       struct gcov_summary tmp;
    382      1.1  mrg 
    383      1.1  mrg       *eof_pos_p = gcov_position ();
    384      1.1  mrg       tag = gcov_read_unsigned ();
    385      1.1  mrg       if (tag != GCOV_TAG_PROGRAM_SUMMARY)
    386      1.1  mrg         break;
    387      1.1  mrg 
    388      1.1  mrg       f_ix--;
    389      1.1  mrg       length = gcov_read_unsigned ();
    390      1.1  mrg       gcov_read_summary (&tmp);
    391      1.1  mrg       if ((error = gcov_is_error ()))
    392      1.1  mrg         goto read_error;
    393      1.1  mrg       if (*summary_pos_p)
    394      1.1  mrg         {
    395      1.1  mrg           /* Save all summaries after the one that will be
    396      1.1  mrg              merged into below. These will need to be rewritten
    397      1.1  mrg              as histogram merging may change the number of non-zero
    398      1.1  mrg              histogram entries that will be emitted, and thus the
    399      1.1  mrg              size of the merged summary.  */
    400      1.1  mrg           (*sum_tail) = (struct gcov_summary_buffer *)
    401      1.1  mrg               xmalloc (sizeof(struct gcov_summary_buffer));
    402      1.1  mrg           (*sum_tail)->summary = tmp;
    403      1.1  mrg           (*sum_tail)->next = 0;
    404      1.1  mrg           sum_tail = &((*sum_tail)->next);
    405      1.1  mrg           goto next_summary;
    406      1.1  mrg         }
    407      1.1  mrg       if (tmp.checksum != crc32)
    408      1.1  mrg         goto next_summary;
    409      1.1  mrg 
    410      1.1  mrg       for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
    411      1.1  mrg         if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
    412      1.1  mrg           goto next_summary;
    413      1.1  mrg       *prg_p = tmp;
    414      1.1  mrg       *summary_pos_p = *eof_pos_p;
    415      1.1  mrg 
    416      1.1  mrg     next_summary:;
    417      1.1  mrg     }
    418      1.1  mrg 
    419      1.1  mrg   /* Merge execution counts for each function.  */
    420      1.1  mrg   for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
    421      1.1  mrg        f_ix++, tag = gcov_read_unsigned ())
    422      1.1  mrg     {
    423      1.1  mrg       const struct gcov_ctr_info *ci_ptr;
    424      1.1  mrg       const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
    425      1.1  mrg 
    426      1.1  mrg       if (tag != GCOV_TAG_FUNCTION)
    427      1.1  mrg         goto read_mismatch;
    428      1.1  mrg 
    429      1.1  mrg       length = gcov_read_unsigned ();
    430      1.1  mrg       if (!length)
    431      1.1  mrg         /* This function did not appear in the other program.
    432      1.1  mrg            We have nothing to merge.  */
    433      1.1  mrg         continue;
    434      1.1  mrg 
    435      1.1  mrg       if (length != GCOV_TAG_FUNCTION_LENGTH)
    436      1.1  mrg         goto read_mismatch;
    437      1.1  mrg 
    438      1.1  mrg       if (!gfi_ptr || gfi_ptr->key != gi_ptr)
    439      1.1  mrg         {
    440      1.1  mrg           /* This function appears in the other program.  We
    441      1.1  mrg              need to buffer the information in order to write
    442      1.1  mrg              it back out -- we'll be inserting data before
    443      1.1  mrg              this point, so cannot simply keep the data in the
    444      1.1  mrg              file.  */
    445      1.1  mrg           fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
    446      1.1  mrg           if (!fn_tail)
    447      1.1  mrg             goto read_mismatch;
    448      1.1  mrg           continue;
    449      1.1  mrg         }
    450      1.1  mrg 
    451      1.1  mrg       length = gcov_read_unsigned ();
    452      1.1  mrg       if (length != gfi_ptr->ident)
    453      1.1  mrg         goto read_mismatch;
    454      1.1  mrg 
    455      1.1  mrg       length = gcov_read_unsigned ();
    456      1.1  mrg       if (length != gfi_ptr->lineno_checksum)
    457      1.1  mrg         goto read_mismatch;
    458      1.1  mrg 
    459      1.1  mrg       length = gcov_read_unsigned ();
    460      1.1  mrg       if (length != gfi_ptr->cfg_checksum)
    461      1.1  mrg         goto read_mismatch;
    462      1.1  mrg 
    463      1.1  mrg       ci_ptr = gfi_ptr->ctrs;
    464      1.1  mrg       for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
    465      1.1  mrg         {
    466      1.1  mrg           gcov_merge_fn merge = gi_ptr->merge[t_ix];
    467      1.1  mrg 
    468      1.1  mrg           if (!merge)
    469      1.1  mrg             continue;
    470      1.1  mrg 
    471      1.1  mrg           tag = gcov_read_unsigned ();
    472      1.1  mrg           length = gcov_read_unsigned ();
    473      1.1  mrg           if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
    474      1.1  mrg               || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
    475      1.1  mrg             goto read_mismatch;
    476      1.1  mrg           (*merge) (ci_ptr->values, ci_ptr->num);
    477      1.1  mrg           ci_ptr++;
    478      1.1  mrg         }
    479      1.1  mrg       if ((error = gcov_is_error ()))
    480      1.1  mrg         goto read_error;
    481      1.1  mrg     }
    482      1.1  mrg 
    483      1.1  mrg   if (tag)
    484      1.1  mrg     {
    485      1.1  mrg     read_mismatch:;
    486      1.1  mrg       gcov_error ("profiling:%s:Merge mismatch for %s %u\n",
    487      1.1  mrg                   filename, f_ix >= 0 ? "function" : "summary",
    488      1.1  mrg                   f_ix < 0 ? -1 - f_ix : f_ix);
    489      1.1  mrg       return -1;
    490      1.1  mrg     }
    491      1.1  mrg   return 0;
    492      1.1  mrg 
    493      1.1  mrg read_error:
    494      1.1  mrg   gcov_error ("profiling:%s:%s merging\n", filename,
    495      1.1  mrg               error < 0 ? "Overflow": "Error");
    496      1.1  mrg   return -1;
    497      1.1  mrg }
    498      1.1  mrg 
    499      1.1  mrg /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
    500      1.1  mrg    the case of appending to an existing file, SUMMARY_POS will be non-zero.
    501      1.1  mrg    We will write the file starting from SUMMAY_POS.  */
    502      1.1  mrg 
    503      1.1  mrg static void
    504      1.1  mrg write_one_data (const struct gcov_info *gi_ptr,
    505      1.1  mrg 		const struct gcov_summary *prg_p,
    506      1.1  mrg 		const gcov_position_t eof_pos,
    507      1.1  mrg 		const gcov_position_t summary_pos)
    508      1.1  mrg {
    509      1.1  mrg   unsigned f_ix;
    510      1.1  mrg   struct gcov_summary_buffer *next_sum_buffer;
    511      1.1  mrg 
    512      1.1  mrg   /* Write out the data.  */
    513      1.1  mrg   if (!eof_pos)
    514      1.1  mrg     {
    515      1.1  mrg       gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
    516      1.1  mrg       gcov_write_unsigned (gi_ptr->stamp);
    517      1.1  mrg     }
    518      1.1  mrg 
    519      1.1  mrg   if (summary_pos)
    520      1.1  mrg     gcov_seek (summary_pos);
    521      1.1  mrg 
    522      1.1  mrg   /* Generate whole program statistics.  */
    523      1.1  mrg   gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
    524      1.1  mrg 
    525      1.1  mrg   /* Rewrite all the summaries that were after the summary we merged
    526      1.1  mrg      into. This is necessary as the merged summary may have a different
    527      1.1  mrg      size due to the number of non-zero histogram entries changing after
    528      1.1  mrg      merging.  */
    529      1.1  mrg 
    530      1.1  mrg   while (sum_buffer)
    531      1.1  mrg     {
    532      1.1  mrg       gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
    533      1.1  mrg       next_sum_buffer = sum_buffer->next;
    534      1.1  mrg       free (sum_buffer);
    535      1.1  mrg       sum_buffer = next_sum_buffer;
    536      1.1  mrg     }
    537      1.1  mrg 
    538      1.1  mrg   /* Write execution counts for each function.  */
    539      1.1  mrg   for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
    540      1.1  mrg     {
    541      1.1  mrg       unsigned buffered = 0;
    542      1.1  mrg       const struct gcov_fn_info *gfi_ptr;
    543      1.1  mrg       const struct gcov_ctr_info *ci_ptr;
    544      1.1  mrg       gcov_unsigned_t length;
    545      1.1  mrg       unsigned t_ix;
    546      1.1  mrg 
    547      1.1  mrg       if (fn_buffer && fn_buffer->fn_ix == f_ix)
    548      1.1  mrg         {
    549      1.1  mrg           /* Buffered data from another program.  */
    550      1.1  mrg           buffered = 1;
    551      1.1  mrg           gfi_ptr = &fn_buffer->info;
    552      1.1  mrg           length = GCOV_TAG_FUNCTION_LENGTH;
    553      1.1  mrg         }
    554      1.1  mrg       else
    555      1.1  mrg         {
    556      1.1  mrg           gfi_ptr = gi_ptr->functions[f_ix];
    557      1.1  mrg           if (gfi_ptr && gfi_ptr->key == gi_ptr)
    558      1.1  mrg             length = GCOV_TAG_FUNCTION_LENGTH;
    559      1.1  mrg           else
    560      1.1  mrg                 length = 0;
    561      1.1  mrg         }
    562      1.1  mrg 
    563      1.1  mrg       gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
    564      1.1  mrg       if (!length)
    565      1.1  mrg         continue;
    566      1.1  mrg 
    567      1.1  mrg       gcov_write_unsigned (gfi_ptr->ident);
    568      1.1  mrg       gcov_write_unsigned (gfi_ptr->lineno_checksum);
    569      1.1  mrg       gcov_write_unsigned (gfi_ptr->cfg_checksum);
    570      1.1  mrg 
    571      1.1  mrg       ci_ptr = gfi_ptr->ctrs;
    572      1.1  mrg       for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
    573      1.1  mrg         {
    574      1.1  mrg           gcov_unsigned_t n_counts;
    575      1.1  mrg           gcov_type *c_ptr;
    576      1.1  mrg 
    577      1.1  mrg           if (!gi_ptr->merge[t_ix])
    578      1.1  mrg             continue;
    579      1.1  mrg 
    580      1.1  mrg           n_counts = ci_ptr->num;
    581      1.1  mrg           gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
    582      1.1  mrg                                  GCOV_TAG_COUNTER_LENGTH (n_counts));
    583      1.1  mrg           c_ptr = ci_ptr->values;
    584      1.1  mrg           while (n_counts--)
    585      1.1  mrg             gcov_write_counter (*c_ptr++);
    586      1.1  mrg           ci_ptr++;
    587      1.1  mrg         }
    588      1.1  mrg       if (buffered)
    589      1.1  mrg         fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
    590      1.1  mrg     }
    591      1.1  mrg 
    592      1.1  mrg   gcov_write_unsigned (0);
    593      1.1  mrg }
    594      1.1  mrg 
    595      1.1  mrg /* Helper function for merging summary.
    596      1.1  mrg    Return -1 on error. Return 0 on success.  */
    597      1.1  mrg 
    598      1.1  mrg static int
    599      1.1  mrg merge_summary (const char *filename, int run_counted,
    600      1.1  mrg 	       const struct gcov_info *gi_ptr, struct gcov_summary *prg,
    601      1.1  mrg 	       struct gcov_summary *this_prg, gcov_unsigned_t crc32,
    602      1.1  mrg 	       struct gcov_summary *all_prg __attribute__ ((unused)))
    603      1.1  mrg {
    604      1.1  mrg   struct gcov_ctr_summary *cs_prg, *cs_tprg;
    605      1.1  mrg   unsigned t_ix;
    606      1.1  mrg #if !GCOV_LOCKED
    607      1.1  mrg   /* summary for all instances of program.  */
    608      1.1  mrg   struct gcov_ctr_summary *cs_all;
    609      1.1  mrg #endif
    610      1.1  mrg 
    611      1.1  mrg   /* Merge the summaries.  */
    612      1.1  mrg   for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
    613      1.1  mrg     {
    614      1.1  mrg       cs_prg = &(prg->ctrs[t_ix]);
    615      1.1  mrg       cs_tprg = &(this_prg->ctrs[t_ix]);
    616      1.1  mrg 
    617      1.1  mrg       if (gi_ptr->merge[t_ix])
    618      1.1  mrg         {
    619      1.1  mrg 	  int first = !cs_prg->runs;
    620      1.1  mrg 
    621      1.1  mrg 	  if (!run_counted)
    622      1.1  mrg 	    cs_prg->runs++;
    623      1.1  mrg           if (first)
    624      1.1  mrg             cs_prg->num = cs_tprg->num;
    625      1.1  mrg           cs_prg->sum_all += cs_tprg->sum_all;
    626      1.1  mrg           if (cs_prg->run_max < cs_tprg->run_max)
    627      1.1  mrg             cs_prg->run_max = cs_tprg->run_max;
    628      1.1  mrg           cs_prg->sum_max += cs_tprg->run_max;
    629      1.1  mrg           if (first)
    630      1.1  mrg             memcpy (cs_prg->histogram, cs_tprg->histogram,
    631      1.1  mrg                    sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
    632      1.1  mrg           else
    633      1.1  mrg             gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
    634      1.1  mrg         }
    635      1.1  mrg       else if (cs_prg->runs)
    636      1.1  mrg         {
    637      1.1  mrg           gcov_error ("profiling:%s:Merge mismatch for summary.\n",
    638      1.1  mrg                       filename);
    639      1.1  mrg           return -1;
    640      1.1  mrg         }
    641      1.1  mrg #if !GCOV_LOCKED
    642      1.1  mrg       cs_all = &all_prg->ctrs[t_ix];
    643      1.1  mrg       if (!cs_all->runs && cs_prg->runs)
    644      1.1  mrg         {
    645      1.1  mrg           cs_all->num = cs_prg->num;
    646      1.1  mrg           cs_all->runs = cs_prg->runs;
    647      1.1  mrg           cs_all->sum_all = cs_prg->sum_all;
    648      1.1  mrg           cs_all->run_max = cs_prg->run_max;
    649      1.1  mrg           cs_all->sum_max = cs_prg->sum_max;
    650      1.1  mrg         }
    651      1.1  mrg       else if (!all_prg->checksum
    652      1.1  mrg                /* Don't compare the histograms, which may have slight
    653      1.1  mrg                   variations depending on the order they were updated
    654      1.1  mrg                   due to the truncating integer divides used in the
    655      1.1  mrg                   merge.  */
    656      1.1  mrg                && (cs_all->num != cs_prg->num
    657      1.1  mrg                    || cs_all->runs != cs_prg->runs
    658      1.1  mrg                    || cs_all->sum_all != cs_prg->sum_all
    659      1.1  mrg                    || cs_all->run_max != cs_prg->run_max
    660      1.1  mrg                    || cs_all->sum_max != cs_prg->sum_max))
    661      1.1  mrg              {
    662      1.1  mrg                gcov_error ("profiling:%s:Data file mismatch - some "
    663      1.1  mrg                            "data files may have been concurrently "
    664      1.1  mrg                            "updated without locking support\n", filename);
    665      1.1  mrg                all_prg->checksum = ~0u;
    666      1.1  mrg              }
    667      1.1  mrg #endif
    668      1.1  mrg     }
    669      1.1  mrg 
    670      1.1  mrg   prg->checksum = crc32;
    671      1.1  mrg 
    672      1.1  mrg   return 0;
    673      1.1  mrg }
    674      1.1  mrg 
    675      1.1  mrg 
    676      1.1  mrg /* Sort N entries in VALUE_ARRAY in descending order.
    677      1.1  mrg    Each entry in VALUE_ARRAY has two values. The sorting
    678      1.1  mrg    is based on the second value.  */
    679      1.1  mrg 
    680      1.1  mrg GCOV_LINKAGE  void
    681      1.1  mrg gcov_sort_n_vals (gcov_type *value_array, int n)
    682      1.1  mrg {
    683      1.1  mrg   int j, k;
    684      1.1  mrg 
    685      1.1  mrg   for (j = 2; j < n; j += 2)
    686      1.1  mrg     {
    687      1.1  mrg       gcov_type cur_ent[2];
    688      1.1  mrg 
    689      1.1  mrg       cur_ent[0] = value_array[j];
    690      1.1  mrg       cur_ent[1] = value_array[j + 1];
    691      1.1  mrg       k = j - 2;
    692      1.1  mrg       while (k >= 0 && value_array[k + 1] < cur_ent[1])
    693      1.1  mrg         {
    694      1.1  mrg           value_array[k + 2] = value_array[k];
    695      1.1  mrg           value_array[k + 3] = value_array[k+1];
    696      1.1  mrg           k -= 2;
    697      1.1  mrg         }
    698      1.1  mrg       value_array[k + 2] = cur_ent[0];
    699      1.1  mrg       value_array[k + 3] = cur_ent[1];
    700      1.1  mrg     }
    701      1.1  mrg }
    702      1.1  mrg 
    703      1.1  mrg /* Sort the profile counters for all indirect call sites. Counters
    704      1.1  mrg    for each call site are allocated in array COUNTERS.  */
    705      1.1  mrg 
    706      1.1  mrg static void
    707      1.1  mrg gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
    708      1.1  mrg {
    709      1.1  mrg   int i;
    710      1.1  mrg   gcov_type *values;
    711      1.1  mrg   int n = counters->num;
    712      1.1  mrg 
    713      1.1  mrg   gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
    714      1.1  mrg   values = counters->values;
    715      1.1  mrg 
    716      1.1  mrg   for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
    717      1.1  mrg     {
    718      1.1  mrg       gcov_type *value_array = &values[i + 1];
    719      1.1  mrg       gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
    720      1.1  mrg     }
    721      1.1  mrg }
    722      1.1  mrg 
    723      1.1  mrg /* Sort topn indirect_call profile counters in GI_PTR.  */
    724      1.1  mrg 
    725      1.1  mrg static void
    726      1.1  mrg gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
    727      1.1  mrg {
    728      1.1  mrg   unsigned int i;
    729      1.1  mrg   int f_ix;
    730      1.1  mrg   const struct gcov_fn_info *gfi_ptr;
    731      1.1  mrg   const struct gcov_ctr_info *ci_ptr;
    732      1.1  mrg 
    733      1.1  mrg   if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
    734      1.1  mrg     return;
    735      1.1  mrg 
    736      1.1  mrg   for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
    737      1.1  mrg     {
    738      1.1  mrg       gfi_ptr = gi_ptr->functions[f_ix];
    739      1.1  mrg       ci_ptr = gfi_ptr->ctrs;
    740      1.1  mrg       for (i = 0; i < GCOV_COUNTERS; i++)
    741      1.1  mrg         {
    742      1.1  mrg           if (!gi_ptr->merge[i])
    743      1.1  mrg             continue;
    744      1.1  mrg           if (i == GCOV_COUNTER_ICALL_TOPNV)
    745      1.1  mrg             {
    746      1.1  mrg               gcov_sort_icall_topn_counter (ci_ptr);
    747      1.1  mrg               break;
    748      1.1  mrg             }
    749      1.1  mrg           ci_ptr++;
    750      1.1  mrg         }
    751      1.1  mrg     }
    752      1.1  mrg }
    753      1.1  mrg 
    754      1.1  mrg /* Dump the coverage counts for one gcov_info object. We merge with existing
    755      1.1  mrg    counts when possible, to avoid growing the .da files ad infinitum. We use
    756      1.1  mrg    this program's checksum to make sure we only accumulate whole program
    757      1.1  mrg    statistics to the correct summary. An object file might be embedded
    758      1.1  mrg    in two separate programs, and we must keep the two program
    759      1.1  mrg    summaries separate.  */
    760      1.1  mrg 
    761      1.1  mrg static void
    762      1.1  mrg dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
    763      1.1  mrg 	       unsigned run_counted,
    764      1.1  mrg 	       gcov_unsigned_t crc32, struct gcov_summary *all_prg,
    765      1.1  mrg 	       struct gcov_summary *this_prg)
    766      1.1  mrg {
    767      1.1  mrg   struct gcov_summary prg; /* summary for this object over all program.  */
    768      1.1  mrg   int error;
    769      1.1  mrg   gcov_unsigned_t tag;
    770      1.1  mrg   gcov_position_t summary_pos = 0;
    771      1.1  mrg   gcov_position_t eof_pos = 0;
    772      1.1  mrg 
    773      1.1  mrg   fn_buffer = 0;
    774      1.1  mrg   sum_buffer = 0;
    775      1.1  mrg 
    776      1.1  mrg   gcov_sort_topn_counter_arrays (gi_ptr);
    777      1.1  mrg 
    778      1.1  mrg   error = gcov_exit_open_gcda_file (gi_ptr, gf);
    779      1.1  mrg   if (error == -1)
    780      1.1  mrg     return;
    781      1.1  mrg 
    782      1.1  mrg   tag = gcov_read_unsigned ();
    783      1.1  mrg   if (tag)
    784      1.1  mrg     {
    785      1.1  mrg       /* Merge data from file.  */
    786      1.1  mrg       if (tag != GCOV_DATA_MAGIC)
    787      1.1  mrg         {
    788      1.1  mrg           gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
    789      1.1  mrg           goto read_fatal;
    790      1.1  mrg         }
    791      1.1  mrg       error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
    792      1.1  mrg 			      &summary_pos, &eof_pos, crc32);
    793      1.1  mrg       if (error == -1)
    794      1.1  mrg         goto read_fatal;
    795      1.1  mrg     }
    796      1.1  mrg 
    797      1.1  mrg   gcov_rewrite ();
    798      1.1  mrg 
    799      1.1  mrg   if (!summary_pos)
    800      1.1  mrg     {
    801      1.1  mrg       memset (&prg, 0, sizeof (prg));
    802      1.1  mrg       summary_pos = eof_pos;
    803      1.1  mrg     }
    804      1.1  mrg 
    805      1.1  mrg   error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
    806      1.1  mrg 			 crc32, all_prg);
    807      1.1  mrg   if (error == -1)
    808      1.1  mrg     goto read_fatal;
    809      1.1  mrg 
    810      1.1  mrg   write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
    811      1.1  mrg   /* fall through */
    812      1.1  mrg 
    813      1.1  mrg read_fatal:;
    814      1.1  mrg   while (fn_buffer)
    815      1.1  mrg     fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
    816      1.1  mrg 
    817      1.1  mrg   if ((error = gcov_close ()))
    818      1.1  mrg     gcov_error (error  < 0 ?
    819      1.1  mrg                 "profiling:%s:Overflow writing\n" :
    820      1.1  mrg                 "profiling:%s:Error writing\n",
    821      1.1  mrg                 gf->filename);
    822      1.1  mrg }
    823      1.1  mrg 
    824      1.1  mrg 
    825      1.1  mrg /* Dump all the coverage counts for the program. It first computes program
    826      1.1  mrg    summary and then traverses gcov_list list and dumps the gcov_info
    827      1.1  mrg    objects one by one.  */
    828      1.1  mrg 
    829      1.1  mrg #if !IN_GCOV_TOOL
    830      1.1  mrg static
    831      1.1  mrg #endif
    832      1.1  mrg void
    833      1.1  mrg gcov_do_dump (struct gcov_info *list, int run_counted)
    834      1.1  mrg {
    835      1.1  mrg   struct gcov_info *gi_ptr;
    836      1.1  mrg   struct gcov_filename gf;
    837      1.1  mrg   gcov_unsigned_t crc32;
    838      1.1  mrg   struct gcov_summary all_prg;
    839      1.1  mrg   struct gcov_summary this_prg;
    840      1.1  mrg 
    841      1.1  mrg   crc32 = compute_summary (list, &this_prg, &gf.max_length);
    842      1.1  mrg 
    843      1.1  mrg   allocate_filename_struct (&gf);
    844      1.1  mrg #if !GCOV_LOCKED
    845      1.1  mrg   memset (&all_prg, 0, sizeof (all_prg));
    846      1.1  mrg #endif
    847      1.1  mrg 
    848      1.1  mrg   /* Now merge each file.  */
    849      1.1  mrg   for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
    850      1.1  mrg     dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
    851      1.1  mrg 
    852      1.1  mrg   free (gf.filename);
    853      1.1  mrg }
    854      1.1  mrg 
    855  1.1.1.2  mrg #if IN_GCOV_TOOL
    856  1.1.1.2  mrg const char *
    857  1.1.1.2  mrg __attribute__ ((unused))
    858  1.1.1.2  mrg gcov_get_filename (struct gcov_info *list)
    859  1.1.1.2  mrg {
    860  1.1.1.2  mrg   return list->filename;
    861  1.1.1.2  mrg }
    862  1.1.1.2  mrg #endif
    863  1.1.1.2  mrg 
    864      1.1  mrg #if !IN_GCOV_TOOL
    865      1.1  mrg void
    866      1.1  mrg __gcov_dump_one (struct gcov_root *root)
    867      1.1  mrg {
    868      1.1  mrg   if (root->dumped)
    869      1.1  mrg     return;
    870      1.1  mrg 
    871      1.1  mrg   gcov_do_dump (root->list, root->run_counted);
    872      1.1  mrg 
    873      1.1  mrg   root->dumped = 1;
    874      1.1  mrg   root->run_counted = 1;
    875      1.1  mrg }
    876      1.1  mrg 
    877      1.1  mrg /* Per-dynamic-object gcov state.  */
    878      1.1  mrg struct gcov_root __gcov_root;
    879      1.1  mrg 
    880      1.1  mrg /* Exactly one of these will be live in the process image.  */
    881      1.1  mrg struct gcov_master __gcov_master =
    882      1.1  mrg   {GCOV_VERSION, 0};
    883      1.1  mrg 
    884  1.1.1.4  mrg void
    885  1.1.1.4  mrg __gcov_exit (void)
    886      1.1  mrg {
    887      1.1  mrg   __gcov_dump_one (&__gcov_root);
    888      1.1  mrg   if (__gcov_root.next)
    889      1.1  mrg     __gcov_root.next->prev = __gcov_root.prev;
    890      1.1  mrg   if (__gcov_root.prev)
    891      1.1  mrg     __gcov_root.prev->next = __gcov_root.next;
    892      1.1  mrg   else
    893      1.1  mrg     __gcov_master.root = __gcov_root.next;
    894  1.1.1.4  mrg 
    895  1.1.1.4  mrg   gcov_error_exit ();
    896      1.1  mrg }
    897      1.1  mrg 
    898      1.1  mrg /* Add a new object file onto the bb chain.  Invoked automatically
    899      1.1  mrg   when running an object file's global ctors.  */
    900      1.1  mrg 
    901      1.1  mrg void
    902      1.1  mrg __gcov_init (struct gcov_info *info)
    903      1.1  mrg {
    904      1.1  mrg   if (!info->version || !info->n_functions)
    905      1.1  mrg     return;
    906      1.1  mrg   if (gcov_version (info, info->version, 0))
    907      1.1  mrg     {
    908      1.1  mrg       if (!__gcov_root.list)
    909      1.1  mrg 	{
    910      1.1  mrg 	  /* Add to master list and at exit function.  */
    911      1.1  mrg 	  if (gcov_version (NULL, __gcov_master.version, "<master>"))
    912      1.1  mrg 	    {
    913      1.1  mrg 	      __gcov_root.next = __gcov_master.root;
    914      1.1  mrg 	      if (__gcov_master.root)
    915      1.1  mrg 		__gcov_master.root->prev = &__gcov_root;
    916      1.1  mrg 	      __gcov_master.root = &__gcov_root;
    917      1.1  mrg 	    }
    918      1.1  mrg 	}
    919      1.1  mrg 
    920      1.1  mrg       info->next = __gcov_root.list;
    921      1.1  mrg       __gcov_root.list = info;
    922      1.1  mrg     }
    923      1.1  mrg }
    924      1.1  mrg #endif /* !IN_GCOV_TOOL */
    925      1.1  mrg #endif /* L_gcov */
    926      1.1  mrg #endif /* inhibit_libc */
    927