Am Wed, 12 Apr 2017 13:38:50 +0200 schrieb Henning Schild <[email protected]>:
> With the new feature to download the used firmware out of sysfs and > a way to get GCOV data into that. It is now time to extract this > information and generate .gcda files for higher level tools to work > with. > Instead of dealing with the details of that just use what the > compiler gives us when we link to its gcov lib. > > Signed-off-by: Henning Schild <[email protected]> > > diff --git a/.gitignore b/.gitignore > --- a/.gitignore > +++ b/.gitignore > @@ -4,6 +4,7 @@ > *.cmd > *.bin > *.gcno > +*.gcda > .tmp_versions > *.dtb > *.dtb.S > @@ -14,6 +15,7 @@ driver/jailhouse.ko > hypervisor/include/jailhouse/config.h > hypervisor/hypervisor.lds > tools/jailhouse > +tools/jailhouse-gcov-extract > tools/jailhouse-config-collect > configs/*.cell > Documentation/generated > diff --git a/tools/Makefile b/tools/Makefile > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -1,7 +1,7 @@ > # > # Jailhouse, a Linux-based partitioning hypervisor > # > -# Copyright (c) Siemens AG, 2013-2016 > +# Copyright (c) Siemens AG, 2013-2017 > # > # Authors: > # Jan Kiszka <[email protected]> > @@ -23,6 +23,7 @@ LDFLAGS := > GCOV_PROFILE := n > > BINARIES := jailhouse > + > HELPERS := \ > jailhouse-cell-linux \ > jailhouse-cell-stats \ > @@ -58,6 +59,17 @@ targets += jailhouse.o > $(obj)/jailhouse: $(obj)/jailhouse.o > $(call if_changed,ld) > > +CFLAGS_jailhouse-gcov-extract.o := > -I$(src)/../hypervisor/include \ > + -I$(src)/../hypervisor/arch/$(SRCARCH)/include > +# just change ldflags not cflags, we are not profiling the tool > +LDFLAGS_jailhouse-gcov-extract := -lgcov -fprofile-arcs > + > +targets += jailhouse-gcov-extract.o > +always += jailhouse-gcov-extract > + > +$(obj)/jailhouse-gcov-extract: $(obj)/jailhouse-gcov-extract.o > + $(call if_changed,ld) > + > $(obj)/jailhouse-config-collect: $(src)/jailhouse-config-create > $(src)/jailhouse-config-collect.tmpl $(call if_changed,gen_collect) > > diff --git a/tools/jailhouse-gcov-extract.c > b/tools/jailhouse-gcov-extract.c new file mode 100644 > --- /dev/null > +++ b/tools/jailhouse-gcov-extract.c > @@ -0,0 +1,217 @@ > +/* > + * Jailhouse, a Linux-based partitioning hypervisor > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Henning Schild <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version 2. > See > + * the COPYING file in the top-level directory. > + */ > + > +#include <stdio.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <sys/mman.h> > +#include <fcntl.h> > +#include <errno.h> > +#include <error.h> > +#include <unistd.h> > +#include <assert.h> > +#include <stdlib.h> > +#include <string.h> > +#include <jailhouse/header.h> > +#include <asm/jailhouse_header.h> > + > +#if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) > +#error "Gcov format of gcc < 4.7 is not supported!" > +#endif > + > +/* > + * the following bits are heavily inspired by > linux/kernel/gcov/gcc_4.7.c > + * with some slight modification > + */ > +#if BITS_PER_LONG >= 64 This was never defined, fixed that. > +typedef long gcov_type; > +#else > +typedef long long gcov_type; > +#endif > + > +#if (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) > +#define GCOV_COUNTERS 10 > +#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 > +#define GCOV_COUNTERS 9 > +#else > +#define GCOV_COUNTERS 8 > +#endif > + > +struct gcov_ctr_info { > + unsigned int num; > + gcov_type *values; > +}; > + > +struct gcov_fn_info { > + struct gcov_info *key; > + unsigned int ident; > + unsigned int lineno_checksum; > + unsigned int cfg_checksum; > + struct gcov_ctr_info ctrs[0]; > +}; > + > +struct gcov_info { > + unsigned int version; > + struct gcov_info *next; > + unsigned int stamp; > + char *filename; > + void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int); > + unsigned int n_functions; > + struct gcov_fn_info **functions; > +}; > +/* > + * end of linux/kernel/gcov/gcc_4.7.c > + */ > + > +static void *hypervisor; > +static ssize_t hypervisor_size; > +extern void __gcov_merge_add(gcov_type *counters, unsigned int > n_counters); +extern void __gcov_init(struct gcov_info *); > +extern void __gcov_dump(); > + > +static void *hypervisor2current(void *hvp) > +{ > + unsigned long hvaddr = (unsigned long)hvp; > + void *ret; > + > + if(hvp == NULL) > + return NULL; > + assert(hvaddr >= JAILHOUSE_BASE && > + hvaddr < JAILHOUSE_BASE + hypervisor_size); > + ret = (void *)(hvaddr - JAILHOUSE_BASE + (unsigned > long)hypervisor); + > + return ret; > +} > + > +/* > + * translate one gcov-"tree" from the hypervisor address space to > the current > + * addresses > + */ > +static void translate_all_pointers(struct gcov_info *info) > +{ > + struct gcov_fn_info *fn_info; > + struct gcov_ctr_info *ctr_info; > + unsigned int i, j, active; > + > + info->next = hypervisor2current(info->next); > + info->filename = hypervisor2current(info->filename); > + active = 0; > + for (i = 0; i < GCOV_COUNTERS; i++) { > + if (info->merge[i]) { > + active++; > + info->merge[i] = &__gcov_merge_add; > + } else > + break; > + } > + info->functions = hypervisor2current(info->functions); > + for (i = 0; i < info->n_functions; i++) { > + info->functions[i] = > hypervisor2current(info->functions[i]); > + fn_info = info->functions[i]; > + if (fn_info) { > + fn_info->key = > hypervisor2current(fn_info->key); > + assert(fn_info->key == info); > + for (j = 0; j < active; j++) { > + ctr_info = fn_info->ctrs + j; > + ctr_info->values = > + > hypervisor2current(ctr_info->values); > + } > + } > + } > +} > + > +int main(int argc, char **argv) > +{ > + struct gcov_info *gcov_info_head, *info, *next; > + struct jailhouse_header *header; > + struct stat sbuf; > + char *filename; > + char *errstr = NULL; > + ssize_t count, ret; > + int fd; > + > + if (argc == 1) { > + filename = "/sys/devices/jailhouse/core"; > + } else { > + if (argc != 2 || (strncmp(argv[1], "-", 1) == 0)) { > + printf("Usage: %s [-h] [FILE]\n", argv[0]); > + if (strcmp(argv[1], "-h")) { > + errno = EINVAL; > + errstr = argv[1]; > + } > + goto out; > + } > + filename = argv[1]; > + } > + fd = open(filename, O_RDONLY); > + if (fd < 1) { > + errstr = filename; > + goto out; > + } > + > + ret = fstat(fd, &sbuf); > + if (ret) { > + errstr = filename; > + goto out; > + } > + hypervisor_size = sbuf.st_size; > + hypervisor = malloc(hypervisor_size); > + if (hypervisor == NULL) { > + errstr = "malloc"; > + goto out_f; > + } > + > + count = 0; > + while (count < hypervisor_size) { > + ret = read(fd, hypervisor + count, > hypervisor_size-count); > + if (ret < 0 && errno != EINTR) { > + errstr = "read"; > + goto out_m; > + } > + count += ret; > + } > + assert(count == hypervisor_size); > + > + header = (struct jailhouse_header *)hypervisor; > + if (strcmp(header->signature, JAILHOUSE_SIGNATURE)) { > + errno = EINVAL; > + error(0, 0, "%s does not seem to be a hypervisor > image", > + filename); > + goto out_m; > + } > + > + gcov_info_head = hypervisor2current(header->gcov_info_head); > + if (!gcov_info_head) { > + errno = EINVAL; > + error(0, 0, "%s does not contain gcov information.", > filename); > + goto out_m; > + } > + info = gcov_info_head; > + for (info = gcov_info_head; info; info = info->next) > + translate_all_pointers(info); > + > + for (info = gcov_info_head; info;) { > + /* remember next because __gcov_init changes it */ > + next = info->next; > + __gcov_init(info); > + info = next; > + } > + __gcov_dump(); > + > +out_m: > + free(hypervisor); > +out_f: > + close(fd); > +out: > + if (errno && errstr) > + error(errno, errno, errstr); > + return 0; > +} -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
