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