xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/libgcov-util.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /* Utility functions for reading gcda files into in-memory
2    gcov_info structures and offline profile processing. */
3 /* Copyright (C) 2014-2019 Free Software Foundation, Inc.
4    Contributed by Rong Xu <xur@google.com>.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21 
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 <http://www.gnu.org/licenses/>.  */
26 
27 
28 #define IN_GCOV_TOOL 1
29 
30 #include "libgcov.h"
31 #include "intl.h"
32 #include "diagnostic.h"
33 #include "version.h"
34 #include "demangle.h"
35 #include "gcov-io.h"
36 
37 /* Borrowed from basic-block.h.  */
38 #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
39 
40 extern gcov_position_t gcov_position();
41 extern int gcov_is_error();
42 
43 /* Verbose mode for debug.  */
44 static int verbose;
45 
46 /* Set verbose flag.  */
47 void gcov_set_verbose (void)
48 {
49   verbose = 1;
50 }
51 
52 /* The following part is to read Gcda and reconstruct GCOV_INFO.  */
53 
54 #include "obstack.h"
55 #include <unistd.h>
56 #ifdef HAVE_FTW_H
57 #include <ftw.h>
58 #endif
59 
60 static void tag_function (unsigned, unsigned);
61 static void tag_blocks (unsigned, unsigned);
62 static void tag_arcs (unsigned, unsigned);
63 static void tag_lines (unsigned, unsigned);
64 static void tag_counters (unsigned, unsigned);
65 static void tag_summary (unsigned, unsigned);
66 
67 /* The gcov_info for the first module.  */
68 static struct gcov_info *curr_gcov_info;
69 /* The gcov_info being processed.  */
70 static struct gcov_info *gcov_info_head;
71 /* This variable contains all the functions in current module.  */
72 static struct obstack fn_info;
73 /* The function being processed.  */
74 static struct gcov_fn_info *curr_fn_info;
75 /* The number of functions seen so far.  */
76 static unsigned num_fn_info;
77 /* This variable contains all the counters for current module.  */
78 static int k_ctrs_mask[GCOV_COUNTERS];
79 /* The kind of counters that have been seen.  */
80 static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
81 /* Number of kind of counters that have been seen.  */
82 static int k_ctrs_types;
83 /* The object summary being processed.  */
84 static struct gcov_summary *curr_object_summary;
85 
86 /* Merge functions for counters.  */
87 #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
88 static gcov_merge_fn ctr_merge_functions[GCOV_COUNTERS] = {
89 #include "gcov-counter.def"
90 };
91 #undef DEF_GCOV_COUNTER
92 
93 /* Set the ctrs field in gcov_fn_info object FN_INFO.  */
94 
95 static void
96 set_fn_ctrs (struct gcov_fn_info *fn_info)
97 {
98   int j = 0, i;
99 
100   for (i = 0; i < GCOV_COUNTERS; i++)
101     {
102       if (k_ctrs_mask[i] == 0)
103         continue;
104       fn_info->ctrs[j].num = k_ctrs[i].num;
105       fn_info->ctrs[j].values = k_ctrs[i].values;
106       j++;
107     }
108   if (k_ctrs_types == 0)
109     k_ctrs_types = j;
110   else
111     gcc_assert (j == k_ctrs_types);
112 }
113 
114 /* For each tag in gcda file, we have an entry here.
115    TAG is the tag value; NAME is the tag name; and
116    PROC is the handler function.  */
117 
118 typedef struct tag_format
119 {
120     unsigned tag;
121     char const *name;
122     void (*proc) (unsigned, unsigned);
123 } tag_format_t;
124 
125 /* Handler table for various Tags.  */
126 
127 static const tag_format_t tag_table[] =
128 {
129   {0, "NOP", NULL},
130   {0, "UNKNOWN", NULL},
131   {0, "COUNTERS", tag_counters},
132   {GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
133   {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
134   {GCOV_TAG_ARCS, "ARCS", tag_arcs},
135   {GCOV_TAG_LINES, "LINES", tag_lines},
136   {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
137   {0, NULL, NULL}
138 };
139 
140 /* Handler for reading function tag.  */
141 
142 static void
143 tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
144 {
145   int i;
146 
147   /* write out previous fn_info.  */
148   if (num_fn_info)
149     {
150       set_fn_ctrs (curr_fn_info);
151       obstack_ptr_grow (&fn_info, curr_fn_info);
152     }
153 
154   /* Here we over allocate a bit, using GCOV_COUNTERS instead of the actual active
155      counter types.  */
156   curr_fn_info = (struct gcov_fn_info *) xcalloc (sizeof (struct gcov_fn_info)
157                    + GCOV_COUNTERS * sizeof (struct gcov_ctr_info), 1);
158 
159   for (i = 0; i < GCOV_COUNTERS; i++)
160      k_ctrs[i].num = 0;
161   k_ctrs_types = 0;
162 
163   curr_fn_info->key = curr_gcov_info;
164   curr_fn_info->ident = gcov_read_unsigned ();
165   curr_fn_info->lineno_checksum = gcov_read_unsigned ();
166   curr_fn_info->cfg_checksum = gcov_read_unsigned ();
167   num_fn_info++;
168 
169   if (verbose)
170     fnotice (stdout, "tag one function id=%d\n", curr_fn_info->ident);
171 }
172 
173 /* Handler for reading block tag.  */
174 
175 static void
176 tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
177 {
178   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
179   gcc_unreachable ();
180 }
181 
182 /* Handler for reading flow arc tag.  */
183 
184 static void
185 tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
186 {
187   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
188   gcc_unreachable ();
189 }
190 
191 /* Handler for reading line tag.  */
192 
193 static void
194 tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
195 {
196   /* TBD: gcov-tool currently does not handle gcno files. Assert here.  */
197   gcc_unreachable ();
198 }
199 
200 /* Handler for reading counters array tag with value as TAG and length of LENGTH.  */
201 
202 static void
203 tag_counters (unsigned tag, unsigned length)
204 {
205   unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
206   gcov_type *values;
207   unsigned ix;
208   unsigned tag_ix;
209 
210   tag_ix = GCOV_COUNTER_FOR_TAG (tag);
211   gcc_assert (tag_ix < GCOV_COUNTERS);
212   k_ctrs_mask [tag_ix] = 1;
213   gcc_assert (k_ctrs[tag_ix].num == 0);
214   k_ctrs[tag_ix].num = n_counts;
215 
216   k_ctrs[tag_ix].values = values = (gcov_type *) xmalloc (n_counts * sizeof (gcov_type));
217   gcc_assert (values);
218 
219   for (ix = 0; ix != n_counts; ix++)
220     values[ix] = gcov_read_counter ();
221 }
222 
223 /* Handler for reading summary tag.  */
224 
225 static void
226 tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
227 {
228   curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1);
229   gcov_read_summary (curr_object_summary);
230 }
231 
232 /* This function is called at the end of reading a gcda file.
233    It flushes the contents in curr_fn_info to gcov_info object OBJ_INFO.  */
234 
235 static void
236 read_gcda_finalize (struct gcov_info *obj_info)
237 {
238   int i;
239 
240   set_fn_ctrs (curr_fn_info);
241   obstack_ptr_grow (&fn_info, curr_fn_info);
242 
243   /* We set the following fields: merge, n_functions, functions
244      and summary.  */
245   obj_info->n_functions = num_fn_info;
246   obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info);
247 
248   /* wrap all the counter array.  */
249   for (i=0; i< GCOV_COUNTERS; i++)
250     {
251       if (k_ctrs_mask[i])
252         obj_info->merge[i] = ctr_merge_functions[i];
253     }
254 }
255 
256 /* Read the content of a gcda file FILENAME, and return a gcov_info data structure.
257    Program level summary CURRENT_SUMMARY will also be updated.  */
258 
259 static struct gcov_info *
260 read_gcda_file (const char *filename)
261 {
262   unsigned tags[4];
263   unsigned depth = 0;
264   unsigned magic, version;
265   struct gcov_info *obj_info;
266   int i;
267 
268   for (i=0; i< GCOV_COUNTERS; i++)
269     k_ctrs_mask[i] = 0;
270   k_ctrs_types = 0;
271 
272   if (!gcov_open (filename))
273     {
274       fnotice (stderr, "%s:cannot open\n", filename);
275       return NULL;
276     }
277 
278   /* Read magic.  */
279   magic = gcov_read_unsigned ();
280   if (magic != GCOV_DATA_MAGIC)
281     {
282       fnotice (stderr, "%s:not a gcov data file\n", filename);
283       gcov_close ();
284       return NULL;
285     }
286 
287   /* Read version.  */
288   version = gcov_read_unsigned ();
289   if (version != GCOV_VERSION)
290     {
291       fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION);
292       gcov_close ();
293       return NULL;
294     }
295 
296   /* Instantiate a gcov_info object.  */
297   curr_gcov_info = obj_info = (struct gcov_info *) xcalloc (sizeof (struct gcov_info) +
298              sizeof (struct gcov_ctr_info) * GCOV_COUNTERS, 1);
299 
300   obj_info->version = version;
301   obstack_init (&fn_info);
302   num_fn_info = 0;
303   curr_fn_info = 0;
304   curr_object_summary = NULL;
305   {
306     size_t len = strlen (filename) + 1;
307     char *str_dup = (char*) xmalloc (len);
308 
309     memcpy (str_dup, filename, len);
310     obj_info->filename = str_dup;
311   }
312 
313   /* Read stamp.  */
314   obj_info->stamp = gcov_read_unsigned ();
315 
316   while (1)
317     {
318       gcov_position_t base;
319       unsigned tag, length;
320       tag_format_t const *format;
321       unsigned tag_depth;
322       int error;
323       unsigned mask;
324 
325       tag = gcov_read_unsigned ();
326       if (!tag)
327         break;
328       length = gcov_read_unsigned ();
329       base = gcov_position ();
330       mask = GCOV_TAG_MASK (tag) >> 1;
331       for (tag_depth = 4; mask; mask >>= 8)
332         {
333           if (((mask & 0xff) != 0xff))
334             {
335               warning (0, "%s:tag `%x' is invalid\n", filename, tag);
336               break;
337             }
338           tag_depth--;
339         }
340       for (format = tag_table; format->name; format++)
341         if (format->tag == tag)
342           goto found;
343       format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
344     found:;
345       if (tag)
346         {
347           if (depth && depth < tag_depth)
348             {
349               if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
350                 warning (0, "%s:tag `%x' is incorrectly nested\n",
351                          filename, tag);
352             }
353           depth = tag_depth;
354           tags[depth - 1] = tag;
355         }
356 
357       if (format->proc)
358         {
359           unsigned long actual_length;
360 
361           (*format->proc) (tag, length);
362 
363           actual_length = gcov_position () - base;
364           if (actual_length > length)
365             warning (0, "%s:record size mismatch %lu bytes overread\n",
366                      filename, actual_length - length);
367           else if (length > actual_length)
368             warning (0, "%s:record size mismatch %lu bytes unread\n",
369                      filename, length - actual_length);
370        }
371 
372       gcov_sync (base, length);
373       if ((error = gcov_is_error ()))
374         {
375           warning (0, error < 0 ? "%s:counter overflow at %lu\n" :
376                                   "%s:read error at %lu\n", filename,
377                    (long unsigned) gcov_position ());
378           break;
379         }
380     }
381 
382   read_gcda_finalize (obj_info);
383   gcov_close ();
384 
385   return obj_info;
386 }
387 
388 #ifdef HAVE_FTW_H
389 /* This will be called by ftw(). It opens and read a gcda file FILENAME.
390    Return a non-zero value to stop the tree walk.  */
391 
392 static int
393 ftw_read_file (const char *filename,
394                const struct stat *status ATTRIBUTE_UNUSED,
395                int type)
396 {
397   int filename_len;
398   int suffix_len;
399   struct gcov_info *obj_info;
400 
401   /* Only read regular files.  */
402   if (type != FTW_F)
403     return 0;
404 
405   filename_len = strlen (filename);
406   suffix_len = strlen (GCOV_DATA_SUFFIX);
407 
408   if (filename_len <= suffix_len)
409     return 0;
410 
411   if (strcmp(filename + filename_len - suffix_len, GCOV_DATA_SUFFIX))
412     return 0;
413 
414   if (verbose)
415     fnotice (stderr, "reading file: %s\n", filename);
416 
417   obj_info = read_gcda_file (filename);
418   if (!obj_info)
419     return 0;
420 
421   obj_info->next = gcov_info_head;
422   gcov_info_head = obj_info;
423 
424   return 0;
425 }
426 #endif
427 
428 /* Initializer for reading a profile dir.  */
429 
430 static inline void
431 read_profile_dir_init (void)
432 {
433   gcov_info_head = 0;
434 }
435 
436 /* Driver for read a profile directory and convert into gcov_info list in memory.
437    Return NULL on error,
438    Return the head of gcov_info list on success.  */
439 
440 struct gcov_info *
441 gcov_read_profile_dir (const char* dir_name, int recompute_summary ATTRIBUTE_UNUSED)
442 {
443   char *pwd;
444   int ret;
445 
446   read_profile_dir_init ();
447 
448   if (access (dir_name, R_OK) != 0)
449     {
450       fnotice (stderr, "cannot access directory %s\n", dir_name);
451       return NULL;
452     }
453   pwd = getcwd (NULL, 0);
454   gcc_assert (pwd);
455   ret = chdir (dir_name);
456   if (ret !=0)
457     {
458       fnotice (stderr, "%s is not a directory\n", dir_name);
459       return NULL;
460     }
461 #ifdef HAVE_FTW_H
462   ftw (".", ftw_read_file, 50);
463 #endif
464   ret = chdir (pwd);
465   free (pwd);
466 
467 
468   return gcov_info_head;;
469 }
470 
471 /* This part of the code is to merge profile counters. These
472    variables are set in merge_wrapper and to be used by
473    global function gcov_read_counter_mem() and gcov_get_merge_weight.  */
474 
475 /* We save the counter value address to this variable.  */
476 static gcov_type *gcov_value_buf;
477 
478 /* The number of counter values to be read by current merging.  */
479 static gcov_unsigned_t gcov_value_buf_size;
480 
481 /* The index of counter values being read.  */
482 static gcov_unsigned_t gcov_value_buf_pos;
483 
484 /* The weight of current merging.  */
485 static unsigned gcov_merge_weight;
486 
487 /* Read a counter value from gcov_value_buf array.  */
488 
489 gcov_type
490 gcov_read_counter_mem (void)
491 {
492   gcov_type ret;
493   gcc_assert (gcov_value_buf_pos < gcov_value_buf_size);
494   ret = *(gcov_value_buf + gcov_value_buf_pos);
495   ++gcov_value_buf_pos;
496   return ret;
497 }
498 
499 /* Return the recorded merge weight.  */
500 
501 unsigned
502 gcov_get_merge_weight (void)
503 {
504   return gcov_merge_weight;
505 }
506 
507 /* A wrapper function for merge functions. It sets up the
508    value buffer and weights and then calls the merge function.  */
509 
510 static void
511 merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n,
512                gcov_type *v2, unsigned w)
513 {
514   gcov_value_buf = v2;
515   gcov_value_buf_pos = 0;
516   gcov_value_buf_size = n;
517   gcov_merge_weight = w;
518   (*f) (v1, n);
519 }
520 
521 /* Offline tool to manipulate profile data.
522    This tool targets on matched profiles. But it has some tolerance on
523    unmatched profiles.
524    When merging p1 to p2 (p2 is the dst),
525    * m.gcda in p1 but not in p2: append m.gcda to p2 with specified weight;
526      emit warning
527    * m.gcda in p2 but not in p1: keep m.gcda in p2 and multiply by
528      specified weight; emit warning.
529    * m.gcda in both p1 and p2:
530    ** p1->m.gcda->f checksum matches p2->m.gcda->f: simple merge.
531    ** p1->m.gcda->f checksum does not matches p2->m.gcda->f: keep
532       p2->m.gcda->f and
533       drop p1->m.gcda->f. A warning is emitted.  */
534 
535 /* Add INFO2's counter to INFO1, multiplying by weight W.  */
536 
537 static int
538 gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
539 {
540   unsigned f_ix;
541   unsigned n_functions = info1->n_functions;
542   int has_mismatch = 0;
543 
544   gcc_assert (info2->n_functions == n_functions);
545   for (f_ix = 0; f_ix < n_functions; f_ix++)
546     {
547       unsigned t_ix;
548       const struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
549       const struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
550       const struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
551 
552       if (!gfi_ptr1 || gfi_ptr1->key != info1)
553         continue;
554       if (!gfi_ptr2 || gfi_ptr2->key != info2)
555         continue;
556 
557       if (gfi_ptr1->cfg_checksum != gfi_ptr2->cfg_checksum)
558         {
559           fnotice (stderr, "in %s, cfg_checksum mismatch, skipping\n",
560                   info1->filename);
561           has_mismatch = 1;
562           continue;
563         }
564       ci_ptr1 = gfi_ptr1->ctrs;
565       ci_ptr2 = gfi_ptr2->ctrs;
566       for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
567         {
568           gcov_merge_fn merge1 = info1->merge[t_ix];
569           gcov_merge_fn merge2 = info2->merge[t_ix];
570 
571           gcc_assert (merge1 == merge2);
572           if (!merge1)
573             continue;
574           gcc_assert (ci_ptr1->num == ci_ptr2->num);
575           merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, ci_ptr2->values, w);
576           ci_ptr1++;
577           ci_ptr2++;
578         }
579     }
580 
581   return has_mismatch;
582 }
583 
584 /* Find and return the match gcov_info object for INFO from ARRAY.
585    SIZE is the length of ARRAY.
586    Return NULL if there is no match.  */
587 
588 static struct gcov_info *
589 find_match_gcov_info (struct gcov_info **array, int size,
590 		      struct gcov_info *info)
591 {
592   struct gcov_info *gi_ptr;
593   struct gcov_info *ret = NULL;
594   int i;
595 
596   for (i = 0; i < size; i++)
597     {
598       gi_ptr = array[i];
599       if (gi_ptr == 0)
600         continue;
601       if (!strcmp (gi_ptr->filename, info->filename))
602         {
603           ret = gi_ptr;
604           array[i] = 0;
605           break;
606         }
607     }
608 
609   if (ret && ret->n_functions != info->n_functions)
610     {
611       fnotice (stderr, "mismatched profiles in %s (%d functions"
612                        " vs %d functions)\n",
613                        ret->filename,
614                        ret->n_functions,
615                        info->n_functions);
616       ret = NULL;
617     }
618   return ret;
619 }
620 
621 /* Merge the list of gcov_info objects from SRC_PROFILE to TGT_PROFILE.
622    Return 0 on success: without mismatch.
623    Reutrn 1 on error.  */
624 
625 int
626 gcov_profile_merge (struct gcov_info *tgt_profile, struct gcov_info *src_profile,
627                     int w1, int w2)
628 {
629   struct gcov_info *gi_ptr;
630   struct gcov_info **tgt_infos;
631   struct gcov_info *tgt_tail;
632   struct gcov_info **in_src_not_tgt;
633   unsigned tgt_cnt = 0, src_cnt = 0;
634   unsigned unmatch_info_cnt = 0;
635   unsigned int i;
636 
637   for (gi_ptr = tgt_profile; gi_ptr; gi_ptr = gi_ptr->next)
638     tgt_cnt++;
639   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
640     src_cnt++;
641   tgt_infos = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
642                  * tgt_cnt);
643   gcc_assert (tgt_infos);
644   in_src_not_tgt = (struct gcov_info **) xmalloc (sizeof (struct gcov_info *)
645                      * src_cnt);
646   gcc_assert (in_src_not_tgt);
647 
648   for (gi_ptr = tgt_profile, i = 0; gi_ptr; gi_ptr = gi_ptr->next, i++)
649     tgt_infos[i] = gi_ptr;
650 
651   tgt_tail = tgt_infos[tgt_cnt - 1];
652 
653   /* First pass on tgt_profile, we multiply w1 to all counters.  */
654   if (w1 > 1)
655     {
656        for (i = 0; i < tgt_cnt; i++)
657          gcov_merge (tgt_infos[i], tgt_infos[i], w1-1);
658     }
659 
660   /* Second pass, add src_profile to the tgt_profile.  */
661   for (gi_ptr = src_profile; gi_ptr; gi_ptr = gi_ptr->next)
662     {
663       struct gcov_info *gi_ptr1;
664 
665       gi_ptr1 = find_match_gcov_info (tgt_infos, tgt_cnt, gi_ptr);
666       if (gi_ptr1 == NULL)
667         {
668           in_src_not_tgt[unmatch_info_cnt++] = gi_ptr;
669           continue;
670         }
671       gcov_merge (gi_ptr1, gi_ptr, w2);
672     }
673 
674   /* For modules in src but not in tgt. We adjust the counter and append.  */
675   for (i = 0; i < unmatch_info_cnt; i++)
676     {
677       gi_ptr = in_src_not_tgt[i];
678       gcov_merge (gi_ptr, gi_ptr, w2 - 1);
679       gi_ptr->next = NULL;
680       tgt_tail->next = gi_ptr;
681       tgt_tail = gi_ptr;
682     }
683 
684   return 0;
685 }
686 
687 typedef gcov_type (*counter_op_fn) (gcov_type, void*, void*);
688 
689 /* Performing FN upon arc counters.  */
690 
691 static void
692 __gcov_add_counter_op (gcov_type *counters, unsigned n_counters,
693                        counter_op_fn fn, void *data1, void *data2)
694 {
695   for (; n_counters; counters++, n_counters--)
696     {
697       gcov_type val = *counters;
698       *counters = fn(val, data1, data2);
699     }
700 }
701 
702 /* Performing FN upon ior counters.  */
703 
704 static void
705 __gcov_ior_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
706                        unsigned n_counters ATTRIBUTE_UNUSED,
707                        counter_op_fn fn ATTRIBUTE_UNUSED,
708                        void *data1 ATTRIBUTE_UNUSED,
709                        void *data2 ATTRIBUTE_UNUSED)
710 {
711   /* Do nothing.  */
712 }
713 
714 /* Performing FN upon time-profile counters.  */
715 
716 static void
717 __gcov_time_profile_counter_op (gcov_type *counters ATTRIBUTE_UNUSED,
718                                 unsigned n_counters ATTRIBUTE_UNUSED,
719                                 counter_op_fn fn ATTRIBUTE_UNUSED,
720                                 void *data1 ATTRIBUTE_UNUSED,
721                                 void *data2 ATTRIBUTE_UNUSED)
722 {
723   /* Do nothing.  */
724 }
725 
726 /* Performing FN upon single counters.  */
727 
728 static void
729 __gcov_single_counter_op (gcov_type *counters, unsigned n_counters,
730                           counter_op_fn fn, void *data1, void *data2)
731 {
732   unsigned i, n_measures;
733 
734   gcc_assert (!(n_counters % 3));
735   n_measures = n_counters / 3;
736   for (i = 0; i < n_measures; i++, counters += 3)
737     {
738       counters[1] = fn (counters[1], data1, data2);
739       counters[2] = fn (counters[2], data1, data2);
740     }
741 }
742 
743 /* Performing FN upon indirect-call profile counters.  */
744 
745 static void
746 __gcov_icall_topn_counter_op (gcov_type *counters, unsigned n_counters,
747                               counter_op_fn fn, void *data1, void *data2)
748 {
749   unsigned i;
750 
751   gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
752   for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
753     {
754       unsigned j;
755       gcov_type *value_array = &counters[i + 1];
756 
757       for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
758         value_array[j + 1] = fn (value_array[j + 1], data1, data2);
759     }
760 }
761 
762 /* Scaling the counter value V by multiplying *(float*) DATA1.  */
763 
764 static gcov_type
765 fp_scale (gcov_type v, void *data1, void *data2 ATTRIBUTE_UNUSED)
766 {
767   float f = *(float *) data1;
768   return (gcov_type) (v * f);
769 }
770 
771 /* Scaling the counter value V by multiplying DATA2/DATA1.  */
772 
773 static gcov_type
774 int_scale (gcov_type v, void *data1, void *data2)
775 {
776   int n = *(int *) data1;
777   int d = *(int *) data2;
778   return (gcov_type) ( RDIV (v,d) * n);
779 }
780 
781 /* Type of function used to process counters.  */
782 typedef void (*gcov_counter_fn) (gcov_type *, gcov_unsigned_t,
783                           counter_op_fn, void *, void *);
784 
785 /* Function array to process profile counters.  */
786 #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) \
787   __gcov ## FN_TYPE ## _counter_op,
788 static gcov_counter_fn ctr_functions[GCOV_COUNTERS] = {
789 #include "gcov-counter.def"
790 };
791 #undef DEF_GCOV_COUNTER
792 
793 /* Driver for scaling profile counters.  */
794 
795 int
796 gcov_profile_scale (struct gcov_info *profile, float scale_factor, int n, int d)
797 {
798   struct gcov_info *gi_ptr;
799   unsigned f_ix;
800 
801   if (verbose)
802     fnotice (stdout, "scale_factor is %f or %d/%d\n", scale_factor, n, d);
803 
804   /* Scaling the counters.  */
805   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
806     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
807       {
808         unsigned t_ix;
809         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
810         const struct gcov_ctr_info *ci_ptr;
811 
812         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
813           continue;
814 
815         ci_ptr = gfi_ptr->ctrs;
816         for (t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
817           {
818             gcov_merge_fn merge = gi_ptr->merge[t_ix];
819 
820             if (!merge)
821               continue;
822             if (d == 0)
823               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
824                                       fp_scale, &scale_factor, NULL);
825             else
826               (*ctr_functions[t_ix]) (ci_ptr->values, ci_ptr->num,
827                                       int_scale, &n, &d);
828             ci_ptr++;
829           }
830       }
831 
832   return 0;
833 }
834 
835 /* Driver to normalize profile counters.  */
836 
837 int
838 gcov_profile_normalize (struct gcov_info *profile, gcov_type max_val)
839 {
840   struct gcov_info *gi_ptr;
841   gcov_type curr_max_val = 0;
842   unsigned f_ix;
843   unsigned int i;
844   float scale_factor;
845 
846   /* Find the largest count value.  */
847   for (gi_ptr = profile; gi_ptr; gi_ptr = gi_ptr->next)
848     for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++)
849       {
850         unsigned t_ix;
851         const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
852         const struct gcov_ctr_info *ci_ptr;
853 
854         if (!gfi_ptr || gfi_ptr->key != gi_ptr)
855           continue;
856 
857         ci_ptr = gfi_ptr->ctrs;
858         for (t_ix = 0; t_ix < 1; t_ix++)
859           {
860             for (i = 0; i < ci_ptr->num; i++)
861               if (ci_ptr->values[i] > curr_max_val)
862                 curr_max_val = ci_ptr->values[i];
863             ci_ptr++;
864           }
865       }
866 
867   scale_factor = (float)max_val / curr_max_val;
868   if (verbose)
869     fnotice (stdout, "max_val is %" PRId64 "\n", curr_max_val);
870 
871   return gcov_profile_scale (profile, scale_factor, 0, 0);
872 }
873 
874 /* The following variables are defined in gcc/gcov-tool.c.  */
875 extern int overlap_func_level;
876 extern int overlap_obj_level;
877 extern int overlap_hot_only;
878 extern int overlap_use_fullname;
879 extern double overlap_hot_threshold;
880 
881 /* Compute the overlap score of two values. The score is defined as:
882     min (V1/SUM_1, V2/SUM_2)  */
883 
884 static double
885 calculate_2_entries (const unsigned long v1, const unsigned long v2,
886                      const double sum_1, const double sum_2)
887 {
888   double val1 = (sum_1 == 0.0 ? 0.0 : v1/sum_1);
889   double val2 = (sum_2 == 0.0 ? 0.0 : v2/sum_2);
890 
891   if (val2 < val1)
892     val1 = val2;
893 
894   return val1;
895 }
896 
897 /*  Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
898     This function also updates cumulative score CUM_1_RESULT and
899     CUM_2_RESULT.  */
900 
901 static double
902 compute_one_gcov (const struct gcov_info *gcov_info1,
903                   const struct gcov_info *gcov_info2,
904                   const double sum_1, const double sum_2,
905                   double *cum_1_result, double *cum_2_result)
906 {
907   unsigned f_ix;
908   double ret = 0;
909   double cum_1 = 0, cum_2 = 0;
910   const struct gcov_info *gcov_info = 0;
911   double *cum_p;
912   double sum;
913 
914   gcc_assert (gcov_info1 || gcov_info2);
915   if (!gcov_info1)
916     {
917       gcov_info = gcov_info2;
918       cum_p = cum_2_result;
919       sum = sum_2;
920       *cum_1_result = 0;
921     } else
922   if (!gcov_info2)
923     {
924       gcov_info = gcov_info1;
925       cum_p = cum_1_result;
926       sum = sum_1;
927       *cum_2_result = 0;
928     }
929 
930   if (gcov_info)
931   {
932     for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
933       {
934         const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
935         if (!gfi_ptr || gfi_ptr->key != gcov_info)
936           continue;
937         const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
938 	unsigned c_num;
939 	for (c_num = 0; c_num < ci_ptr->num; c_num++)
940 	  cum_1 += ci_ptr->values[c_num] / sum;
941       }
942     *cum_p = cum_1;
943     return 0.0;
944   }
945 
946   for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
947     {
948       double func_cum_1 = 0.0;
949       double func_cum_2 = 0.0;
950       double func_val = 0.0;
951       int nonzero = 0;
952       int hot = 0;
953       const struct gcov_fn_info *gfi_ptr1 = gcov_info1->functions[f_ix];
954       const struct gcov_fn_info *gfi_ptr2 = gcov_info2->functions[f_ix];
955 
956       if (!gfi_ptr1 || gfi_ptr1->key != gcov_info1)
957         continue;
958       if (!gfi_ptr2 || gfi_ptr2->key != gcov_info2)
959         continue;
960 
961       const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
962       const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
963       unsigned c_num;
964       for (c_num = 0; c_num < ci_ptr1->num; c_num++)
965 	{
966 	  if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
967 	    {
968 	      func_val += calculate_2_entries (ci_ptr1->values[c_num],
969 					       ci_ptr2->values[c_num],
970 					       sum_1, sum_2);
971 
972 	      func_cum_1 += ci_ptr1->values[c_num] / sum_1;
973 	      func_cum_2 += ci_ptr2->values[c_num] / sum_2;
974 	      nonzero = 1;
975 	      if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
976 		  || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
977 		hot = 1;
978 	    }
979 	}
980 
981       ret += func_val;
982       cum_1 += func_cum_1;
983       cum_2 += func_cum_2;
984       if (overlap_func_level && nonzero && (!overlap_hot_only || hot))
985         {
986           printf("   \tfunc_id=%10d \toverlap =%6.5f%% (%5.5f%% %5.5f%%)\n",
987                  gfi_ptr1->ident, func_val*100, func_cum_1*100, func_cum_2*100);
988         }
989     }
990   *cum_1_result = cum_1;
991   *cum_2_result = cum_2;
992   return ret;
993 }
994 
995 /* Test if all counter values in this GCOV_INFO are cold.
996    "Cold" is defined as the counter value being less than
997    or equal to THRESHOLD.  */
998 
999 static bool
1000 gcov_info_count_all_cold (const struct gcov_info *gcov_info,
1001                           gcov_type threshold)
1002 {
1003   unsigned f_ix;
1004 
1005   for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
1006     {
1007       const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
1008 
1009       if (!gfi_ptr || gfi_ptr->key != gcov_info)
1010         continue;
1011       const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
1012       for (unsigned c_num = 0; c_num < ci_ptr->num; c_num++)
1013 	if (ci_ptr->values[c_num] > threshold)
1014 	  return false;
1015     }
1016 
1017   return true;
1018 }
1019 
1020 /* Test if all counter values in this GCOV_INFO are 0.  */
1021 
1022 static bool
1023 gcov_info_count_all_zero (const struct gcov_info *gcov_info)
1024 {
1025   return gcov_info_count_all_cold (gcov_info, 0);
1026 }
1027 
1028 /* A pair of matched GCOV_INFO.
1029    The flag is a bitvector:
1030      b0: obj1's all counts are 0;
1031      b1: obj1's all counts are cold (but no 0);
1032      b2: obj1 is hot;
1033      b3: no obj1 to match obj2;
1034      b4: obj2's all counts are 0;
1035      b5: obj2's all counts are cold (but no 0);
1036      b6: obj2 is hot;
1037      b7: no obj2 to match obj1;
1038  */
1039 struct overlap_t {
1040    const struct gcov_info *obj1;
1041    const struct gcov_info *obj2;
1042    char flag;
1043 };
1044 
1045 #define FLAG_BOTH_ZERO(flag) ((flag & 0x1) && (flag & 0x10))
1046 #define FLAG_BOTH_COLD(flag) ((flag & 0x2) && (flag & 0x20))
1047 #define FLAG_ONE_HOT(flag) ((flag & 0x4) || (flag & 0x40))
1048 
1049 /* Cumlative overlap dscore for profile1 and profile2.  */
1050 static double overlap_sum_1, overlap_sum_2;
1051 
1052 /* The number of gcda files in the profiles.  */
1053 static unsigned gcda_files[2];
1054 
1055 /* The number of unique gcda files in the profiles
1056    (not existing in the other profile).  */
1057 static unsigned unique_gcda_files[2];
1058 
1059 /* The number of gcda files that all counter values are 0.  */
1060 static unsigned zero_gcda_files[2];
1061 
1062 /* The number of gcda files that all counter values are cold (but not 0).  */
1063 static unsigned cold_gcda_files[2];
1064 
1065 /* The number of gcda files that includes hot counter values.  */
1066 static unsigned hot_gcda_files[2];
1067 
1068 /* The number of gcda files with hot count value in either profiles.  */
1069 static unsigned both_hot_cnt;
1070 
1071 /* The number of gcda files with all counts cold (but not 0) in
1072    both profiles. */
1073 static unsigned both_cold_cnt;
1074 
1075 /* The number of gcda files with all counts 0 in both profiles.  */
1076 static unsigned both_zero_cnt;
1077 
1078 /* Extract the basename of the filename NAME.  */
1079 
1080 static char *
1081 extract_file_basename (const char *name)
1082 {
1083   char *str;
1084   int len = 0;
1085   char *path = xstrdup (name);
1086   char sep_str[2];
1087 
1088   sep_str[0] = DIR_SEPARATOR;
1089   sep_str[1] = 0;
1090   str = strstr(path, sep_str);
1091   do{
1092       len = strlen(str) + 1;
1093       path = &path[strlen(path) - len + 2];
1094       str = strstr(path, sep_str);
1095   } while(str);
1096 
1097   return path;
1098 }
1099 
1100 /* Utility function to get the filename.  */
1101 
1102 static const char *
1103 get_file_basename (const char *name)
1104 {
1105   if (overlap_use_fullname)
1106     return name;
1107   return extract_file_basename (name);
1108 }
1109 
1110 /* A utility function to set the flag for the gcda files.  */
1111 
1112 static void
1113 set_flag (struct overlap_t *e)
1114 {
1115   char flag = 0;
1116 
1117   if (!e->obj1)
1118     {
1119       unique_gcda_files[1]++;
1120       flag = 0x8;
1121     }
1122   else
1123     {
1124       gcda_files[0]++;
1125       if (gcov_info_count_all_zero (e->obj1))
1126         {
1127           zero_gcda_files[0]++;
1128           flag = 0x1;
1129         }
1130       else
1131       if (gcov_info_count_all_cold (e->obj1, overlap_sum_1
1132 			      * overlap_hot_threshold))
1133         {
1134           cold_gcda_files[0]++;
1135           flag = 0x2;
1136         }
1137       else
1138         {
1139           hot_gcda_files[0]++;
1140           flag = 0x4;
1141         }
1142     }
1143 
1144   if (!e->obj2)
1145     {
1146       unique_gcda_files[0]++;
1147       flag |= (0x8 << 4);
1148     }
1149   else
1150     {
1151       gcda_files[1]++;
1152       if (gcov_info_count_all_zero (e->obj2))
1153         {
1154           zero_gcda_files[1]++;
1155           flag |= (0x1 << 4);
1156         }
1157       else
1158       if (gcov_info_count_all_cold (e->obj2, overlap_sum_2
1159 			      * overlap_hot_threshold))
1160         {
1161           cold_gcda_files[1]++;
1162           flag |= (0x2 << 4);
1163         }
1164       else
1165         {
1166           hot_gcda_files[1]++;
1167           flag |= (0x4 << 4);
1168         }
1169     }
1170 
1171   gcc_assert (flag);
1172   e->flag = flag;
1173 }
1174 
1175 /* Test if INFO1 and INFO2 are from the matched source file.
1176    Return 1 if they match; return 0 otherwise.  */
1177 
1178 static int
1179 matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
1180 {
1181   /* For FDO, we have to match the name. This can be expensive.
1182      Maybe we should use hash here.  */
1183   if (strcmp (info1->filename, info2->filename))
1184     return 0;
1185 
1186   if (info1->n_functions != info2->n_functions)
1187     {
1188       fnotice (stderr, "mismatched profiles in %s (%d functions"
1189                        " vs %d functions)\n",
1190                        info1->filename,
1191                        info1->n_functions,
1192                        info2->n_functions);
1193       return 0;
1194     }
1195   return 1;
1196 }
1197 
1198 /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
1199    GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
1200    match and 1.0 meaning a perfect match.  */
1201 
1202 static double
1203 calculate_overlap (struct gcov_info *gcov_list1,
1204                    struct gcov_info *gcov_list2)
1205 {
1206   unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
1207   unsigned int i, j;
1208   const struct gcov_info *gi_ptr;
1209   struct overlap_t *all_infos;
1210 
1211   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
1212     list1_cnt++;
1213   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
1214     list2_cnt++;
1215   all_cnt = list1_cnt + list2_cnt;
1216   all_infos = (struct overlap_t *) xmalloc (sizeof (struct overlap_t)
1217                * all_cnt * 2);
1218   gcc_assert (all_infos);
1219 
1220   i = 0;
1221   for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next, i++)
1222     {
1223       all_infos[i].obj1 = gi_ptr;
1224       all_infos[i].obj2 = 0;
1225     }
1226 
1227   for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next, i++)
1228     {
1229       all_infos[i].obj1 = 0;
1230       all_infos[i].obj2 = gi_ptr;
1231     }
1232 
1233   for (i = list1_cnt; i < all_cnt; i++)
1234     {
1235       if (all_infos[i].obj2 == 0)
1236         continue;
1237       for (j = 0; j < list1_cnt; j++)
1238         {
1239           if (all_infos[j].obj2 != 0)
1240             continue;
1241           if (matched_gcov_info (all_infos[i].obj2, all_infos[j].obj1))
1242             {
1243               all_infos[j].obj2 = all_infos[i].obj2;
1244               all_infos[i].obj2 = 0;
1245               break;
1246             }
1247         }
1248     }
1249 
1250   for (i = 0; i < all_cnt; i++)
1251     if (all_infos[i].obj1 || all_infos[i].obj2)
1252       {
1253         set_flag (all_infos + i);
1254         if (FLAG_ONE_HOT (all_infos[i].flag))
1255             both_hot_cnt++;
1256         if (FLAG_BOTH_COLD(all_infos[i].flag))
1257             both_cold_cnt++;
1258         if (FLAG_BOTH_ZERO(all_infos[i].flag))
1259             both_zero_cnt++;
1260       }
1261 
1262   double prg_val = 0;
1263   double sum_val = 0;
1264   double sum_cum_1 = 0;
1265   double sum_cum_2 = 0;
1266 
1267   for (i = 0; i < all_cnt; i++)
1268     {
1269       double val;
1270       double cum_1, cum_2;
1271       const char *filename;
1272 
1273       if (all_infos[i].obj1 == 0 && all_infos[i].obj2 == 0)
1274         continue;
1275       if (FLAG_BOTH_ZERO (all_infos[i].flag))
1276           continue;
1277 
1278       if (all_infos[i].obj1)
1279         filename = get_file_basename (all_infos[i].obj1->filename);
1280       else
1281         filename = get_file_basename (all_infos[i].obj2->filename);
1282 
1283       if (overlap_func_level)
1284         printf("\n   processing %36s:\n", filename);
1285 
1286       val = compute_one_gcov (all_infos[i].obj1, all_infos[i].obj2,
1287           overlap_sum_1, overlap_sum_2, &cum_1, &cum_2);
1288 
1289       if (overlap_obj_level && (!overlap_hot_only || FLAG_ONE_HOT (all_infos[i].flag)))
1290         {
1291           printf("   obj=%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
1292                   filename, val*100, cum_1*100, cum_2*100);
1293           sum_val += val;
1294           sum_cum_1 += cum_1;
1295           sum_cum_2 += cum_2;
1296         }
1297 
1298       prg_val += val;
1299 
1300     }
1301 
1302   if (overlap_obj_level)
1303     printf("   SUM:%36s  overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
1304            "", sum_val*100, sum_cum_1*100, sum_cum_2*100);
1305 
1306   printf ("  Statistics:\n"
1307           "                    profile1_#     profile2_#       overlap_#\n");
1308   printf ("    gcda files:  %12u\t%12u\t%12u\n", gcda_files[0], gcda_files[1],
1309 	  gcda_files[0]-unique_gcda_files[0]);
1310   printf ("  unique files:  %12u\t%12u\n", unique_gcda_files[0],
1311 	  unique_gcda_files[1]);
1312   printf ("     hot files:  %12u\t%12u\t%12u\n", hot_gcda_files[0],
1313 	  hot_gcda_files[1], both_hot_cnt);
1314   printf ("    cold files:  %12u\t%12u\t%12u\n", cold_gcda_files[0],
1315 	  cold_gcda_files[1], both_cold_cnt);
1316   printf ("    zero files:  %12u\t%12u\t%12u\n", zero_gcda_files[0],
1317 	  zero_gcda_files[1], both_zero_cnt);
1318 
1319   return prg_val;
1320 }
1321 
1322 /* Compute the overlap score of two lists of gcov_info objects PROFILE1 and
1323    PROFILE2.
1324    Return 0 on success: without mismatch. Reutrn 1 on error.  */
1325 
1326 int
1327 gcov_profile_overlap (struct gcov_info *profile1, struct gcov_info *profile2)
1328 {
1329   double result;
1330 
1331   result = calculate_overlap (profile1, profile2);
1332 
1333   if (result > 0)
1334     {
1335       printf("\nProgram level overlap result is %3.2f%%\n\n", result*100);
1336       return 0;
1337     }
1338   return 1;
1339 }
1340