[xen master] gcov: rename folder and header to coverage

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[xen master] gcov: rename folder and header to coverage

patchbot
commit ec320542e4f4de12305551ef5e3cd4d2ced85771
Author:     Roger Pau Monne <[hidden email]>
AuthorDate: Thu Nov 9 12:15:00 2017 +0100
Commit:     Jan Beulich <[hidden email]>
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é <[hidden email]>
    Reviewed-by: Konrad Rzeszutek Wilk <[hidden email]>
---
 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 <[hidden email]>
+ *
+ *    Uses gcc-internal data definitions.
+ *
+ *  Imported from Linux and modified for Xen by
+ *    Wei Liu <[hidden email]>
+ */
+
+
+#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 <[hidden email]>
+ */
+
+#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 <[hidden email]>
+ */
+
+#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 <[hidden email]>
+ */
+
+#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 <[hidden email]>
+ *
+ *    Uses gcc-internal data definitions.
+ *    Based on the gcov-kernel patch by:
+ *       Hubertus Franke <[hidden email]>
+ *       Nigel Hinds <[hidden email]>
+ *       Rajan Ravindran <[hidden email]>
+ *       Peter Oberparleiter <[hidden email]>
+ *       Paul Larson
+ *
+ *  Modified for Xen by:
+ *    Wei Liu <[hidden email]>
+ */
+
+#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 <[hidden email]>
+ *
+ *    Uses gcc-internal data definitions.
+ *    Based on the gcov-kernel patch by:
+ *       Hubertus Franke <[hidden email]>
+ *       Nigel Hinds <[hidden email]>
+ *       Rajan Ravindran <[hidden email]>
+ *       Peter Oberparleiter <[hidden email]>
+ *       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 <[hidden email]>
- *
- *    Uses gcc-internal data definitions.
- *
- *  Imported from Linux and modified for Xen by
- *    Wei Liu <[hidden email]>
- */
-
-
-#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 <[hidden email]>
- */
-
-#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 <[hidden email]>
- */
-
-#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 <[hidden email]>
- */
-
-#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 <[hidden email]>
- *
- *    Uses gcc-internal data definitions.
- *    Based on the gcov-kernel patch by:
- *       Hubertus Franke <[hidden email]>
- *       Nigel Hinds <[hidden email]>
- *       Rajan Ravindran <[hidden email]>
- *       Peter Oberparleiter <[hidden email]>
- *       Paul Larson
- *
- *  Modified for Xen by:
- *    Wei Liu <[hidden email]>
- */
-
-#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 <[hidden email]>
- *
- *    Uses gcc-internal data definitions.
- *    Based on the gcov-kernel patch by:
- *       Hubertus Franke <[hidden email]>
- *       Nigel Hinds <[hidden email]>
- *       Rajan Ravindran <[hidden email]>
- *       Peter Oberparleiter <[hidden email]>
- *       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
[hidden email]
https://lists.xenproject.org/xen-changelog