aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.vnet.ibm.com>2015-05-07 17:11:45 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-05-15 07:59:18 +1000
commit614aa6a7833839146de2769a09de355a49b8ed3d (patch)
tree99abce24c9d73c5135a2ebe1a2efe02085f0fbbe
parente8782725c718875eab9764812c640bcb5002eacd (diff)
downloadskiboot-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.main2
-rw-r--r--core/gcov-profiling.c62
-rw-r--r--core/init.c8
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();