diff libgcc/libgcov-driver.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/libgcc/libgcov-driver.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/libgcc/libgcov-driver.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,6 +1,6 @@
 /* Routines required for instrumenting a program.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1989-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -24,6 +24,7 @@
 <http://www.gnu.org/licenses/>.  */
 
 #include "libgcov.h"
+#include "gcov-io.h"
 
 #if defined(inhibit_libc)
 /* If libc and its header files are not available, provide dummy functions.  */
@@ -72,9 +73,8 @@
 struct gcov_filename
 {
   char *filename;  /* filename buffer */
-  size_t max_length;  /* maximum filename length */
   int strip; /* leading chars to strip from filename */
-  size_t prefix; /* chars to prepend to filename */
+  char *prefix; /* prefix string */
 };
 
 static struct gcov_fn_buffer *
@@ -157,25 +157,6 @@
   return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
 }
 
-/* Add an unsigned value to the current crc */
-
-static gcov_unsigned_t
-crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
-{
-  unsigned ix;
-
-  for (ix = 32; ix--; value <<= 1)
-    {
-      unsigned feedback;
-
-      feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
-      crc32 <<= 1;
-      crc32 ^= feedback;
-    }
-
-  return crc32;
-}
-
 /* Check if VERSION of the info block PTR matches libgcov one.
    Return 1 on success, or zero in case of versions mismatch.
    If FILENAME is not NULL, its value used for reporting purposes
@@ -199,149 +180,8 @@
   return 1;
 }
 
-/* Insert counter VALUE into HISTOGRAM.  */
-
-static void
-gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
-{
-  unsigned i;
-
-  i = gcov_histo_index(value);
-  histogram[i].num_counters++;
-  histogram[i].cum_value += value;
-  if (value < histogram[i].min_value)
-    histogram[i].min_value = value;
-}
-
-/* Computes a histogram of the arc counters to place in the summary SUM.  */
-
-static void
-gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
-{
-  struct gcov_info *gi_ptr;
-  const struct gcov_fn_info *gfi_ptr;
-  const struct gcov_ctr_info *ci_ptr;
-  struct gcov_ctr_summary *cs_ptr;
-  unsigned t_ix, f_ix, ctr_info_ix, ix;
-  int h_ix;
-
-  /* This currently only applies to arc counters.  */
-  t_ix = GCOV_COUNTER_ARCS;
-
-  /* First check if there are any counts recorded for this counter.  */
-  cs_ptr = &(sum->ctrs[t_ix]);
-  if (!cs_ptr->num)
-    return;
-
-  for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-    {
-      cs_ptr->histogram[h_ix].num_counters = 0;
-      cs_ptr->histogram[h_ix].min_value = cs_ptr->run_max;
-      cs_ptr->histogram[h_ix].cum_value = 0;
-    }
-
-  /* Walk through all the per-object structures and record each of
-     the count values in histogram.  */
-  for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
-    {
-      if (!gi_ptr->merge[t_ix])
-        continue;
-
-      /* Find the appropriate index into the gcov_ctr_info array
-         for the counter we are currently working on based on the
-         existence of the merge function pointer for this object.  */
-      for (ix = 0, ctr_info_ix = 0; ix < t_ix; ix++)
-        {
-          if (gi_ptr->merge[ix])
-            ctr_info_ix++;
-        }
-      for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
-        {
-          gfi_ptr = gi_ptr->functions[f_ix];
-
-          if (!gfi_ptr || gfi_ptr->key != gi_ptr)
-            continue;
-
-          ci_ptr = &gfi_ptr->ctrs[ctr_info_ix];
-          for (ix = 0; ix < ci_ptr->num; ix++)
-            gcov_histogram_insert (cs_ptr->histogram, ci_ptr->values[ix]);
-        }
-    }
-}
-
 /* buffer for the fn_data from another program.  */
 static struct gcov_fn_buffer *fn_buffer;
-/* buffer for summary from other programs to be written out. */
-static struct gcov_summary_buffer *sum_buffer;
-
-/* This function computes the program level summary and the histo-gram.
-   It computes and returns CRC32 and stored summary in THIS_PRG.
-   Also determines the longest filename length of the info files.  */
-
-#if !IN_GCOV_TOOL
-static
-#endif
-gcov_unsigned_t
-compute_summary (struct gcov_info *list, struct gcov_summary *this_prg,
-		 size_t *max_length)
-{
-  struct gcov_info *gi_ptr;
-  const struct gcov_fn_info *gfi_ptr;
-  struct gcov_ctr_summary *cs_ptr;
-  const struct gcov_ctr_info *ci_ptr;
-  int f_ix;
-  unsigned t_ix;
-  gcov_unsigned_t c_num;
-  gcov_unsigned_t crc32 = 0;
-
-  /* Find the totals for this execution.  */
-  memset (this_prg, 0, sizeof (*this_prg));
-  *max_length = 0;
-  for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
-    {
-      size_t len = strlen (gi_ptr->filename);
-      if (len > *max_length)
-	*max_length = len;
-      
-      crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
-      crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
-
-      for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
-        {
-          gfi_ptr = gi_ptr->functions[f_ix];
-
-          if (gfi_ptr && gfi_ptr->key != gi_ptr)
-            gfi_ptr = 0;
-
-          crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
-          crc32 = crc32_unsigned (crc32,
-                                  gfi_ptr ? gfi_ptr->lineno_checksum : 0);
-          if (!gfi_ptr)
-            continue;
-
-          ci_ptr = gfi_ptr->ctrs;
-          for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
-            {
-              if (!gi_ptr->merge[t_ix])
-                continue;
-
-              cs_ptr = &(this_prg->ctrs[t_ix]);
-              cs_ptr->num += ci_ptr->num;
-              crc32 = crc32_unsigned (crc32, ci_ptr->num);
-
-              for (c_num = 0; c_num < ci_ptr->num; c_num++)
-                {
-                  cs_ptr->sum_all += ci_ptr->values[c_num];
-                  if (cs_ptr->run_max < ci_ptr->values[c_num])
-                    cs_ptr->run_max = ci_ptr->values[c_num];
-                }
-              ci_ptr++;
-            }
-        }
-    }
-  gcov_compute_histogram (list, this_prg);
-  return crc32;
-}
 
 /* Including system dependent components. */
 #include "libgcov-driver-system.c"
@@ -353,18 +193,13 @@
 static int
 merge_one_data (const char *filename,
 		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)
+		struct gcov_summary *summary)
 {
   gcov_unsigned_t tag, length;
   unsigned t_ix;
-  int f_ix;
+  int f_ix = -1;
   int error = 0;
   struct gcov_fn_buffer **fn_tail = &fn_buffer;
-  struct gcov_summary_buffer **sum_tail = &sum_buffer;
 
   length = gcov_read_unsigned ();
   if (!gcov_version (gi_ptr, length, filename))
@@ -372,50 +207,21 @@
 
   length = gcov_read_unsigned ();
   if (length != gi_ptr->stamp)
-    /* Read from a different compilation. Overwrite the file.  */
-    return 0;
-
-  /* Look for program summary.  */
-  for (f_ix = 0;;)
     {
-      struct gcov_summary tmp;
-
-      *eof_pos_p = gcov_position ();
-      tag = gcov_read_unsigned ();
-      if (tag != GCOV_TAG_PROGRAM_SUMMARY)
-        break;
-
-      f_ix--;
-      length = gcov_read_unsigned ();
-      gcov_read_summary (&tmp);
-      if ((error = gcov_is_error ()))
-        goto read_error;
-      if (*summary_pos_p)
-        {
-          /* Save all summaries after the one that will be
-             merged into below. These will need to be rewritten
-             as histogram merging may change the number of non-zero
-             histogram entries that will be emitted, and thus the
-             size of the merged summary.  */
-          (*sum_tail) = (struct gcov_summary_buffer *)
-              xmalloc (sizeof(struct gcov_summary_buffer));
-          (*sum_tail)->summary = tmp;
-          (*sum_tail)->next = 0;
-          sum_tail = &((*sum_tail)->next);
-          goto next_summary;
-        }
-      if (tmp.checksum != crc32)
-        goto next_summary;
-
-      for (t_ix = 0; t_ix != GCOV_COUNTERS_SUMMABLE; t_ix++)
-        if (tmp.ctrs[t_ix].num != this_prg->ctrs[t_ix].num)
-          goto next_summary;
-      *prg_p = tmp;
-      *summary_pos_p = *eof_pos_p;
-
-    next_summary:;
+      /* Read from a different compilation.  Overwrite the file.  */
+      gcov_error ("profiling:%s:overwriting an existing profile data "
+		  "with a different timestamp\n", filename);
+      return 0;
     }
 
+  tag = gcov_read_unsigned ();
+  if (tag != GCOV_TAG_OBJECT_SUMMARY)
+    goto read_mismatch;
+  length = gcov_read_unsigned ();
+  gcc_assert (length > 0);
+  gcov_read_summary (summary);
+
+  tag = gcov_read_unsigned ();
   /* Merge execution counts for each function.  */
   for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
        f_ix++, tag = gcov_read_unsigned ())
