Files
xen/tools/misc/xencov_split
T
Frediano Ziglio cc1eca5194 gcov: Add script to split coverage informations.
Split coverage informations extracted from xencov utility.
This script accept coverage blob either as file or from input and extract
into files compatible with gcc format (gcda).

Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
2013-05-30 09:30:18 +01:00

190 lines
4.3 KiB
Perl
Executable File

#!/usr/bin/perl
# xencov_split - split coverage information from Xen
#
# Copyright (C) 2013 - Citrix Systems
# -----
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
use strict;
use File::Path qw(mkpath);
# some magic constants
my $magic = 0x67636461;
my $ctrBase = 0x01a10000;
my $xenMagic = 0x58544346; # file header
my $xenTagFunc = 0x58544366; # functions tag
my $xenTagCount0 = 0x58544330; # counter 0 tag
my $xenTagEnd = 0x5854432e; # end file
# open input file
if ($ARGV[0]) {
my $fn = $ARGV[0];
open(IN, '<', $fn) or die "opening file \"$fn\"";
} else {
open(IN, '<&STDIN') or die "redirecting input";
}
my $pos = 0;
sub getRaw($)
{
my $l = shift;
die 'got no data to read' if $l < 0;
my $res = '';
do {
my $data;
my $r = read(IN, $data, $l);
die "error $! reading data from input at position $pos" if !defined($r);
die "unexpected end of file at position $pos" if !$r;
$l -= $r;
$pos += $r;
$res .= $data;
} while ($l > 0);
return $res;
}
sub get32()
{
return unpack('V', getRaw(4));
}
sub get64()
{
# This is returned as raw data as some Perl version could not
# support 64 bit integer
# This is ok for little endian machines
return getRaw(8);
}
sub align()
{
my $l = $pos & 7;
getRaw(8-$l) if $l;
}
# read a string prefixed by length
sub getS()
{
my $l = get32();
my $res = getRaw($l);
align();
return $res;
}
sub parseFunctions($)
{
my $numCounters = shift;
my $num = get32();
my @funcs;
for my $n (1..$num) {
my @data;
my $ident = get32();
my $checksum = get32();
for my $n (1..$numCounters) {
push @data, get32(); # number of counters for a type
}
push @funcs, [$ident, $checksum, \@data];
}
align();
return @funcs;
}
sub parseCounters($)
{
my $tag = shift;
die sprintf("wrong tag 0x%08x pos $pos (0x%08x)", $tag, $pos) if $tag < $xenTagCount0;
$tag -= $xenTagCount0;
die sprintf('wrong tag 0x%08x', $tag) if $tag > 5;
my $data = '';
my $num = get32();
for my $n (1..$num) {
$data .= get64();
}
align();
return [$tag, $data];
}
sub parseFile()
{
my $ver = get32();
my $stamp = get32();
my $fn = getS();
align();
my $numCounters;
print "got file $fn\n";
die if $fn !~ m,^(/.*?)[^/]+\.gcda$,;
mkpath(".$1");
open(OUT, '>', ".$fn") or die;
print OUT pack('VVV', $magic, $ver, $stamp);
# read counters of file
my @ctrs;
my @funcs;
my $tag;
for (;;) {
$tag = get32();
last if ($tag == $xenMagic || $tag == $xenTagEnd);
if ($tag == $xenTagFunc) {
die if scalar(@funcs);
@funcs = parseFunctions(scalar(@ctrs));
next;
}
# must be a counter
push @ctrs, parseCounters($tag);
++$numCounters;
}
# print all functions
for my $f (@funcs) {
# tag tag_len ident checksum
print OUT pack('VVVV', 0x01000000, 2, $f->[0], $f->[1]);
# all counts
my $n = 0;
for my $c (@{$f->[2]}) {
my ($type, $data) = @{$ctrs[$n]};
print OUT pack('VV', $ctrBase + 0x20000 * $type, $c*2);
die "--$c--$type--$data--" if length($data) < $c * 8;
print OUT substr($data, 0, $c * 8);
$ctrs[$n] = [$type, substr($data, $c * 8)];
++$n;
}
}
close(OUT);
return $tag;
}
my $tag = get32();
die 'no coverage or wrong file format' if $tag != $xenMagic;
for (;;) {
if ($tag == $xenMagic) {
$tag = parseFile();
} elsif ($tag == $xenTagEnd) {
last;
} else {
die "wrong tag $tag";
}
}