Revision e26110cf

b/Makefile
201 201
libqemustub.a: $(stub-obj-y)
202 202
libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o
203 203

  
204
block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
205
util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
206

  
204 207
######################################################################
205 208

  
206 209
qemu-img.o: qemu-img-cmds.h
b/configure
1137 1137
  --libdir=PATH            install libraries in PATH
1138 1138
  --sysconfdir=PATH        install config in PATH$confsuffix
1139 1139
  --localstatedir=PATH     install local state in PATH (set at runtime on win32)
1140
  --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]
1140
  --with-confsuffix=SUFFIX suffix for QEMU data inside datadir/libdir/sysconfdir [$confsuffix]
1141 1141
  --enable-modules         enable modules support
1142 1142
  --enable-debug-tcg       enable TCG debugging
1143 1143
  --disable-debug-tcg      disable TCG debugging (default)
......
2362 2362
else
2363 2363
    glib_req_ver=2.12
2364 2364
fi
2365
if $pkg_config --atleast-version=$glib_req_ver gthread-2.0; then
2366
    glib_cflags=`$pkg_config --cflags gthread-2.0`
2367
    glib_libs=`$pkg_config --libs gthread-2.0`
2368
    CFLAGS="$glib_cflags $CFLAGS"
2369
    LIBS="$glib_libs $LIBS"
2370
    libs_qga="$glib_libs $libs_qga"
2371
else
2372
    error_exit "glib-$glib_req_ver required to compile QEMU"
2365

  
2366
for i in gthread-2.0 gmodule-2.0; do
2367
    if $pkg_config --atleast-version=$glib_req_ver $i; then
2368
        glib_cflags=`$pkg_config --cflags $i`
2369
        glib_libs=`$pkg_config --libs $i`
2370
        CFLAGS="$glib_cflags $CFLAGS"
2371
        LIBS="$glib_libs $LIBS"
2372
        libs_qga="$glib_libs $libs_qga"
2373
    else
2374
        error_exit "glib-$glib_req_ver $i is required to compile QEMU"
2375
    fi
2376
done
2377

  
2378
##########################################
2379
# SHA command probe for modules
2380
if test "$modules" = yes; then
2381
    shacmd_probe="sha1sum sha1 shasum"
2382
    for c in $shacmd_probe; do
2383
        if which $c &>/dev/null; then
2384
            shacmd="$c"
2385
            break
2386
        fi
2387
    done
2388
    if test "$shacmd" = ""; then
2389
        error_exit "one of the checksum commands is required to enable modules: $shacmd_probe"
2390
    fi
2373 2391
fi
2374 2392

  
2375 2393
##########################################
......
3661 3679
fi
3662 3680

  
3663 3681
qemu_confdir=$sysconfdir$confsuffix
3682
qemu_moddir=$libdir$confsuffix
3664 3683
qemu_datadir=$datadir$confsuffix
3665 3684
qemu_localedir="$datadir/locale"
3666 3685

  
......
3751 3770
echo "BIOS directory    `eval echo $qemu_datadir`"
3752 3771
echo "binary directory  `eval echo $bindir`"
3753 3772
echo "library directory `eval echo $libdir`"
3773
echo "module directory  `eval echo $qemu_moddir`"
3754 3774
echo "libexec directory `eval echo $libexecdir`"
3755 3775
echo "include directory `eval echo $includedir`"
3756 3776
echo "config directory  `eval echo $sysconfdir`"
......
3890 3910
echo "qemu_confdir=$qemu_confdir" >> $config_host_mak
3891 3911
echo "qemu_datadir=$qemu_datadir" >> $config_host_mak
3892 3912
echo "qemu_docdir=$qemu_docdir" >> $config_host_mak
3913
echo "qemu_moddir=$qemu_moddir" >> $config_host_mak
3893 3914
if test "$mingw32" = "no" ; then
3894 3915
  echo "qemu_localstatedir=$local_statedir" >> $config_host_mak
3895 3916
fi
......
4023 4044
  echo "BUILD_DOCS=yes" >> $config_host_mak
4024 4045
fi
4025 4046
if test "$modules" = "yes"; then
4047
  # $shacmd can generate a hash started with digit, which the compiler doesn't
4048
  # like as an symbol. So prefix it with an underscore
4049
  echo "CONFIG_STAMP=_`(echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ `" >> $config_host_mak
4026 4050
  echo "CONFIG_MODULES=y" >> $config_host_mak
4027 4051
fi
4028 4052
if test "$sdl" = "yes" ; then
b/include/qemu/module.h
14 14
#ifndef QEMU_MODULE_H
15 15
#define QEMU_MODULE_H
16 16

  
17
#include "qemu/osdep.h"
18

  
19
#define DSO_STAMP_FUN         glue(qemu_stamp, CONFIG_STAMP)
20
#define DSO_STAMP_FUN_STR     stringify(DSO_STAMP_FUN)
21

  
22
#ifdef BUILD_DSO
23
void DSO_STAMP_FUN(void);
24
/* This is a dummy symbol to identify a loaded DSO as a QEMU module, so we can
25
 * distinguish "version mismatch" from "not a QEMU module", when the stamp
26
 * check fails during module loading */
27
void qemu_module_dummy(void);
28

  
29
#define module_init(function, type)                                         \
30
static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
31
{                                                                           \
32
    register_dso_module_init(function, type);                               \
33
}
34
#else
17 35
/* This should not be used directly.  Use block_init etc. instead.  */
18 36
#define module_init(function, type)                                         \
19
static void __attribute__((constructor)) do_qemu_init_ ## function(void) {  \
37
static void __attribute__((constructor)) do_qemu_init_ ## function(void)    \
38
{                                                                           \
20 39
    register_module_init(function, type);                                   \
21 40
}
41
#endif
22 42

  
23 43
typedef enum {
24 44
    MODULE_INIT_BLOCK,
......
34 54
#define type_init(function) module_init(function, MODULE_INIT_QOM)
35 55

  
36 56
void register_module_init(void (*fn)(void), module_init_type type);
57
void register_dso_module_init(void (*fn)(void), module_init_type type);
37 58

  
38 59
void module_call_init(module_init_type type);
39 60

  
b/module-common.c
1
#include "config-host.h"
2
#include "qemu/module.h"
3

  
4
void qemu_module_dummy(void)
5
{
6
}
7

  
8
void DSO_STAMP_FUN(void)
9
{
10
}
b/rules.mak
82 82
%$(DSOSUF): LDFLAGS += $(LDFLAGS_SHARED)
83 83
%$(DSOSUF): %.mo libqemustub.a
84 84
	$(call LINK,$^)
85
	@# Copy to build root so modules can be loaded when program started without install
86
	$(if $(findstring /,$@),$(call quiet-command,cp $@ $(subst /,-,$@), "  CP    $(subst /,-,$@)"))
85 87

  
86 88
.PHONY: modules
87 89
modules:
......
211 213
	$(eval $(patsubst %.o,%.mo,$o): $o) \
212 214
	$(eval $(patsubst %.o,%.mo,$o)-objs := $o))
213 215
$(foreach o,$(filter-out $(modules-m), $(patsubst %.o,%.mo,$($1))), \
216
    $(eval $o-objs += module-common.o)
214 217
    $(eval $o: $($o-objs))
215 218
    $(eval modules-objs-m += $($o-objs))
216 219
    $(eval modules-m += $o)
b/scripts/create_config
108 108
    value=${line#*=}
109 109
    echo "#define $name $value"
110 110
    ;;
111
 DSOSUF=*)
112
    echo "#define HOST_DSOSUF \"${line#*=}\""
113
    ;;
111 114
esac
112 115

  
113 116
done # read
b/util/module.c
13 13
 * GNU GPL, version 2 or (at your option) any later version.
14 14
 */
15 15

  
16
#include <stdlib.h>
17
#include <gmodule.h>
16 18
#include "qemu-common.h"
17 19
#include "qemu/queue.h"
18 20
#include "qemu/module.h"
......
21 23
{
22 24
    void (*init)(void);
23 25
    QTAILQ_ENTRY(ModuleEntry) node;
26
    module_init_type type;
24 27
} ModuleEntry;
25 28

  
26 29
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
27 30

  
28 31
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
29 32

  
30
static void init_types(void)
33
static ModuleTypeList dso_init_list;
34

  
35
static void init_lists(void)
31 36
{
32 37
    static int inited;
33 38
    int i;
......
40 45
        QTAILQ_INIT(&init_type_list[i]);
41 46
    }
42 47

  
48
    QTAILQ_INIT(&dso_init_list);
49

  
43 50
    inited = 1;
44 51
}
45 52

  
......
48 55
{
49 56
    ModuleTypeList *l;
50 57

  
51
    init_types();
58
    init_lists();
52 59

  
53 60
    l = &init_type_list[type];
54 61

  
......
62 69

  
63 70
    e = g_malloc0(sizeof(*e));
64 71
    e->init = fn;
72
    e->type = type;
65 73

  
66 74
    l = find_type(type);
67 75

  
68 76
    QTAILQ_INSERT_TAIL(l, e, node);
69 77
}
70 78

  
79
void register_dso_module_init(void (*fn)(void), module_init_type type)
80
{
81
    ModuleEntry *e;
82

  
83
    init_lists();
84

  
85
    e = g_malloc0(sizeof(*e));
86
    e->init = fn;
87
    e->type = type;
88

  
89
    QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
90
}
91

  
92
static void module_load(module_init_type type);
93

  
71 94
void module_call_init(module_init_type type)
72 95
{
73 96
    ModuleTypeList *l;
74 97
    ModuleEntry *e;
75 98

  
99
    module_load(type);
76 100
    l = find_type(type);
77 101

  
78 102
    QTAILQ_FOREACH(e, l, node) {
79 103
        e->init();
80 104
    }
81 105
}
106

  
107
#ifdef CONFIG_MODULES
108
static int module_load_file(const char *fname)
109
{
110
    GModule *g_module;
111
    void (*sym)(void);
112
    const char *dsosuf = HOST_DSOSUF;
113
    int len = strlen(fname);
114
    int suf_len = strlen(dsosuf);
115
    ModuleEntry *e, *next;
116
    int ret;
117

  
118
    if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) {
119
        /* wrong suffix */
120
        ret = -EINVAL;
121
        goto out;
122
    }