@@ -502,38 +308,15 @@
 
 static void
 write_one_data (const struct gcov_info *gi_ptr,
-		const struct gcov_summary *prg_p,
-		const gcov_position_t eof_pos,
-		const gcov_position_t summary_pos)
+		const struct gcov_summary *prg_p)
 {
   unsigned f_ix;
-  struct gcov_summary_buffer *next_sum_buffer;
 
-  /* Write out the data.  */
-  if (!eof_pos)
-    {
-      gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
-      gcov_write_unsigned (gi_ptr->stamp);
-    }
-
-  if (summary_pos)
-    gcov_seek (summary_pos);
+  gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
+  gcov_write_unsigned (gi_ptr->stamp);
 
   /* Generate whole program statistics.  */
-  gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
-
-  /* Rewrite all the summaries that were after the summary we merged
-     into. This is necessary as the merged summary may have a different
-     size due to the number of non-zero histogram entries changing after
-     merging.  */
-
-  while (sum_buffer)
-    {
-      gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
-      next_sum_buffer = sum_buffer->next;
-      free (sum_buffer);
-      sum_buffer = next_sum_buffer;
-    }
+  gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, prg_p);
 
   /* Write execution counts for each function.  */
   for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
@@ -592,87 +375,19 @@
   gcov_write_unsigned (0);
 }
 
