Merge remote-tracking branch 'remotes/bonzini/configure' into staging

* remotes/bonzini/configure:
  build: softmmu targets do not have a "main.o" file
  configure: Disable libtool if -fPIE does not work with it (bug #1257099)
  block: convert block drivers linked with libs to modules
  Makefile: introduce common-obj-m and block-obj-m for DSO
  Makefile: install modules with "make install"
  module: implement module loading
  rules.mak: introduce DSO rules
  darwin: do not use -mdynamic-no-pic
  block: use per-object cflags and libs
  rules.mak: allow per object cflags and libs
  rules.mak: fix $(obj) to a real relative path
  util: Split out exec_dir from os_find_datadir

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-02-24 15:37:59 +00:00
commit 6dedf0522c
21 changed files with 541 additions and 127 deletions

3
.gitignore vendored
View file

@ -66,6 +66,9 @@ libuser
*.cp
*.dvi
*.exe
*.dll
*.so
*.mo
*.fn
*.ky
*.log

View file

@ -127,13 +127,29 @@ defconfig:
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/Makefile.objs
endif
dummy := $(call unnest-vars,, \
stub-obj-y \
util-obj-y \
qga-obj-y \
block-obj-y \
block-obj-m \
common-obj-y \
common-obj-m)
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/tests/Makefile
endif
ifeq ($(CONFIG_SMARTCARD_NSS),y)
include $(SRC_PATH)/libcacard/Makefile
endif
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
@ -192,6 +208,9 @@ Makefile: $(version-obj-y) $(version-lobj-y)
libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
######################################################################
qemu-img.o: qemu-img-cmds.h
@ -247,6 +266,8 @@ clean:
rm -f qemu-options.def
find . -name '*.[oda]' -type f -exec rm -f {} +
find . -name '*.l[oa]' -type f -exec rm -f {} +
find . -name '*$(DSOSUF)' -type f -exec rm -f {} +
find . -name '*.mo' -type f -exec rm -f {} +
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f fsdev/*.pod
rm -rf .libs */.libs
@ -354,6 +375,12 @@ install-datadir install-localstatedir
ifneq ($(TOOLS),)
$(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)"
endif
ifneq ($(CONFIG_MODULES),)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_moddir)"
for s in $(patsubst %.mo,%$(DSOSUF),$(modules-m)); do \
$(INSTALL_PROG) $(STRIP_OPT) $$s "$(DESTDIR)$(qemu_moddir)/$${s//\//-}"; \
done
endif
ifneq ($(HELPERS-y),)
$(INSTALL_DIR) "$(DESTDIR)$(libexecdir)"
$(INSTALL_PROG) $(STRIP_OPT) $(HELPERS-y) "$(DESTDIR)$(libexecdir)"

View file

@ -19,6 +19,8 @@ block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
block-obj-y += qemu-coroutine-sleep.o
block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
block-obj-m = block/
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
# only pull in the actual virtio-9p device if we also enabled virtio.
@ -41,7 +43,7 @@ libcacard-y += libcacard/vcardt.o
# single QEMU executable should support all CPUs and machines.
ifeq ($(CONFIG_SOFTMMU),y)
common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
common-obj-y = blockdev.o blockdev-nbd.o block/
common-obj-y += net/
common-obj-y += qdev-monitor.o device-hotplug.o
common-obj-$(CONFIG_WIN32) += os-win32.o
@ -111,18 +113,3 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
# by libqemuutil.a. These should be moved to a separate .json schema.
qga-obj-y = qga/ qapi-types.o qapi-visit.o
qga-vss-dll-obj-y = qga/
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
nested-vars += \
stub-obj-y \
util-obj-y \
qga-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
common-obj-y
dummy := $(call unnest-vars)

View file

