Do we have to split params.def? I can include params.h and link in params.o (a special version as we don't have some global vars).
As for lipo_cutoff, I think we don't need a special handling -- we should use the default value of 100 and let logic in dyn-ipa.c takes care of the rest. Please find the update patch which reads the default values from params.def. -Rong On Fri, Jan 17, 2014 at 12:05 PM, Xinliang David Li <davi...@google.com> wrote: > For LIPO parameters, you can do this > 1) isolate all LIPO specific parameters into lipo_params.def, and > include it from params.def. > 2) include lipo_params.def (after proper definition of DEFPARAM) in > the profile tool source dir. > > By so doing, the compiler setting and profile tool will be in sync. > (Unfortuately, for historic reason, the lipo_cutoff default val is > still set in dyn-ipa.c even with the parameter, so some comments needs > to be added in dyn-ipa.c to make sure the value should be doubly > updated). > > David > > On Fri, Jan 17, 2014 at 11:15 AM, Rong Xu <x...@google.com> wrote: >> Hi, >> >> This patch port the gcov-tool work to google/gcc-4_8 branches. >> >> Tested with spec2006, profiledbootstrap and google internal benchmarks. >> >> -Rong
Index: Makefile.in =================================================================== --- Makefile.in (revision 206671) +++ Makefile.in (working copy) @@ -123,7 +123,8 @@ SUBDIRS =@subdirs@ build # Selection of languages to be made. CONFIG_LANGUAGES = @all_selected_languages@ -LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) $(CONFIG_LANGUAGES) +LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) gcov-tool$(exeext) \ + $(CONFIG_LANGUAGES) # Default values for variables overridden in Makefile fragments. # CFLAGS is for the user to override to, e.g., do a cross build with -O2. @@ -194,6 +195,7 @@ GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $( build/gengtype-lex.o-warn = -Wno-error gengtype-lex.o-warn = -Wno-error expmed.o-warn = -Wno-error +libgcov-util.o-warn = -Wno-error # All warnings have to be shut off in stage1 if the compiler used then # isn't gcc; configure determines that. WARN_CFLAGS will be either @@ -755,6 +757,7 @@ GCC_TARGET_INSTALL_NAME := $(target_noncanonical)- CPP_INSTALL_NAME := $(shell echo cpp|sed '$(program_transform_name)') GCOV_INSTALL_NAME := $(shell echo gcov|sed '$(program_transform_name)') PROFILE_TOOL_INSTALL_NAME := $(shell echo profile_tool|sed '$(program_transform_name)') +GCOV_TOOL_INSTALL_NAME := $(shell echo gcov-tool|sed '$(program_transform_name)') # Setup the testing framework, if you have one EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \ @@ -1480,7 +1483,8 @@ ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANG ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \ $(OBJS-libcommon-target) @TREEBROWSER@ main.o c-family/cppspec.o \ - $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) + $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \ + $(GCOV_TOOL_OBJS) # This lists all host object files, whether they are included in this # compilation or not. @@ -1505,6 +1509,7 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \ gcc-ranlib$(exeext) \ gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \ + gcov-tool$(exeect) \ gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a \ libcommon-target.a libcommon.a libgcc.mk @@ -4070,6 +4075,24 @@ GCOV_DUMP_OBJS = gcov-dump.o vec.o ggc-none.o gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) \ $(LIBS) -o $@ + +libgcov-util.o: $(srcdir)/../libgcc/libgcov-util.c gcov-io.c $(GCOV_IO_H) \ + $(srcdir)/../libgcc/libgcov-driver.c $(srcdir)/../libgcc/libgcov-driver-system.c \ + $(srcdir)/../libgcc/libgcov-merge.c $(srcdir)/../libgcc/libgcov.h \ + $(SYSTEM_H) coretypes.h $(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H) + +$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -o $@ $< +dyn-ipa.o: $(srcdir)/../libgcc/dyn-ipa.c gcov-io.c $(srcdir)/../libgcc/libgcov.h \ + $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \ + $(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H) + +$(COMPILER) -DIN_GCOV_TOOL -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \ + $(INCLUDES) -o $@ $< + +GCOV_TOOL_OBJS = gcov-tool.o libgcov-util.o dyn-ipa.o params.o +gcov-tool.o: gcov-tool.c $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \ + $(CONFIG_H) version.h $(DIAGNOSTIC_H) +gcov-tool$(exeext): $(GCOV_TOOL_OBJS) $(LIBDEPS) + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_TOOL_OBJS) \ + $(LIBS) -o $@ # # Build the include directories. The stamp files are stmp-* rather than # s-* so that mostlyclean does not force the include directory to @@ -4697,6 +4720,13 @@ install-common: native lang.install-common install $(INSTALL_PROGRAM) $(srcdir)/../contrib/profile_tool \ $(DESTDIR)$(bindir)/$(PROFILE_TOOL_INSTALL_NAME)$(exeext); \ fi +# Install gcov-tool if it was compiled. + -if [ -f gcov-tool$(exeext) ]; \ + then \ + rm -f $(DESTDIR)$(bindir)/$(GCOV_TOOL_INSTALL_NAME)$(exeext); \ + $(INSTALL_PROGRAM) \ + gcov-tool$(exeext) $(DESTDIR)$(bindir)/$(GCOV_TOOL_INSTALL_NAME)$(exeext); \ + fi # Install the driver program as $(target_noncanonical)-gcc, # $(target_noncanonical)-gcc-$(version) Index: params.c =================================================================== --- params.c (revision 206671) +++ params.c (working copy) @@ -70,7 +70,9 @@ void global_init_params (void) { add_params (lang_independent_params, LAST_PARAM); +#ifndef IN_GCOV_TOOL targetm_common.option_default_params (); +#endif } /* Note that all parameters have been added and all default values Index: coretypes.h =================================================================== --- coretypes.h (revision 206671) +++ coretypes.h (working copy) @@ -43,6 +43,9 @@ see the files COPYING3 and COPYING.RUNTIME respect #ifndef USED_FOR_TARGET +typedef HOST_WIDEST_INT gcov_type; +typedef unsigned HOST_WIDEST_INT gcov_type_unsigned; + struct bitmap_head_def; typedef struct bitmap_head_def *bitmap; typedef const struct bitmap_head_def *const_bitmap; Index: gcov-tool.c =================================================================== --- gcov-tool.c (revision 0) +++ gcov-tool.c (revision 0) @@ -0,0 +1,603 @@ +/* Gcc offline profile processing tool support. */ +/* Compile this one with gcc. */ +/* Copyright (C) 2014 Free Software Foundation, Inc. + Contributed by Rong Xu <x...@google.com>. + +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 "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "intl.h" +#include "diagnostic.h" +#include "version.h" +#include "gcov-io.h" +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <ftw.h> +#include <getopt.h> +#include "params.h" + +extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int); +extern int gcov_profile_normalize (struct gcov_info*, gcov_type); +extern int gcov_profile_scale (struct gcov_info*, float); +extern int gcov_profile_scale2 (struct gcov_info*, int, int); +extern struct gcov_info* gcov_read_profile_dir (const char*, int); +extern void gcov_exit (void); +extern void set_gcov_list (struct gcov_info *); +extern void gcov_set_verbose (void); + +static int verbose; + +gcov_unsigned_t __gcov_lipo_grouping_algorithm; +gcov_unsigned_t __gcov_lipo_merge_modu_edges; +gcov_unsigned_t __gcov_lipo_weak_inclusion; +gcov_unsigned_t __gcov_lipo_max_mem; +gcov_unsigned_t __gcov_lipo_random_group_size; +gcov_unsigned_t __gcov_lipo_cutoff; +gcov_unsigned_t __gcov_lipo_random_seed; +gcov_unsigned_t __gcov_lipo_dump_cgraph; +gcov_unsigned_t __gcov_lipo_propagate_scale; + +/* Remove file NAME if it has a gcda suffix. */ + +static int +unlink_gcda_file (const char *name, + const struct stat *status ATTRIBUTE_UNUSED, + int type ATTRIBUTE_UNUSED, + struct FTW *ftwbuf ATTRIBUTE_UNUSED) +{ + int ret = 0; + int len = strlen (name); + int len1 = strlen (GCOV_DATA_SUFFIX); + + if (len > len1 && !strncmp (len -len1 + name, GCOV_DATA_SUFFIX, len1)) + remove (name); + + if (ret) + { + fnotice (stderr, "error in removing %s\n", name); + exit (FATAL_EXIT_CODE); + } + + return ret; +} + +/* Remove the gcda files in PATH recursively. */ + +static int +unlink_profile_dir (const char *path) +{ + return nftw(path, unlink_gcda_file, 64, FTW_DEPTH | FTW_PHYS); +} + +/* Merging profile D1 and D2 with weight as W1 and W2, respectively. + The result profile is written to directory OUT. + Return 0 on success. */ + +static int +profile_merge (const char *d1, const char *d2, const char *out, int w1, int w2) +{ + char *pwd; + int ret; + struct gcov_info * d1_profile; + struct gcov_info * d2_profile; + + + d1_profile = gcov_read_profile_dir (d1, 0); + if (!d1_profile) + return 1; + + if (d2) + { + d2_profile = gcov_read_profile_dir (d2, 0); + if (!d2_profile) + return 1; + + /* The actual merge: we overwrite to d1_profile. */ + ret = gcov_profile_merge (d1_profile, d2_profile, w1, w2); + + if (ret) + return ret; + } + + /* Output new profile. */ + unlink_profile_dir (out); + mkdir (out, 0755); + pwd = getcwd (NULL, 0); + gcc_assert (pwd); + ret = chdir (out); + gcc_assert (ret == 0); + + set_gcov_list (d1_profile); + gcov_exit (); + + ret = chdir (pwd); + free (pwd); + return 0; +} + +/* Usage message for profile merge. */ + +static void +print_merge_usage_message (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + + fnotice (file, " merge [options] <dir1> <dir2> Merge coverage file contents\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); + fnotice (file, " -o, --output <dir> Output directory\n"); + fnotice (file, " -w, --weight <w1,w2> Set weights (float point values)\n"); +} + +static const struct option merge_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "output", required_argument, NULL, 'o' }, + { "weight", required_argument, NULL, 'w' }, + { 0, 0, 0, 0 } +}; + +/* Print merge usage and exit. */ + +static void +merge_usage (void) +{ + fnotice (stderr, "Merge subcomand usage:"); + print_merge_usage_message (true); + exit (FATAL_EXIT_CODE); +} + +/* Driver for profile merge sub-command. */ + +static int +do_merge (int argc, char **argv) +{ + int opt; + int ret; + const char *output_dir = 0; + int w1 = 1, w2 = 1; + + optind = 0; + while ((opt = getopt_long (argc, argv, "vo:w:", merge_options, NULL)) != -1) + { + switch (opt) + { + case 'v': + verbose = 1; + gcov_set_verbose (); + break; + case 'o': + output_dir = optarg; + break; + case 'w': + sscanf (optarg, "%d,%d", &w1, &w2); + if (w1 < 0 || w2 < 0) + { + fnotice (stderr, "weights need to be non-negative\n"); + exit (FATAL_EXIT_CODE); + } + break; + default: + merge_usage (); + } + } + + if (output_dir == NULL) + output_dir = "merged_profile"; + + if (argc - optind == 2) + ret = profile_merge (argv[optind], argv[optind+1], output_dir, w1, w2); + else + merge_usage (); + + return ret; +} + +/* Scale the counters in profile DIR by a factor of N/D. + Result is written to dir OUT. Return 0 on success. */ + +static int +profile_rewrite2 (const char *dir, const char *out, int n, int d) +{ + char *pwd; + int ret; + struct gcov_info * profile; + + + profile = gcov_read_profile_dir (dir, 0); + if (!profile) + return 1; + + /* Output new profile. */ + unlink_profile_dir (out); + mkdir (out, 0755); + pwd = getcwd (NULL, 0); + gcc_assert (pwd); + ret = chdir (out); + gcc_assert (ret == 0); + + gcov_profile_scale2 (profile, n, d); + + set_gcov_list (profile); + gcov_exit (); + + ret = chdir (pwd); + free (pwd); + return 0; +} + +/* If N_VAL is no-zero, normalize the profile by setting the largest counter + counter value to N_VAL and scale others counters proportionally. + Otherwise, multiply the all counters by SCALE. */ + +static int +profile_rewrite (const char *d1, const char *out, long long n_val, float scale) +{ + char *pwd; + int ret; + struct gcov_info * d1_profile; + + + d1_profile = gcov_read_profile_dir (d1, 0); + if (!d1_profile) + return 1; + + /* Output new profile. */ + unlink_profile_dir (out); + mkdir (out, 0755); + pwd = getcwd (NULL, 0); + gcc_assert (pwd); + ret = chdir (out); + gcc_assert (ret == 0); + + if (n_val) + gcov_profile_normalize (d1_profile, (gcov_type) n_val); + else + gcov_profile_scale (d1_profile, scale); + + set_gcov_list (d1_profile); + gcov_exit (); + + ret = chdir (pwd); + free (pwd); + return 0; +} + +/* Usage function for profile rewrite. */ + +static void +print_rewrite_usage_message (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + + fnotice (file, " rewrite [options] <dir> Rewrite coverage file contents\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); + fnotice (file, " -o, --output <dir> Output directory\n"); + fnotice (file, " -s, --scale <float or simple-frac> Scale the profile counters\n"); + fnotice (file, " -n, --normalize <long long> Normalize the profile\n"); +} + +static const struct option rewrite_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "output", required_argument, NULL, 'o' }, + { "scale", required_argument, NULL, 's' }, + { "normalize", required_argument, NULL, 'n' }, + { 0, 0, 0, 0 } +}; + +/* Print profile rewrite usage and exit. */ + +static void +rewrite_usage (void) +{ + fnotice (stderr, "Rewrite subcommand usage:"); + print_rewrite_usage_message (true); + exit (FATAL_EXIT_CODE); +} + +/* Driver for profile rewrite sub-command. */ + +static int +do_rewrite (int argc, char **argv) +{ + int opt; + int ret; + const char *output_dir = 0; + long long normalize_val = 0; + float scale = 1.0; + int numerator = -1; + int denominator = -1; + + optind = 0; + while ((opt = getopt_long (argc, argv, "vo:s:n:", rewrite_options, NULL)) != -1) + { + switch (opt) + { + case 'v': + verbose = 1; + gcov_set_verbose (); + break; + case 'o': + output_dir = optarg; + break; + case 'n': + if (scale != 1.0) + { + fnotice (stderr, "scaling cannot co-exist with normalization\n"); + scale = 1.0; + } + normalize_val = atoll (optarg); + break; + case 's': + ret = 0; + if (strstr (optarg, "/")) + { + ret = sscanf (optarg, "%d/%d", &numerator, &denominator); + if (ret == 2) + { + gcc_assert (numerator >= 0); + gcc_assert (denominator > 0); + scale = 0.0; + } + } + if (ret != 2) + { + ret = sscanf (optarg, "%f", &scale); + gcc_assert (ret == 1); + } + + if (scale < 0.0) + { + fnotice (stderr, "scale needs to be non-negative\n"); + exit (FATAL_EXIT_CODE); + } + if (normalize_val != 0) + { + fnotice (stderr, "normalization cannot co-exist with scaling\n"); + normalize_val = 0; + } + break; + default: + rewrite_usage (); + } + } + + if (output_dir == NULL) + output_dir = "rewrite_profile"; + + if (argc - optind == 1) + { + if (denominator > 0) + ret = profile_rewrite2 (argv[optind], output_dir, numerator, denominator); + else + ret = profile_rewrite (argv[optind], output_dir, normalize_val, scale); + } + else + rewrite_usage (); + + return ret; +} + +/* Print a usage message and exit. If ERROR_P is nonzero, this is an error, + otherwise the output of --help. */ + +static void +print_usage (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE; + + fnotice (file, "Usage: %s [OPTION]... SUB_COMMAND [OPTION]...\n\n", progname); + fnotice (file, "Offline tool to handle gcda counts.\n\n"); + fnotice (file, " -h, --help Print this help, then exit\n"); + fnotice (file, " -v, --version Print version number, then exit\n"); + fnotice (file, " -A, --lipo_algorithm <0|1> Choose LIPO module grouping algorithm\n"); + fnotice (file, " -E, --lipo_merge_edge Merge module edges in LIPO module grouping\n"); + fnotice (file, " -W, --lipo_weak_inclusion Don't force strict inclusion in grouping\n"); + fnotice (file, " -C, --lipo_cutoff <0..100> Set LIPO module grouping cutoff\n"); + fnotice (file, " -M, --lipo_max_memory <int> Set the max memory in LIPO module grouping\n"); + fnotice (file, " -R, --lipo_random_group_size <int> Set LIPO random grouping size\n"); + fnotice (file, " -S, --lipo_random_group_seed <int> Set LIPO random grouping seed\n"); + fnotice (file, " -D, --lipo_dump_cgraph Dump dynamic call graph\n"); + fnotice (file, " -P, --lipo_propagate_scale Set LIPO propagate scale to true\n"); + fnotice (file, "\n"); + print_merge_usage_message (error_p); + print_rewrite_usage_message (error_p); + fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n", + bug_report_url); + exit (status); +} + +/* Print version information and exit. */ + +static void +print_version (void) +{ + fnotice (stdout, "%s %s%s\n", progname, pkgversion_string, version_string); + fprintf (stdout, "Copyright %s 2014 Free Software Foundation, Inc.\n", + _("(C)")); + fnotice (stdout, + _("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")); + exit (SUCCESS_EXIT_CODE); +} + +static const struct option options[] = +{ + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "lipo_algorithm", required_argument, NULL, 'A' }, + { "lipo_merge_edge", no_argument, NULL, 'E' }, + { "lipo_weak_inclusion", no_argument, NULL, 'W' }, + { "lipo_cutoff", required_argument, NULL, 'C' }, + { "lipo_max_memory", required_argument, NULL, 'M' }, + { "lipo_random_group_size", required_argument, NULL, 'R' }, + { "lipo_random_group_seed", required_argument, NULL, 'S' }, + { "lipo_dump_cgraph", no_argument, NULL, 'D' }, + { "lipo_propagate_scale", no_argument, NULL, 'P' }, + { 0, 0, 0, 0 } +}; + +/* Process args, return index to first non-arg. */ + +static int +process_args (int argc, char **argv) +{ + int opt; + int ret; + + while ((opt = getopt_long (argc, argv, "+hvA:EWC:M:R:S:DP", options, NULL)) != -1) + { + switch (opt) + { + case 'h': + print_usage (false); + /* Print_usage will exit. */ + case 'v': + print_version (); + /* Print_version will exit. */ + case 'E': + __gcov_lipo_merge_modu_edges = 1; + break; + case 'W': + __gcov_lipo_weak_inclusion = 1; + break; + case 'D': + __gcov_lipo_dump_cgraph = 1; + break; + case 'P': + __gcov_lipo_propagate_scale = 1; + break; + case 'A': + sscanf (optarg, "%d", &ret); + if (ret != 0 && ret != 1) + { + fprintf (stderr, "LIPO grouping algorithm can only be 0 or 1. \n"); + exit (-1); + } + __gcov_lipo_grouping_algorithm = ret; + break; + case 'R': + sscanf (optarg, "%d", &ret); + if (ret < 1) + { + fprintf (stderr, "LIPO random group size needs to be positive.\n"); + exit (-1); + } + __gcov_lipo_random_group_size = ret; + break; + case 'S': + sscanf (optarg, "%d", &ret); + __gcov_lipo_random_seed = ret;; + break; + case 'M': + sscanf (optarg, "%d", &ret); + if (ret < 0) + { + fprintf (stderr, "LIPO max-memory size needs to be positive. \n"); + exit (-1); + } + __gcov_lipo_max_mem = ret; + break; + case 'C': + sscanf (optarg, "%d", &ret); + if (ret < 0 || ret > 100) + { + fprintf (stderr, "LIPO cutoff value range is [0, 100]. \n"); + exit (-1); + } + __gcov_lipo_cutoff = ret;; + break; + default: + print_usage (true); + /* Print_usage will exit. */ + } + } + + return optind; +} + +/* Get the default param value from params.def. */ + +#define GET_DEFAULT_PARAM_VALUE(p) compiler_params[p].default_value +static void +set_lipo_default_params (void) +{ + __gcov_lipo_grouping_algorithm = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_GROUPING_ALGORITHM); + __gcov_lipo_merge_modu_edges = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_MERGE_MODU_EDGES); + __gcov_lipo_weak_inclusion = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_WEAK_INCLUSION); + __gcov_lipo_max_mem = GET_DEFAULT_PARAM_VALUE (PARAM_MAX_LIPO_MEMORY); + __gcov_lipo_random_group_size = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_RANDOM_GROUP_SIZE); + __gcov_lipo_cutoff = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_CUTOFF); + __gcov_lipo_random_seed = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_RANDOM_SEED); + __gcov_lipo_dump_cgraph = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_DUMP_CGRAPH); + __gcov_lipo_propagate_scale = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_PROPAGATE_SCALE); +} + +/* Main function for gcov-tool. */ + +int +main (int argc, char **argv) +{ + const char *p; + const char *sub_command; + + 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); + + /* Handle response files. */ + expandargv (&argc, &argv); + + /* Register the language-independent parameters. */ + global_init_params (); + finish_params (); + set_lipo_default_params (); + + process_args (argc, argv); + if (optind >= argc) + print_usage (true); + + sub_command = argv[optind]; + + if (!strcmp (sub_command, "merge")) + return do_merge (argc - optind, argv + optind); + else if (!strcmp (sub_command, "rewrite")) + return do_rewrite (argc - optind, argv + optind); + + print_usage (true); +} Index: gcov-io.c =================================================================== --- gcov-io.c (revision 206671) +++ gcov-io.c (working copy) @@ -555,7 +555,7 @@ gcov_read_counter (void) buffer, or NULL on empty string. You must copy the string before calling another gcov function. */ -#if !IN_LIBGCOV +#if !IN_LIBGCOV || IN_GCOV_TOOL GCOV_LINKAGE const char * gcov_read_string (void) { @@ -632,7 +632,7 @@ gcov_read_summary (struct gcov_summary *summary) } } -#if !IN_LIBGCOV && IN_GCOV != 1 +#if IN_GCOV_TOOL || !IN_LIBGCOV && IN_GCOV != 1 /* Read LEN words (unsigned type) and construct MOD_INFO. */ GCOV_LINKAGE void @@ -685,7 +685,7 @@ gcov_read_module_info (struct gcov_module_info *mo } #endif -#if !IN_LIBGCOV +#if !IN_LIBGCOV || IN_GCOV_TOOL /* Reset to a known position. BASE should have been obtained from gcov_position, LENGTH should be a record length. */