diff options
author | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-07 17:11:45 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-15 07:59:18 +1000 |
commit | 614aa6a7833839146de2769a09de355a49b8ed3d (patch) | |
tree | 99abce24c9d73c5135a2ebe1a2efe02085f0fbbe | |
parent | e8782725c718875eab9764812c640bcb5002eacd (diff) | |
download | skiboot-614aa6a7833839146de2769a09de355a49b8ed3d.zip skiboot-614aa6a7833839146de2769a09de355a49b8ed3d.tar.gz skiboot-614aa6a7833839146de2769a09de355a49b8ed3d.tar.bz2 |
Construct linked list of gcov data structures
The gcov constructors call __gcov_init() for each gcov covered file,
which we then need to turn into a linked list of all gcov files so
that we can traverse them later to pull out gcov profiling data.
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | Makefile.main | 2 | ||||
-rw-r--r-- | core/gcov-profiling.c | 62 | ||||
-rw-r--r-- | core/init.c | 8 |
3 files changed, 68 insertions, 4 deletions
diff --git a/Makefile.main b/Makefile.main index bd03ff4..c01b16b 100644 --- a/Makefile.main +++ b/Makefile.main @@ -53,7 +53,7 @@ CPPFLAGS += -ffreestanding CFLAGS := -fno-strict-aliasing -fstack-protector-all -pie -mbig-endian -m64 ifeq ($(SKIBOOT_GCOV),1) -CFLAGS += -fprofile-arcs -ftest-coverage +CFLAGS += -fprofile-arcs -ftest-coverage -DSKIBOOT_GCOV=1 endif ifeq ($(STACK_CHECK),1) diff --git a/core/gcov-profiling.c b/core/gcov-profiling.c index 453ae7f..cf8b509 100644 --- a/core/gcov-profiling.c +++ b/core/gcov-profiling.c @@ -14,11 +14,43 @@ * limitations under the License. */ +#include <skiboot.h> #include <compiler.h> +#include <stdio.h> typedef long gcov_type; -void __gcov_init(void* f) __attrconst; +/* + * This is GCC internal data structure. See GCC libgcc/libgcov.h for + * details. + * + * If gcc changes this, we have to change it. + */ + +typedef unsigned int gcov_unsigned_int; + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 9 +#define GCOV_COUNTERS 9 +#else +#define GCOV_COUNTERS 8 +#endif + +struct gcov_info +{ + gcov_unsigned_int version; + struct gcov_info *next; + gcov_unsigned_int stamp; + const char *filename; + void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int); + unsigned int n_functions; + struct gcov_fn_info **functions; +}; + +/* We have a list of all gcov info set up at startup */ +struct gcov_info *gcov_info_list; + +void __gcov_init(struct gcov_info* f); +void skiboot_gcov_done(void); void __gcov_flush(void) __attrconst; void __gcov_merge_add(gcov_type *counters, unsigned int n_counters) __attrconst; void __gcov_merge_single(gcov_type *counters, unsigned int n_counters) __attrconst; @@ -26,13 +58,37 @@ void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters) __attrcons void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters) __attrconst; void __gcov_merge_time_profile(gcov_type *counters, unsigned int n_counters) __attrconst; -void __gcov_init(void* f) +void __gcov_init(struct gcov_info* f) { - (void)f; + static gcov_unsigned_int version = 0; + if (version == 0) { + printf("GCOV version: %u\n", f->version); + version = f->version; + } + + if (gcov_info_list) + f->next = gcov_info_list; + + gcov_info_list = f; return; } +void skiboot_gcov_done(void) +{ + struct gcov_info *i = gcov_info_list; + + if (i->filename) + printf("GCOV: gcov_info_list looks sane (first file: %s)\n", + i->filename); + else + prlog(PR_WARNING, "GCOV: gcov_info_list doesn't look sane. " + "i->filename == NULL."); + + printf("GCOV: gcov_info_list at 0x%p\n", gcov_info_list); +} + + void __gcov_merge_add(gcov_type *counters, unsigned int n_counters) { (void)counters; diff --git a/core/init.c b/core/init.c index d4c0c25..0e28f95 100644 --- a/core/init.c +++ b/core/init.c @@ -56,6 +56,10 @@ enum proc_gen proc_gen; static uint64_t kernel_entry; static bool kernel_32bit; +#ifdef SKIBOOT_GCOV +void skiboot_gcov_done(void); +#endif + struct debug_descriptor debug_descriptor = { .eye_catcher = "OPALdbug", .version = DEBUG_DESC_VERSION, @@ -585,6 +589,10 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) (debug_descriptor.console_log_levels & 0x0f)); prlog(PR_TRACE, "You will not see this\n"); +#ifdef SKIBOOT_GCOV + skiboot_gcov_done(); +#endif + /* Initialize boot cpu's cpu_thread struct */ init_boot_cpu(); |