@ -130,8 +130,6 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/
endif
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
GENERATED_HEADERS += hmp-commands.h qmp-commands-old.h
endif # CONFIG_SOFTMMU
@ -139,13 +137,26 @@ endif # CONFIG_SOFTMMU
# Workaround for http://gcc.gnu.org/PR55489, see configure.
%/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS)
nested-vars += obj-y
dummy := $(call unnest-vars,,obj-y)
# This resolves all nested paths, so it must come last
# we are making another call to unnest-vars with different vars, protect obj-y,
# it can be overriden in subdir Makefile.objs
obj-y-save := $(obj-y)
block-obj-y :=
common-obj-y :=
include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,.., \
block-obj-y \
block-obj-m \
common-obj-y \
common-obj-m)
all-obj-y = $(obj-y)
all-obj-y += $(addprefix ../, $(common-obj-y))
# Now restore obj-y
obj-y := $(obj-y-save)
all-obj-y = $(obj-y) $(common-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
ifndef CONFIG_HAIKU
LIBS+=-lm

View file

@ -24,4 +24,15 @@ common-obj-y += commit.o
common-obj-y += mirror.o
common-obj-y += backup.o
$(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS)
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
iscsi.o-libs := $(LIBISCSI_LIBS)
curl.o-cflags := $(CURL_CFLAGS)
curl.o-libs := $(CURL_LIBS)
rbd.o-cflags := $(RBD_CFLAGS)
rbd.o-libs := $(RBD_LIBS)
gluster.o-cflags := $(GLUSTERFS_CFLAGS)
gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio

156
configure vendored
View file

@ -12,7 +12,10 @@ else
fi
TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
TMPB="qemu-conf-${RANDOM}-$$-${RANDOM}"
TMPO="${TMPDIR1}/${TMPB}.o"
TMPL="${TMPDIR1}/${TMPB}.lo"
TMPA="${TMPDIR1}/lib${TMPB}.la"
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
# NB: do not call "exit" in the trap handler; this is buggy with some shells;
@ -86,6 +89,38 @@ compile_prog() {
do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags
}
do_libtool() {
local mode=$1
shift
# Run the compiler, capturing its output to the log.
echo $libtool $mode --tag=CC $cc "$@" >> config.log
$libtool $mode --tag=CC $cc "$@" >> config.log 2>&1 || return $?
# Test passed. If this is an --enable-werror build, rerun
# the test with -Werror and bail out if it fails. This
# makes warning-generating-errors in configure test code
# obvious to developers.
if test "$werror" != "yes"; then
return 0
fi
# Don't bother rerunning the compile if we were already using -Werror
case "$*" in
*-Werror*)
return 0
;;
esac
echo $libtool $mode --tag=CC $cc -Werror "$@" >> config.log
$libtool $mode --tag=CC $cc -Werror "$@" >> config.log 2>&1 && return $?
error_exit "configure test passed without -Werror but failed with -Werror." \
"This is probably a bug in the configure script. The failing command" \
"will be at the bottom of config.log." \
"You can run configure with --disable-werror to bypass this check."
}
libtool_prog() {
do_libtool --mode=compile $QEMU_CFLAGS -c -fPIE -DPIE -o $TMPO $TMPC || return $?
do_libtool --mode=link $LDFLAGS -o $TMPA $TMPL -rpath /usr/local/lib
}
# symbolically link $1 to $2. Portable version of "ln -sf".
symlink() {
rm -rf "$2"
@ -205,6 +240,9 @@ mingw32="no"
gcov="no"
gcov_tool="gcov"
EXESUF=""
DSOSUF=".so"
LDFLAGS_SHARED="-shared"
modules="no"
prefix="/usr/local"
mandir="\${prefix}/share/man"
datadir="\${prefix}/share"
@ -515,11 +553,10 @@ OpenBSD)
Darwin)
bsd="yes"
darwin="yes"
LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
if [ "$cpu" = "x86_64" ] ; then
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
LDFLAGS="-arch x86_64 $LDFLAGS"
else
QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS"
fi
cocoa="yes"
audio_drv_list="coreaudio"
@ -610,6 +647,7 @@ fi
if test "$mingw32" = "yes" ; then
EXESUF=".exe"
DSOSUF=".dll"
QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
# enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
@ -676,6 +714,9 @@ for opt do
;;
--disable-debug-info)
;;
--enable-modules)
modules="yes"
;;
--cpu=*)
;;
--target-list=*) target_list="$optarg"
@ -1131,7 +1172,8 @@ Advanced options (experts only):
--libdir=PATH install libraries in PATH
--sysconfdir=PATH install config in PATH$confsuffix
--localstatedir=PATH install local state in PATH (set at runtime on win32)
--with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]
--with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix]
--enable-modules enable modules support
--enable-debug-tcg enable TCG debugging
--disable-debug-tcg disable TCG debugging (default)
--enable-debug-info enable debugging information (default)
@ -1428,6 +1470,32 @@ EOF
fi
fi
# check for broken gcc and libtool in RHEL5
if test -n "$libtool" -a "$pie" != "no" ; then
cat > $TMPC <<EOF
void *f(unsigned char *buf, int len);
void *g(unsigned char *buf, int len);
void *
f(unsigned char *buf, int len)
{
return (void*)0L;
}
void *
g(unsigned char *buf, int len)
{
return f(buf, len);
}
EOF
if ! libtool_prog; then
echo "Disabling libtool due to broken toolchain support"
libtool=
fi
fi
##########################################
# __sync_fetch_and_and requires at least -march=i486. Many toolchains
# use i686 as default anyway, but for those that don't, an explicit
@ -2347,8 +2415,6 @@ EOF
curl_libs=`$curlconfig --libs 2>/dev/null`
if compile_prog "$curl_cflags" "$curl_libs" ; then
curl=yes
libs_tools="$curl_libs $libs_tools"
libs_softmmu="$curl_libs $libs_softmmu"
else
if test "$curl" = "yes" ; then
feature_not_found "curl" "Install libcurl devel"
@ -2386,13 +2452,32 @@ if test "$mingw32" = yes; then
else
glib_req_ver=2.12
fi
if $pkg_config --atleast-version=$glib_req_ver gthread-2.0; then
glib_cflags=`$pkg_config --cflags gthread-2.0`
glib_libs=`$pkg_config --libs gthread-2.0`
LIBS="$glib_libs $LIBS"
libs_qga="$glib_libs $libs_qga"
else
error_exit "glib-$glib_req_ver required to compile QEMU"
for i in gthread-2.0 gmodule-2.0; do
if $pkg_config --atleast-version=$glib_req_ver $i; then
glib_cflags=`$pkg_config --cflags $i`
glib_libs=`$pkg_config --libs $i`
CFLAGS="$glib_cflags $CFLAGS"
LIBS="$glib_libs $LIBS"
libs_qga="$glib_libs $libs_qga"
else
error_exit "glib-$glib_req_ver $i is required to compile QEMU"
fi
done
##########################################
# SHA command probe for modules
if test "$modules" = yes; then
shacmd_probe="sha1sum sha1 shasum"
for c in $shacmd_probe; do
if which $c &>/dev/null; then
shacmd="$c"
break
fi
done
if test "$shacmd" = ""; then
error_exit "one of the checksum commands is required to enable modules: $shacmd_probe"
fi
fi
##########################################
@ -2503,8 +2588,6 @@ EOF
rbd_libs="-lrbd -lrados"
if compile_prog "" "$rbd_libs" ; then
rbd=yes
libs_tools="$rbd_libs $libs_tools"
libs_softmmu="$rbd_libs $libs_softmmu"
else
if test "$rbd" = "yes" ; then
feature_not_found "rados block device" "Install librbd/ceph devel"
@ -2521,9 +2604,6 @@ if test "$libssh2" != "no" ; then
libssh2_cflags=`$pkg_config libssh2 --cflags`
libssh2_libs=`$pkg_config libssh2 --libs`
libssh2=yes
libs_tools="$libssh2_libs $libs_tools"
libs_softmmu="$libssh2_libs $libs_softmmu"
QEMU_CFLAGS="$QEMU_CFLAGS $libssh2_cflags"
else
if test "$libssh2" = "yes" ; then
error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2"
@ -2569,8 +2649,6 @@ int main(void) { io_setup(0, NULL); io_set_eventfd(NULL, 0); eventfd(0, 0); retu
EOF
if compile_prog "" "-laio" ; then
linux_aio=yes
libs_softmmu="$libs_softmmu -laio"
libs_tools="$libs_tools -laio"
else
if test "$linux_aio" = "yes" ; then
feature_not_found "linux AIO" "Install libaio devel"
@ -2739,9 +2817,6 @@ if test "$glusterfs" != "no" ; then
glusterfs="yes"
glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
glusterfs_libs=`$pkg_config --libs glusterfs-api`
CFLAGS="$CFLAGS $glusterfs_cflags"
libs_tools="$glusterfs_libs $libs_tools"
libs_softmmu="$glusterfs_libs $libs_softmmu"
if $pkg_config --atleast-version=5 glusterfs-api; then
glusterfs_discard="yes"
fi
@ -3112,11 +3187,9 @@ EOF
libiscsi="yes"
libiscsi_cflags=$($pkg_config --cflags libiscsi)
libiscsi_libs=$($pkg_config --libs libiscsi)
CFLAGS="$CFLAGS $libiscsi_cflags"
LIBS="$LIBS $libiscsi_libs"
elif compile_prog "" "-liscsi" ; then
libiscsi="yes"
LIBS="$LIBS -liscsi"
libiscsi_libs="-liscsi"
else
if test "$libiscsi" = "yes" ; then
feature_not_found "libiscsi" "Install libiscsi devel"
@ -3717,6 +3790,7 @@ if test "$mingw32" = "yes" ; then
fi
qemu_confdir=$sysconfdir$confsuffix
qemu_moddir=$libdir$confsuffix
qemu_datadir=$datadir$confsuffix
qemu_localedir="$datadir/locale"
@ -3807,6 +3881,7 @@ echo "Install prefix $prefix"
echo "BIOS directory `eval echo $qemu_datadir`"
echo "binary directory `eval echo $bindir`"
echo "library directory `eval echo $libdir`"
echo "module directory `eval echo $qemu_moddir`"
echo "libexec directory `eval echo $libexecdir`"
echo "include directory `eval echo $includedir`"
echo "config directory `eval echo $sysconfdir`"
@ -3833,6 +3908,7 @@ echo "python $python"
if test "$slirp" = "yes" ; then
echo "smbd $smbd"
fi
echo "module support $modules"
echo "host CPU $cpu"
echo "host big endian $bigendian"
echo "target list $target_list"
@ -3945,6 +4021,7 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak
echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
echo "qemu_moddir=$qemu_moddir" >> $config_host_mak
if test "$mingw32" = "no" ; then
echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
fi
@ -4077,6 +4154,12 @@ echo "TARGET_DIRS=$target_list" >> $config_host_mak
if [ "$docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_host_mak
fi
if test "$modules" = "yes"; then
# $shacmd can generate a hash started with digit, which the compiler doesn't
# like as an symbol. So prefix it with an underscore
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 "$sdl" = "yes" ; then
echo "CONFIG_SDL=y" >> $config_host_mak
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
@ -4148,8 +4231,9 @@ if test "$bswap_h" = "yes" ; then
echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak
fi
if test "$curl" = "yes" ; then
echo "CONFIG_CURL=y" >> $config_host_mak
echo "CONFIG_CURL=m" >> $config_host_mak
echo "CURL_CFLAGS=$curl_cflags" >> $config_host_mak
echo "CURL_LIBS=$curl_libs" >> $config_host_mak
fi
if test "$brlapi" = "yes" ; then
echo "CONFIG_BRLAPI=y" >> $config_host_mak
@ -4238,10 +4322,12 @@ if test "$glx" = "yes" ; then
fi
if test "$libiscsi" = "yes" ; then
echo "CONFIG_LIBISCSI=y" >> $config_host_mak
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
if test "$libiscsi_version" = "1.4.0"; then
echo "CONFIG_LIBISCSI_1_4=y" >> $config_host_mak
fi
echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak
fi
if test "$libnfs" = "yes" ; then
@ -4266,7 +4352,9 @@ if test "$qom_cast_debug" = "yes" ; then
echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak
fi
if test "$rbd" = "yes" ; then
echo "CONFIG_RBD=y" >> $config_host_mak
echo "CONFIG_RBD=m" >> $config_host_mak
echo "RBD_CFLAGS=$rbd_cflags" >> $config_host_mak
echo "RBD_LIBS=$rbd_libs" >> $config_host_mak
fi
echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak
@ -4309,7 +4397,9 @@ if test "$getauxval" = "yes" ; then
fi
if test "$glusterfs" = "yes" ; then
echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
echo "CONFIG_GLUSTERFS=m" >> $config_host_mak
echo "GLUSTERFS_CFLAGS=$glusterfs_cflags" >> $config_host_mak
echo "GLUSTERFS_LIBS=$glusterfs_libs" >> $config_host_mak
fi
if test "$glusterfs_discard" = "yes" ; then
@ -4321,7 +4411,9 @@ if test "$glusterfs_zerofill" = "yes" ; then
fi
if test "$libssh2" = "yes" ; then
echo "CONFIG_LIBSSH2=y" >> $config_host_mak
echo "CONFIG_LIBSSH2=m" >> $config_host_mak
echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
fi
if test "$virtio_blk_data_plane" = "yes" ; then
@ -4452,6 +4544,8 @@ echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
echo "DSOSUF=$DSOSUF" >> $config_host_mak
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak

View file

@ -352,7 +352,7 @@ char *qemu_find_file(int type, const char *name);
/* OS specific functions */
void os_setup_early_signal_handling(void);
char *os_find_datadir(const char *argv0);
char *os_find_datadir(void);
void os_parse_cmd_args(int index, const char *optarg);
void os_pidfile_error(void);

View file

@ -14,11 +14,31 @@
#ifndef QEMU_MODULE_H
#define QEMU_MODULE_H
#include "qemu/osdep.h"
#define DSO_STAMP_FUN glue(qemu_stamp, CONFIG_STAMP)
#define DSO_STAMP_FUN_STR stringify(DSO_STAMP_FUN)
#ifdef BUILD_DSO
void DSO_STAMP_FUN(void);
/* This is a dummy symbol to identify a loaded DSO as a QEMU module, so we can
* distinguish "version mismatch" from "not a QEMU module", when the stamp
* check fails during module loading */
void qemu_module_dummy(void);
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_dso_module_init(function, type); \
}
#else
/* This should not be used directly. Use block_init etc. instead. */
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) { \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_module_init(function, type); \
}
#endif
typedef enum {
MODULE_INIT_BLOCK,
@ -34,6 +54,7 @@ typedef enum {
#define type_init(function) module_init(function, MODULE_INIT_QOM)
void register_module_init(void (*fn)(void), module_init_type type);
void register_dso_module_init(void (*fn)(void), module_init_type type);
void module_call_init(module_init_type type);

View file

@ -215,6 +215,15 @@ bool fips_get_state(void);
*/
char *qemu_get_local_state_pathname(const char *relative_pathname);
/* Find program directory, and save it for later usage with
* qemu_get_exec_dir().
* Try OS specific API first, if not working, parse from argv0. */
void qemu_init_exec_dir(const char *argv0);
/* Get the saved exec dir.
* Caller needs to release the returned string by g_free() */
char *qemu_get_exec_dir(void);
/**
* qemu_getauxval:
* @type: the auxiliary vector key to lookup

10
module-common.c Normal file
View file

@ -0,0 +1,10 @@
#include "config-host.h"
#include "qemu/module.h"
void qemu_module_dummy(void)
{
}
void DSO_STAMP_FUN(void)
{
}

View file

@ -84,46 +84,17 @@ void os_setup_signal_handling(void)
running from the build tree this will be "$bindir/../pc-bios". */
#define SHARE_SUFFIX "/share/qemu"
#define BUILD_SUFFIX "/pc-bios"
char *os_find_datadir(const char *argv0)
char *os_find_datadir(void)
{
char *dir;
char *p = NULL;
char *dir, *exec_dir;
char *res;
char buf[PATH_MAX];
size_t max_len;
#if defined(__linux__)
{
int len;
len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
if (len > 0) {
buf[len] = 0;
p = buf;
}
exec_dir = qemu_get_exec_dir();
if (exec_dir == NULL) {
return NULL;
}
#elif defined(__FreeBSD__)
{
static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t len = sizeof(buf) - 1;
*buf = '\0';
if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
*buf) {
buf[sizeof(buf) - 1] = '\0';
p = buf;
}
}
#endif
/* If we don't have any way of figuring out the actual executable
location then try argv[0]. */
if (!p) {
p = realpath(argv0, buf);
if (!p) {
return NULL;
}
}
dir = dirname(p);
dir = dirname(dir);
dir = dirname(exec_dir);
max_len = strlen(dir) +
MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
@ -137,6 +108,7 @@ char *os_find_datadir(const char *argv0)
}
}
g_free(exec_dir);
return res;
}
#undef SHARE_SUFFIX

View file

@ -84,26 +84,9 @@ void os_setup_early_signal_handling(void)
}
/* Look for support files in the same directory as the executable. */
char *os_find_datadir(const char *argv0)
char *os_find_datadir(void)
{
char *p;
char buf[MAX_PATH];
DWORD len;
len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
if (len == 0) {
return NULL;
}
buf[len] = 0;
p = buf + len - 1;
while (p != buf && *p != '\\')
p--;
*p = 0;
if (access(buf, R_OK) == 0) {
return g_strdup(buf);
}
return NULL;
return qemu_get_exec_dir();
}
void os_set_line_buffering(void)

View file

@ -2719,6 +2719,7 @@ int main(int argc, char **argv)
#endif
error_set_progname(argv[0]);
qemu_init_exec_dir(argv[0]);
qemu_init_main_loop();
bdrv_init();

View file

@ -381,6 +381,7 @@ int main(int argc, char **argv)
#endif
progname = basename(argv[0]);
qemu_init_exec_dir(argv[0]);
while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
switch (c) {

View file

@ -376,6 +376,7 @@ int main(int argc, char **argv)
memset(&sa_sigterm, 0, sizeof(sa_sigterm));
sa_sigterm.sa_handler = termsig_handler;
sigaction(SIGTERM, &sa_sigterm, NULL);
qemu_init_exec_dir(argv[0]);
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch (ch) {

View file

@ -22,8 +22,15 @@ QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
# Same as -I$(SRC_PATH) -I., but for the nested source/object directories
QEMU_INCLUDES += -I$(<D) -I$(@D)
maybe-add = $(filter-out $1, $2) $1
extract-libs = $(strip $(sort $(foreach o,$1,$($o-libs)) \
$(foreach o,$(call expand-objs,$1),$($o-libs))))
expand-objs = $(strip $(sort $(filter %.o,$1)) \
$(foreach o,$(filter %.mo,$1),$($o-objs)) \
$(filter-out %.o %.mo,$1))
%.o: %.c
$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CC $(TARGET_DIR)$@")
%.o: %.rc
$(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
@ -33,8 +40,8 @@ LINKPROG = $(or $(CXX),$(CC))
ifeq ($(LIBTOOL),)
LINK = $(call quiet-command,$(LINKPROG) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
$(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
$(LIBS)," LINK $(TARGET_DIR)$@")
$(call expand-objs,$1) $(version-obj-y) \
$(call extract-libs,$1) $(LIBS)," LINK $(TARGET_DIR)$@")
else
LIBTOOL += $(if $(V),,--quiet)
%.lo: %.c
@ -45,12 +52,12 @@ LIBTOOL += $(if $(V),,--quiet)
$(call quiet-command,$(LIBTOOL) --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN $(TARGET_DIR)$@")
LINK = $(call quiet-command,\
$(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
$(if $(filter %.lo %.la,$1),$(LIBTOOL) --mode=link --tag=CC \
)$(LINKPROG) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
$(sort $(filter %.o, $1)) $(filter-out %.o, $1) \
$(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \
$(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
$(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
$(call expand-objs,$1) \
$(if $(filter %.lo %.la,$1),$(version-lobj-y),$(version-obj-y)) \
$(if $(filter %.lo %.la,$1),$(LIBTOOLFLAGS)) \
$(call extract-libs,$1) $(LIBS),$(if $(filter %.lo %.la,$1),"lt LINK ", " LINK ")"$(TARGET_DIR)$@")
endif
%.asm: %.S
@ -71,6 +78,16 @@ endif
%.o: %.dtrace
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN $(TARGET_DIR)$@")
DSO_CFLAGS := -fPIC -DBUILD_DSO
%$(DSOSUF): LDFLAGS += $(LDFLAGS_SHARED)
%$(DSOSUF): %.mo libqemustub.a
$(call LINK,$^)
@# Copy to build root so modules can be loaded when program started without install
$(if $(findstring /,$@),$(call quiet-command,cp $@ $(subst /,-,$@), " CP $(subst /,-,$@)"))
.PHONY: modules
modules:
%$(EXESUF): %.o
$(call LINK,$^)
@ -146,9 +163,6 @@ clean: clean-timestamp
# magic to descend into other directories
obj := .
old-nested-dirs :=
define push-var
$(eval save-$2-$1 = $(value $1))
$(eval $1 :=)
@ -160,11 +174,27 @@ $(eval $1 = $(value save-$2-$1) $$(subdir-$2-$1))
$(eval save-$2-$1 :=)
endef
define fix-obj-vars
$(foreach v,$($1), \
$(if $($v-cflags), \
$(eval $2$v-cflags := $($v-cflags)) \
$(eval $v-cflags := )) \
$(if $($v-libs), \
$(eval $2$v-libs := $($v-libs)) \
$(eval $v-libs := )) \
$(if $($v-objs), \
$(eval $2$v-objs := $(addprefix $2,$($v-objs))) \
$(eval $v-objs := )))
endef
define unnest-dir
$(foreach var,$(nested-vars),$(call push-var,$(var),$1/))
$(eval obj := $(obj)/$1)
$(eval obj-parent-$1 := $(obj))
$(eval obj := $(if $(obj),$(obj)/$1,$1))
$(eval include $(SRC_PATH)/$1/Makefile.objs)
$(eval obj := $(patsubst %/$1,%,$(obj)))
$(foreach v,$(nested-vars),$(call fix-obj-vars,$v,$(if $(obj),$(obj)/)))
$(eval obj := $(obj-parent-$1))
$(eval obj-parent-$1 := )
$(foreach var,$(nested-vars),$(call pop-var,$(var),$1/))
endef
@ -178,10 +208,34 @@ $(if $(nested-dirs),
$(call unnest-vars-1))
endef
define process-modules
$(foreach o,$(filter %.o,$($1)),
$(eval $(patsubst %.o,%.mo,$o): $o) \
$(eval $(patsubst %.o,%.mo,$o)-objs := $o))
$(foreach o,$(filter-out $(modules-m), $(patsubst %.o,%.mo,$($1))), \
$(eval $o-objs += module-common.o)
$(eval $o: $($o-objs))
$(eval modules-objs-m += $($o-objs))
$(eval modules-m += $o)
$(eval $o:; $$(call quiet-command,touch $$@," GEN $$(TARGET_DIR)$$@"))
$(if $(CONFIG_MODULES),$(eval modules: $(patsubst %.mo,%$(DSOSUF),$o)))) \
$(eval modules-objs-m := $(sort $(modules-objs-m)))
$(foreach o,$(modules-objs-m), \
$(if $(CONFIG_MODULES),$(eval $o-cflags := $(call maybe-add, $(DSO_CFLAGS), $($o-cflags)))))
$(eval $(patsubst %-m,%-$(call lnot,$(CONFIG_MODULES)),$1) += $($1))
endef
define unnest-vars
$(eval obj := $1)
$(eval nested-vars := $2)
$(eval old-nested-dirs := )
$(call unnest-vars-1)
$(if $1,$(foreach v,$(nested-vars),$(eval \
$v := $(addprefix $1/,$($v)))))
$(foreach var,$(nested-vars),$(eval $(var) := $(filter-out %/, $($(var)))))
$(shell mkdir -p $(sort $(foreach var,$(nested-vars),$(dir $($(var))))))
$(foreach var,$(nested-vars), $(eval \
-include $(addsuffix *.d, $(sort $(dir $($(var)))))))
$(foreach v,$(filter %-m,$(nested-vars)), \
$(call process-modules,$v))
endef

View file

@ -108,6 +108,9 @@ case $line in
value=${line#*=}
echo "#define $name $value"
;;
DSOSUF=*)
echo "#define HOST_DSOSUF \"${line#*=}\""
;;
esac
done # read

View file

@ -13,6 +13,8 @@
* GNU GPL, version 2 or (at your option) any later version.
*/
#include <stdlib.h>
#include <gmodule.h>
#include "qemu-common.h"
#include "qemu/queue.h"
#include "qemu/module.h"
@ -21,13 +23,16 @@ typedef struct ModuleEntry
{
void (*init)(void);
QTAILQ_ENTRY(ModuleEntry) node;
module_init_type type;
} ModuleEntry;
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
static void init_types(void)
static ModuleTypeList dso_init_list;
static void init_lists(void)
{
static int inited;
int i;
@ -40,6 +45,8 @@ static void init_types(void)
QTAILQ_INIT(&init_type_list[i]);
}
QTAILQ_INIT(&dso_init_list);
inited = 1;
}
@ -48,7 +55,7 @@ static ModuleTypeList *find_type(module_init_type type)
{
ModuleTypeList *l;
init_types();
init_lists();
l = &init_type_list[type];
@ -62,20 +69,154 @@ void register_module_init(void (*fn)(void), module_init_type type)
e = g_malloc0(sizeof(*e));
e->init = fn;
e->type = type;
l = find_type(type);
QTAILQ_INSERT_TAIL(l, e, node);
}
void register_dso_module_init(void (*fn)(void), module_init_type type)
{
ModuleEntry *e;
init_lists();
e = g_malloc0(sizeof(*e));
e->init = fn;
e->type = type;
QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
}
static void module_load(module_init_type type);
void module_call_init(module_init_type type)
{
ModuleTypeList *l;
ModuleEntry *e;
module_load(type);
l = find_type(type);
QTAILQ_FOREACH(e, l, node) {
e->init();
}
}
#ifdef CONFIG_MODULES
static int module_load_file(const char *fname)
{
GModule *g_module;
void (*sym)(void);
const char *dsosuf = HOST_DSOSUF;
int len = strlen(fname);
int suf_len = strlen(dsosuf);
ModuleEntry *e, *next;
int ret;
if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) {
/* wrong suffix */
ret = -EINVAL;
goto out;
}
if (access(fname, F_OK)) {
ret = -ENOENT;
goto out;
}
assert(QTAILQ_EMPTY(&dso_init_list));
g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
if (!g_module) {
fprintf(stderr, "Failed to open module: %s\n",
g_module_error());
ret = -EINVAL;
goto out;
}
if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
fprintf(stderr, "Failed to initialize module: %s\n",
fname);
/* Print some info if this is a QEMU module (but from different build),
* this will make debugging user problems easier. */
if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
fprintf(stderr,
"Note: only modules from the same build can be loaded.\n");
}
g_module_close(g_module);
ret = -EINVAL;
} else {
QTAILQ_FOREACH(e, &dso_init_list, node) {
register_module_init(e->init, e->type);
}
ret = 0;
}
QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
QTAILQ_REMOVE(&dso_init_list, e, node);
g_free(e);
}
out:
return ret;
}
#endif
void module_load(module_init_type type)
{
#ifdef CONFIG_MODULES
char *fname = NULL;
const char **mp;
static const char *block_modules[] = {
CONFIG_BLOCK_MODULES
};
char *exec_dir;
char *dirs[3];
int i = 0;
int ret;
if (!g_module_supported()) {
fprintf(stderr, "Module is not supported by system.\n");
return;
}
switch (type) {
case MODULE_INIT_BLOCK:
mp = block_modules;
break;
default:
/* no other types have dynamic modules for now*/
return;
}
exec_dir = qemu_get_exec_dir();
dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
dirs[i++] = g_strdup_printf("%s", exec_dir ? : "");
assert(i == ARRAY_SIZE(dirs));
g_free(exec_dir);
exec_dir = NULL;
for ( ; *mp; mp++) {
for (i = 0; i < ARRAY_SIZE(dirs); i++) {
fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF);
ret = module_load_file(fname);
/* Try loading until loaded a module file */
if (!ret) {
break;
}
g_free(fname);
fname = NULL;
}
if (ret == -ENOENT) {
fprintf(stderr, "Can't find module: %s\n", *mp);
}
g_free(fname);
}
for (i = 0; i < ARRAY_SIZE(dirs); i++) {
g_free(dirs[i]);
}
#endif
}

View file

@ -57,6 +57,7 @@ extern int daemon(int, int);
#include "trace.h"
#include "qemu/sockets.h"
#include <sys/mman.h>
#include <libgen.h>
#ifdef CONFIG_LINUX
#include <sys/syscall.h>
@ -274,3 +275,56 @@ void qemu_set_tty_echo(int fd, bool echo)
tcsetattr(fd, TCSANOW, &tty);
}
static char exec_dir[PATH_MAX];
void qemu_init_exec_dir(const char *argv0)
{
char *dir;
char *p = NULL;
char buf[PATH_MAX];
assert(!exec_dir[0]);
#if defined(__linux__)
{
int len;
len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
if (len > 0) {
buf[len] = 0;
p = buf;
}
}
#elif defined(__FreeBSD__)
{
static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
size_t len = sizeof(buf) - 1;
*buf = '\0';
if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
*buf) {
buf[sizeof(buf) - 1] = '\0';
p = buf;
}
}
#endif
/* If we don't have any way of figuring out the actual executable
location then try argv[0]. */
if (!p) {
if (!argv0) {
return;
}
p = realpath(argv0, buf);
if (!p) {
return;
}
}
dir = dirname(p);
pstrcpy(exec_dir, sizeof(exec_dir), dir);
}
char *qemu_get_exec_dir(void)
{
return g_strdup(exec_dir);
}

View file

@ -208,3 +208,33 @@ void qemu_set_tty_echo(int fd, bool echo)
dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
}
}
static char exec_dir[PATH_MAX];
void qemu_init_exec_dir(const char *argv0)
{
char *p;
char buf[MAX_PATH];
DWORD len;
len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
if (len == 0) {
return;
}
buf[len] = 0;
p = buf + len - 1;
while (p != buf && *p != '\\') {
p--;
}
*p = 0;
if (access(buf, R_OK) == 0) {
pstrcpy(exec_dir, sizeof(exec_dir), buf);
}
}
char *qemu_get_exec_dir(void)
{
return g_strdup(exec_dir);
}

3
vl.c
View file

@ -2827,6 +2827,7 @@ int main(int argc, char **argv, char **envp)
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
qemu_init_exec_dir(argv[0]);
g_mem_set_vtable(&mem_trace);
if (!g_thread_supported()) {
@ -3865,7 +3866,7 @@ int main(int argc, char **argv, char **envp)
/* If no data_dir is specified then try to find it relative to the
executable path. */
if (data_dir_idx < ARRAY_SIZE(data_dir)) {
data_dir[data_dir_idx] = os_find_datadir(argv[0]);
data_dir[data_dir_idx] = os_find_datadir();
if (data_dir[data_dir_idx] != NULL) {
data_dir_idx++;
}