diff options
Diffstat (limited to 'libgcc/libgcov-driver.c')
-rw-r--r-- | libgcc/libgcov-driver.c | 324 |
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); } |