123
    if (access(fname, F_OK)) {
124
        ret = -ENOENT;
125
        goto out;
126
    }
127

  
128
    assert(QTAILQ_EMPTY(&dso_init_list));
129

  
130
    g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
131
    if (!g_module) {
132
        fprintf(stderr, "Failed to open module: %s\n",
133
                g_module_error());
134
        ret = -EINVAL;
135
        goto out;
136
    }
137
    if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
138
        fprintf(stderr, "Failed to initialize module: %s\n",
139
                fname);
140
        /* Print some info if this is a QEMU module (but from different build),
141
         * this will make debugging user problems easier. */
142
        if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
143
            fprintf(stderr,
144
                    "Note: only modules from the same build can be loaded.\n");
145
        }
146
        g_module_close(g_module);
147
        ret = -EINVAL;
148
    } else {
149
        QTAILQ_FOREACH(e, &dso_init_list, node) {
150
            register_module_init(e->init, e->type);
151
        }
152
        ret = 0;
153
    }
154

  
155
    QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
156
        QTAILQ_REMOVE(&dso_init_list, e, node);
157
        g_free(e);
158
    }
159
out:
160
    return ret;
161
}
162
#endif
163

  
164
void module_load(module_init_type type)
165
{
166
#ifdef CONFIG_MODULES
167
    char *fname = NULL;
168
    const char **mp;
169
    static const char *block_modules[] = {
170
        CONFIG_BLOCK_MODULES
171
    };
172
    char *exec_dir;
173
    char *dirs[3];
174
    int i = 0;
175
    int ret;
176

  
177
    if (!g_module_supported()) {
178
        fprintf(stderr, "Module is not supported by system.\n");
179
        return;
180
    }
181

  
182
    switch (type) {
183
    case MODULE_INIT_BLOCK:
184
        mp = block_modules;
185
        break;
186
    default:
187
        /* no other types have dynamic modules for now*/
188
        return;
189
    }
190

  
191
    exec_dir = qemu_get_exec_dir();
192
    dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
193
    dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
194
    dirs[i++] = g_strdup_printf("%s", exec_dir ? : "");
195
    assert(i == ARRAY_SIZE(dirs));
196
    g_free(exec_dir);
197
    exec_dir = NULL;
198

  
199
    for ( ; *mp; mp++) {
200
        for (i = 0; i < ARRAY_SIZE(dirs); i++) {
201
            fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF);
202
            ret = module_load_file(fname);
203
            /* Try loading until loaded a module file */
204
            if (!ret) {
205
                break;
206
            }
207
            g_free(fname);
208
            fname = NULL;
209
        }
210
        if (ret == -ENOENT) {
211
            fprintf(stderr, "Can't find module: %s\n", *mp);
212
        }
213

  
214
        g_free(fname);
215
    }
216

  
217
    for (i = 0; i < ARRAY_SIZE(dirs); i++) {
218
        g_free(dirs[i]);
219
    }
220

  
221
#endif
222
}

Also available in: Unified diff