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