[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 |