All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Yonggang Luo <luoyonggang@gmail.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Richard Henderson <richard.henderson@linaro.org>,
	qemu-devel@nongnu.org
Subject: Re: [PATCH v3 6/6] plugin: Getting qemu-plugin works under win32.
Date: Tue, 06 Oct 2020 12:29:47 +0100	[thread overview]
Message-ID: <87sgar1tjo.fsf@linaro.org> (raw)
In-Reply-To: <20201001163429.1348-7-luoyonggang@gmail.com>


Yonggang Luo <luoyonggang@gmail.com> writes:

> We removed the need of .symbols file, so is the
> configure script, if we one expose a function to qemu-plugin
> just need prefix the function with QEMU_PLUGIN_EXPORT
>
> Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
> ---
>  Makefile                     |   1 -
>  configure                    |  71 -------------
>  contrib/plugins/hotblocks.c  |   1 +
>  contrib/plugins/hotpages.c   |   1 +
>  contrib/plugins/howvec.c     |   1 +
>  contrib/plugins/lockstep.c   |   1 +
>  include/qemu/qemu-plugin.h   | 197 +++++++++++++++++++++++++++--------
>  meson.build                  |   6 +-
>  plugins/api.c                |  62 +++++------
>  plugins/core.c               |  10 +-
>  plugins/loader.c             |  50 ++++++++-
>  plugins/meson.build          |  10 +-
>  plugins/plugin.h             |   1 +
>  plugins/qemu-plugins.symbols |  40 -------
>  tests/plugin/bb.c            |   1 +
>  tests/plugin/empty.c         |   1 +
>  tests/plugin/insn.c          |   1 +
>  tests/plugin/mem.c           |   1 +
>  18 files changed, 251 insertions(+), 205 deletions(-)
>  delete mode 100644 plugins/qemu-plugins.symbols
>
> diff --git a/Makefile b/Makefile
> index 54fc1a9d10..9981dd5209 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -105,7 +105,6 @@ config-host.mak: $(SRC_PATH)/configure $(SRC_PATH)/pc-bios $(SRC_PATH)/VERSION
>  
>  # Force configure to re-run if the API symbols are updated
>  ifeq ($(CONFIG_PLUGIN),y)
> -config-host.mak: $(SRC_PATH)/plugins/qemu-plugins.symbols
>  
>  .PHONY: plugins
>  plugins:
> diff --git a/configure b/configure
> index 1c21a73c3b..ea447919fc 100755
> --- a/configure
> +++ b/configure
> @@ -5435,61 +5435,6 @@ if compile_prog "" "" ; then
>    atomic64=yes
>  fi
>  
> -#########################################
> -# See if --dynamic-list is supported by the linker
> -ld_dynamic_list="no"
> -if test "$static" = "no" ; then
> -    cat > $TMPTXT <<EOF
> -{
> -  foo;
> -};
> -EOF
> -
> -    cat > $TMPC <<EOF
> -#include <stdio.h>
> -void foo(void);
> -
> -void foo(void)
> -{
> -  printf("foo\n");
> -}
> -
> -int main(void)
> -{
> -  foo();
> -  return 0;
> -}
> -EOF
> -
> -    if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then
> -        ld_dynamic_list="yes"
> -    fi
> -fi
> -
> -#########################################
> -# See if -exported_symbols_list is supported by the linker
> -
> -ld_exported_symbols_list="no"
> -if test "$static" = "no" ; then
> -    cat > $TMPTXT <<EOF
> -  _foo
> -EOF
> -
> -    if compile_prog "" "-Wl,-exported_symbols_list,$TMPTXT" ; then
> -        ld_exported_symbols_list="yes"
> -    fi
> -fi
> -
> -if  test "$plugins" = "yes" &&
> -    test "$ld_dynamic_list" = "no" &&
> -    test "$ld_exported_symbols_list" = "no" ; then
> -  error_exit \
> -      "Plugin support requires dynamic linking and specifying a set of symbols " \
> -      "that are exported to plugins. Unfortunately your linker doesn't " \
> -      "support the flag (--dynamic-list or -exported_symbols_list) used " \
> -      "for this purpose. You can't build with --static."
> -fi
> -
>  ########################################
>  # See if __attribute__((alias)) is supported.
>  # This false for Xcode 9, but has been remedied for Xcode 10.
> @@ -7074,22 +7019,6 @@ fi
>  
>  if test "$plugins" = "yes" ; then
>      echo "CONFIG_PLUGIN=y" >> $config_host_mak
> -    # Copy the export object list to the build dir
> -    if test "$ld_dynamic_list" = "yes" ; then
> -	echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak
> -	ld_symbols=qemu-plugins-ld.symbols
> -	cp "$source_path/plugins/qemu-plugins.symbols" $ld_symbols
> -    elif test "$ld_exported_symbols_list" = "yes" ; then
> -	echo "CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST=yes" >> $config_host_mak
> -	ld64_symbols=qemu-plugins-ld64.symbols
> -	echo "# Automatically generated by configure - do not modify" > $ld64_symbols
> -	grep 'qemu_' "$source_path/plugins/qemu-plugins.symbols" | sed 's/;//g' | \
> -	    sed -E 's/^[[:space:]]*(.*)/_\1/' >> $ld64_symbols
> -    else
> -	error_exit \
> -	    "If \$plugins=yes, either \$ld_dynamic_list or " \
> -	    "\$ld_exported_symbols_list should have been set to 'yes'."
> -    fi
>  fi
>  
>  if test -n "$gdb_bin" ; then
> diff --git a/contrib/plugins/hotblocks.c b/contrib/plugins/hotblocks.c
> index 37435a3fc7..39e77d2980 100644
> --- a/contrib/plugins/hotblocks.c
> +++ b/contrib/plugins/hotblocks.c
> @@ -13,6 +13,7 @@
>  #include <stdio.h>
>  #include <glib.h>
>  
> +#define QEMU_PLUGIN_IMPLEMENTATION
>  #include <qemu-plugin.h>

