[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT PATCH v2 5/8] support/scripts: fetch trace data from running Unikraft



Thanks for updating the scripts locations, it's much better now.

Reviewed-by: Costin Lupu <costin.lupu@xxxxxxxxx>

On 5/30/19 2:44 AM, Yuri Volchkov wrote:
> Fetch tracebuffer, key-values and tracepoint definitions using objcopy
> and gdb.
> 
> This patch introduces uk-gdb.py script, which is a gdb-extension
> providing handy helpers. Currently, it is only tracepoints related
> stuff, but possibilities are going beyond that.
> 
> The uk-gdb.py can be loaded into gdb manually (via "source" command)
> or using gdb's auto-load feature. Gdb looks for a file named
> objfile-gdb.py, where objfile is the object file's real name.
> 
> To achieve that uk-gdb.py is copied into the build directory with a
> little modification - hardcode the absolute path to the Unikraft's
> scripts directory.
> 
> The trace.py is a tool for analyzing traces. Currently, it does only
> the basic stuff: fetches tracing data from a running instance (can run
> gdb for you) and prints out parsed information (in the next
> patch). But it will eventually be able to do more. For example
> statistics of most frequently occurred events.
> 
> Signed-off-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
> ---
>  Makefile                             |  12 ++-
>  support/scripts/uk-gdb.py            | 122 +++++++++++++++++++++++++++
>  support/scripts/uk_trace/__init__.py |   0
>  support/scripts/uk_trace/parse.py    |  57 +++++++++++++
>  support/scripts/uk_trace/trace.py    | 103 ++++++++++++++++++++++
>  5 files changed, 293 insertions(+), 1 deletion(-)
>  create mode 100644 support/scripts/uk-gdb.py
>  create mode 100644 support/scripts/uk_trace/__init__.py
>  create mode 100644 support/scripts/uk_trace/parse.py
>  create mode 100755 support/scripts/uk_trace/trace.py
> 
> diff --git a/Makefile b/Makefile
> index c0492920..e423be8d 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -534,8 +534,18 @@ libs: $(UK_ALIBS) $(UK_ALIBS-y) $(UK_OLIBS) $(UK_OLIBS-y)
>  
>  images: $(UK_IMAGES) $(UK_IMAGES-y)
>  
> -all: images
> +GDB_HELPER_LINKS := $(addsuffix  .dbg-gdb.py,$(UK_IMAGES-y) $(UK_IMAGES))
> +$(GDB_HELPER_LINKS):
> +     $(call verbose_cmd,LN,$(notdir $@), ln -sf uk-gdb.py $@)
>  
> +SCRIPTS_DIR_BACKSLASHED = $(subst /,\/,$(SCRIPTS_DIR))
> +$(BUILD_DIR)/uk-gdb.py: $(SCRIPTS_DIR)/uk-gdb.py
> +     $(call verbose_cmd,GEN,$(notdir $@), \
> +     sed '/scripts_dir = / 
> s/os.path.dirname(os.path.realpath(__file__))/"$(SCRIPTS_DIR_BACKSLASHED)"/g' 
> $^ > $@)
> +
> +gdb_helpers: $(GDB_HELPER_LINKS) $(BUILD_DIR)/uk-gdb.py
> +
> +all: images gdb_helpers
>  
> ################################################################################
>  # Cleanup rules
>  
> ################################################################################
> diff --git a/support/scripts/uk-gdb.py b/support/scripts/uk-gdb.py
> new file mode 100644
> index 00000000..e4b0038d
> --- /dev/null
> +++ b/support/scripts/uk-gdb.py
> @@ -0,0 +1,122 @@
> +#!/user/bin/env python3
> +# SPDX-License-Identifier: BSD-3-Clause */
> +#
> +# Authors: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
> +#
> +# Copyright (c) 2019, NEC Laboratories Europe GmbH, NEC Corporation.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# 1. Redistributions of source code must retain the above copyright
> +#    notice, this list of conditions and the following disclaimer.
> +# 2. Redistributions in binary form must reproduce the above copyright
> +#    notice, this list of conditions and the following disclaimer in the
> +#    documentation and/or other materials provided with the distribution.
> +# 3. Neither the name of the copyright holder nor the names of its
> +#    contributors may be used to endorse or promote products derived from
> +#    this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +# POSSIBILITY OF SUCH DAMAGE.
> +#
> +# THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
> +
> +import gdb
> +import pickle
> +import os, sys
> +import tempfile, shutil
> +
> +scripts_dir = os.path.dirname(os.path.realpath(__file__))
> +sys.path.append(scripts_dir)
> +
> +import uk_trace.parse as parse
> +
> +type_char = gdb.lookup_type('char')
> +type_void = gdb.lookup_type('void')
> +
> +PTR_SIZE = type_void.pointer().sizeof
> +
> +def get_trace_buffer():
> +    inf = gdb.selected_inferior()
> +
> +    try:
> +        trace_buff = gdb.parse_and_eval('uk_trace_buffer')
> +        trace_buff_size = trace_buff.type.sizeof
> +        trace_buff_addr = int(trace_buff.address)
> +        trace_buff_writep = int(gdb.parse_and_eval('uk_trace_buffer_writep'))
> +    except gdb.error:
> +        gdb.write("Error getting the trace buffer. Is tracing enabled?\n")
> +        raise gdb.error
> +
> +    if (trace_buff_writep == 0):
> +        # This can happen as effect of compile optimization if none of
> +        # tracepoints were called
> +        used = 0
> +    else:
> +        used = trace_buff_writep - trace_buff_addr
> +
> +    return bytes(inf.read_memory(trace_buff_addr, used))
> +
> +def save_traces(out):
> +    elf = gdb.current_progspace().filename
> +
> +    pickler = pickle.Pickler(out)
> +
> +    # keyvals need to go first, because they have format_version
> +    # key. Even if the format is changed we must guarantee that at
> +    # least keyvals are always stored first. However, ideally, next
> +    # versions should just have modifications at the very end to keep
> +    # compatibility with previously collected data.
> +    pickler.dump(parse.get_keyvals(elf))
> +    pickler.dump(elf)
> +    pickler.dump(PTR_SIZE)
> +    # We are saving raw trace buffer here. Another option is to pickle
> +    # already parsed samples. But in the chosen case it is a lot
> +    # easier to debug the parser, because python in gdb is not very
> +    # convenient for development.
> +    pickler.dump(parse.get_tp_sections(elf))
> +    pickler.dump(get_trace_buffer())
> +
> +class uk(gdb.Command):
> +    def __init__(self):
> +        gdb.Command.__init__(self, 'uk',
> +                             gdb.COMMAND_USER, gdb.COMPLETE_COMMAND, True)
> +
> +class uk_trace(gdb.Command):
> +    def __init__(self):
> +        gdb.Command.__init__(self, 'uk trace',
> +                             gdb.COMMAND_USER, gdb.COMPLETE_COMMAND, True)
> +    def invoke(self, arg, from_tty):
> +        # TODO
> +        pass
> +
> +class uk_trace_save(gdb.Command):
> +    def __init__(self):
> +        gdb.Command.__init__(self, 'uk trace save',
> +                             gdb.COMMAND_USER, gdb.COMPLETE_COMMAND)
> +    def invoke(self, arg, from_tty):
> +        if not arg:
> +            gdb.write('Missing argument. Usage: uk trace save <filename>\n')
> +            return
> +
> +        gdb.write('Saving traces to %s ...\n' % arg)
> +
> +        with tempfile.NamedTemporaryFile() as out:
> +            save_traces(out)
> +            out.flush()
> +            shutil.copyfile(out.name, arg)
> +
> +uk()
> +uk_trace()
> +uk_trace_save()
> diff --git a/support/scripts/uk_trace/__init__.py 
> b/support/scripts/uk_trace/__init__.py
> new file mode 100644
> index 00000000..e69de29b
> diff --git a/support/scripts/uk_trace/parse.py 
> b/support/scripts/uk_trace/parse.py
> new file mode 100644
> index 00000000..407f47e3
> --- /dev/null
> +++ b/support/scripts/uk_trace/parse.py
> @@ -0,0 +1,57 @@
> +# SPDX-License-Identifier: BSD-3-Clause */
> +#
> +# Authors: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
> +#
> +# Copyright (c) 2019, NEC Laboratories Europe GmbH, NEC Corporation.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# 1. Redistributions of source code must retain the above copyright
> +#    notice, this list of conditions and the following disclaimer.
> +# 2. Redistributions in binary form must reproduce the above copyright
> +#    notice, this list of conditions and the following disclaimer in the
> +#    documentation and/or other materials provided with the distribution.
> +# 3. Neither the name of the copyright holder nor the names of its
> +#    contributors may be used to endorse or promote products derived from
> +#    this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +# POSSIBILITY OF SUCH DAMAGE.
> +#
> +# THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
> +
> +import subprocess
> +import re
> +import tempfile
> +
> +def get_tp_sections(elf):
> +    f = tempfile.NamedTemporaryFile()
> +    objcopy_cmd  = 'objcopy -O binary %s ' % elf
> +    objcopy_cmd += '--only-section=.uk_tracepoints_list ' + f.name
> +    objcopy_cmd = objcopy_cmd.split()
> +    subprocess.check_call(objcopy_cmd)
> +    return f.read()
> +
> +def get_keyvals(elf):
> +    readelf_cmd = 'readelf -p .uk_trace_keyvals %s' % elf
> +    readelf_cmd = readelf_cmd.split()
> +    raw_data = subprocess.check_output(readelf_cmd).decode()
> +    filtered = re.findall(r'^\s*\[ *\d+\]\s+(.+) = (.+)$', raw_data,
> +                          re.MULTILINE)
> +
> +    ret = dict()
> +    for key,val in filtered:
> +        ret[key] = val
> +
> +    return ret
> diff --git a/support/scripts/uk_trace/trace.py 
> b/support/scripts/uk_trace/trace.py
> new file mode 100755
> index 00000000..10c985e5
> --- /dev/null
> +++ b/support/scripts/uk_trace/trace.py
> @@ -0,0 +1,103 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: BSD-3-Clause */
> +#
> +# Authors: Yuri Volchkov <yuri.volchkov@xxxxxxxxx>
> +#
> +# Copyright (c) 2019, NEC Laboratories Europe GmbH, NEC Corporation.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# 1. Redistributions of source code must retain the above copyright
> +#    notice, this list of conditions and the following disclaimer.
> +# 2. Redistributions in binary form must reproduce the above copyright
> +#    notice, this list of conditions and the following disclaimer in the
> +#    documentation and/or other materials provided with the distribution.
> +# 3. Neither the name of the copyright holder nor the names of its
> +#    contributors may be used to endorse or promote products derived from
> +#    this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +# POSSIBILITY OF SUCH DAMAGE.
> +#
> +# THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
> +
> +import click
> +import os, sys
> +import pickle
> +import subprocess
> +
> +import parse
> +
> +@click.group()
> +def cli():
> +    pass
> +
> +def parse_tf(trace_file):
> +    try:
> +        with open(trace_file, 'rb') as tf:
> +            unpickler = pickle.Unpickler(tf)
> +
> +            keyvals = unpickler.load()
> +            elf = unpickler.load()
> +            ptr_size = unpickler.load()
> +            tp_defs = unpickler.load()
> +            trace_buff = unpickler.load()
> +    except EOFError:
> +        print("Unexpected end of trace file", file=sys.stderr)
> +        quit(-1)
> +    except Exception as inst:
> +        print("Problem occurred during reading the tracefile: %s" % 
> str(inst))
> +        quit(-1)
> +
> +    return parse.sample_parser(keyvals, tp_defs, trace_buff, ptr_size)
> +
> +@cli.command()
> +@click.argument('uk_img', type=click.Path(exists=True))
> +@click.option('--out', '-o', type=click.Path(),
> +              default='tracefile', show_default=True,
> +              help='Output binary file')
> +@click.option('--remote', '-r', type=click.STRING,
> +              default=':1234', show_default=True,
> +              help='How to connect to the gdb session '+
> +              '(parameters for "target remote" command)')
> +@click.option('--verbose', is_flag=True, default=False)
> +def fetch(uk_img, out, remote, verbose):
> +    """Fetch binary trace file from Unikraft (using gdb)"""
> +
> +    if os.path.exists(out):
> +        os.remove(out)
> +
> +    helper_path = os.path.abspath(uk_img) + '-gdb.py'
> +    gdb_cmd = ['gdb', '-nh', '-batch',
> +               click.format_filename(uk_img),
> +               '-iex', 'add-auto-load-safe-path ' + helper_path,
> +               '-ex', 'target remote ' + remote,
> +               '-ex', 'uk trace save ' + out
> +    ]
> +
> +    proc = subprocess.Popen(gdb_cmd,
> +                            stdout=subprocess.PIPE,
> +                            stderr=subprocess.STDOUT
> +    )
> +    _stdout, _ = proc.communicate()
> +    _stdout = _stdout.decode()
> +    if proc.returncode or not os.path.exists(out):
> +        print(_stdout)
> +        sys.exit(1)
> +    if verbose:
> +        print(_stdout)
> +
> +
> +if __name__ == '__main__':
> +    cli()
> 

_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.