-/* Helper function for merging summary.
-   Return -1 on error. Return 0 on success.  */
-
-static int
-merge_summary (const char *filename, int run_counted,
-	       const struct gcov_info *gi_ptr, struct gcov_summary *prg,
-	       struct gcov_summary *this_prg, gcov_unsigned_t crc32,
-	       struct gcov_summary *all_prg __attribute__ ((unused)))
-{
-  struct gcov_ctr_summary *cs_prg, *cs_tprg;
-  unsigned t_ix;
-#if !GCOV_LOCKED 
-  /* summary for all instances of program.  */ 
-  struct gcov_ctr_summary *cs_all;
-#endif 
-
-  /* Merge the summaries.  */
-  for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
-    {
-      cs_prg = &(prg->ctrs[t_ix]);
-      cs_tprg = &(this_prg->ctrs[t_ix]);
-
-      if (gi_ptr->merge[t_ix])
-        {
-	  int first = !cs_prg->runs;
+/* Helper function for merging summary.  */
 
-	  if (!run_counted)
-	    cs_prg->runs++;
-          if (first)
-            cs_prg->num = cs_tprg->num;
-          cs_prg->sum_all += cs_tprg->sum_all;
-          if (cs_prg->run_max < cs_tprg->run_max)
-            cs_prg->run_max = cs_tprg->run_max;
-          cs_prg->sum_max += cs_tprg->run_max;
-          if (first)
-            memcpy (cs_prg->histogram, cs_tprg->histogram,
-                   sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-          else
-            gcov_histogram_merge (cs_prg->histogram, cs_tprg->histogram);
-        }
-      else if (cs_prg->runs)
-        {
-          gcov_error ("profiling:%s:Merge mismatch for summary.\n",
-                      filename);
-          return -1;
-        }
-#if !GCOV_LOCKED
-      cs_all = &all_prg->ctrs[t_ix];
-      if (!cs_all->runs && cs_prg->runs)
-        {
-          cs_all->num = cs_prg->num;
-          cs_all->runs = cs_prg->runs;
-          cs_all->sum_all = cs_prg->sum_all;
-          cs_all->run_max = cs_prg->run_max;
-          cs_all->sum_max = cs_prg->sum_max;
-        }
-      else if (!all_prg->checksum
-               /* Don't compare the histograms, which may have slight
-                  variations depending on the order they were updated
-                  due to the truncating integer divides used in the
-                  merge.  */
-               && (cs_all->num != cs_prg->num
-                   || cs_all->runs != cs_prg->runs
-                   || cs_all->sum_all != cs_prg->sum_all
-                   || cs_all->run_max != cs_prg->run_max
-                   || cs_all->sum_max != cs_prg->sum_max))
-             {
-               gcov_error ("profiling:%s:Data file mismatch - some "
-                           "data files may have been concurrently "
-                           "updated without locking support\n", filename);
-               all_prg->checksum = ~0u;
-             }
-#endif
+static void
+merge_summary (int run_counted, struct gcov_summary *summary,
+	      gcov_type run_max)
+{
+  if (!run_counted)
+    {
+      summary->runs++;
+      summary->sum_max += run_max;
     }
-  
-  prg->checksum = crc32;
-
-  return 0;
 }
 
-
 /* Sort N entries in VALUE_ARRAY in descending order.
    Each entry in VALUE_ARRAY has two values. The sorting
    is based on the second value.  */
@@ -760,18 +475,13 @@
 
 static void
 dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
-	       unsigned run_counted,
-	       gcov_unsigned_t crc32, struct gcov_summary *all_prg,
-	       struct gcov_summary *this_prg)
+	       unsigned run_counted, gcov_type run_max)
 {
-  struct gcov_summary prg; /* summary for this object over all program.  */
+  struct gcov_summary summary = {};
   int error;
   gcov_unsigned_t tag;
-  gcov_position_t summary_pos = 0;
-  gcov_position_t eof_pos = 0;
 
   fn_buffer = 0;
-  sum_buffer = 0;
 
   gcov_sort_topn_counter_arrays (gi_ptr);
 
@@ -788,26 +498,16 @@
           gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
           goto read_fatal;
         }
-      error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
-			      &summary_pos, &eof_pos, crc32);
+      error = merge_one_data (gf->filename, gi_ptr, &summary);
       if (error == -1)
         goto read_fatal;
     }
 
   gcov_rewrite ();
 
-  if (!summary_pos)
-    {
-      memset (&prg, 0, sizeof (prg));
-      summary_pos = eof_pos;
-    }
+  merge_summary (run_counted, &summary, run_max);
 
-  error = merge_summary (gf->filename, run_counted, gi_ptr, &prg, this_prg,
-			 crc32, all_prg);
-  if (error == -1)
-    goto read_fatal;
-
-  write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
+  write_one_data (gi_ptr, &summary);
   /* fall through */
 
 read_fatal:;
@@ -834,22 +534,30 @@
 {
   struct gcov_info *gi_ptr;
   struct gcov_filename gf;
-  gcov_unsigned_t crc32;
-  struct gcov_summary all_prg;
-  struct gcov_summary this_prg;
 
-  crc32 = compute_summary (list, &this_prg, &gf.max_length);
+  /* Compute run_max of this program run.  */
+  gcov_type run_max = 0;
+  for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
+    for (unsigned f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
+      {
+	const struct gcov_ctr_info *cinfo
+	  = &gi_ptr->functions[f_ix]->ctrs[GCOV_COUNTER_ARCS];
+
+	for (unsigned i = 0; i < cinfo->num; i++)
+	  if (run_max < cinfo->values[i])
+	    run_max = cinfo->values[i];
+      }
 
   allocate_filename_struct (&gf);
-#if !GCOV_LOCKED
-  memset (&all_prg, 0, sizeof (all_prg));
-#endif
 
   /* Now merge each file.  */
   for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
-    dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
+    {
+      dump_one_gcov (gi_ptr, &gf, run_counted, run_max);
+      free (gf.filename);
+    }
 
-  free (gf.filename);
+  free (gf.prefix);
 }
 
 #if IN_GCOV_TOOL