qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
Cc: qemu-devel@nongnu.org, peter.maydell@linaro.org,
	maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru,
	pbonzini@redhat.com, vilanova@ac.upc.edu
Subject: Re: [Qemu-devel] [RFC PATCH v2 2/7] Add plugin support
Date: Fri, 07 Sep 2018 13:34:43 +0100	[thread overview]
Message-ID: <87worxzdss.fsf@linaro.org> (raw)
In-Reply-To: <152819516675.30857.9162557650483931182.stgit@pasha-ThinkPad-T60>


Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> writes:

> This patch adds support for dynamically loaded plugins.
> Every plugin is a dynamic library with a set of optional exported
> functions that will be called from QEMU.
>
> Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
> ---
>  Makefile.target           |    1
>  configure                 |   14 ++++++-
>  include/qemu/plugins.h    |    8 ++++
>  plugins/include/plugins.h |   12 ++++++
>  plugins/plugins.c         |   91 +++++++++++++++++++++++++++++++++++++++++++++
>  qemu-options.hx           |   10 +++++
>  vl.c                      |    8 ++++
>  7 files changed, 143 insertions(+), 1 deletion(-)
>  create mode 100644 include/qemu/plugins.h
>  create mode 100644 plugins/include/plugins.h
>  create mode 100644 plugins/plugins.c
>
> diff --git a/Makefile.target b/Makefile.target
> index dad2cf8..4cffd96 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -93,6 +93,7 @@ all: $(PROGS) stap
>  # cpu emulator library
>  obj-y += exec.o
>  obj-y += accel/
> +obj-$(CONFIG_PLUGINS) += plugins/plugins.o
>  obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o
>  obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o
>  obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
> diff --git a/configure b/configure
> index a71bf9b..34e6f00 100755
> --- a/configure
> +++ b/configure
> @@ -373,6 +373,7 @@ EXESUF=""
>  DSOSUF=".so"
>  LDFLAGS_SHARED="-shared"
>  modules="no"
> +plugins="no"
>  prefix="/usr/local"
>  mandir="\${prefix}/share/man"
>  datadir="\${prefix}/share"
> @@ -922,6 +923,12 @@ for opt do
>    --disable-modules)
>        modules="no"
>    ;;
> +  --enable-plugins)
> +      plugins="yes"
> +  ;;
> +  --disable-plugins)
> +      plugins="no"
> +  ;;
>    --cpu=*)
>    ;;
>    --target-list=*) target_list="$optarg"
> @@ -1567,6 +1574,7 @@ disabled with --disable-FEATURE, default is enabled if available:
>    guest-agent-msi build guest agent Windows MSI installation package
>    pie             Position Independent Executables
>    modules         modules support
> +  plugins         plugins support
>    debug-tcg       TCG debugging (default is disabled)
>    debug-info      debugging information
>    sparse          sparse checker
> @@ -3392,7 +3400,7 @@ else
>      glib_req_ver=2.22
>  fi
>  glib_modules=gthread-2.0
> -if test "$modules" = yes; then
> +if test "$modules" = yes || test "$plugins" = yes; then
>      glib_modules="$glib_modules gmodule-export-2.0"
>  fi
>
> @@ -5777,6 +5785,7 @@ if test "$slirp" = "yes" ; then
>      echo "smbd              $smbd"
>  fi
>  echo "module support    $modules"
> +echo "plugin support    $plugins"
>  echo "host CPU          $cpu"
>  echo "host big endian   $bigendian"
>  echo "target list       $target_list"
> @@ -6111,6 +6120,9 @@ if test "$modules" = "yes"; then
>    echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak
>    echo "CONFIG_MODULES=y" >> $config_host_mak
>  fi
> +if test "$plugins" = "yes"; then
> +  echo "CONFIG_PLUGINS=y" >> $config_host_mak
> +fi
>  if test "$have_x11" = "yes" -a "$need_x11" = "yes"; then
>    echo "CONFIG_X11=y" >> $config_host_mak
>    echo "X11_CFLAGS=$x11_cflags" >> $config_host_mak
> diff --git a/include/qemu/plugins.h b/include/qemu/plugins.h
> new file mode 100644
> index 0000000..4464822
> --- /dev/null
> +++ b/include/qemu/plugins.h
> @@ -0,0 +1,8 @@
> +#ifndef PLUGINS_H
> +#define PLUGINS_H
> +
> +void qemu_plugin_parse_cmd_args(const char *optarg);
> +void qemu_plugin_load(const char *filename, const char *args);
> +void qemu_plugins_init(void);

I think you want to have an #ifdef CONFIG_PLUGINS here and some empty
inlines for the non CONFIG_PLUGINS case so you don't need to ifdef so
much later.

> +
> +#endif /* PLUGINS_H */
> diff --git a/plugins/include/plugins.h b/plugins/include/plugins.h
> new file mode 100644
> index 0000000..100a786
> --- /dev/null
> +++ b/plugins/include/plugins.h
> @@ -0,0 +1,12 @@
> +#ifndef PLUGINS_INTERFACE_H
> +#define PLUGINS_INTERFACE_H
> +
> +#include <stdbool.h>
> +
> +/* Plugin interface */
> +
> +bool plugin_init(const char *args);
> +bool plugin_needs_before_insn(uint64_t pc, void *cpu);
> +void plugin_before_insn(uint64_t pc, void *cpu);
> +
> +#endif /* PLUGINS_INTERFACE_H */
> diff --git a/plugins/plugins.c b/plugins/plugins.c
> new file mode 100644
> index 0000000..eabc931
> --- /dev/null
> +++ b/plugins/plugins.c
> @@ -0,0 +1,91 @@
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/error-report.h"
> +#include "qemu/plugins.h"
> +#include "qemu/queue.h"
> +#include <gmodule.h>
> +
> +typedef bool (*PluginInitFunc)(const char *);
> +typedef bool (*PluginNeedsBeforeInsnFunc)(uint64_t, void *);
> +typedef void (*PluginBeforeInsnFunc)(uint64_t, void *);
> +
> +typedef struct QemuPluginInfo {
> +    const char *filename;
> +    const char *args;
> +    GModule *g_module;
> +
> +    PluginInitFunc init;
> +    PluginNeedsBeforeInsnFunc needs_before_insn;
> +    PluginBeforeInsnFunc before_insn;
> +
> +    QLIST_ENTRY(QemuPluginInfo) next;
> +} QemuPluginInfo;
> +
> +static QLIST_HEAD(, QemuPluginInfo) qemu_plugins
> +                                = QLIST_HEAD_INITIALIZER(qemu_plugins);
> +
> +static QemuOptsList qemu_plugin_opts = {
> +    .name = "plugin",
> +    .head = QTAILQ_HEAD_INITIALIZER(qemu_plugin_opts.head),
> +    .desc = {
> +        {
> +            .name = "file",
> +            .type = QEMU_OPT_STRING,
> +        },{
> +            .name = "args",
> +            .type = QEMU_OPT_STRING,
> +        },
> +        { /* end of list */ }
> +    },
> +};
> +
> +void qemu_plugin_parse_cmd_args(const char *optarg)
> +{
> +    QemuOpts *opts = qemu_opts_parse_noisily(&qemu_plugin_opts, optarg, false);
> +    qemu_plugin_load(qemu_opt_get(opts, "file"),
> +        qemu_opt_get(opts, "args"));
> +}
> +
> +void qemu_plugin_load(const char *filename, const char *args)
> +{
> +    GModule *g_module;
> +    QemuPluginInfo *info = NULL;
> +    if (!filename) {
> +        error_report("plugin name was not specified");
> +        return;
> +    }
> +    g_module = g_module_open(filename,
> +        G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
> +    if (!g_module) {
> +        error_report("can't load plugin '%s'", filename);
> +        return;
> +    }
> +    info = g_new0(QemuPluginInfo, 1);
> +    info->filename = g_strdup(filename);
> +    info->g_module = g_module;
> +    if (args) {
> +        info->args = g_strdup(args);
> +    }
> +
> +    g_module_symbol(g_module, "plugin_init", (gpointer*)&info->init);
> +
> +    /* Get the instrumentation callbacks */
> +    g_module_symbol(g_module, "plugin_needs_before_insn",
> +        (gpointer*)&info->needs_before_insn);
> +    g_module_symbol(g_module, "plugin_before_insn",
> +        (gpointer*)&info->before_insn);
> +
> +    QLIST_INSERT_HEAD(&qemu_plugins, info, next);
> +
> +    return;
> +}
> +
> +void qemu_plugins_init(void)
> +{
> +    QemuPluginInfo *info;
> +    QLIST_FOREACH(info, &qemu_plugins, next) {
> +        if (info->init) {
> +            info->init(info->args);
> +        }
> +    }
> +}
> diff --git a/qemu-options.hx b/qemu-options.hx
> index c0d3951..d171544 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3950,6 +3950,16 @@ Dump json-encoded vmstate information for current machine type to file
>  in @var{file}
>  ETEXI
>
> +#ifdef CONFIG_PLUGINS
> +DEF("plugin", HAS_ARG, QEMU_OPTION_plugin, \
> +           "-plugin file=<file>[,args=<args>] load <dso> plugin with <args>\n", QEMU_ARCH_ALL)
> +STEXI
> +@item -plugin file=@var{file}[,args=@var{args}]
> +@findex -plugin
> +Load @var{file} plugin passing @var{args} arguments.
> +ETEXI
> +#endif
> +
>  STEXI
>  @end table
>  ETEXI
> diff --git a/vl.c b/vl.c
> index 0603171..05420bf 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -129,6 +129,7 @@ int main(int argc, char **argv)
>  #include "qapi/qapi-commands-run-state.h"
>  #include "qapi/qmp/qerror.h"
>  #include "sysemu/iothread.h"
> +#include "qemu/plugins.h"
>
>  #define MAX_VIRTIO_CONSOLES 1
>
> @@ -3925,6 +3926,11 @@ int main(int argc, char **argv, char **envp)
>                      exit(1);
>                  }
>                  break;
> +#ifdef CONFIG_PLUGINS
> +            case QEMU_OPTION_plugin:
> +                qemu_plugin_parse_cmd_args(optarg);
> +                break;
> +#endif
>              case QEMU_OPTION_nodefconfig:
>              case QEMU_OPTION_nouserconfig:
>                  /* Nothing to be parsed here. Especially, do not error out below. */
> @@ -4470,6 +4476,8 @@ int main(int argc, char **argv, char **envp)
>      }
>      parse_numa_opts(current_machine);
>
> +    qemu_plugins_init();
> +

