[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |