gcov.patch From: Christian Prochaska --- gcc/gcov.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 132 insertions(+), 7 deletions(-) diff --git a/gcc/gcov.c b/gcc/gcov.c index c7c52ce..e039ef0 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -47,6 +47,8 @@ along with Gcov; see the file COPYING3. If not see #include +#include + #include "md5.h" using namespace std; @@ -55,6 +57,7 @@ using namespace std; #include "gcov-io.h" #include "gcov-io.c" + /* The gcno file is generated by -ftest-coverage option. The gcda file is generated by a program compiled with -fprofile-arcs. Their formats are documented in gcov-io.h. */ @@ -436,6 +439,11 @@ static unsigned bbg_supports_has_unexecuted_blocks; static char *da_file_name; +/* Name and file pointer of the input file for the annotation source list (gcan). */ + +#define GCOV_ANNOTATE_SUFFIX ".gcan" +static char *an_file_name; + /* Data file is missing. */ static int no_data_file; @@ -504,6 +512,16 @@ static int flag_human_readable_numbers = 0; static int flag_function_summary = 0; +/* + * Genode autopilot mode + * + * - scans for gcov data files + * - strips the Genode depot path from source paths + * - writes results to stdout + */ + +static int flag_genode_autopilot = 0; + /* Object directory file prefix. This is the directory/file where the graph and data files are looked for, if nonzero. */ @@ -750,6 +768,43 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true) return count; } +void process_files(const char *dir_path) +{ + char new_path[strlen(dir_path) + sizeof('/') + NAME_MAX]; + + DIR *dir = opendir(dir_path); + + if (!dir) + return; + + struct dirent *dirent; + + while((dirent = readdir(dir)) != NULL) { + + snprintf(new_path, sizeof(new_path), "%s/%s", dir_path, dirent->d_name); + + struct stat stat_buf; + + if (stat(new_path, &stat_buf) != 0) + continue; + + if (S_ISDIR(stat_buf.st_mode)) { + process_files(new_path); + continue; + } + + if (!S_ISREG(stat_buf.st_mode)) + continue; + + if (!strstr(dirent->d_name, ".gcda")) + continue; + + process_file(new_path); + } + + closedir(dir); +} + int main (int argc, char **argv) { @@ -775,13 +830,25 @@ main (int argc, char **argv) expandargv (&argc, &argv); argno = process_args (argc, argv); - if (optind == argc) + if ((optind == argc) && !flag_genode_autopilot) print_usage (true); if (argc - argno > 1) multiple_files = 1; first_arg = argno; + + if (flag_genode_autopilot) { + + /* search .gcda files and process each one */ + process_files("/"); + + process_all_functions(); + generate_results(NULL); + release_structures(); + + return 0; + } for (; argno != argc; argno++) { @@ -833,7 +900,8 @@ print_usage (int error_p) fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n"); fnotice (file, " -v, --version Print version number, then exit\n"); fnotice (file, " -w, --verbose Print verbose informations\n"); - fnotice (file, " -x, --hash-filenames Hash long pathnames\n"); + fnotice (file, " -x, --hash-filenames Hash long pathnames\n\n"); + fnotice (file, " -g, --genode-autopilot Genode autopilot mode\n"); fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n", bug_report_url); exit (status); @@ -877,6 +945,7 @@ static const struct option options[] = { "display-progress", no_argument, NULL, 'd' }, { "hash-filenames", no_argument, NULL, 'x' }, { "use-colors", no_argument, NULL, 'k' }, + { "genode-autopilot", no_argument, NULL, 'g' }, { 0, 0, 0, 0 } }; @@ -887,7 +956,7 @@ process_args (int argc, char **argv) { int opt; - const char *opts = "abcdfhijklmno:prs:uvwx"; + const char *opts = "abcdfghijklmno:prs:uvwx"; while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1) { switch (opt) @@ -904,6 +973,9 @@ process_args (int argc, char **argv) case 'f': flag_function_summary = 1; break; + case 'g': + flag_genode_autopilot = 1; + break; case 'h': print_usage (false); /* print_usage will exit. */ @@ -1234,11 +1306,43 @@ process_all_functions (void) static void output_gcov_file (const char *file_name, source_info *src) { + if (flag_genode_autopilot) { + + /* output only if the file name appears in the .gcan file */ + + FILE *annotate_file = fopen(an_file_name, "r"); + + if (!annotate_file) + return; + + char *source_file = NULL; + size_t len = 0; + bool annotate = false; + + while (getline(&source_file, &len, annotate_file) != -1) { + + /* remove '\n' */ + source_file[strlen(source_file) - 1] = 0; + + if (strstr(src->coverage.name, source_file) != NULL) { + annotate = true; + break; + } + } + + fclose(annotate_file); + + if (!annotate) + return; + } + char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name); if (src->coverage.lines) { - FILE *gcov_file = fopen (gcov_file_name, "w"); + FILE *gcov_file = flag_genode_autopilot ? + stdout : + fopen (gcov_file_name, "w"); if (gcov_file) { fnotice (stdout, "Creating '%s'\n", gcov_file_name); @@ -1246,7 +1350,8 @@ output_gcov_file (const char *file_name, source_info *src) if (ferror (gcov_file)) fnotice (stderr, "Error writing output file '%s'\n", gcov_file_name); - fclose (gcov_file); + if (!flag_genode_autopilot) + fclose (gcov_file); } else fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name); @@ -1329,7 +1434,10 @@ generate_results (const char *file_name) function_summary (&src->coverage, "File"); total_lines += src->coverage.lines; total_executed += src->coverage.lines_executed; - if (flag_gcov_file) + + if (flag_gcov_file && + !(flag_genode_autopilot && + (src->coverage.lines_executed == src->coverage.lines))) { if (flag_intermediate_format) /* Output the intermediate format without requiring source @@ -1384,7 +1492,8 @@ create_file_names (const char *file_name) /* Free previous file names. */ free (bbg_file_name); free (da_file_name); - da_file_name = bbg_file_name = NULL; + free (an_file_name); + da_file_name = bbg_file_name = an_file_name = NULL; bbg_file_time = 0; bbg_stamp = 0; @@ -1430,6 +1539,10 @@ create_file_names (const char *file_name) strcpy (da_file_name, name); strcpy (da_file_name + length, GCOV_DATA_SUFFIX); + an_file_name = XNEWVEC (char, length + strlen (GCOV_ANNOTATE_SUFFIX) + 1); + strcpy (an_file_name, name); + strcpy (an_file_name + length, GCOV_ANNOTATE_SUFFIX); + free (name); return; } @@ -1486,6 +1599,18 @@ find_source (const char *file_name) #endif && IS_DIR_SEPARATOR (src->coverage.name[source_length])) src->coverage.name += source_length + 1; + + if (flag_genode_autopilot) { + + /* strip path of the Genode depot */ + + char *depot_relative_path = strstr(src->name, "/depot/"); + if (depot_relative_path) { + src->name = depot_relative_path + strlen("/depot"); + src->coverage.name = src->name; + } + } + if (!stat (src->name, &status)) src->file_time = status.st_mtime; }