For example this fails to build currently.

>      /* do monitor/qmp handling at preconfig state if requested */
>      main_loop();
>


--
Alex Bennée

  parent reply	other threads:[~2018-09-07 12:34 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-05 10:39 [Qemu-devel] [RFC PATCH v2 0/7] QEMU binary instrumentation prototype Pavel Dovgalyuk
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 1/7] tcg: add headers for non-target helpers Pavel Dovgalyuk
2018-06-05 13:07   ` Thomas Huth
2018-06-06  7:30     ` Pavel Dovgalyuk
2018-09-07 12:16   ` Alex Bennée
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 2/7] Add plugin support Pavel Dovgalyuk
2018-09-07 10:11   ` Alex Bennée
2018-09-13  6:40     ` Pavel Dovgalyuk
2018-09-07 12:34   ` Alex Bennée [this message]
2018-09-10  8:30     ` Pavel Dovgalyuk
2018-09-07 14:14   ` Alex Bennée
2018-09-10 11:41     ` Pavel Dovgalyuk
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 3/7] plugins: provide helper functions for plugins Pavel Dovgalyuk
2018-09-07 13:06   ` Alex Bennée
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 4/7] tcg: add instrumenting module Pavel Dovgalyuk
2018-09-07 13:36   ` Alex Bennée
2018-09-13  6:55     ` Pavel Dovgalyuk
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 5/7] plugins: add plugin template Pavel Dovgalyuk
2018-09-07 13:41   ` Alex Bennée
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 6/7] plugin: add instruction execution logger Pavel Dovgalyuk
2018-09-07 13:59   ` Alex Bennée
2018-06-05 10:39 ` [Qemu-devel] [RFC PATCH v2 7/7] plugins: add syscall logging plugin sample Pavel Dovgalyuk
2018-09-07 14:06   ` Alex Bennée
2018-09-10  9:18     ` Pavel Dovgalyuk
2018-09-10 13:58       ` Alex Bennée
2018-06-05 10:49 ` [Qemu-devel] [RFC PATCH v2 0/7] QEMU binary instrumentation prototype Peter Maydell
2018-06-05 11:56   ` Pavel Dovgalyuk
2018-06-25  5:46     ` Pavel Dovgalyuk
2018-06-25  9:06       ` Peter Maydell
2018-09-07 14:10       ` Alex Bennée
2018-07-10 13:06     ` Stefan Hajnoczi
2018-07-11  6:02       ` Pavel Dovgalyuk
2018-07-30 13:26         ` Pavel Dovgalyuk
2018-08-29  5:39       ` Pavel Dovgalyuk
2018-08-29 19:57         ` Peter Maydell
2018-08-30  4:03           ` Alex Bennée
2018-06-06  8:52 ` no-reply
2018-06-06  9:21 ` no-reply
2018-06-06 10:45 ` no-reply
2018-09-07 14:39 ` Alex Bennée
2018-09-08  0:57   ` Peter Maydell
2018-09-10  9:01     ` Alex Bennée
2018-09-10 11:44       ` Pavel Dovgalyuk

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=87worxzdss.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=Pavel.Dovgaluk@ispras.ru \
    --cc=dovgaluk@ispras.ru \
    --cc=maria.klimushenkova@ispras.ru \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=vilanova@ac.upc.edu \
    /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).