As mentioned in earlier patch we should be able to just have the tweak
in api.c and avoid touching all the plugins themselves.
>  
> -#define QEMU_PLUGIN_VERSION 0
> +#define QEMU_PLUGIN_VERSION 1
> +
> +typedef void *(*qemu_plugin_global_dlsym_t)(void* context, const char *name);
>  
>  typedef struct {
>      /* string describing architecture */
> @@ -73,8 +71,23 @@ typedef struct {
>              int max_vcpus;
>          } system;
>      };
> +    void *context;
> +    qemu_plugin_global_dlsym_t dlsym;
>  } qemu_info_t;
>  
> +/**
> + * qemu_plugin_initialize() - Initialize a plugin before install
> + * @info: a block describing some details about the guest
> + *
> + * All plugins must export this symbol, and in most case using qemu-plugin.h
> + * provided implementation directly.
> + * For plugin provide this function, the QEMU_PLUGIN_VERSION should >= 1
> + *
> + * Note: This function only used to loading qemu's exported functions, nothing
> + * else should doding in this function.
> + */
> +QEMU_PLUGIN_EXPORT int qemu_plugin_initialize(const qemu_info_t *info);
> +

So this is essentially working around the linker/dlopen stage and
manually linking in all the API functions? Does this affect the
efficiency of the API calls?
> -void qemu_plugin_outs(const char *string);
> +typedef void (*qemu_plugin_outs_t)(const char *string);
> +
> +#if !defined(QEMU_PLUGIN_API_IMPLEMENTATION)
> +#if defined(QEMU_PLUGIN_IMPLEMENTATION)
> +#define QEMU_PLUGIN_EXTERN
> +#else
> +#define QEMU_PLUGIN_EXTERN extern
> +#endif

As mentioned in the earlier patch I want to understand why the extern is
required. Could we avoid it with a parameter to the compiler when
building plugins?

