/* Dump a gcov file, for debugging use.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002-2014 Free Software Foundation, Inc.
Contributed by Nathan Sidwell <nathan@codesourcery.com>
Gcov 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 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
Gcov is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Gcov; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with Gcov; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "version.h"
+#include "intl.h"
+#include "diagnostic.h"
#include <getopt.h>
#define IN_GCOV (-1)
#include "gcov-io.h"
#include "gcov-io.c"
-static void dump_file (const char *);
+static void dump_gcov_file (const char *);
static void print_prefix (const char *, unsigned, gcov_position_t);
static void print_usage (void);
static void print_version (void);
static void tag_lines (const char *, unsigned, unsigned);
static void tag_counters (const char *, unsigned, unsigned);
static void tag_summary (const char *, unsigned, unsigned);
+static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
+ const struct gcov_ctr_summary *summary);
extern int main (int, char **);
typedef struct tag_format
static int flag_dump_contents = 0;
static int flag_dump_positions = 0;
+static int flag_dump_working_sets = 0;
static const struct option options[] =
{
{ "version", no_argument, NULL, 'v' },
{ "long", no_argument, NULL, 'l' },
{ "positions", no_argument, NULL, 'o' },
+ { "working-sets", no_argument, NULL, 'w' },
{ 0, 0, 0, 0 }
};
main (int argc ATTRIBUTE_UNUSED, char **argv)
{
int opt;
+ const char *p;
- while ((opt = getopt_long (argc, argv, "hlpv", options, NULL)) != -1)
+ p = argv[0] + strlen (argv[0]);
+ while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
+ progname = p;
+
+ xmalloc_set_program_name (progname);
+
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
+ gcc_init_libintl ();
+
+ diagnostic_initialize (global_dc, 0);
+
+ while ((opt = getopt_long (argc, argv, "hlpvw", options, NULL)) != -1)
{
switch (opt)
{
case 'p':
flag_dump_positions = 1;
break;
+ case 'w':
+ flag_dump_working_sets = 1;
+ break;
default:
fprintf (stderr, "unknown flag `%c'\n", opt);
}
}
while (argv[optind])
- dump_file (argv[optind++]);
+ dump_gcov_file (argv[optind++]);
return 0;
}
printf (" -v, --version Print version number\n");
printf (" -l, --long Dump record contents too\n");
printf (" -p, --positions Dump record positions\n");
+ printf (" -w, --working-sets Dump working set computed from summary\n");
}
static void
print_version (void)
{
- char v[4];
- unsigned version = GCOV_VERSION;
- unsigned ix;
-
- for (ix = 4; ix--; version >>= 8)
- v[ix] = version;
- printf ("gcov %.4s (GCC %s)\n", v, version_string);
- printf ("Copyright (C) 2002 Free Software Foundation, Inc.\n");
- printf ("This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
+ printf ("gcov-dump %s%s\n", pkgversion_string, version_string);
+ printf ("Copyright (C) 2014 Free Software Foundation, Inc.\n");
+ printf ("This is free software; see the source for copying conditions.\n"
+ "There is NO warranty; not even for MERCHANTABILITY or \n"
+ "FITNESS FOR A PARTICULAR PURPOSE.\n\n");
}
static void
}
static void
-dump_file (const char *filename)
+dump_gcov_file (const char *filename)
{
unsigned tags[4];
unsigned depth = 0;
unsigned version;
const char *type = NULL;
int endianness = 0;
-
+ char m[4], v[4];
+
if ((endianness = gcov_magic (magic, GCOV_DATA_MAGIC)))
type = "data";
else if ((endianness = gcov_magic (magic, GCOV_NOTE_MAGIC)))
return;
}
version = gcov_read_unsigned ();
-
+ GCOV_UNSIGNED2STRING (v, version);
+ GCOV_UNSIGNED2STRING (m, magic);
+
printf ("%s:%s:magic `%.4s':version `%.4s'%s\n", filename, type,
- (const char *)&magic, (const char *)&version,
- endianness < 0 ? " (swapped endianness)" : "");
+ m, v, endianness < 0 ? " (swapped endianness)" : "");
if (version != GCOV_VERSION)
{
- unsigned expected = GCOV_VERSION;
-
- printf ("%s:warning:current version is `%.4s'\n", filename,
- (const char *)&expected);
+ char e[4];
+
+ GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
+ printf ("%s:warning:current version is `%.4s'\n", filename, e);
}
}
printf ("%s:stamp %lu\n", filename, (unsigned long)stamp);
}
-
+
while (1)
{
gcov_position_t base, position = gcov_position ();
break;
}
}
- if (!gcov_is_eof ())
- printf ("%s:early end of file\n", filename);
gcov_close ();
}
static void
tag_function (const char *filename ATTRIBUTE_UNUSED,
- unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+ unsigned tag ATTRIBUTE_UNUSED, unsigned length)
{
unsigned long pos = gcov_position ();
- printf (" ident=%u", gcov_read_unsigned ());
- printf (", checksum=0x%08x", gcov_read_unsigned ());
-
- if (gcov_position () - pos < length)
+ if (!length)
+ printf (" placeholder");
+ else
{
- const char *name;
+ printf (" ident=%u", gcov_read_unsigned ());
+ printf (", lineno_checksum=0x%08x", gcov_read_unsigned ());
+ printf (", cfg_checksum=0x%08x", gcov_read_unsigned ());
- name = gcov_read_string ();
- printf (", `%s'", name ? name : "NULL");
- name = gcov_read_string ();
- printf (" %s", name ? name : "NULL");
- printf (":%u", gcov_read_unsigned ());
+ if (gcov_position () - pos < length)
+ {
+ const char *name;
+
+ name = gcov_read_string ();
+ printf (", `%s'", name ? name : "NULL");
+ name = gcov_read_string ();
+ printf (" %s", name ? name : "NULL");
+ printf (":%u", gcov_read_unsigned ());
+ }
}
}
tag_blocks (const char *filename ATTRIBUTE_UNUSED,
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
{
- unsigned n_blocks = length / 4;
+ unsigned n_blocks = GCOV_TAG_BLOCKS_NUM (length);
printf (" %u blocks", n_blocks);
tag_arcs (const char *filename ATTRIBUTE_UNUSED,
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
{
- unsigned n_arcs = (length - 4) / 8;
+ unsigned n_arcs = GCOV_TAG_ARCS_NUM (length);
printf (" %u arcs", n_arcs);
if (flag_dump_contents)
dst = gcov_read_unsigned ();
flags = gcov_read_unsigned ();
printf (" %u:%04x", dst, flags);
+ if (flags)
+ {
+ char c = '(';
+
+ if (flags & GCOV_ARC_ON_TREE)
+ printf ("%ctree", c), c = ',';
+ if (flags & GCOV_ARC_FAKE)
+ printf ("%cfake", c), c = ',';
+ if (flags & GCOV_ARC_FALLTHROUGH)
+ printf ("%cfall", c), c = ',';
+ printf (")");
+ }
}
}
}
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
{
static const char *const counter_names[] = GCOV_COUNTER_NAMES;
- unsigned n_counts = length / 8;
+ unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
printf (" %s %u counts",
counter_names[GCOV_COUNTER_FOR_TAG (tag)], n_counts);
count = gcov_read_counter ();
printf (" ");
- printf (HOST_WIDEST_INT_PRINT_DEC, count);
+ printf ("%"PRId64, count);
}
}
}
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
{
struct gcov_summary summary;
- unsigned ix;
+ unsigned ix, h_ix;
+ gcov_bucket_type *histo_bucket;
gcov_read_summary (&summary);
printf (" checksum=0x%08x", summary.checksum);
- for (ix = 0; ix != GCOV_COUNTERS; ix++)
+ for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++)
{
printf ("\n");
print_prefix (filename, 0, 0);
printf ("\t\tcounts=%u, runs=%u",
summary.ctrs[ix].num, summary.ctrs[ix].runs);
- printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].sum_all);
- printf (", run_max=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].run_max);
- printf (", sum_max=" HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT)summary.ctrs[ix].sum_max);
+ printf (", sum_all=%"PRId64,
+ (int64_t)summary.ctrs[ix].sum_all);
+ printf (", run_max=%"PRId64,
+ (int64_t)summary.ctrs[ix].run_max);
+ printf (", sum_max=%"PRId64,
+ (int64_t)summary.ctrs[ix].sum_max);
+ if (ix != GCOV_COUNTER_ARCS)
+ continue;
+ printf ("\n");
+ print_prefix (filename, 0, 0);
+ printf ("\t\tcounter histogram:");
+ for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
+ {
+ histo_bucket = &summary.ctrs[ix].histogram[h_ix];
+ if (!histo_bucket->num_counters)
+ continue;
+ printf ("\n");
+ print_prefix (filename, 0, 0);
+ printf ("\t\t%d: num counts=%u, min counter="
+ "%"PRId64 ", cum_counter="
+ "%"PRId64,
+ h_ix, histo_bucket->num_counters,
+ (int64_t)histo_bucket->min_value,
+ (int64_t)histo_bucket->cum_value);
+ }
+ if (flag_dump_working_sets)
+ dump_working_sets (filename, &summary.ctrs[ix]);
+ }
+}
+
+static void
+dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
+ const struct gcov_ctr_summary *summary)
+{
+ gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS];
+ unsigned ws_ix, pctinc, pct;
+ gcov_working_set_t *ws_info;
+
+ compute_working_sets (summary, gcov_working_sets);
+
+ printf ("\n");
+ print_prefix (filename, 0, 0);
+ printf ("\t\tcounter working sets:");
+ /* Multiply the percentage by 100 to avoid float. */
+ pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS;
+ for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS;
+ ws_ix++, pct += pctinc)
+ {
+ if (ws_ix == NUM_GCOV_WORKING_SETS - 1)
+ pct = 9990;
+ ws_info = &gcov_working_sets[ws_ix];
+ /* Print out the percentage using int arithmatic to avoid float. */
+ printf ("\n");
+ print_prefix (filename, 0, 0);
+ printf ("\t\t%u.%02u%%: num counts=%u, min counter="
+ "%"PRId64,
+ pct / 100, pct - (pct / 100 * 100),
+ ws_info->num_counters,
+ (int64_t)ws_info->min_counter);
}
}