diff --git a/repos/base/recipes/pkg/test-xml_generator/runtime b/repos/base/recipes/pkg/test-xml_generator/runtime
index b264189d7d..cfb2746cdd 100644
--- a/repos/base/recipes/pkg/test-xml_generator/runtime
+++ b/repos/base/recipes/pkg/test-xml_generator/runtime
@@ -80,6 +80,11 @@
+
+
+
+
+
diff --git a/repos/libports/ports/gcov.hash b/repos/libports/ports/gcov.hash
index a9a3085fc4..a32fd4e691 100644
--- a/repos/libports/ports/gcov.hash
+++ b/repos/libports/ports/gcov.hash
@@ -1 +1 @@
-f0518e32e26d8286b84789e661c4999e01d8b569
+f08ebbb6104c2ac722fc5222939bfd9bcdef3d1f
diff --git a/repos/libports/src/app/gcov/patches/gcov.patch b/repos/libports/src/app/gcov/patches/gcov.patch
index 68fcfe1085..9faabefe4d 100644
--- a/repos/libports/src/app/gcov/patches/gcov.patch
+++ b/repos/libports/src/app/gcov/patches/gcov.patch
@@ -4,11 +4,11 @@ From: Christian Prochaska
---
- gcc/gcov.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 84 insertions(+), 5 deletions(-)
+ gcc/gcov.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 128 insertions(+), 6 deletions(-)
diff --git a/gcc/gcov.c b/gcc/gcov.c
-index 50061c7..eead285 100644
+index 50061c7..b9ddccb 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -41,10 +41,13 @@ along with Gcov; see the file COPYING3. If not see
@@ -25,7 +25,19 @@ index 50061c7..eead285 100644
/* 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. */
-@@ -350,6 +353,16 @@ static int flag_all_blocks = 0;
+@@ -299,6 +302,11 @@ static unsigned bbg_stamp;
+
+ 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;
+@@ -350,6 +358,16 @@ static int flag_all_blocks = 0;
static int flag_function_summary = 0;
@@ -42,7 +54,7 @@ index 50061c7..eead285 100644
/* Object directory file prefix. This is the directory/file where the
graph and data files are looked for, if nonzero. */
-@@ -407,6 +420,43 @@ static void release_structures (void);
+@@ -407,6 +425,43 @@ static void release_structures (void);
static void release_function (function_t *);
extern int main (int, char **);
@@ -86,7 +98,7 @@ index 50061c7..eead285 100644
int
main (int argc, char **argv)
{
-@@ -437,7 +487,7 @@ main (int argc, char **argv)
+@@ -437,7 +492,7 @@ main (int argc, char **argv)
sources = XNEWVEC (source_t, a_sources);
argno = process_args (argc, argv);
@@ -95,7 +107,7 @@ index 50061c7..eead285 100644
print_usage (true);
if (argc - argno > 1)
-@@ -445,6 +495,15 @@ main (int argc, char **argv)
+@@ -445,6 +500,18 @@ main (int argc, char **argv)
first_arg = argno;
@@ -104,14 +116,17 @@ index 50061c7..eead285 100644
+ /* search .gcda files and process each one */
+ process_files("/");
+
-+ /* finish processing arguments */
-+ argno = argc;
++ generate_results(NULL);
++
++ release_structures();
++
++ return 0;
+ }
+
for (; argno != argc; argno++)
{
if (flag_display_progress)
-@@ -488,7 +547,8 @@ print_usage (int error_p)
+@@ -488,7 +555,8 @@ print_usage (int error_p)
fnotice (file, " -r, --relative-only Only show data for relative sources\n");
fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
@@ -121,7 +136,7 @@ index 50061c7..eead285 100644
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
bug_report_url);
exit (status);
-@@ -528,6 +588,7 @@ static const struct option options[] =
+@@ -528,6 +596,7 @@ static const struct option options[] =
{ "source-prefix", required_argument, NULL, 's' },
{ "unconditional-branches", no_argument, NULL, 'u' },
{ "display-progress", no_argument, NULL, 'd' },
@@ -129,7 +144,7 @@ index 50061c7..eead285 100644
{ 0, 0, 0, 0 }
};
-@@ -538,7 +599,7 @@ process_args (int argc, char **argv)
+@@ -538,7 +607,7 @@ process_args (int argc, char **argv)
{
int opt;
@@ -138,7 +153,7 @@ index 50061c7..eead285 100644
-1)
{
switch (opt)
-@@ -555,6 +616,9 @@ process_args (int argc, char **argv)
+@@ -555,6 +624,9 @@ process_args (int argc, char **argv)
case 'f':
flag_function_summary = 1;
break;
@@ -148,7 +163,41 @@ index 50061c7..eead285 100644
case 'h':
print_usage (false);
/* print_usage will exit. */
-@@ -788,14 +852,17 @@ output_gcov_file (const char *file_name, source_t *src)
+@@ -784,18 +856,51 @@ process_file (const char *file_name)
+ static void
+ output_gcov_file (const char *file_name, source_t *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)
{
@@ -168,7 +217,28 @@ index 50061c7..eead285 100644
}
else
fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
-@@ -1114,6 +1181,18 @@ find_source (const char *file_name)
+@@ -968,7 +1073,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;
+
+@@ -1014,6 +1120,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;
+ }
+@@ -1114,6 +1224,18 @@ find_source (const char *file_name)
#endif
&& IS_DIR_SEPARATOR (src->coverage.name[source_length]))
src->coverage.name += source_length + 1;
diff --git a/repos/libports/src/lib/gcov/libc/libc.cc b/repos/libports/src/lib/gcov/libc/libc.cc
index 266f14cdc1..145f0fe725 100644
--- a/repos/libports/src/lib/gcov/libc/libc.cc
+++ b/repos/libports/src/lib/gcov/libc/libc.cc
@@ -12,6 +12,7 @@
* under the terms of the GNU Affero General Public License version 3.
*/
+#include
#include
#include
#include
@@ -20,6 +21,7 @@
#include
#include
#include
+#include
extern "C" {
#include "stdio.h"
@@ -35,11 +37,12 @@ FILE *stderr = &stderr_file;
struct Gcov_env
{
- Genode::Env &env;
- Genode::Heap heap { env.ram(), env.rm() };
- Genode::Allocator_avl fs_alloc { &heap };
- File_system::Connection fs { env, fs_alloc, "gcov_data" };
- unsigned long seek_offset { 0 };
+ Genode::Env &env;
+ Genode::Attached_rom_dataspace config { env, "config" };
+ Genode::Heap heap { env.ram(), env.rm() };
+ Genode::Allocator_avl fs_alloc { &heap };
+ File_system::Connection fs { env, fs_alloc, "gcov_data" };
+ unsigned long seek_offset { 0 };
/* only one file is open at a time */
Genode::Constructible file_handle;
@@ -118,6 +121,55 @@ extern "C" FILE *fopen(const char *path, const char *mode)
gcov_env->seek_offset = 0;
+ /*
+ * Write the list of source files to be annotated by gcov into a '.gcan'
+ * file in the same directory as the '.gcda' file.
+ */
+
+ try {
+
+ Genode::Xml_node config(gcov_env->config.local_addr(),
+ gcov_env->config.size());
+
+ Genode::Xml_node libgcov_node = config.sub_node("libgcov");
+
+ Absolute_path annotate_file_name { file_name };
+ annotate_file_name.remove_trailing('a');
+ annotate_file_name.remove_trailing('d');
+ annotate_file_name.append("an");
+
+ File_system::File_handle annotate_file_handle {
+ gcov_env->fs.file(dir, annotate_file_name.base() + 1,
+ File_system::WRITE_ONLY, true) };
+
+ File_system::seek_off_t seek_offset = 0;
+
+ libgcov_node.for_each_sub_node("annotate",
+ [&] (Genode::Xml_node annotate_node) {
+
+ Absolute_path source_path;
+
+ annotate_node.attribute("source").value(source_path.base(),
+ source_path.capacity());
+
+ seek_offset += File_system::write(gcov_env->fs,
+ annotate_file_handle,
+ source_path.base(),
+ Genode::strlen(source_path.base()),
+ seek_offset);
+
+ seek_offset += File_system::write(gcov_env->fs,
+ annotate_file_handle,
+ "\n",
+ 1,
+ seek_offset);
+ });
+
+ gcov_env->fs.close(annotate_file_handle);
+ }
+ catch (Genode::Xml_node::Nonexistent_sub_node) { }
+ catch (Genode::Xml_attribute::Nonexistent_attribute) { }
+
return &gcov_env->file;
}