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