c77556a5d1
2014-07-10 Rong Xu <xur@google.com> Add gcov-tool: an offline gcda profile processing tool Support. * gcc/gcov-io.c (gcov_position): Make avaialble to gcov-tool. (gcov_is_error): Ditto. (gcov_read_string): Ditto. (gcov_read_sync): Ditto. * gcc/gcov-io.h: Move counter defines to gcov-counter.def. * gcc/gcov-dump.c (tag_counters): Use gcov-counter.def. * gcc/coverage.c: Ditto. * gcc/gcov-tool.c: Offline gcda profile processing tool. (unlink_gcda_file): Remove one gcda file. (unlink_profile_dir): Remove gcda files from the profile path. (gcov_output_files): Output gcda files to an output dir. (profile_merge): Merge two profiles in directory. (print_merge_usage_message): Print merge usage. (merge_usage): Print merge usage and exit. (do_merge): Driver for profile merge sub-command. (profile_rewrite): Rewrite profile. (print_rewrite_usage_message): Print rewrite usage. (rewrite_usage): Print rewrite usage and exit. (do_rewrite): Driver for profile rewrite sub-command. (print_usage): Print gcov-info usage and exit. (print_version): Print gcov-info version. (process_args): Process arguments. (main): Main routine for gcov-tool. * gcc/Makefile.in: Build and install gcov-tool. * gcc/gcov-counter.def: New file split from gcov-io.h. * libgcc/libgcov-driver.c (gcov_max_filename): Make available to gcov-tool. * libgcc/libgcov-merge.c (__gcov_merge_add): Replace gcov_read_counter() with a Macro. (__gcov_merge_ior): Ditto. (__gcov_merge_time_profile): Ditto. (__gcov_merge_single): Ditto. (__gcov_merge_delta): Ditto. * libgcc/libgcov-util.c (void gcov_set_verbose): Set the verbose flag in the utility functions. (set_fn_ctrs): Utility function for reading gcda files to in-memory gcov_list object link lists. (tag_function): Ditto. (tag_blocks): Ditto. (tag_arcs): Ditto. (tag_lines): Ditto. (tag_counters): Ditto. (tag_summary): Ditto. (read_gcda_finalize): Ditto. (read_gcda_file): Ditto. (ftw_read_file): Ditto. (read_profile_dir_init): Ditto. (gcov_read_profile_dir): Ditto. (gcov_read_counter_mem): Ditto. (gcov_get_merge_weight): Ditto. (merge_wrapper): A wrapper function that calls merging handler. (gcov_merge): Merge two gcov_info objects with weights. (find_match_gcov_info): Find the matched gcov_info in the list. (gcov_profile_merge): Merge two gcov_info object lists. (__gcov_add_counter_op): Process edge profile counter values. (__gcov_ior_counter_op): Process IOR profile counter values. (__gcov_delta_counter_op): Process delta profile counter values. (__gcov_single_counter_op): Process single profile counter values. (fp_scale): Callback function for float-point scaling. (int_scale): Callback function for integer fraction scaling. (gcov_profile_scale): Scaling profile counters. (gcov_profile_normalize): Normalize profile counters. * libgcc/libgcov.h: Add headers and functions for gcov-tool use. (gcov_get_counter): New. (gcov_get_counter_target): Ditto. (struct gcov_info): Make the functions field mutable in gcov-tool compilation. * gcc/doc/gcc.texi: Include gcov-tool.texi. * gcc/doc/gcov-tool.texi: Document for gcov-tool. From-SVN: r212448
170 lines
5.4 KiB
C
170 lines
5.4 KiB
C
/* Routines required for instrumenting a program. */
|
|
/* Compile this one with gcc. */
|
|
/* Copyright (C) 1989-2014 Free Software Foundation, Inc.
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional
|
|
permissions described in the GCC Runtime Library Exception, version
|
|
3.1, as published by the Free Software Foundation.
|
|
|
|
You should have received a copy of the GNU General Public License and
|
|
a copy of the GCC Runtime Library Exception along with this program;
|
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "libgcov.h"
|
|
|
|
#if defined(inhibit_libc)
|
|
/* If libc and its header files are not available, provide dummy functions. */
|
|
|
|
#ifdef L_gcov_merge_add
|
|
void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
|
|
unsigned n_counters __attribute__ ((unused))) {}
|
|
#endif
|
|
|
|
#ifdef L_gcov_merge_single
|
|
void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
|
|
unsigned n_counters __attribute__ ((unused))) {}
|
|
#endif
|
|
|
|
#ifdef L_gcov_merge_delta
|
|
void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
|
|
unsigned n_counters __attribute__ ((unused))) {}
|
|
#endif
|
|
|
|
#else
|
|
|
|
#ifdef L_gcov_merge_add
|
|
/* The profile merging function that just adds the counters. It is given
|
|
an array COUNTERS of N_COUNTERS old counters and it reads the same number
|
|
of counters from the gcov file. */
|
|
void
|
|
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
|
|
{
|
|
for (; n_counters; counters++, n_counters--)
|
|
*counters += gcov_get_counter ();
|
|
}
|
|
#endif /* L_gcov_merge_add */
|
|
|
|
#ifdef L_gcov_merge_ior
|
|
/* The profile merging function that just adds the counters. It is given
|
|
an array COUNTERS of N_COUNTERS old counters and it reads the same number
|
|
of counters from the gcov file. */
|
|
void
|
|
__gcov_merge_ior (gcov_type *counters, unsigned n_counters)
|
|
{
|
|
for (; n_counters; counters++, n_counters--)
|
|
*counters |= gcov_get_counter_target ();
|
|
}
|
|
#endif
|
|
|
|
#ifdef L_gcov_merge_time_profile
|
|
/* Time profiles are merged so that minimum from all valid (greater than zero)
|
|
is stored. There could be a fork that creates new counters. To have
|
|
the profile stable, we chosen to pick the smallest function visit time. */
|
|
void
|
|
__gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
|
|
{
|
|
unsigned int i;
|
|
gcov_type value;
|
|
|
|
for (i = 0; i < n_counters; i++)
|
|
{
|
|
value = gcov_get_counter_target ();
|
|
|
|
if (value && (!counters[i] || value < counters[i]))
|
|
counters[i] = value;
|
|
}
|
|
}
|
|
#endif /* L_gcov_merge_time_profile */
|
|
|
|
#ifdef L_gcov_merge_single
|
|
/* The profile merging function for choosing the most common value.
|
|
It is given an array COUNTERS of N_COUNTERS old counters and it
|
|
reads the same number of counters from the gcov file. The counters
|
|
are split into 3-tuples where the members of the tuple have
|
|
meanings:
|
|
|
|
-- the stored candidate on the most common value of the measured entity
|
|
-- counter
|
|
-- total number of evaluations of the value */
|
|
void
|
|
__gcov_merge_single (gcov_type *counters, unsigned n_counters)
|
|
{
|
|
unsigned i, n_measures;
|
|
gcov_type value, counter, all;
|
|
|
|
gcc_assert (!(n_counters % 3));
|
|
n_measures = n_counters / 3;
|
|
for (i = 0; i < n_measures; i++, counters += 3)
|
|
{
|
|
value = gcov_get_counter_target ();
|
|
counter = gcov_get_counter ();
|
|
all = gcov_get_counter ();
|
|
|
|
if (counters[0] == value)
|
|
counters[1] += counter;
|
|
else if (counter > counters[1])
|
|
{
|
|
counters[0] = value;
|
|
counters[1] = counter - counters[1];
|
|
}
|
|
else
|
|
counters[1] -= counter;
|
|
counters[2] += all;
|
|
}
|
|
}
|
|
#endif /* L_gcov_merge_single */
|
|
|
|
#ifdef L_gcov_merge_delta
|
|
/* The profile merging function for choosing the most common
|
|
difference between two consecutive evaluations of the value. It is
|
|
given an array COUNTERS of N_COUNTERS old counters and it reads the
|
|
same number of counters from the gcov file. The counters are split
|
|
into 4-tuples where the members of the tuple have meanings:
|
|
|
|
-- the last value of the measured entity
|
|
-- the stored candidate on the most common difference
|
|
-- counter
|
|
-- total number of evaluations of the value */
|
|
void
|
|
__gcov_merge_delta (gcov_type *counters, unsigned n_counters)
|
|
{
|
|
unsigned i, n_measures;
|
|
gcov_type value, counter, all;
|
|
|
|
gcc_assert (!(n_counters % 4));
|
|
n_measures = n_counters / 4;
|
|
for (i = 0; i < n_measures; i++, counters += 4)
|
|
{
|
|
/* last = */ gcov_get_counter ();
|
|
value = gcov_get_counter_target ();
|
|
counter = gcov_get_counter ();
|
|
all = gcov_get_counter ();
|
|
|
|
if (counters[1] == value)
|
|
counters[2] += counter;
|
|
else if (counter > counters[2])
|
|
{
|
|
counters[1] = value;
|
|
counters[2] = counter - counters[2];
|
|
}
|
|
else
|
|
counters[2] -= counter;
|
|
counters[3] += all;
|
|
}
|
|
}
|
|
#endif /* L_gcov_merge_delta */
|
|
#endif /* inhibit_libc */
|