<snip>
>  
>  static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
>  {
> +    qemu_plugin_initialize_func_t initialize = NULL;
>      qemu_plugin_install_func_t install;
>      struct qemu_plugin_ctx *ctx;
>      gpointer sym;
>      int rc;
> +    int version = -1;
>  
>      ctx = qemu_memalign(qemu_dcache_linesize, sizeof(*ctx));
>      memset(ctx, 0, sizeof(*ctx));
> @@ -184,7 +187,7 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
>                       desc->path, g_module_error());
>          goto err_symbol;
>      } else {
> -        int version = *(int *)sym;
> +        version = *(int *)sym;
>          if (version < QEMU_PLUGIN_MIN_VERSION) {
>              error_report("TCG plugin %s requires API version %d, but "
>                           "this QEMU supports only a minimum version of %d",
> @@ -198,6 +201,21 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
>          }
>      }
>  
> +    if (version >= QEMU_PLUGIN_VERSION_1) {
> +        /* This version should call to qemu_plugin_initialize first */
> +        if (!g_module_symbol(ctx->handle, "qemu_plugin_initialize", &sym)) {
> +            error_report("%s: %s", __func__, g_module_error());
> +            goto err_symbol;
> +        }
> +        initialize = (qemu_plugin_initialize_func_t) sym;
> +        /* symbol was found; it could be NULL though */
> +        if (initialize == NULL) {
> +            error_report("%s: %s: qemu_plugin_initialize is NULL",
> +                        __func__, desc->path);
> +            goto err_symbol;
> +        }
> +    }
> +
>      qemu_rec_mutex_lock(&plugin.lock);
>  
>      /* find an unused random id with &ctx as the seed */
> @@ -216,6 +234,16 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
>          }
>      }
>      QTAILQ_INSERT_TAIL(&plugin.ctxs, ctx, entry);
> +    if (initialize != NULL) {
> +        rc = initialize(info);
> +        if (rc) {
> +            error_report("%s: qemu_plugin_initialize returned error code %d",
> +                        __func__, rc);
> +            /* qemu_plugin_initialize only loading function symbols */
> +            goto err_symbol;
> +        }
> +    }
> +
>      ctx->installing = true;
>      rc = install(ctx->id, info, desc->argc, desc->argv);
>      ctx->installing = false;
> @@ -254,6 +282,17 @@ static void plugin_desc_free(struct qemu_plugin_desc *desc)
>      g_free(desc);
>  }
>  
> +static void *qemu_plugin_global_dlsym(void* context, const char *name)
> +{
> +    GModule *global_handle = context;
> +    gpointer sym = NULL;
> +    if (!g_module_symbol(global_handle, name, &sym)) {
> +        error_report("%s: %s", __func__, g_module_error());
> +        return NULL;
> +    }
> +    return sym;
> +}
> +
>  /**
>   * qemu_plugin_load_list - load a list of plugins
>   * @head: head of the list of descriptors of the plugins to be loaded
> @@ -267,6 +306,7 @@ int qemu_plugin_load_list(QemuPluginList *head)
>  {
>      struct qemu_plugin_desc *desc, *next;
>      g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1);
> +    GModule *global_handle = NULL;
>  
>      info->target_name = TARGET_NAME;
>      info->version.min = QEMU_PLUGIN_MIN_VERSION;
> @@ -276,6 +316,12 @@ int qemu_plugin_load_list(QemuPluginList *head)
>      info->system_emulation = true;
>      info->system.smp_vcpus = ms->smp.cpus;
>      info->system.max_vcpus = ms->smp.max_cpus;
> +    global_handle = g_module_open(NULL, G_MODULE_BIND_LOCAL);
> +    if (global_handle == NULL) {
> +        goto err_dlopen;
> +    }
> +    info->dlsym = qemu_plugin_global_dlsym;
> +    info->context = (void*)global_handle;
>  #else
>      info->system_emulation = false;
>  #endif
> @@ -289,6 +335,8 @@ int qemu_plugin_load_list(QemuPluginList *head)
>          }
>          QTAILQ_REMOVE(head, desc, entry);
>      }
> +
> +err_dlopen:
>      return 0;

This doesn't compile cleanly for both linux-user and softmmu:

  Compiling C object libqemu-aarch64-linux-user.fa.p/tcg_tcg-common.c.o
  ../../plugins/loader.c: In function ‘qemu_plugin_load_list’:
  ../../plugins/loader.c:339:1: error: label ‘err_dlopen’ defined but not used [-Werror=unused-label]
   err_dlopen:
   ^~~~~~~~~~
  ../../plugins/loader.c:309:14: error: unused variable ‘global_handle’ [-Werror=unused-variable]
       GModule *global_handle = NULL;
                ^~~~~~~~~~~~~
  At top level:
  ../../plugins/loader.c:285:14: error: ‘qemu_plugin_global_dlsym’ defined but not used [-Werror=unused-function]
   static void *qemu_plugin_global_dlsym(void* context, const char *name)
                ^~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors
  make: *** [Makefile.ninja:6703: libqemu-aarch64-linux-user.fa.p/plugins_loader.c.o] Error 1
  make: *** Waiting for unfinished jobs....

-- 
Alex Bennée


  reply	other threads:[~2020-10-06 11:31 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-01 16:34 [PATCH v3 0/6] Enable plugin support on msys2/mingw Yonggang Luo
2020-10-01 16:34 ` [PATCH v3 1/6] plugins: Fixes a issue when dlsym failed, the handle not closed Yonggang Luo
2020-10-05  9:59   ` Alex Bennée
2020-10-01 16:34 ` [PATCH v3 2/6] plugin: Fixes compiling errors on msys2/mingw Yonggang Luo
2020-10-05 10:00   ` Alex Bennée
2020-10-01 16:34 ` [PATCH v3 3/6] cirrus: Enable plugin in cirrus for windows Yonggang Luo
2020-10-05 10:17   ` Alex Bennée
2020-10-01 16:34 ` [PATCH v3 4/6] plugin: define QEMU_PLUGIN_API_IMPLEMENTATION first Yonggang Luo
2020-10-05 10:44   ` Alex Bennée
2020-10-05 15:58     ` 罗勇刚(Yonggang Luo)
2020-10-01 16:34 ` [PATCH v3 5/6] plugin: getting qemu_plugin_get_hwaddr only expose one function prototype Yonggang Luo
2020-10-05 10:48   ` Alex Bennée
2020-10-05 15:34     ` 罗勇刚(Yonggang Luo)
2020-10-05 15:46       ` Alex Bennée
2020-10-01 16:34 ` [PATCH v3 6/6] plugin: Getting qemu-plugin works under win32 Yonggang Luo
2020-10-06 11:29   ` Alex Bennée [this message]
2020-10-06 12:08     ` 罗勇刚(Yonggang Luo)
2020-10-06 11:35 ` [PATCH v3 0/6] Enable plugin support on msys2/mingw Alex Bennée
2021-01-27  3:52   ` 罗勇刚(Yonggang Luo)
2021-02-10 15:10     ` Alex Bennée

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=87sgar1tjo.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=luoyonggang@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.