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