720919bc14
Issue #3307
275 lines
7.4 KiB
Diff
275 lines
7.4 KiB
Diff
gcov.patch
|
|
|
|
From: Christian Prochaska <christian.prochaska@genode-labs.com>
|
|
|
|
|
|
---
|
|
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 <getopt.h>
|
|
|
|
+#include <dirent.h>
|
|
+
|
|
#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;
|
|
}
|