From: George Dunlap <george.dunlap@eu.citrix.com>
To: Frediano Ziglio <frediano.ziglio@citrix.com>
Cc: Matthew Daley <mattjd@gmail.com>,
Christoph Egger <chegger@amazon.de>,
Ian Campbell <Ian.Campbell@citrix.com>,
Miguel Clara <miguelmclara@gmail.com>,
xen-devel@lists.xen.org
Subject: Re: [PATCH] gcov: Support gcc 4.7
Date: Mon, 17 Jun 2013 10:50:08 +0100 [thread overview]
Message-ID: <51BEDBD0.9010409@eu.citrix.com> (raw)
In-Reply-To: <1371457748.9654.3.camel@hamster.uk.xensource.com>
On 17/06/13 09:29, Frediano Ziglio wrote:
> gcc 4.7 changed format used internally for coverage data.
> This patch address these changes.
> The information that gcc generate are mostly the same but to support common
> sections.
> The only difference in the blob exported by Xen is that functions have 2
> different checksums instead of one.
>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
At this point we'd like to completely freeze the tree except for
critical bugfixes. I think this will have to wait for 4.4.
-George
> ---
> tools/misc/xencov_split | 26 ++++++--
> xen/arch/x86/xen.lds.S | 1 +
> xen/common/gcov/gcov.c | 161 +++++++++++++++++++++++++++++++++++++--------
> xen/include/public/gcov.h | 16 ++++-
> xen/include/xen/gcov.h | 68 ++++++++++++++++++-
> 5 files changed, 235 insertions(+), 37 deletions(-)
>
> Patch tested with gcc 4.7, x64 with x86 dom0 and lcov 1.10.
>
> diff --git a/tools/misc/xencov_split b/tools/misc/xencov_split
> index 2e5aa80..af0f580 100755
> --- a/tools/misc/xencov_split
> +++ b/tools/misc/xencov_split
> @@ -27,7 +27,8 @@ my $magic = 0x67636461;
> my $ctrBase = 0x01a10000;
>
> my $xenMagic = 0x58544346; # file header
> -my $xenTagFunc = 0x58544366; # functions tag
> +my $xenTagFunc = 0x58544366; # functions tag
> +my $xenTagFunc2 = 0x58544367; # functions tag2
> my $xenTagCount0 = 0x58544330; # counter 0 tag
> my $xenTagEnd = 0x5854432e; # end file
>
> @@ -86,9 +87,9 @@ sub getS()
> return $res;
> }
>
> -sub parseFunctions($)
> +sub parseFunctions($$)
> {
> - my $numCounters = shift;
> + my ($numCounters, $ver) = @_;
> my $num = get32();
>
> my @funcs;
> @@ -96,10 +97,12 @@ sub parseFunctions($)
> my @data;
> my $ident = get32();
> my $checksum = get32();
> + my $checksum2 = 0;
> + $checksum2 = get32() if $ver > 1;
> for my $n (1..$numCounters) {
> push @data, get32(); # number of counters for a type
> }
> - push @funcs, [$ident, $checksum, \@data];
> + push @funcs, [$ver, $ident, $checksum, $checksum2, \@data];
> }
> align();
> return @funcs;
> @@ -147,7 +150,12 @@ sub parseFile()
> last if ($tag == $xenMagic || $tag == $xenTagEnd);
> if ($tag == $xenTagFunc) {
> die if scalar(@funcs);
> - @funcs = parseFunctions(scalar(@ctrs));
> + @funcs = parseFunctions(scalar(@ctrs), 1);
> + next;
> + }
> + if ($tag == $xenTagFunc2) {
> + die if scalar(@funcs);
> + @funcs = parseFunctions(scalar(@ctrs), 2);
> next;
> }
>
> @@ -159,10 +167,14 @@ sub parseFile()
> # print all functions
> for my $f (@funcs) {
> # tag tag_len ident checksum
> - print OUT pack('VVVV', 0x01000000, 2, $f->[0], $f->[1]);
> + if ($f->[0] == 1) {
> + print OUT pack('VVVV', 0x01000000, 2, $f->[1], $f->[2]);
> + } else {
> + print OUT pack('VVVVV', 0x01000000, 3, $f->[1], $f->[2], $f->[3]);
> + }
> # all counts
> my $n = 0;
> - for my $c (@{$f->[2]}) {
> + for my $c (@{$f->[4]}) {
> my ($type, $data) = @{$ctrs[$n]};
> print OUT pack('VV', $ctrBase + 0x20000 * $type, $c*2);
> die "--$c--$type--$data--" if length($data) < $c * 8;
> diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
> index d959941..bdc4c91 100644
> --- a/xen/arch/x86/xen.lds.S
> +++ b/xen/arch/x86/xen.lds.S
> @@ -112,6 +112,7 @@ SECTIONS
> . = ALIGN(8);
> __ctors_start = .;
> *(.ctors)
> + *(.init_array)
> __ctors_end = .;
> } :text
> . = ALIGN(32);
> diff --git a/xen/common/gcov/gcov.c b/xen/common/gcov/gcov.c
> index b5717b9..1d32d8f 100644
> --- a/xen/common/gcov/gcov.c
> +++ b/xen/common/gcov/gcov.c
> @@ -106,17 +106,120 @@ static int write_string(write_iter_t *iter, const char *s)
>
> static inline int next_type(const struct gcov_info *info, int *type)
> {
> - while ( ++*type < XENCOV_COUNTERS && !counter_active(info, *type) )
> + while ( ++*type < XENCOV_COUNTERS_MASK && !counter_active(info, *type) )
> continue;
> return *type;
> }
>
> +static inline const struct gcov_fn_info_407 *
> +next_func(const struct gcov_info_407 *info, int *n_func)
> +{
> + while ( ++*n_func < info->n_functions ) {
> + const struct gcov_fn_info_407 *fn = info->functions[*n_func];
> +
> + /* the test for info member handle common data redefinitions
> + in object files */
> + if ( fn && fn->info == info)
> + return fn;
> + }
> +
> + return NULL;
> +}
> +
> +static inline const struct gcov_ctr_info_407 *
> +next_ctr(const struct gcov_fn_info_407 *fn, int *n_ctr)
> +{
> + while ( ++*n_ctr < XENCOV_COUNTERS_407 )
> + if ( fn->info->merge[*n_ctr] )
> + return &fn->ctrs[*n_ctr];
> +
> + return NULL;
> +}
> +
> static inline void align_iter(write_iter_t *iter)
> {
> iter->write_offset =
> (iter->write_offset + sizeof(uint64_t) - 1) & -sizeof(uint64_t);
> }
>
> +static int write_info(write_iter_t *iter, const struct gcov_info* info)
> +{
> + const struct gcov_ctr_info *ctr;
> + int type, ret;
> + size_t size_fn = sizeof(struct gcov_fn_info);
> +
> + /* dump counters */
> + ctr = info->counts;
> + for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS_MASK; ++ctr )
> + {
> + align_iter(iter);
> + chk(write32(iter, XENCOV_TAG_COUNTER(type)));
> + chk(write32(iter, ctr->num));
> + chk(write_raw(iter, ctr->values,
> + ctr->num * sizeof(ctr->values[0])));
> +
> + size_fn += sizeof(unsigned);
> + }
> +
> + /* dump all functions together */
> + align_iter(iter);
> + chk(write32(iter, XENCOV_TAG_FUNC));
> + chk(write32(iter, info->n_functions));
> + chk(write_raw(iter, info->functions, info->n_functions * size_fn));
> +
> + return 0;
> +}
> +
> +static int write_info_407(write_iter_t *iter, const struct gcov_info_407* info)
> +{
> + int ret;
> + const struct gcov_fn_info_407 *fn;
> + const struct gcov_ctr_info_407 *ctr;
> + int n_func, n_ctr;
> + unsigned int num_func = 0;
> + unsigned int ctrs[XENCOV_COUNTERS_407];
> +
> + for ( n_ctr = 0; n_ctr < XENCOV_COUNTERS_407; ++n_ctr )
> + ctrs[n_ctr] = 0;
> +
> + /* scan to total counters */
> + for ( n_func = -1; (fn = next_func(info, &n_func)) != NULL; )
> + {
> + ++num_func;
> + for ( n_ctr = -1; (ctr = next_ctr(fn, &n_ctr)) != NULL; )
> + ctrs[n_ctr] += ctr->num;
> + }
> +
> + /* output counters */
> + for ( n_ctr = 0; n_ctr < XENCOV_COUNTERS_407; ++n_ctr )
> + {
> + if ( !ctrs[n_ctr] ) continue;
> + align_iter(iter);
> + chk(write32(iter, XENCOV_TAG_COUNTER(n_ctr)));
> + chk(write32(iter, ctrs[n_ctr]));
> + for ( n_func = -1; (fn = next_func(info, &n_func)) != NULL; )
> + {
> + ctr = &fn->ctrs[n_ctr];
> + chk(write_raw(iter, ctr->values,
> + ctr->num * sizeof(ctr->values[0])));
> + }
> + }
> +
> + /* dump all functions together */
> + align_iter(iter);
> + chk(write32(iter, XENCOV_TAG_FUNC2));
> + chk(write32(iter, num_func));
> + for ( n_func = -1; (fn = next_func(info, &n_func)) != NULL; )
> + {
> + chk(write32(iter, fn->ident));
> + chk(write32(iter, fn->lineno_checksum));
> + chk(write32(iter, fn->cfg_checksum));
> + for ( n_ctr = -1; (ctr = next_ctr(fn, &n_ctr)) != NULL; )
> + chk(write32(iter, ctr->num));
> + }
> + return 0;
> +}
> +
> static int write_gcov(write_iter_t *iter)
> {
> struct gcov_info *info;
> @@ -128,10 +231,6 @@ static int write_gcov(write_iter_t *iter)
> /* dump all files */
> for ( info = info_list ; info; info = info->next )
> {
> - const struct gcov_ctr_info *ctr;
> - int type;
> - size_t size_fn = sizeof(struct gcov_fn_info);
> -
> align_iter(iter);
> chk(write32(iter, XENCOV_TAG_FILE));
> chk(write32(iter, info->version));
> @@ -139,23 +238,10 @@ static int write_gcov(write_iter_t *iter)
> chk(write_string(iter, info->filename));
>
> /* dump counters */
> - ctr = info->counts;
> - for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS; ++ctr )
> - {
> - align_iter(iter);
> - chk(write32(iter, XENCOV_TAG_COUNTER(type)));
> - chk(write32(iter, ctr->num));
> - chk(write_raw(iter, ctr->values,
> - ctr->num * sizeof(ctr->values[0])));
> -
> - size_fn += sizeof(unsigned);
> - }
> -
> - /* dump all functions together */
> - align_iter(iter);
> - chk(write32(iter, XENCOV_TAG_FUNC));
> - chk(write32(iter, info->n_functions));
> - chk(write_raw(iter, info->functions, info->n_functions * size_fn));
> + if (info->version < XENCOV_VERSION_407)
> + chk(write_info(iter, info));
> + else
> + chk(write_info_407(iter, (struct gcov_info_407 *) info));
> }
>
> /* stop tag */
> @@ -164,19 +250,38 @@ static int write_gcov(write_iter_t *iter)
> return 0;
> }
>
> +static void reset_info(struct gcov_info *info)
> +{
> + const struct gcov_ctr_info *ctr;
> + int type;
> +
> + ctr = info->counts;
> + for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS_MASK; ++ctr )
> + memset(ctr->values, 0, ctr->num * sizeof(ctr->values[0]));
> +}
> +
> +static void reset_info_407(struct gcov_info_407 *info)
> +{
> + const struct gcov_fn_info_407 *fn;
> + const struct gcov_ctr_info_407 *ctr;
> + int n_func, n_ctr;
> +
> + for ( n_func = -1; (fn = next_func(info, &n_func)) != NULL; )
> + for ( n_ctr = -1; (ctr = next_ctr(fn, &n_ctr)) != NULL; )
> + memset(ctr->values, 0, ctr->num * sizeof(ctr->values[0]));
> +}
> +
> static int reset_counters(void)
> {
> struct gcov_info *info;
>
> for ( info = info_list ; info; info = info->next )
> {
> - const struct gcov_ctr_info *ctr;
> - int type;
> -
> /* reset counters */
> - ctr = info->counts;
> - for ( type = -1; next_type(info, &type) < XENCOV_COUNTERS; ++ctr )
> - memset(ctr->values, 0, ctr->num * sizeof(ctr->values[0]));
> + if ( info->version < XENCOV_VERSION_407 )
> + reset_info(info);
> + else
> + reset_info_407((struct gcov_info_407 *) info);
> }
>
> return 0;
> diff --git a/xen/include/public/gcov.h b/xen/include/public/gcov.h
> index 1b29b48..e7573fb 100644
> --- a/xen/include/public/gcov.h
> +++ b/xen/include/public/gcov.h
> @@ -28,10 +28,12 @@
> #ifndef __XEN_PUBLIC_GCOV_H__
> #define __XEN_PUBLIC_GCOV_H__ __XEN_PUBLIC_GCOV_H__
>
> -#define XENCOV_COUNTERS 5
> +#define XENCOV_COUNTERS_MASK 5
> +#define XENCOV_COUNTERS 8
> #define XENCOV_TAG_BASE 0x58544300u
> #define XENCOV_TAG_FILE (XENCOV_TAG_BASE+0x46u)
> #define XENCOV_TAG_FUNC (XENCOV_TAG_BASE+0x66u)
> +#define XENCOV_TAG_FUNC2 (XENCOV_TAG_BASE+0x67u)
> #define XENCOV_TAG_COUNTER(n) (XENCOV_TAG_BASE+0x30u+((n)&0xfu))
> #define XENCOV_TAG_END (XENCOV_TAG_BASE+0x2eu)
> #define XENCOV_IS_TAG_COUNTER(n) \
> @@ -93,6 +95,18 @@ struct xencov_function
> };
>
> /**
> + * Information for each function
> + * Number of counter is equal to the number of counter structures got before
> + */
> +struct xencov_function2
> +{
> + uint32_t ident;
> + uint32_t lineno_checksum;
> + uint32_t cfg_checksum;
> + uint32_t num_counters[1];
> +};
> +
> +/**
> * Information for all functions
> * Aligned to 8 bytes
> */
> diff --git a/xen/include/xen/gcov.h b/xen/include/xen/gcov.h
> index 27c5c37..f36388a 100644
> --- a/xen/include/xen/gcov.h
> +++ b/xen/include/xen/gcov.h
> @@ -40,6 +40,8 @@ struct gcov_fn_info
> unsigned int n_ctrs[0];
> };
>
> +typedef void (*gcov_merge_func)(gcov_type *, unsigned int);
> +
> /**
> * struct gcov_ctr_info - profiling data per counter type
> * @num: number of counter values for this type
> @@ -53,7 +55,7 @@ struct gcov_ctr_info
> {
> unsigned int num;
> gcov_type *values;
> - void (*merge)(gcov_type *, unsigned int);
> + gcov_merge_func merge;
> };
>
> /**
> @@ -82,6 +84,70 @@ struct gcov_info
> struct gcov_ctr_info counts[0];
> };
>
> +struct gcov_info_407;
> +
> +/**
> + * struct gcov_ctr_info_407 - 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_407
> +{
> + unsigned int num;
> + gcov_type *values;
> +};
> +
> +
> +/**
> + * struct gcov_fn_info_407 - profiling meta data per function
> + * @ident: object file-unique function identifier
> + * @lineno_checksum: function lineno checksum
> + * @cfg_checksum: function cfg checksum
> + * @ctrs: counters for this function
> + *
> + * This data is generated by gcc during compilation and doesn't change
> + * at run-time.
> + */
> +struct gcov_fn_info_407
> +{
> + const struct gcov_info_407 *info;
> + unsigned int ident;
> + unsigned int lineno_checksum;
> + unsigned int cfg_checksum;
> + struct gcov_ctr_info_407 ctrs[0];
> +};
> +
> +#define XENCOV_COUNTERS_407 8
> +#define XENCOV_VERSION_407 0x34303700
> +
> +/**
> + * struct gcov_info_407 - 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
> + * @merge: merge functions
> + * @n_functions: number of instrumented functions
> + * @functions: function data
> + *
> + * 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_407
> +{
> + unsigned int version;
> + struct gcov_info *next;
> + unsigned int stamp;
> + const char *filename;
> + gcov_merge_func merge[XENCOV_COUNTERS_407];
> + unsigned int n_functions;
> + const struct gcov_fn_info_407 * const *functions;
> +};
> +
>
> /**
> * Sysctl operations for coverage
next prev parent reply other threads:[~2013-06-17 9:50 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-17 8:29 [PATCH] gcov: Support gcc 4.7 Frediano Ziglio
2013-06-17 8:58 ` Jan Beulich
2013-06-28 10:18 ` Frediano Ziglio
2013-06-28 10:26 ` Jan Beulich
2013-06-17 9:50 ` George Dunlap [this message]
2013-06-17 10:42 ` Ian Campbell
2013-06-17 10:46 ` Frediano Ziglio
2013-06-17 10:49 ` Ian Campbell
2013-06-17 12:25 ` Frediano Ziglio
2013-06-18 14:32 ` Frediano Ziglio
2013-06-18 14:53 ` George Dunlap
2013-06-18 15:04 ` Frediano Ziglio
2013-06-17 10:49 ` Egger, Christoph
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51BEDBD0.9010409@eu.citrix.com \
--to=george.dunlap@eu.citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=chegger@amazon.de \
--cc=frediano.ziglio@citrix.com \
--cc=mattjd@gmail.com \
--cc=miguelmclara@gmail.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).