X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fgcov-tool.c;h=ce96db0f42cd69373f646eb0e8cd0762b8a186d5;hb=b7c41230322051912d979e132c52100158745b73;hp=a83b797ee099e83e9e2ed11be44bda5ad66561af;hpb=c77556a5d1e225024a4f9dafe5a1a6c316a86b83;p=gcc.git diff --git a/gcc/gcov-tool.c b/gcc/gcov-tool.c index a83b797ee09..ce96db0f42c 100644 --- a/gcc/gcov-tool.c +++ b/gcc/gcov-tool.c @@ -1,5 +1,5 @@ /* Gcc offline profile processing tool support. */ -/* Copyright (C) 2014 Free Software Foundation, Inc. +/* Copyright (C) 2014-2019 Free Software Foundation, Inc. Contributed by Rong Xu . This file is part of GCC. @@ -35,20 +35,25 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include #include #include +#if HAVE_FTW_H #include +#endif #include extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int); +extern int gcov_profile_overlap (struct gcov_info*, struct gcov_info*); extern int gcov_profile_normalize (struct gcov_info*, gcov_type); extern int gcov_profile_scale (struct gcov_info*, float, 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_do_dump (struct gcov_info *, int); +extern const char *gcov_get_filename (struct gcov_info *list); extern void gcov_set_verbose (void); /* Set to verbose output mode. */ static bool verbose; +#if HAVE_FTW_H + /* Remove file NAME if it has a gcda suffix. */ static int @@ -65,17 +70,22 @@ unlink_gcda_file (const char *name, ret = remove (name); if (ret) - fatal_error ("error in removing %s\n", name); + fatal_error (input_location, "error in removing %s", name); return ret; } +#endif /* Remove the gcda files in PATH recursively. */ static int -unlink_profile_dir (const char *path) +unlink_profile_dir (const char *path ATTRIBUTE_UNUSED) { +#if HAVE_FTW_H return nftw(path, unlink_gcda_file, 64, FTW_DEPTH | FTW_PHYS); +#else + return -1; +#endif } /* Output GCOV_INFO lists PROFILE to directory OUT. Note that @@ -90,12 +100,8 @@ gcov_output_files (const char *out, struct gcov_info *profile) /* Try to make directory if it doesn't already exist. */ if (access (out, F_OK) == -1) { -#ifdef TARGET_POSIX_IO - if (mkdir (out, 0755) == -1 && errno != EEXIST) -#else - if (mkdir (out) == -1 && errno != EEXIST) -#endif - fatal_error ("Cannot make directory %s", out); + if (mkdir (out, S_IRWXU | S_IRWXG | S_IRWXO) == -1 && errno != EEXIST) + fatal_error (input_location, "Cannot make directory %s", out); } else unlink_profile_dir (out); @@ -103,18 +109,25 @@ gcov_output_files (const char *out, struct gcov_info *profile) pwd = getcwd (NULL, 0); if (pwd == NULL) - fatal_error ("Cannot get current directory name"); + fatal_error (input_location, "Cannot get current directory name"); ret = chdir (out); if (ret) - fatal_error ("Cannot change directory to %s", out); + fatal_error (input_location, "Cannot change directory to %s", out); + + /* Verify that output file does not exist (either was removed by + unlink_profile_data or removed by user). */ + const char *filename = gcov_get_filename (profile); + + if (access (filename, F_OK) != -1) + fatal_error (input_location, "output file %s already exists in folder %s", + filename, out); - set_gcov_list (profile); - gcov_exit (); + gcov_do_dump (profile, 0); ret = chdir (pwd); if (ret) - fatal_error ("Cannot change directory to %s", pwd); + fatal_error (input_location, "Cannot change directory to %s", pwd); free (pwd); } @@ -160,8 +173,8 @@ print_merge_usage_message (int error_p) FILE *file = error_p ? stderr : stdout; fnotice (file, " merge [options] Merge coverage file contents\n"); - fnotice (file, " -v, --verbose Verbose mode\n"); fnotice (file, " -o, --output Output directory\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); fnotice (file, " -w, --weight Set weights (float point values)\n"); } @@ -175,7 +188,7 @@ static const struct option merge_options[] = /* Print merge usage and exit. */ -static void +static void ATTRIBUTE_NORETURN merge_usage (void) { fnotice (stderr, "Merge subcomand usage:"); @@ -189,7 +202,6 @@ static int do_merge (int argc, char **argv) { int opt; - int ret; const char *output_dir = 0; int w1 = 1, w2 = 1; @@ -208,7 +220,7 @@ do_merge (int argc, char **argv) case 'w': sscanf (optarg, "%d,%d", &w1, &w2); if (w1 < 0 || w2 < 0) - fatal_error ("weights need to be non-negative\n"); + fatal_error (input_location, "weights need to be non-negative"); break; default: merge_usage (); @@ -218,12 +230,10 @@ do_merge (int argc, char **argv) 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 + if (argc - optind != 2) merge_usage (); - return ret; + return profile_merge (argv[optind], argv[optind+1], output_dir, w1, w2); } /* If N_VAL is no-zero, normalize the profile by setting the largest counter @@ -231,7 +241,7 @@ do_merge (int argc, char **argv) Otherwise, multiply the all counters by SCALE. */ static int -profile_rewrite (const char *d1, const char *out, long long n_val, +profile_rewrite (const char *d1, const char *out, int64_t n_val, float scale, int n, int d) { struct gcov_info * d1_profile; @@ -257,10 +267,10 @@ print_rewrite_usage_message (int error_p) FILE *file = error_p ? stderr : stdout; fnotice (file, " rewrite [options] Rewrite coverage file contents\n"); - fnotice (file, " -v, --verbose Verbose mode\n"); + fnotice (file, " -n, --normalize Normalize the profile\n"); fnotice (file, " -o, --output Output directory\n"); fnotice (file, " -s, --scale Scale the profile counters\n"); - fnotice (file, " -n, --normalize Normalize the profile\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); } static const struct option rewrite_options[] = @@ -274,7 +284,7 @@ static const struct option rewrite_options[] = /* Print profile rewrite usage and exit. */ -static void +static void ATTRIBUTE_NORETURN rewrite_usage (void) { fnotice (stderr, "Rewrite subcommand usage:"); @@ -290,7 +300,7 @@ do_rewrite (int argc, char **argv) int opt; int ret; const char *output_dir = 0; - long long normalize_val = 0; + int64_t normalize_val = 0; float scale = 0.0; int numerator = 1; int denominator = 1; @@ -310,7 +320,11 @@ do_rewrite (int argc, char **argv) break; case 'n': if (!do_scaling) - normalize_val = atoll (optarg); +#if defined(INT64_T_IS_LONG) + normalize_val = strtol (optarg, (char **)NULL, 10); +#else + normalize_val = strtoll (optarg, (char **)NULL, 10); +#endif else fnotice (stderr, "scaling cannot co-exist with normalization," " skipping\n"); @@ -341,7 +355,7 @@ do_rewrite (int argc, char **argv) } if (scale < 0.0) - fatal_error ("scale needs to be non-negative\n"); + fatal_error (input_location, "scale needs to be non-negative"); if (normalize_val != 0) { @@ -370,6 +384,120 @@ do_rewrite (int argc, char **argv) return ret; } +/* Driver function to computer the overlap score b/w profile D1 and D2. + Return 1 on error and 0 if OK. */ + +static int +profile_overlap (const char *d1, const char *d2) +{ + 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; + + return gcov_profile_overlap (d1_profile, d2_profile); + } + + return 1; +} + +/* Usage message for profile overlap. */ + +static void +print_overlap_usage_message (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + + fnotice (file, " overlap [options] Compute the overlap of two profiles\n"); + fnotice (file, " -f, --function Print function level info\n"); + fnotice (file, " -F, --fullname Print full filename\n"); + fnotice (file, " -h, --hotonly Only print info for hot objects/functions\n"); + fnotice (file, " -o, --object Print object level info\n"); + fnotice (file, " -t , --hot_threshold Set the threshold for hotness\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); +} + +static const struct option overlap_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "function", no_argument, NULL, 'f' }, + { "fullname", no_argument, NULL, 'F' }, + { "object", no_argument, NULL, 'o' }, + { "hotonly", no_argument, NULL, 'h' }, + { "hot_threshold", required_argument, NULL, 't' }, + { 0, 0, 0, 0 } +}; + +/* Print overlap usage and exit. */ + +static void ATTRIBUTE_NORETURN +overlap_usage (void) +{ + fnotice (stderr, "Overlap subcomand usage:"); + print_overlap_usage_message (true); + exit (FATAL_EXIT_CODE); +} + +int overlap_func_level; +int overlap_obj_level; +int overlap_hot_only; +int overlap_use_fullname; +double overlap_hot_threshold = 0.005; + +/* Driver for profile overlap sub-command. */ + +static int +do_overlap (int argc, char **argv) +{ + int opt; + int ret; + + optind = 0; + while ((opt = getopt_long (argc, argv, "vfFoht:", overlap_options, NULL)) != -1) + { + switch (opt) + { + case 'v': + verbose = true; + gcov_set_verbose (); + break; + case 'f': + overlap_func_level = 1; + break; + case 'F': + overlap_use_fullname = 1; + break; + case 'o': + overlap_obj_level = 1; + break; + case 'h': + overlap_hot_only = 1; + break; + case 't': + overlap_hot_threshold = atof (optarg); + break; + default: + overlap_usage (); + } + } + + if (argc - optind == 2) + ret = profile_overlap (argv[optind], argv[optind+1]); + else + overlap_usage (); + + return ret; +} + + /* Print a usage message and exit. If ERROR_P is nonzero, this is an error, otherwise the output of --help. */ @@ -385,6 +513,7 @@ print_usage (int error_p) fnotice (file, " -v, --version Print version number, then exit\n"); print_merge_usage_message (error_p); print_rewrite_usage_message (error_p); + print_overlap_usage_message (error_p); fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n", bug_report_url); exit (status); @@ -396,7 +525,7 @@ static void print_version (void) { fnotice (stdout, "%s %s%s\n", progname, pkgversion_string, version_string); - fnotice (stdout, "Copyright %s 2014 Free Software Foundation, Inc.\n", + fnotice (stdout, "Copyright %s 2019 Free Software Foundation, Inc.\n", _("(C)")); fnotice (stdout, _("This is free software; see the source for copying conditions.\n" @@ -426,9 +555,11 @@ process_args (int argc, char **argv) case 'h': print_usage (false); /* Print_usage will exit. */ + /* FALLTHRU */ case 'v': print_version (); /* Print_version will exit. */ + /* FALLTHRU */ default: print_usage (true); /* Print_usage will exit. */ @@ -473,6 +604,8 @@ main (int argc, char **argv) return do_merge (argc - optind, argv + optind); else if (!strcmp (sub_command, "rewrite")) return do_rewrite (argc - optind, argv + optind); + else if (!strcmp (sub_command, "overlap")) + return do_overlap (argc - optind, argv + optind); print_usage (true); }