|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] gcov: rename folder and header to coverage
commit ec320542e4f4de12305551ef5e3cd4d2ced85771
Author: Roger Pau Monne <roger.pau@xxxxxxxxxx>
AuthorDate: Thu Nov 9 12:15:00 2017 +0100
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Fri Dec 15 11:28:12 2017 +0100
gcov: rename folder and header to coverage
Preparatory change before adding llvm profiling support.
No functional change.
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
xen/common/Makefile | 2 +-
xen/common/coverage/Makefile | 6 +
xen/common/coverage/gcc_3_4.c | 367 ++++++++++++++++++++++++++++++++++++++++
xen/common/coverage/gcc_4_7.c | 204 ++++++++++++++++++++++
xen/common/coverage/gcc_4_9.c | 33 ++++
xen/common/coverage/gcc_5.c | 33 ++++
xen/common/coverage/gcc_7.c | 30 ++++
xen/common/coverage/gcov.c | 257 ++++++++++++++++++++++++++++
xen/common/coverage/gcov.h | 40 +++++
xen/common/coverage/gcov_base.c | 67 ++++++++
xen/common/gcov/Makefile | 6 -
xen/common/gcov/gcc_3_4.c | 367 ----------------------------------------
xen/common/gcov/gcc_4_7.c | 204 ----------------------
xen/common/gcov/gcc_4_9.c | 33 ----
xen/common/gcov/gcc_5.c | 33 ----
xen/common/gcov/gcc_7.c | 30 ----
xen/common/gcov/gcov.c | 257 ----------------------------
xen/common/gcov/gcov.h | 40 -----
xen/common/gcov/gcov_base.c | 67 --------
xen/common/sysctl.c | 2 +-
xen/include/xen/coverage.h | 9 +
xen/include/xen/gcov.h | 9 -
22 files changed, 1048 insertions(+), 1048 deletions(-)
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 66cc2c8..ad18163 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -74,7 +74,7 @@ tmem-y := tmem.o tmem_xen.o tmem_control.o
tmem-$(CONFIG_COMPAT) += compat/tmem_xen.o
obj-$(CONFIG_TMEM) += $(tmem-y)
-subdir-$(CONFIG_GCOV) += gcov
+subdir-$(CONFIG_GCOV) += coverage
subdir-$(CONFIG_UBSAN) += ubsan
subdir-y += libelf
diff --git a/xen/common/coverage/Makefile b/xen/common/coverage/Makefile
new file mode 100644
index 0000000..a7a4849
--- /dev/null
+++ b/xen/common/coverage/Makefile
@@ -0,0 +1,6 @@
+obj-y += gcov_base.o gcov.o
+obj-y += $(call cc-ifversion,lt,0x040700, \
+ gcc_3_4.o, $(call cc-ifversion,lt,0x040900, \
+ gcc_4_7.o, $(call cc-ifversion,lt,0x050000, \
+ gcc_4_9.o, $(call cc-ifversion,lt,0x070000, \
+ gcc_5.o, gcc_7.o))))
diff --git a/xen/common/coverage/gcc_3_4.c b/xen/common/coverage/gcc_3_4.c
new file mode 100644
index 0000000..3631f4b
--- /dev/null
+++ b/xen/common/coverage/gcc_3_4.c
@@ -0,0 +1,367 @@
+/*
+ * This code provides functions to handle gcc's profiling data format
+ * introduced with gcc 3.4. Future versions of gcc may change the gcov
+ * format (as happened before), so all format-specific information needs
+ * to be kept modular and easily exchangeable.
+ *
+ * This file is based on gcc-internal definitions. Functions and data
+ * structures are defined to be compatible with gcc counterparts.
+ * For a better understanding, refer to gcc source: gcc/gcov-io.h.
+ *
+ * Copyright IBM Corp. 2009
+ * Author(s): Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
+ *
+ * Uses gcc-internal data definitions.
+ *
+ * Imported from Linux and modified for Xen by
+ * Wei Liu <wei.liu2@xxxxxxxxxx>
+ */
+
+
+#include <xen/lib.h>
+
+#include "gcov.h"
+
+#if !(GCC_VERSION >= 30400 && GCC_VERSION < 40700)
+#error "Wrong version of GCC used to compile gcov"
+#endif
+
+#define GCOV_COUNTERS 5
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @ident: object file-unique function identifier
+ * @checksum: function checksum
+ * @n_ctrs: number of values per counter type belonging to this function
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ */
+struct gcov_fn_info
+{
+ unsigned int ident;
+ unsigned int checksum;
+ unsigned int n_ctrs[0];
+};
+
+/**
+ * struct gcov_ctr_info - profiling data per counter type
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ * @merge: merge function for counter values of this type (unused)
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info
+{
+ unsigned int num;
+ gcov_type *values;
+ void (*merge)(gcov_type *, unsigned int);
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: time stamp
+ * @filename: name of the associated gcov data file
+ * @n_functions: number of instrumented functions
+ * @functions: function data
+ * @ctr_mask: mask specifying which counter types are active
+ * @counts: counter data per counter type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info
+{
+ unsigned int version;
+ struct gcov_info *next;
+ unsigned int stamp;
+ const char *filename;
+ unsigned int n_functions;
+ const struct gcov_fn_info *functions;
+ unsigned int ctr_mask;
+ struct gcov_ctr_info counts[0];
+};
+
+/**
+ * struct type_info - iterator helper array
+ * @ctr_type: counter type
+ * @offset: index of the first value of the current function for this type
+ *
+ * This array is needed to convert the in-memory data format into the in-file
+ * data format:
+ *
+ * In-memory:
+ * for each counter type
+ * for each function
+ * values
+ *
+ * In-file:
+ * for each function
+ * for each counter type
+ * values
+ *
+ * See gcc source gcc/gcov-io.h for more information on data organization.
+ */
+struct type_info {
+ int ctr_type;
+ unsigned int offset;
+};
+
+/**
+ * struct gcov_iterator - specifies current file position in logical records
+ * @info: associated profiling data
+ * @record: record type
+ * @function: function number
+ * @type: counter type
+ * @count: index into values array
+ * @num_types: number of counter types
+ * @type_info: helper array to get values-array offset for current function
+ */
+struct gcov_iterator {
+ const struct gcov_info *info;
+
+ int record;
+ unsigned int function;
+ unsigned int type;
+ unsigned int count;
+
+ int num_types;
+ struct type_info type_info[GCOV_COUNTERS];
+};
+
+/* Mapping of logical record number to actual file content. */
+#define RECORD_FILE_MAGIC 0
+#define RECORD_GCOV_VERSION 1
+#define RECORD_TIME_STAMP 2
+#define RECORD_FUNCTION_TAG 3
+#define RECORD_FUNCTON_TAG_LEN 4
+#define RECORD_FUNCTION_IDENT 5
+#define RECORD_FUNCTION_CHECK 6
+#define RECORD_COUNT_TAG 7
+#define RECORD_COUNT_LEN 8
+#define RECORD_COUNT 9
+
+static int counter_active(const struct gcov_info *info, unsigned int type)
+{
+ return (1 << type) & info->ctr_mask;
+}
+
+static unsigned int num_counter_active(const struct gcov_info *info)
+{
+ unsigned int i;
+ unsigned int result = 0;
+
+ for ( i = 0; i < GCOV_COUNTERS; i++ )
+ if ( counter_active(info, i) )
+ result++;
+
+ return result;
+}
+
+void gcov_info_link(struct gcov_info *info)
+{
+ info->next = gcov_info_head;
+ gcov_info_head = info;
+}
+
+struct gcov_info *gcov_info_next(const struct gcov_info *info)
+{
+ if ( !info )
+ return gcov_info_head;
+
+ return info->next;
+}
+
+const char *gcov_info_filename(const struct gcov_info *info)
+{
+ return info->filename;
+}
+
+void gcov_info_reset(struct gcov_info *info)
+{
+ unsigned int active = num_counter_active(info);
+ unsigned int i;
+
+ for ( i = 0; i < active; i++ )
+ memset(info->counts[i].values, 0,
+ info->counts[i].num * sizeof(gcov_type));
+}
+
+static size_t get_fn_size(const struct gcov_info *info)
+{
+ size_t size;
+
+ size = sizeof(struct gcov_fn_info) + num_counter_active(info) *
+ sizeof(unsigned int);
+ if ( __alignof__(struct gcov_fn_info) > sizeof(unsigned int) )
+ size = ROUNDUP(size, __alignof__(struct gcov_fn_info));
+ return size;
+}
+
+static struct gcov_fn_info *get_fn_info(const struct gcov_info *info,
+ unsigned int fn)
+{
+ return (struct gcov_fn_info *)
+ ((char *) info->functions + fn * get_fn_size(info));
+}
+
+static struct gcov_fn_info *get_func(struct gcov_iterator *iter)
+{
+ return get_fn_info(iter->info, iter->function);
+}
+
+static struct type_info *get_type(struct gcov_iterator *iter)
+{
+ return &iter->type_info[iter->type];
+}
+
+/**
+ * gcov_iter_next - advance file iterator to next logical record
+ * @iter: file iterator
+ *
+ * Return zero if new position is valid, non-zero if iterator has reached end.
+ */
+static int gcov_iter_next(struct gcov_iterator *iter)
+{
+ switch ( iter->record )
+ {
+ case RECORD_FILE_MAGIC:
+ case RECORD_GCOV_VERSION:
+ case RECORD_FUNCTION_TAG:
+ case RECORD_FUNCTON_TAG_LEN:
+ case RECORD_FUNCTION_IDENT:
+ case RECORD_COUNT_TAG:
+ /* Advance to next record */
+ iter->record++;
+ break;
+ case RECORD_COUNT:
+ /* Advance to next count */
+ iter->count++;
+ /* fall through */
+ case RECORD_COUNT_LEN:
+ if ( iter->count < get_func(iter)->n_ctrs[iter->type] )
+ {
+ iter->record = 9;
+ break;
+ }
+ /* Advance to next counter type */
+ get_type(iter)->offset += iter->count;
+ iter->count = 0;
+ iter->type++;
+ /* fall through */
+ case RECORD_FUNCTION_CHECK:
+ if ( iter->type < iter->num_types )
+ {
+ iter->record = 7;
+ break;
+ }
+ /* Advance to next function */
+ iter->type = 0;
+ iter->function++;
+ /* fall through */
+ case RECORD_TIME_STAMP:
+ if ( iter->function < iter->info->n_functions )
+ iter->record = 3;
+ else
+ iter->record = -1;
+ break;
+ }
+ /* Check for EOF. */
+ if ( iter->record == -1 )
+ return -EINVAL;
+ else
+ return 0;
+}
+
+/**
+ * gcov_iter_write - write data to buffer
+ * @iter: file iterator
+ * @buf: buffer to write to, if it is NULL, nothing is written
+ * @pos: position inside buffer to start writing
+ *
+ * Return number of bytes written into buffer.
+ */
+static size_t gcov_iter_write(struct gcov_iterator *iter, char *buf,
+ size_t pos)
+{
+ size_t ret = 0;
+
+ switch ( iter->record )
+ {
+ case RECORD_FILE_MAGIC:
+ ret = gcov_store_uint32(buf, pos, GCOV_DATA_MAGIC);
+ break;
+ case RECORD_GCOV_VERSION:
+ ret = gcov_store_uint32(buf, pos, iter->info->version);
+ break;
+ case RECORD_TIME_STAMP:
+ ret = gcov_store_uint32(buf, pos, iter->info->stamp);
+ break;
+ case RECORD_FUNCTION_TAG:
+ ret = gcov_store_uint32(buf, pos, GCOV_TAG_FUNCTION);
+ break;
+ case RECORD_FUNCTON_TAG_LEN:
+ ret = gcov_store_uint32(buf, pos, 2);
+ break;
+ case RECORD_FUNCTION_IDENT:
+ ret = gcov_store_uint32(buf, pos, get_func(iter)->ident);
+ break;
+ case RECORD_FUNCTION_CHECK:
+ ret = gcov_store_uint32(buf, pos, get_func(iter)->checksum);
+ break;
+ case RECORD_COUNT_TAG:
+ ret = gcov_store_uint32(buf, pos,
+
GCOV_TAG_FOR_COUNTER(get_type(iter)->ctr_type));
+ break;
+ case RECORD_COUNT_LEN:
+ ret = gcov_store_uint32(buf, pos,
+ get_func(iter)->n_ctrs[iter->type] * 2);
+ break;
+ case RECORD_COUNT:
+ ret = gcov_store_uint64(buf, pos, iter->info->counts[iter->type].
+ values[iter->count + get_type(iter)->offset]);
+ break;
+ }
+
+ return ret;
+}
+
+/* If buffer is NULL, no data is written. */
+size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info)
+{
+ struct gcov_iterator iter = { .info = info };
+ unsigned int i;
+ size_t pos = 0;
+
+ for ( i = 0; i < GCOV_COUNTERS; i++ )
+ {
+ if ( counter_active(info, i) )
+ {
+ iter.type_info[iter.num_types].ctr_type = i;
+ iter.type_info[iter.num_types].offset = 0;
+ iter.num_types++;
+ }
+ }
+
+ do {
+ pos += gcov_iter_write(&iter, buffer, pos);
+ } while ( gcov_iter_next(&iter) == 0 );
+
+ return pos;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcc_4_7.c b/xen/common/coverage/gcc_4_7.c
new file mode 100644
index 0000000..25b4a8b
--- /dev/null
+++ b/xen/common/coverage/gcc_4_7.c
@@ -0,0 +1,204 @@
+/*
+ * This code provides functions to handle gcc's profiling data format
+ * introduced with gcc 4.7.
+ *
+ * This file is based heavily on gcc_3_4.c file.
+ *
+ * For a better understanding, refer to gcc source:
+ * gcc/gcov-io.h
+ * libgcc/libgcov.c
+ *
+ * Uses gcc-internal data definitions.
+ *
+ * Imported from Linux and modified for Xen by
+ * Wei Liu <wei.liu2@xxxxxxxxxx>
+ */
+
+#include <xen/string.h>
+
+#include "gcov.h"
+
+/*
+ * GCOV_COUNTERS will be defined if this file is included by other
+ * source files.
+ */
+#ifndef GCOV_COUNTERS
+# if !(GCC_VERSION >= 40700 && GCC_VERSION < 40900)
+# error "Wrong version of GCC used to compile gcov"
+# endif
+#define GCOV_COUNTERS 8
+#endif
+
+#define GCOV_TAG_FUNCTION_LENGTH 3
+
+static struct gcov_info *gcov_info_head;
+
+/**
+ * struct gcov_ctr_info - information about counters for a single function
+ * @num: number of counter values for this type
+ * @values: array of counter values for this type
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the values array.
+ */
+struct gcov_ctr_info {
+ unsigned int num;
+ gcov_type *values;
+};
+
+/**
+ * struct gcov_fn_info - profiling meta data per function
+ * @key: comdat key
+ * @ident: unique ident of function
+ * @lineno_checksum: function lineo_checksum
+ * @cfg_checksum: function cfg checksum
+ * @ctrs: instrumented counters
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time.
+ *
+ * Information about a single function. This uses the trailing array
+ * idiom. The number of counters is determined from the merge pointer
+ * array in gcov_info. The key is used to detect which of a set of
+ * comdat functions was selected -- it points to the gcov_info object
+ * of the object file containing the selected comdat function.
+ */
+struct gcov_fn_info {
+ const struct gcov_info *key;
+ unsigned int ident;
+ unsigned int lineno_checksum;
+ unsigned int cfg_checksum;
+ struct gcov_ctr_info ctrs[0];
+};
+
+/**
+ * struct gcov_info - profiling data per object file
+ * @version: gcov version magic indicating the gcc version used for compilation
+ * @next: list head for a singly-linked list
+ * @stamp: uniquifying time stamp
+ * @filename: name of the associated gcov data file
+ * @merge: merge functions (null for unused counter type)
+ * @n_functions: number of instrumented functions
+ * @functions: pointer to pointers to function information
+ *
+ * This data is generated by gcc during compilation and doesn't change
+ * at run-time with the exception of the next pointer.
+ */
+struct gcov_info {
+ unsigned int version;
+ struct gcov_info *next;
+ unsigned int stamp;
+ const char *filename;
+ void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
+ unsigned int n_functions;
+ struct gcov_fn_info **functions;
+};
+
+static int counter_active(const struct gcov_info *info, unsigned int type)
+{
+ return info->merge[type] ? 1 : 0;
+}
+
+void gcov_info_link(struct gcov_info *info)
+{
+ info->next = gcov_info_head;
+ gcov_info_head = info;
+}
+
+struct gcov_info *gcov_info_next(const struct gcov_info *info)
+{
+ if ( !info )
+ return gcov_info_head;
+ return info->next;
+}
+
+void gcov_info_reset(struct gcov_info *info)
+{
+ struct gcov_ctr_info *ci_ptr;
+ unsigned int fi_idx;
+ unsigned int ct_idx;
+
+ for ( fi_idx = 0; fi_idx < info->n_functions; fi_idx++ )
+ {
+ ci_ptr = info->functions[fi_idx]->ctrs;
+
+ for ( ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++ )
+ {
+ if ( !counter_active(info, ct_idx) )
+ continue;
+
+ memset(ci_ptr->values, 0, sizeof(gcov_type) * ci_ptr->num);
+ ci_ptr++;
+ }
+ }
+}
+
+const char *gcov_info_filename(const struct gcov_info *info)
+{
+ return info->filename;
+}
+
+
+/**
+ * gcov_info_to_gcda - convert profiling data set to gcda file format
+ * @buffer: the buffer to store file data or %NULL if no data should be stored
+ * @info: profiling data set to be converted
+ *
+ * Returns the number of bytes that were/would have been stored into the
buffer.
+ */
+size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info)
+{
+ struct gcov_fn_info *fi_ptr;
+ struct gcov_ctr_info *ci_ptr;
+ unsigned int fi_idx;
+ unsigned int ct_idx;
+ unsigned int cv_idx;
+ size_t pos = 0;
+
+ /* File header. */
+ pos += gcov_store_uint32(buffer, pos, GCOV_DATA_MAGIC);
+ pos += gcov_store_uint32(buffer, pos, info->version);
+ pos += gcov_store_uint32(buffer, pos, info->stamp);
+
+ for ( fi_idx = 0; fi_idx < info->n_functions; fi_idx++ )
+ {
+ fi_ptr = info->functions[fi_idx];
+
+ /* Function record. */
+ pos += gcov_store_uint32(buffer, pos, GCOV_TAG_FUNCTION);
+ pos += gcov_store_uint32(buffer, pos, GCOV_TAG_FUNCTION_LENGTH);
+ pos += gcov_store_uint32(buffer, pos, fi_ptr->ident);
+ pos += gcov_store_uint32(buffer, pos, fi_ptr->lineno_checksum);
+ pos += gcov_store_uint32(buffer, pos, fi_ptr->cfg_checksum);
+
+ ci_ptr = fi_ptr->ctrs;
+
+ for ( ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++ )
+ {
+ if (! counter_active(info, ct_idx) )
+ continue;
+
+ /* Counter record. */
+ pos += gcov_store_uint32(buffer, pos,
+ GCOV_TAG_FOR_COUNTER(ct_idx));
+ pos += gcov_store_uint32(buffer, pos, ci_ptr->num * 2);
+
+ for ( cv_idx = 0; cv_idx < ci_ptr->num; cv_idx++ )
+ pos += gcov_store_uint64(buffer, pos, ci_ptr->values[cv_idx]);
+
+ ci_ptr++;
+ }
+ }
+
+ return pos;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcc_4_9.c b/xen/common/coverage/gcc_4_9.c
new file mode 100644
index 0000000..dcea961
--- /dev/null
+++ b/xen/common/coverage/gcc_4_9.c
@@ -0,0 +1,33 @@
+/*
+ * This code provides functions to handle gcc's profiling data format
+ * introduced with gcc 4.7.
+ *
+ * For a better understanding, refer to gcc source:
+ * gcc/gcov-io.h
+ * libgcc/libgcov.c
+ *
+ * Uses gcc-internal data definitions.
+ *
+ * Imported from Linux and modified for Xen by
+ * Wei Liu <wei.liu2@xxxxxxxxxx>
+ */
+
+#include "gcov.h"
+
+#if !(GCC_VERSION >= 40900 && GCC_VERSION < 50000)
+#error "Wrong version of GCC used to compile gcov"
+#endif
+
+#define GCOV_COUNTERS 9
+
+#include "gcc_4_7.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcc_5.c b/xen/common/coverage/gcc_5.c
new file mode 100644
index 0000000..6e0d276
--- /dev/null
+++ b/xen/common/coverage/gcc_5.c
@@ -0,0 +1,33 @@
+/*
+ * This code provides functions to handle gcc's profiling data format
+ * introduced with gcc 5.
+ *
+ * For a better understanding, refer to gcc source:
+ * gcc/gcov-io.h
+ * libgcc/libgcov.c
+ *
+ * Uses gcc-internal data definitions.
+ *
+ * Imported from Linux and modified for Xen by
+ * Wei Liu <wei.liu2@xxxxxxxxxx>
+ */
+
+#include "gcov.h"
+
+#if GCC_VERSION < 50000 || GCC_VERSION >= 70000
+#error "Wrong version of GCC used to compile gcov"
+#endif
+
+#define GCOV_COUNTERS 10
+
+#include "gcc_4_7.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcc_7.c b/xen/common/coverage/gcc_7.c
new file mode 100644
index 0000000..3962eb4
--- /dev/null
+++ b/xen/common/coverage/gcc_7.c
@@ -0,0 +1,30 @@
+/*
+ * This code provides functions to handle gcc's profiling data format
+ * introduced with gcc 7.
+ *
+ * For a better understanding, refer to gcc source:
+ * gcc/gcov-io.h
+ * libgcc/libgcov.c
+ *
+ * Uses gcc-internal data definitions.
+ */
+
+#include "gcov.h"
+
+#if GCC_VERSION < 70000
+#error "Wrong version of GCC used to compile gcov"
+#endif
+
+#define GCOV_COUNTERS 9
+
+#include "gcc_4_7.c"
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcov.c b/xen/common/coverage/gcov.c
new file mode 100644
index 0000000..283d2ee
--- /dev/null
+++ b/xen/common/coverage/gcov.c
@@ -0,0 +1,257 @@
+/*
+ * This code maintains a list of active profiling data structures.
+ *
+ * Copyright IBM Corp. 2009
+ * Author(s): Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
+ *
+ * Uses gcc-internal data definitions.
+ * Based on the gcov-kernel patch by:
+ * Hubertus Franke <frankeh@xxxxxxxxxx>
+ * Nigel Hinds <nhinds@xxxxxxxxxx>
+ * Rajan Ravindran <rajancr@xxxxxxxxxx>
+ * Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
+ * Paul Larson
+ *
+ * Modified for Xen by:
+ * Wei Liu <wei.liu2@xxxxxxxxxx>
+ */
+
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/types.h>
+
+#include <public/sysctl.h>
+
+#include "gcov.h"
+
+/**
+ * gcov_store_uint32 - store 32 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
+ * store anything.
+ */
+size_t gcov_store_uint32(void *buffer, size_t off, uint32_t v)
+{
+ uint32_t *data;
+
+ if ( buffer )
+ {
+ data = buffer + off;
+ *data = v;
+ }
+
+ return sizeof(*data);
+}
+
+/**
+ * gcov_store_uint64 - store 64 bit number in gcov format to buffer
+ * @buffer: target buffer or NULL
+ * @off: offset into the buffer
+ * @v: value to be stored
+ *
+ * Number format defined by gcc: numbers are recorded in the 32 bit
+ * unsigned binary form of the endianness of the machine generating the
+ * file. 64 bit numbers are stored as two 32 bit numbers, the low part
+ * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't
store
+ * anything.
+ */
+size_t gcov_store_uint64(void *buffer, size_t off, uint64_t v)
+{
+ uint32_t *data;
+
+ if ( buffer )
+ {
+ data = buffer + off;
+
+ data[0] = (v & 0xffffffffUL);
+ data[1] = (v >> 32);
+ }
+
+ return sizeof(*data) * 2;
+}
+
+static size_t gcov_info_payload_size(const struct gcov_info *info)
+{
+ return gcov_info_to_gcda(NULL, info);
+}
+
+static int gcov_info_dump_payload(const struct gcov_info *info,
+ XEN_GUEST_HANDLE_PARAM(char) buffer,
+ uint32_t *off)
+{
+ char *buf;
+ uint32_t buf_size;
+ int ret;
+
+ /*
+ * Allocate a buffer and dump payload there. This helps us to not
+ * have copy_to_guest in other functions and retain their simple
+ * semantics.
+ */
+
+ buf_size = gcov_info_payload_size(info);
+ buf = xmalloc_array(char, buf_size);
+
+ if ( !buf )
+ {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ gcov_info_to_gcda(buf, info);
+
+ if ( copy_to_guest_offset(buffer, *off, buf, buf_size) )
+ {
+ ret = -EFAULT;
+ goto out;
+ }
+ *off += buf_size;
+
+ ret = 0;
+ out:
+ xfree(buf);
+ return ret;
+
+}
+
+static uint32_t gcov_get_size(void)
+{
+ uint32_t total_size = sizeof(uint32_t); /* Magic number XCOV */
+ struct gcov_info *info = NULL;
+
+ while ( (info = gcov_info_next(info)) )
+ {
+ /* File name length, including trailing \0 */
+ total_size += strlen(gcov_info_filename(info)) + 1;
+
+ /* Payload size field */
+ total_size += sizeof(uint32_t);
+
+ /* Payload itself */
+ total_size += gcov_info_payload_size(info);
+ }
+
+ return total_size;
+}
+
+static void gcov_reset_all_counters(void)
+{
+ struct gcov_info *info = NULL;
+
+ while ( (info = gcov_info_next(info)) )
+ gcov_info_reset(info);
+}
+
+static int gcov_dump_one_record(const struct gcov_info *info,
+ XEN_GUEST_HANDLE_PARAM(char) buffer,
+ uint32_t *off)
+{
+ uint32_t payload_size;
+ uint32_t len;
+
+ /* File name, including trailing \0 */
+ len = strlen(gcov_info_filename(info)) + 1;
+ if ( copy_to_guest_offset(buffer, *off, gcov_info_filename(info), len) )
+ return -EFAULT;
+ *off += len;
+
+ payload_size = gcov_info_payload_size(info);
+ /* Payload size */
+ if ( copy_to_guest_offset(buffer, *off, (char*)&payload_size,
+ sizeof(uint32_t)) )
+ return -EFAULT;
+ *off += sizeof(uint32_t);
+
+ /* Payload itself */
+ return gcov_info_dump_payload(info, buffer, off);
+}
+
+static int gcov_dump_all(XEN_GUEST_HANDLE_PARAM(char) buffer,
+ uint32_t *buffer_size)
+{
+ uint32_t off;
+ uint32_t magic = XEN_GCOV_FORMAT_MAGIC;
+ struct gcov_info *info = NULL;
+ int ret;
+
+ if ( *buffer_size < gcov_get_size() )
+ {
+ ret = -ENOBUFS;
+ goto out;
+ }
+
+ off = 0;
+
+ /* Magic number */
+ if ( copy_to_guest_offset(buffer, off, (char *)&magic, sizeof(magic)) )
+ {
+ ret = -EFAULT;
+ goto out;
+ }
+ off += sizeof(magic);
+
+ while ( (info = gcov_info_next(info)) )
+ {
+ ret = gcov_dump_one_record(info, buffer, &off);
+ if ( ret )
+ goto out;
+ }
+
+ *buffer_size = off;
+
+ ret = 0;
+ out:
+ return ret;
+}
+
+int sysctl_gcov_op(struct xen_sysctl_gcov_op *op)
+{
+ int ret;
+
+ switch ( op->cmd )
+ {
+ case XEN_SYSCTL_GCOV_get_size:
+ op->size = gcov_get_size();
+ ret = 0;
+ break;
+
+ case XEN_SYSCTL_GCOV_read:
+ {
+ XEN_GUEST_HANDLE_PARAM(char) buf;
+ uint32_t size = op->size;
+
+ buf = guest_handle_cast(op->buffer, char);
+
+ ret = gcov_dump_all(buf, &size);
+ op->size = size;
+
+ break;
+ }
+
+ case XEN_SYSCTL_GCOV_reset:
+ gcov_reset_all_counters();
+ ret = 0;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/coverage/gcov.h b/xen/common/coverage/gcov.h
new file mode 100644
index 0000000..efc1fd7
--- /dev/null
+++ b/xen/common/coverage/gcov.h
@@ -0,0 +1,40 @@
+#ifndef _GCOV_H_
+#define _GCOV_H_
+
+#include <xen/guest_access.h>
+#include <xen/types.h>
+
+/*
+ * Profiling data types used for gcc 3.4 and above - these are defined by
+ * gcc and need to be kept as close to the original definition as possible to
+ * remain compatible.
+ */
+#define GCOV_DATA_MAGIC ((unsigned int)0x67636461)
+#define GCOV_TAG_FUNCTION ((unsigned int)0x01000000)
+#define GCOV_TAG_COUNTER_BASE ((unsigned int)0x01a10000)
+#define GCOV_TAG_FOR_COUNTER(count) \
+ GCOV_TAG_COUNTER_BASE + ((unsigned int)(count) << 17)
+
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+#if BITS_PER_LONG >= 64
+typedef long gcov_type;
+#else
+typedef long long gcov_type;
+#endif
+
+/* Opaque gcov_info -- tied to specific gcc gcov formats */
+struct gcov_info;
+
+void gcov_info_link(struct gcov_info *info);
+struct gcov_info *gcov_info_next(const struct gcov_info *info);
+void gcov_info_reset(struct gcov_info *info);
+const char *gcov_info_filename(const struct gcov_info *info);
+size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info);
+
+size_t gcov_store_uint32(void *buffer, size_t off, uint32_t v);
+size_t gcov_store_uint64(void *buffer, size_t off, uint64_t v);
+
+#endif /* _GCOV_H_ */
diff --git a/xen/common/coverage/gcov_base.c b/xen/common/coverage/gcov_base.c
new file mode 100644
index 0000000..d0c6d0a
--- /dev/null
+++ b/xen/common/coverage/gcov_base.c
@@ -0,0 +1,67 @@
+/*
+ * Common code across gcov implementations
+ *
+ * Copyright Citrix Systems R&D UK
+ * Author(s): Wei Liu <wei.liu2@xxxxxxxxxx>
+ *
+ * Uses gcc-internal data definitions.
+ * Based on the gcov-kernel patch by:
+ * Hubertus Franke <frankeh@xxxxxxxxxx>
+ * Nigel Hinds <nhinds@xxxxxxxxxx>
+ * Rajan Ravindran <rajancr@xxxxxxxxxx>
+ * Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
+ * Paul Larson
+ */
+
+#include "gcov.h"
+
+#include <xen/init.h>
+
+/*
+ * __gcov_init is called by gcc-generated constructor code for each object
+ * file compiled with -fprofile-arcs.
+ */
+void __init __gcov_init(struct gcov_info *info)
+{
+ /* Link all gcov info together. */
+ gcov_info_link(info);
+}
+
+/*
+ * These functions may be referenced by gcc-generated profiling code but serve
+ * no function for Xen.
+ */
+void __gcov_exit(void)
+{
+ /* Unused. */
+}
+
+void __gcov_flush(void)
+{
+ /* Unused. */
+}
+
+void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
+{
+ /* Unused. */
+}
+
+void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
+{
+ /* Unused. */
+}
+
+void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
+{
+ /* Unused. */
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/gcov/Makefile b/xen/common/gcov/Makefile
deleted file mode 100644
index a7a4849..0000000
--- a/xen/common/gcov/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-y += gcov_base.o gcov.o
-obj-y += $(call cc-ifversion,lt,0x040700, \
- gcc_3_4.o, $(call cc-ifversion,lt,0x040900, \
- gcc_4_7.o, $(call cc-ifversion,lt,0x050000, \
- gcc_4_9.o, $(call cc-ifversion,lt,0x070000, \
- gcc_5.o, gcc_7.o))))
diff --git a/xen/common/gcov/gcc_3_4.c b/xen/common/gcov/gcc_3_4.c
deleted file mode 100644
index 3631f4b..0000000
--- a/xen/common/gcov/gcc_3_4.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * This code provides functions to handle gcc's profiling data format
- * introduced with gcc 3.4. Future versions of gcc may change the gcov
- * format (as happened before), so all format-specific information needs
- * to be kept modular and easily exchangeable.
- *
- * This file is based on gcc-internal definitions. Functions and data
- * structures are defined to be compatible with gcc counterparts.
- * For a better understanding, refer to gcc source: gcc/gcov-io.h.
- *
- * Copyright IBM Corp. 2009
- * Author(s): Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
- *
- * Uses gcc-internal data definitions.
- *
- * Imported from Linux and modified for Xen by
- * Wei Liu <wei.liu2@xxxxxxxxxx>
- */
-
-
-#include <xen/lib.h>
-
-#include "gcov.h"
-
-#if !(GCC_VERSION >= 30400 && GCC_VERSION < 40700)
-#error "Wrong version of GCC used to compile gcov"
-#endif
-
-#define GCOV_COUNTERS 5
-
-static struct gcov_info *gcov_info_head;
-
-/**
- * struct gcov_fn_info - profiling meta data per function
- * @ident: object file-unique function identifier
- * @checksum: function checksum
- * @n_ctrs: number of values per counter type belonging to this function
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time.
- */
-struct gcov_fn_info
-{
- unsigned int ident;
- unsigned int checksum;
- unsigned int n_ctrs[0];
-};
-
-/**
- * struct gcov_ctr_info - profiling data per counter type
- * @num: number of counter values for this type
- * @values: array of counter values for this type
- * @merge: merge function for counter values of this type (unused)
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the values array.
- */
-struct gcov_ctr_info
-{
- unsigned int num;
- gcov_type *values;
- void (*merge)(gcov_type *, unsigned int);
-};
-
-/**
- * struct gcov_info - profiling data per object file
- * @version: gcov version magic indicating the gcc version used for compilation
- * @next: list head for a singly-linked list
- * @stamp: time stamp
- * @filename: name of the associated gcov data file
- * @n_functions: number of instrumented functions
- * @functions: function data
- * @ctr_mask: mask specifying which counter types are active
- * @counts: counter data per counter type
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the next pointer.
- */
-struct gcov_info
-{
- unsigned int version;
- struct gcov_info *next;
- unsigned int stamp;
- const char *filename;
- unsigned int n_functions;
- const struct gcov_fn_info *functions;
- unsigned int ctr_mask;
- struct gcov_ctr_info counts[0];
-};
-
-/**
- * struct type_info - iterator helper array
- * @ctr_type: counter type
- * @offset: index of the first value of the current function for this type
- *
- * This array is needed to convert the in-memory data format into the in-file
- * data format:
- *
- * In-memory:
- * for each counter type
- * for each function
- * values
- *
- * In-file:
- * for each function
- * for each counter type
- * values
- *
- * See gcc source gcc/gcov-io.h for more information on data organization.
- */
-struct type_info {
- int ctr_type;
- unsigned int offset;
-};
-
-/**
- * struct gcov_iterator - specifies current file position in logical records
- * @info: associated profiling data
- * @record: record type
- * @function: function number
- * @type: counter type
- * @count: index into values array
- * @num_types: number of counter types
- * @type_info: helper array to get values-array offset for current function
- */
-struct gcov_iterator {
- const struct gcov_info *info;
-
- int record;
- unsigned int function;
- unsigned int type;
- unsigned int count;
-
- int num_types;
- struct type_info type_info[GCOV_COUNTERS];
-};
-
-/* Mapping of logical record number to actual file content. */
-#define RECORD_FILE_MAGIC 0
-#define RECORD_GCOV_VERSION 1
-#define RECORD_TIME_STAMP 2
-#define RECORD_FUNCTION_TAG 3
-#define RECORD_FUNCTON_TAG_LEN 4
-#define RECORD_FUNCTION_IDENT 5
-#define RECORD_FUNCTION_CHECK 6
-#define RECORD_COUNT_TAG 7
-#define RECORD_COUNT_LEN 8
-#define RECORD_COUNT 9
-
-static int counter_active(const struct gcov_info *info, unsigned int type)
-{
- return (1 << type) & info->ctr_mask;
-}
-
-static unsigned int num_counter_active(const struct gcov_info *info)
-{
- unsigned int i;
- unsigned int result = 0;
-
- for ( i = 0; i < GCOV_COUNTERS; i++ )
- if ( counter_active(info, i) )
- result++;
-
- return result;
-}
-
-void gcov_info_link(struct gcov_info *info)
-{
- info->next = gcov_info_head;
- gcov_info_head = info;
-}
-
-struct gcov_info *gcov_info_next(const struct gcov_info *info)
-{
- if ( !info )
- return gcov_info_head;
-
- return info->next;
-}
-
-const char *gcov_info_filename(const struct gcov_info *info)
-{
- return info->filename;
-}
-
-void gcov_info_reset(struct gcov_info *info)
-{
- unsigned int active = num_counter_active(info);
- unsigned int i;
-
- for ( i = 0; i < active; i++ )
- memset(info->counts[i].values, 0,
- info->counts[i].num * sizeof(gcov_type));
-}
-
-static size_t get_fn_size(const struct gcov_info *info)
-{
- size_t size;
-
- size = sizeof(struct gcov_fn_info) + num_counter_active(info) *
- sizeof(unsigned int);
- if ( __alignof__(struct gcov_fn_info) > sizeof(unsigned int) )
- size = ROUNDUP(size, __alignof__(struct gcov_fn_info));
- return size;
-}
-
-static struct gcov_fn_info *get_fn_info(const struct gcov_info *info,
- unsigned int fn)
-{
- return (struct gcov_fn_info *)
- ((char *) info->functions + fn * get_fn_size(info));
-}
-
-static struct gcov_fn_info *get_func(struct gcov_iterator *iter)
-{
- return get_fn_info(iter->info, iter->function);
-}
-
-static struct type_info *get_type(struct gcov_iterator *iter)
-{
- return &iter->type_info[iter->type];
-}
-
-/**
- * gcov_iter_next - advance file iterator to next logical record
- * @iter: file iterator
- *
- * Return zero if new position is valid, non-zero if iterator has reached end.
- */
-static int gcov_iter_next(struct gcov_iterator *iter)
-{
- switch ( iter->record )
- {
- case RECORD_FILE_MAGIC:
- case RECORD_GCOV_VERSION:
- case RECORD_FUNCTION_TAG:
- case RECORD_FUNCTON_TAG_LEN:
- case RECORD_FUNCTION_IDENT:
- case RECORD_COUNT_TAG:
- /* Advance to next record */
- iter->record++;
- break;
- case RECORD_COUNT:
- /* Advance to next count */
- iter->count++;
- /* fall through */
- case RECORD_COUNT_LEN:
- if ( iter->count < get_func(iter)->n_ctrs[iter->type] )
- {
- iter->record = 9;
- break;
- }
- /* Advance to next counter type */
- get_type(iter)->offset += iter->count;
- iter->count = 0;
- iter->type++;
- /* fall through */
- case RECORD_FUNCTION_CHECK:
- if ( iter->type < iter->num_types )
- {
- iter->record = 7;
- break;
- }
- /* Advance to next function */
- iter->type = 0;
- iter->function++;
- /* fall through */
- case RECORD_TIME_STAMP:
- if ( iter->function < iter->info->n_functions )
- iter->record = 3;
- else
- iter->record = -1;
- break;
- }
- /* Check for EOF. */
- if ( iter->record == -1 )
- return -EINVAL;
- else
- return 0;
-}
-
-/**
- * gcov_iter_write - write data to buffer
- * @iter: file iterator
- * @buf: buffer to write to, if it is NULL, nothing is written
- * @pos: position inside buffer to start writing
- *
- * Return number of bytes written into buffer.
- */
-static size_t gcov_iter_write(struct gcov_iterator *iter, char *buf,
- size_t pos)
-{
- size_t ret = 0;
-
- switch ( iter->record )
- {
- case RECORD_FILE_MAGIC:
- ret = gcov_store_uint32(buf, pos, GCOV_DATA_MAGIC);
- break;
- case RECORD_GCOV_VERSION:
- ret = gcov_store_uint32(buf, pos, iter->info->version);
- break;
- case RECORD_TIME_STAMP:
- ret = gcov_store_uint32(buf, pos, iter->info->stamp);
- break;
- case RECORD_FUNCTION_TAG:
- ret = gcov_store_uint32(buf, pos, GCOV_TAG_FUNCTION);
- break;
- case RECORD_FUNCTON_TAG_LEN:
- ret = gcov_store_uint32(buf, pos, 2);
- break;
- case RECORD_FUNCTION_IDENT:
- ret = gcov_store_uint32(buf, pos, get_func(iter)->ident);
- break;
- case RECORD_FUNCTION_CHECK:
- ret = gcov_store_uint32(buf, pos, get_func(iter)->checksum);
- break;
- case RECORD_COUNT_TAG:
- ret = gcov_store_uint32(buf, pos,
-
GCOV_TAG_FOR_COUNTER(get_type(iter)->ctr_type));
- break;
- case RECORD_COUNT_LEN:
- ret = gcov_store_uint32(buf, pos,
- get_func(iter)->n_ctrs[iter->type] * 2);
- break;
- case RECORD_COUNT:
- ret = gcov_store_uint64(buf, pos, iter->info->counts[iter->type].
- values[iter->count + get_type(iter)->offset]);
- break;
- }
-
- return ret;
-}
-
-/* If buffer is NULL, no data is written. */
-size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info)
-{
- struct gcov_iterator iter = { .info = info };
- unsigned int i;
- size_t pos = 0;
-
- for ( i = 0; i < GCOV_COUNTERS; i++ )
- {
- if ( counter_active(info, i) )
- {
- iter.type_info[iter.num_types].ctr_type = i;
- iter.type_info[iter.num_types].offset = 0;
- iter.num_types++;
- }
- }
-
- do {
- pos += gcov_iter_write(&iter, buffer, pos);
- } while ( gcov_iter_next(&iter) == 0 );
-
- return pos;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcc_4_7.c b/xen/common/gcov/gcc_4_7.c
deleted file mode 100644
index 25b4a8b..0000000
--- a/xen/common/gcov/gcc_4_7.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * This code provides functions to handle gcc's profiling data format
- * introduced with gcc 4.7.
- *
- * This file is based heavily on gcc_3_4.c file.
- *
- * For a better understanding, refer to gcc source:
- * gcc/gcov-io.h
- * libgcc/libgcov.c
- *
- * Uses gcc-internal data definitions.
- *
- * Imported from Linux and modified for Xen by
- * Wei Liu <wei.liu2@xxxxxxxxxx>
- */
-
-#include <xen/string.h>
-
-#include "gcov.h"
-
-/*
- * GCOV_COUNTERS will be defined if this file is included by other
- * source files.
- */
-#ifndef GCOV_COUNTERS
-# if !(GCC_VERSION >= 40700 && GCC_VERSION < 40900)
-# error "Wrong version of GCC used to compile gcov"
-# endif
-#define GCOV_COUNTERS 8
-#endif
-
-#define GCOV_TAG_FUNCTION_LENGTH 3
-
-static struct gcov_info *gcov_info_head;
-
-/**
- * struct gcov_ctr_info - information about counters for a single function
- * @num: number of counter values for this type
- * @values: array of counter values for this type
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the values array.
- */
-struct gcov_ctr_info {
- unsigned int num;
- gcov_type *values;
-};
-
-/**
- * struct gcov_fn_info - profiling meta data per function
- * @key: comdat key
- * @ident: unique ident of function
- * @lineno_checksum: function lineo_checksum
- * @cfg_checksum: function cfg checksum
- * @ctrs: instrumented counters
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time.
- *
- * Information about a single function. This uses the trailing array
- * idiom. The number of counters is determined from the merge pointer
- * array in gcov_info. The key is used to detect which of a set of
- * comdat functions was selected -- it points to the gcov_info object
- * of the object file containing the selected comdat function.
- */
-struct gcov_fn_info {
- const struct gcov_info *key;
- unsigned int ident;
- unsigned int lineno_checksum;
- unsigned int cfg_checksum;
- struct gcov_ctr_info ctrs[0];
-};
-
-/**
- * struct gcov_info - profiling data per object file
- * @version: gcov version magic indicating the gcc version used for compilation
- * @next: list head for a singly-linked list
- * @stamp: uniquifying time stamp
- * @filename: name of the associated gcov data file
- * @merge: merge functions (null for unused counter type)
- * @n_functions: number of instrumented functions
- * @functions: pointer to pointers to function information
- *
- * This data is generated by gcc during compilation and doesn't change
- * at run-time with the exception of the next pointer.
- */
-struct gcov_info {
- unsigned int version;
- struct gcov_info *next;
- unsigned int stamp;
- const char *filename;
- void (*merge[GCOV_COUNTERS])(gcov_type *, unsigned int);
- unsigned int n_functions;
- struct gcov_fn_info **functions;
-};
-
-static int counter_active(const struct gcov_info *info, unsigned int type)
-{
- return info->merge[type] ? 1 : 0;
-}
-
-void gcov_info_link(struct gcov_info *info)
-{
- info->next = gcov_info_head;
- gcov_info_head = info;
-}
-
-struct gcov_info *gcov_info_next(const struct gcov_info *info)
-{
- if ( !info )
- return gcov_info_head;
- return info->next;
-}
-
-void gcov_info_reset(struct gcov_info *info)
-{
- struct gcov_ctr_info *ci_ptr;
- unsigned int fi_idx;
- unsigned int ct_idx;
-
- for ( fi_idx = 0; fi_idx < info->n_functions; fi_idx++ )
- {
- ci_ptr = info->functions[fi_idx]->ctrs;
-
- for ( ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++ )
- {
- if ( !counter_active(info, ct_idx) )
- continue;
-
- memset(ci_ptr->values, 0, sizeof(gcov_type) * ci_ptr->num);
- ci_ptr++;
- }
- }
-}
-
-const char *gcov_info_filename(const struct gcov_info *info)
-{
- return info->filename;
-}
-
-
-/**
- * gcov_info_to_gcda - convert profiling data set to gcda file format
- * @buffer: the buffer to store file data or %NULL if no data should be stored
- * @info: profiling data set to be converted
- *
- * Returns the number of bytes that were/would have been stored into the
buffer.
- */
-size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info)
-{
- struct gcov_fn_info *fi_ptr;
- struct gcov_ctr_info *ci_ptr;
- unsigned int fi_idx;
- unsigned int ct_idx;
- unsigned int cv_idx;
- size_t pos = 0;
-
- /* File header. */
- pos += gcov_store_uint32(buffer, pos, GCOV_DATA_MAGIC);
- pos += gcov_store_uint32(buffer, pos, info->version);
- pos += gcov_store_uint32(buffer, pos, info->stamp);
-
- for ( fi_idx = 0; fi_idx < info->n_functions; fi_idx++ )
- {
- fi_ptr = info->functions[fi_idx];
-
- /* Function record. */
- pos += gcov_store_uint32(buffer, pos, GCOV_TAG_FUNCTION);
- pos += gcov_store_uint32(buffer, pos, GCOV_TAG_FUNCTION_LENGTH);
- pos += gcov_store_uint32(buffer, pos, fi_ptr->ident);
- pos += gcov_store_uint32(buffer, pos, fi_ptr->lineno_checksum);
- pos += gcov_store_uint32(buffer, pos, fi_ptr->cfg_checksum);
-
- ci_ptr = fi_ptr->ctrs;
-
- for ( ct_idx = 0; ct_idx < GCOV_COUNTERS; ct_idx++ )
- {
- if (! counter_active(info, ct_idx) )
- continue;
-
- /* Counter record. */
- pos += gcov_store_uint32(buffer, pos,
- GCOV_TAG_FOR_COUNTER(ct_idx));
- pos += gcov_store_uint32(buffer, pos, ci_ptr->num * 2);
-
- for ( cv_idx = 0; cv_idx < ci_ptr->num; cv_idx++ )
- pos += gcov_store_uint64(buffer, pos, ci_ptr->values[cv_idx]);
-
- ci_ptr++;
- }
- }
-
- return pos;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcc_4_9.c b/xen/common/gcov/gcc_4_9.c
deleted file mode 100644
index dcea961..0000000
--- a/xen/common/gcov/gcc_4_9.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * This code provides functions to handle gcc's profiling data format
- * introduced with gcc 4.7.
- *
- * For a better understanding, refer to gcc source:
- * gcc/gcov-io.h
- * libgcc/libgcov.c
- *
- * Uses gcc-internal data definitions.
- *
- * Imported from Linux and modified for Xen by
- * Wei Liu <wei.liu2@xxxxxxxxxx>
- */
-
-#include "gcov.h"
-
-#if !(GCC_VERSION >= 40900 && GCC_VERSION < 50000)
-#error "Wrong version of GCC used to compile gcov"
-#endif
-
-#define GCOV_COUNTERS 9
-
-#include "gcc_4_7.c"
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcc_5.c b/xen/common/gcov/gcc_5.c
deleted file mode 100644
index 6e0d276..0000000
--- a/xen/common/gcov/gcc_5.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * This code provides functions to handle gcc's profiling data format
- * introduced with gcc 5.
- *
- * For a better understanding, refer to gcc source:
- * gcc/gcov-io.h
- * libgcc/libgcov.c
- *
- * Uses gcc-internal data definitions.
- *
- * Imported from Linux and modified for Xen by
- * Wei Liu <wei.liu2@xxxxxxxxxx>
- */
-
-#include "gcov.h"
-
-#if GCC_VERSION < 50000 || GCC_VERSION >= 70000
-#error "Wrong version of GCC used to compile gcov"
-#endif
-
-#define GCOV_COUNTERS 10
-
-#include "gcc_4_7.c"
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcc_7.c b/xen/common/gcov/gcc_7.c
deleted file mode 100644
index 3962eb4..0000000
--- a/xen/common/gcov/gcc_7.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This code provides functions to handle gcc's profiling data format
- * introduced with gcc 7.
- *
- * For a better understanding, refer to gcc source:
- * gcc/gcov-io.h
- * libgcc/libgcov.c
- *
- * Uses gcc-internal data definitions.
- */
-
-#include "gcov.h"
-
-#if GCC_VERSION < 70000
-#error "Wrong version of GCC used to compile gcov"
-#endif
-
-#define GCOV_COUNTERS 9
-
-#include "gcc_4_7.c"
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcov.c b/xen/common/gcov/gcov.c
deleted file mode 100644
index 283d2ee..0000000
--- a/xen/common/gcov/gcov.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * This code maintains a list of active profiling data structures.
- *
- * Copyright IBM Corp. 2009
- * Author(s): Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
- *
- * Uses gcc-internal data definitions.
- * Based on the gcov-kernel patch by:
- * Hubertus Franke <frankeh@xxxxxxxxxx>
- * Nigel Hinds <nhinds@xxxxxxxxxx>
- * Rajan Ravindran <rajancr@xxxxxxxxxx>
- * Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
- * Paul Larson
- *
- * Modified for Xen by:
- * Wei Liu <wei.liu2@xxxxxxxxxx>
- */
-
-#include <xen/errno.h>
-#include <xen/guest_access.h>
-#include <xen/types.h>
-
-#include <public/sysctl.h>
-
-#include "gcov.h"
-
-/**
- * gcov_store_uint32 - store 32 bit number in gcov format to buffer
- * @buffer: target buffer or NULL
- * @off: offset into the buffer
- * @v: value to be stored
- *
- * Number format defined by gcc: numbers are recorded in the 32 bit
- * unsigned binary form of the endianness of the machine generating the
- * file. Returns the number of bytes stored. If @buffer is %NULL, doesn't
- * store anything.
- */
-size_t gcov_store_uint32(void *buffer, size_t off, uint32_t v)
-{
- uint32_t *data;
-
- if ( buffer )
- {
- data = buffer + off;
- *data = v;
- }
-
- return sizeof(*data);
-}
-
-/**
- * gcov_store_uint64 - store 64 bit number in gcov format to buffer
- * @buffer: target buffer or NULL
- * @off: offset into the buffer
- * @v: value to be stored
- *
- * Number format defined by gcc: numbers are recorded in the 32 bit
- * unsigned binary form of the endianness of the machine generating the
- * file. 64 bit numbers are stored as two 32 bit numbers, the low part
- * first. Returns the number of bytes stored. If @buffer is %NULL, doesn't
store
- * anything.
- */
-size_t gcov_store_uint64(void *buffer, size_t off, uint64_t v)
-{
- uint32_t *data;
-
- if ( buffer )
- {
- data = buffer + off;
-
- data[0] = (v & 0xffffffffUL);
- data[1] = (v >> 32);
- }
-
- return sizeof(*data) * 2;
-}
-
-static size_t gcov_info_payload_size(const struct gcov_info *info)
-{
- return gcov_info_to_gcda(NULL, info);
-}
-
-static int gcov_info_dump_payload(const struct gcov_info *info,
- XEN_GUEST_HANDLE_PARAM(char) buffer,
- uint32_t *off)
-{
- char *buf;
- uint32_t buf_size;
- int ret;
-
- /*
- * Allocate a buffer and dump payload there. This helps us to not
- * have copy_to_guest in other functions and retain their simple
- * semantics.
- */
-
- buf_size = gcov_info_payload_size(info);
- buf = xmalloc_array(char, buf_size);
-
- if ( !buf )
- {
- ret = -ENOMEM;
- goto out;
- }
-
- gcov_info_to_gcda(buf, info);
-
- if ( copy_to_guest_offset(buffer, *off, buf, buf_size) )
- {
- ret = -EFAULT;
- goto out;
- }
- *off += buf_size;
-
- ret = 0;
- out:
- xfree(buf);
- return ret;
-
-}
-
-static uint32_t gcov_get_size(void)
-{
- uint32_t total_size = sizeof(uint32_t); /* Magic number XCOV */
- struct gcov_info *info = NULL;
-
- while ( (info = gcov_info_next(info)) )
- {
- /* File name length, including trailing \0 */
- total_size += strlen(gcov_info_filename(info)) + 1;
-
- /* Payload size field */
- total_size += sizeof(uint32_t);
-
- /* Payload itself */
- total_size += gcov_info_payload_size(info);
- }
-
- return total_size;
-}
-
-static void gcov_reset_all_counters(void)
-{
- struct gcov_info *info = NULL;
-
- while ( (info = gcov_info_next(info)) )
- gcov_info_reset(info);
-}
-
-static int gcov_dump_one_record(const struct gcov_info *info,
- XEN_GUEST_HANDLE_PARAM(char) buffer,
- uint32_t *off)
-{
- uint32_t payload_size;
- uint32_t len;
-
- /* File name, including trailing \0 */
- len = strlen(gcov_info_filename(info)) + 1;
- if ( copy_to_guest_offset(buffer, *off, gcov_info_filename(info), len) )
- return -EFAULT;
- *off += len;
-
- payload_size = gcov_info_payload_size(info);
- /* Payload size */
- if ( copy_to_guest_offset(buffer, *off, (char*)&payload_size,
- sizeof(uint32_t)) )
- return -EFAULT;
- *off += sizeof(uint32_t);
-
- /* Payload itself */
- return gcov_info_dump_payload(info, buffer, off);
-}
-
-static int gcov_dump_all(XEN_GUEST_HANDLE_PARAM(char) buffer,
- uint32_t *buffer_size)
-{
- uint32_t off;
- uint32_t magic = XEN_GCOV_FORMAT_MAGIC;
- struct gcov_info *info = NULL;
- int ret;
-
- if ( *buffer_size < gcov_get_size() )
- {
- ret = -ENOBUFS;
- goto out;
- }
-
- off = 0;
-
- /* Magic number */
- if ( copy_to_guest_offset(buffer, off, (char *)&magic, sizeof(magic)) )
- {
- ret = -EFAULT;
- goto out;
- }
- off += sizeof(magic);
-
- while ( (info = gcov_info_next(info)) )
- {
- ret = gcov_dump_one_record(info, buffer, &off);
- if ( ret )
- goto out;
- }
-
- *buffer_size = off;
-
- ret = 0;
- out:
- return ret;
-}
-
-int sysctl_gcov_op(struct xen_sysctl_gcov_op *op)
-{
- int ret;
-
- switch ( op->cmd )
- {
- case XEN_SYSCTL_GCOV_get_size:
- op->size = gcov_get_size();
- ret = 0;
- break;
-
- case XEN_SYSCTL_GCOV_read:
- {
- XEN_GUEST_HANDLE_PARAM(char) buf;
- uint32_t size = op->size;
-
- buf = guest_handle_cast(op->buffer, char);
-
- ret = gcov_dump_all(buf, &size);
- op->size = size;
-
- break;
- }
-
- case XEN_SYSCTL_GCOV_reset:
- gcov_reset_all_counters();
- ret = 0;
- break;
-
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- return ret;
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/gcov/gcov.h b/xen/common/gcov/gcov.h
deleted file mode 100644
index efc1fd7..0000000
--- a/xen/common/gcov/gcov.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _GCOV_H_
-#define _GCOV_H_
-
-#include <xen/guest_access.h>
-#include <xen/types.h>
-
-/*
- * Profiling data types used for gcc 3.4 and above - these are defined by
- * gcc and need to be kept as close to the original definition as possible to
- * remain compatible.
- */
-#define GCOV_DATA_MAGIC ((unsigned int)0x67636461)
-#define GCOV_TAG_FUNCTION ((unsigned int)0x01000000)
-#define GCOV_TAG_COUNTER_BASE ((unsigned int)0x01a10000)
-#define GCOV_TAG_FOR_COUNTER(count) \
- GCOV_TAG_COUNTER_BASE + ((unsigned int)(count) << 17)
-
-#define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
-
-#if BITS_PER_LONG >= 64
-typedef long gcov_type;
-#else
-typedef long long gcov_type;
-#endif
-
-/* Opaque gcov_info -- tied to specific gcc gcov formats */
-struct gcov_info;
-
-void gcov_info_link(struct gcov_info *info);
-struct gcov_info *gcov_info_next(const struct gcov_info *info);
-void gcov_info_reset(struct gcov_info *info);
-const char *gcov_info_filename(const struct gcov_info *info);
-size_t gcov_info_to_gcda(char *buffer, const struct gcov_info *info);
-
-size_t gcov_store_uint32(void *buffer, size_t off, uint32_t v);
-size_t gcov_store_uint64(void *buffer, size_t off, uint64_t v);
-
-#endif /* _GCOV_H_ */
diff --git a/xen/common/gcov/gcov_base.c b/xen/common/gcov/gcov_base.c
deleted file mode 100644
index d0c6d0a..0000000
--- a/xen/common/gcov/gcov_base.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Common code across gcov implementations
- *
- * Copyright Citrix Systems R&D UK
- * Author(s): Wei Liu <wei.liu2@xxxxxxxxxx>
- *
- * Uses gcc-internal data definitions.
- * Based on the gcov-kernel patch by:
- * Hubertus Franke <frankeh@xxxxxxxxxx>
- * Nigel Hinds <nhinds@xxxxxxxxxx>
- * Rajan Ravindran <rajancr@xxxxxxxxxx>
- * Peter Oberparleiter <oberpar@xxxxxxxxxxxxxxxxxx>
- * Paul Larson
- */
-
-#include "gcov.h"
-
-#include <xen/init.h>
-
-/*
- * __gcov_init is called by gcc-generated constructor code for each object
- * file compiled with -fprofile-arcs.
- */
-void __init __gcov_init(struct gcov_info *info)
-{
- /* Link all gcov info together. */
- gcov_info_link(info);
-}
-
-/*
- * These functions may be referenced by gcc-generated profiling code but serve
- * no function for Xen.
- */
-void __gcov_exit(void)
-{
- /* Unused. */
-}
-
-void __gcov_flush(void)
-{
- /* Unused. */
-}
-
-void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
-{
- /* Unused. */
-}
-
-void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
-{
- /* Unused. */
-}
-
-void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
-{
- /* Unused. */
-}
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 08198b7..56def76 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -27,7 +27,7 @@
#include <xsm/xsm.h>
#include <xen/pmstat.h>
#include <xen/livepatch.h>
-#include <xen/gcov.h>
+#include <xen/coverage.h>
long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
{
diff --git a/xen/include/xen/coverage.h b/xen/include/xen/coverage.h
new file mode 100644
index 0000000..b34c304
--- /dev/null
+++ b/xen/include/xen/coverage.h
@@ -0,0 +1,9 @@
+#ifndef _XEN_COV_H
+#define _XEN_COV_H
+
+#ifdef CONFIG_GCOV
+#include <public/sysctl.h>
+int sysctl_gcov_op(struct xen_sysctl_gcov_op *op);
+#endif
+
+#endif /* _XEN_GCOV_H */
diff --git a/xen/include/xen/gcov.h b/xen/include/xen/gcov.h
deleted file mode 100644
index ef22eaf..0000000
--- a/xen/include/xen/gcov.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _XEN_GCOV_H
-#define _XEN_GCOV_H
-
-#ifdef CONFIG_GCOV
-#include <public/sysctl.h>
-int sysctl_gcov_op(struct xen_sysctl_gcov_op *op);
-#endif
-
-#endif /* _XEN_GCOV_H */
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |