1 /* Routines required for instrumenting a program.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1989-2018 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