aboutsummaryrefslogtreecommitdiff
path: root/libgcc/libgcov-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/libgcov-driver.c')
-rw-r--r--libgcc/libgcov-driver.c324
1 files changed, 38 insertions, 286 deletions
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index 1f2c4a7..cdebb74 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<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. */
@@ -156,25 +157,6 @@ fail:
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
@@ -198,117 +180,8 @@ gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
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;
- unsigned f_ix, ix;
- int h_ix;
-
- /* First check if there are any counts recorded for this counter. */
- if (!sum->num)
- return;
-
- for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
- {
- sum->histogram[h_ix].num_counters = 0;
- sum->histogram[h_ix].min_value = sum->run_max;
- sum->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)
- {
- 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[0];
- for (ix = 0; ix < ci_ptr->num; ix++)
- gcov_histogram_insert (sum->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. */
-
-#if !IN_GCOV_TOOL
-static
-#endif
-gcov_unsigned_t
-compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
-{
- struct gcov_info *gi_ptr;
- const struct gcov_fn_info *gfi_ptr;
- const struct gcov_ctr_info *ci_ptr;
- int f_ix;
- gcov_unsigned_t c_num;
- gcov_unsigned_t crc32 = 0;
-
- /* Find the totals for this execution. */
- memset (this_prg, 0, sizeof (*this_prg));
- for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
- {
- 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;
- this_prg->num += ci_ptr->num;
- crc32 = crc32_unsigned (crc32, ci_ptr->num);
-
- for (c_num = 0; c_num < ci_ptr->num; c_num++)
- {
- this_prg->sum_all += ci_ptr->values[c_num];
- if (this_prg->run_max < ci_ptr->values[c_num])
- this_prg->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"
@@ -320,18 +193,13 @@ compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
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))
@@ -346,46 +214,14 @@ merge_one_data (const char *filename,
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;
-
- if (tmp.num != this_prg->num)
- goto next_summary;
- *prg_p = tmp;
- *summary_pos_p = *eof_pos_p;
-
- next_summary:;
- }
+ 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 ())
@@ -472,38 +308,15 @@ read_error:
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++)
@@ -562,70 +375,19 @@ write_one_data (const struct gcov_info *gi_ptr,
gcov_write_unsigned (0);
}
-/* Helper function for merging summary.
- Return -1 on error. Return 0 on success. */
+/* Helper function for merging summary. */
-static int
-merge_summary (const char *filename __attribute__ ((unused)), int run_counted,
- struct gcov_summary *prg,
- struct gcov_summary *this_prg, gcov_unsigned_t crc32,
- struct gcov_summary *all_prg __attribute__ ((unused)))
+static void
+merge_summary (int run_counted, struct gcov_summary *summary,
+ gcov_type run_max)
{
-#if !GCOV_LOCKED
- /* summary for all instances of program. */
- struct gcov_summary *all;
-#endif
-
- /* Merge the summary. */
- int first = !prg->runs;
-
if (!run_counted)
- prg->runs++;
- if (first)
- prg->num = this_prg->num;
- prg->sum_all += this_prg->sum_all;
- if (prg->run_max < this_prg->run_max)
- prg->run_max = this_prg->run_max;
- prg->sum_max += this_prg->run_max;
- if (first)
- memcpy (prg->histogram, this_prg->histogram,
- sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
- else
- gcov_histogram_merge (prg->histogram, this_prg->histogram);
-#if !GCOV_LOCKED
- all = all_prg;
- if (!all->runs && prg->runs)
- {
- all->num = prg->num;
- all->runs = prg->runs;
- all->sum_all = prg->sum_all;
- all->run_max = prg->run_max;
- all->sum_max = 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. */
- && (all->num != prg->num
- || all->runs != prg->runs
- || all->sum_all != prg->sum_all
- || all->run_max != prg->run_max
- || all->sum_max != 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;
+ summary->runs++;
+ summary->sum_max += run_max;
}
-#endif
-
- 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. */
@@ -713,18 +475,13 @@ gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
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);
@@ -741,26 +498,16 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
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;
- }
-
- error = merge_summary (gf->filename, run_counted, &prg, this_prg,
- crc32, all_prg);
- if (error == -1)
- goto read_fatal;
+ merge_summary (run_counted, &summary, run_max);
- write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
+ write_one_data (gi_ptr, &summary);
/* fall through */
read_fatal:;
@@ -787,21 +534,26 @@ gcov_do_dump (struct gcov_info *list, int run_counted)
{
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);
+ /* 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);
}