[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 6/9] gcov: userspace tools to extract and split gcov data
Provide two tools: a small C program to extract data from hypervisor and a python script to split data into multiple files. The file xencov.c is salvaged and modified from the original xencov.c. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- v2: fix INSTALL_BIN typo Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- tools/misc/Makefile | 6 ++ tools/misc/xencov.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/misc/xencov_split | 100 ++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 tools/misc/xencov.c create mode 100755 tools/misc/xencov_split diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 5ba6672..8152f7b 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -13,6 +13,7 @@ CFLAGS += $(CFLAGS_libxenstore) INSTALL_BIN-$(CONFIG_X86) += xen-cpuid INSTALL_BIN-$(CONFIG_X86) += xen-detect INSTALL_BIN += xencons +INSTALL_BIN += xencov_split INSTALL_BIN += $(INSTALL_BIN-y) # Everything to be installed in regular sbin/ @@ -24,6 +25,7 @@ INSTALL_SBIN-$(CONFIG_X86) += xen-lowmemd INSTALL_SBIN-$(CONFIG_X86) += xen-mfndump INSTALL_SBIN += xen-ringwatch INSTALL_SBIN += xen-tmem-list-parse +INSTALL_SBIN += xencov INSTALL_SBIN += xenlockprof INSTALL_SBIN += xenperf INSTALL_SBIN += xenpm @@ -41,6 +43,7 @@ TARGETS_ALL := $(INSTALL_BIN) $(INSTALL_SBIN) $(INSTALL_PRIVBIN) TARGETS_COPY += xen-bugtool TARGETS_COPY += xen-ringwatch TARGETS_COPY += xencons +TARGETS_COPY += xencov_split TARGETS_COPY += xenpvnetboot # Everything which needs to be built @@ -102,4 +105,7 @@ xen-livepatch: xen-livepatch.o xen-lowmemd: xen-lowmemd.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) +xencov: xencov.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) + -include $(DEPS) diff --git a/tools/misc/xencov.c b/tools/misc/xencov.c new file mode 100644 index 0000000..d83bc66 --- /dev/null +++ b/tools/misc/xencov.c @@ -0,0 +1,148 @@ +/* + * xencov: extract test coverage information from Xen. + * + * Copyright (c) 2013, 2016, Citrix Systems R&D Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <xenctrl.h> + +static xc_interface *xch = NULL; + +int gcov_sysctl(int op, struct xen_sysctl *sysctl, + struct xc_hypercall_buffer *buf, uint32_t buf_size) +{ + DECLARE_HYPERCALL_BUFFER_ARGUMENT(buf); + + memset(sysctl, 0, sizeof(*sysctl)); + sysctl->cmd = XEN_SYSCTL_gcov_op; + + sysctl->u.gcov_op.cmd = op; + sysctl->u.gcov_op.size = buf_size; + set_xen_guest_handle(sysctl->u.gcov_op.buffer, buf); + + return xc_sysctl(xch, sysctl); +} + +static void gcov_read(const char *fn) +{ + struct xen_sysctl sys; + uint32_t total_len; + DECLARE_HYPERCALL_BUFFER(uint8_t, p); + FILE *f; + + if (gcov_sysctl(XEN_SYSCTL_GCOV_get_size, &sys, NULL, 0) < 0) + err(1, "getting total length"); + total_len = sys.u.gcov_op.size; + + /* Shouldn't exceed a few hundred kilobytes */ + if (total_len > 8u * 1024u * 1024u) + errx(1, "gcov data too big %u bytes\n", total_len); + + p = xc_hypercall_buffer_alloc(xch, p, total_len); + if (!p) + err(1, "allocating buffer"); + + memset(p, 0, total_len); + if (gcov_sysctl(XEN_SYSCTL_GCOV_read, &sys, HYPERCALL_BUFFER(p), + total_len) < 0) + err(1, "getting gcov data"); + + if (!strcmp(fn, "-")) + f = stdout; + else + f = fopen(fn, "w"); + + if (!f) + err(1, "opening output file"); + + if (fwrite(p, 1, total_len, f) != total_len) + err(1, "writing gcov data to file"); + + if (f != stdout) + fclose(f); + + xc_hypercall_buffer_free(xch, p); +} + +static void gcov_reset(void) +{ + struct xen_sysctl sys; + + if (gcov_sysctl(XEN_SYSCTL_GCOV_reset, &sys, NULL, 0) < 0) + err(1, "resetting gcov information"); +} + +static void usage(int exit_code) +{ + FILE *out = exit_code ? stderr : stdout; + + fprintf(out, "xencov {reset|read} [<filename>]\n" + "\treset reset information\n" + "\tread read information from xen to filename\n" + "\tfilename optional filename (default output)\n" + ); + exit(exit_code); +} + +int main(int argc, char **argv) +{ + int opt; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + usage(0); + break; + default: + usage(1); + } + } + + argv += optind; + argc -= optind; + if (argc <= 0) + usage(1); + + xch = xc_interface_open(NULL, NULL, 0); + if (!xch) + err(1, "opening xc interface"); + + if (strcmp(argv[0], "reset") == 0) + gcov_reset(); + else if ( strcmp(argv[0], "read") == 0 ) + gcov_read(argc > 1 ? argv[1] : "-"); + else + usage(1); + + xc_interface_close(xch); + + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/misc/xencov_split b/tools/misc/xencov_split new file mode 100755 index 0000000..2c06f49 --- /dev/null +++ b/tools/misc/xencov_split @@ -0,0 +1,100 @@ +#!/usr/bin/python + +import sys, os, os.path as path, struct, errno +from optparse import OptionParser + +def xencov_split(opts): + """Split input into multiple gcda files""" + + # Check native byte order and explicitly specify it. The "native" + # byte order in struct module takes into account padding while the + # data is always packed. + if sys.byteorder == 'little': + bo_prefix = '<' + else: + bo_prefix = '>' + + input_file = opts.args[0] + + f = open(input_file) + + # Magic number + s = f.read(4) + magic, = struct.unpack(bo_prefix + "I", s) + # See public/sysctl.h for magic number -- "XCOV" + if magic != 0x58434f56: + raise Exception("Invalid magic number") + + # The rest is zero or more records + content = f.read() + + f.close() + + while content: + off = content.find('\x00') + fmt = bo_prefix + str(off) + 's' + fn, = struct.unpack_from(fmt, content) + content = content[off+1:] + + fmt = bo_prefix + 'I' + sz, = struct.unpack_from(fmt, content) + content = content[struct.calcsize(fmt):] + + fmt = bo_prefix + str(sz) + 's' + payload, = struct.unpack_from(fmt, content) + content = content[sz:] + + # Create and store files + if opts.output_dir == '.': + opts.output_dir = os.getcwd() + + dir = opts.output_dir + path.dirname(fn) + try: + os.makedirs(dir) + except OSError, e: + if e.errno == errno.EEXIST and os.path.isdir(dir): + pass + else: + raise + + full_path = dir + '/' + path.basename(fn) + f = open(full_path, "w") + f.write(payload) + f.close() + +def main(): + """ Main entrypoint """ + + # Change stdout to be line-buffered. + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1) + + # Normalise $CWD to the directory this script is in + # os.chdir(path.dirname(path.abspath(sys.argv[0]))) + + parser = OptionParser( + usage = "%prog [OPTIONS] <INPUT>", + description = "Utility to split xencov data file", + ) + + parser.add_option("--output-dir", action = "store", + dest = "output_dir", default = ".", + type = "string", + help = ('Specify the directory to place output files, ' + 'defaults to current directory'), + ) + + opts, args = parser.parse_args() + opts.args = args + + xencov_split(opts) + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Exception, e: + print >>sys.stderr, "Error:", e + sys.exit(1) + except KeyboardInterrupt: + sys.exit(1) + -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |