Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / util / module.c
blob32e263163c75dfa8e93ca67c739d4a501162353c
1 /*
2 * QEMU Module Infrastructure
4 * Copyright IBM, Corp. 2009
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
12 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
16 #include "qemu/osdep.h"
17 #ifdef CONFIG_MODULES
18 #include <gmodule.h>
19 #endif
20 #include "qemu/queue.h"
21 #include "qemu/module.h"
22 #include "qemu/cutils.h"
23 #include "qemu/config-file.h"
24 #include "qapi/error.h"
25 #ifdef CONFIG_MODULE_UPGRADES
26 #include "qemu-version.h"
27 #endif
28 #include "trace.h"
30 typedef struct ModuleEntry
32 void (*init)(void);
33 QTAILQ_ENTRY(ModuleEntry) node;
34 module_init_type type;
35 } ModuleEntry;
37 typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
39 static ModuleTypeList init_type_list[MODULE_INIT_MAX];
40 static bool modules_init_done[MODULE_INIT_MAX];
42 static ModuleTypeList dso_init_list;
44 static void init_lists(void)
46 static int inited;
47 int i;
49 if (inited) {
50 return;
53 for (i = 0; i < MODULE_INIT_MAX; i++) {
54 QTAILQ_INIT(&init_type_list[i]);
57 QTAILQ_INIT(&dso_init_list);
59 inited = 1;
63 static ModuleTypeList *find_type(module_init_type type)
65 init_lists();
67 return &init_type_list[type];
70 void register_module_init(void (*fn)(void), module_init_type type)
72 ModuleEntry *e;
73 ModuleTypeList *l;
75 e = g_malloc0(sizeof(*e));
76 e->init = fn;
77 e->type = type;
79 l = find_type(type);
81 QTAILQ_INSERT_TAIL(l, e, node);
84 void register_dso_module_init(void (*fn)(void), module_init_type type)
86 ModuleEntry *e;
88 init_lists();
90 e = g_malloc0(sizeof(*e));
91 e->init = fn;
92 e->type = type;
94 QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
97 void module_call_init(module_init_type type)
99 ModuleTypeList *l;
100 ModuleEntry *e;
102 if (modules_init_done[type]) {
103 return;
106 l = find_type(type);
108 QTAILQ_FOREACH(e, l, node) {
109 e->init();
112 modules_init_done[type] = true;
115 #ifdef CONFIG_MODULES
117 static const QemuModinfo module_info_stub[] = { {
118 /* end of list */
119 } };
120 static const QemuModinfo *module_info = module_info_stub;
121 static const char *module_arch;
123 void module_init_info(const QemuModinfo *info)
125 module_info = info;
128 void module_allow_arch(const char *arch)
130 module_arch = arch;
133 static bool module_check_arch(const QemuModinfo *modinfo)
135 if (modinfo->arch) {
136 if (!module_arch) {
137 /* no arch set -> ignore all */
138 return false;
140 if (strcmp(module_arch, modinfo->arch) != 0) {
141 /* mismatch */
142 return false;
145 return true;
149 * module_load_dso: attempt to load an existing dso file
151 * fname: full pathname of the file to load
152 * export_symbols: if true, add the symbols to the global name space
153 * errp: error to set.
155 * Return value: true on success, false on error, and errp will be set.
157 static bool module_load_dso(const char *fname, bool export_symbols,
158 Error **errp)
160 GModule *g_module;
161 void (*sym)(void);
162 ModuleEntry *e, *next;
163 int flags;
165 assert(QTAILQ_EMPTY(&dso_init_list));
167 flags = 0;
168 if (!export_symbols) {
169 flags |= G_MODULE_BIND_LOCAL;
171 g_module = g_module_open(fname, flags);
172 if (!g_module) {
173 error_setg(errp, "failed to open module: %s", g_module_error());
174 return false;
176 if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
177 error_setg(errp, "failed to initialize module: %s", fname);
179 * Print some info if this is a QEMU module (but from different build),
180 * this will make debugging user problems easier.
182 if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
183 error_append_hint(errp,
184 "Only modules from the same build can be loaded.\n");
186 g_module_close(g_module);
187 return false;
190 QTAILQ_FOREACH(e, &dso_init_list, node) {
191 e->init();
192 register_module_init(e->init, e->type);
194 trace_module_load_module(fname);
195 QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
196 QTAILQ_REMOVE(&dso_init_list, e, node);
197 g_free(e);
199 return true;
202 int module_load(const char *prefix, const char *name, Error **errp)
204 int rv = -1;
205 #ifdef CONFIG_MODULE_UPGRADES
206 char *version_dir;
207 #endif
208 const char *search_dir;
209 char *dirs[5];
210 char *module_name;
211 int i = 0, n_dirs = 0;
212 bool export_symbols = false;
213 static GHashTable *loaded_modules;
214 const QemuModinfo *modinfo;
215 const char **sl;
217 if (!g_module_supported()) {
218 error_setg(errp, "%s", "this platform does not support GLib modules");
219 return -1;
222 if (!loaded_modules) {
223 loaded_modules = g_hash_table_new(g_str_hash, g_str_equal);
226 /* allocate all resources managed by the out: label here */
227 module_name = g_strdup_printf("%s%s", prefix, name);
229 if (g_hash_table_contains(loaded_modules, module_name)) {
230 g_free(module_name);
231 return 2; /* module already loaded */
233 g_hash_table_add(loaded_modules, module_name);
235 search_dir = getenv("QEMU_MODULE_DIR");
236 if (search_dir != NULL) {
237 dirs[n_dirs++] = g_strdup_printf("%s", search_dir);
239 dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR);
241 #ifdef CONFIG_MODULE_UPGRADES
242 version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION),
243 G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~",
244 '_');
245 dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir);
246 #endif
247 assert(n_dirs <= ARRAY_SIZE(dirs));
249 /* end of resources managed by the out: label */
251 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
252 if (modinfo->arch) {
253 if (strcmp(modinfo->name, module_name) == 0) {
254 if (!module_check_arch(modinfo)) {
255 error_setg(errp, "module arch does not match: "
256 "expected '%s', got '%s'", module_arch, modinfo->arch);
257 goto out;
261 if (modinfo->deps) {
262 if (strcmp(modinfo->name, module_name) == 0) {
263 /* we depend on other module(s) */
264 for (sl = modinfo->deps; *sl != NULL; sl++) {
265 int subrv = module_load("", *sl, errp);
266 if (subrv <= 0) {
267 rv = subrv;
268 goto out;
271 } else {
272 for (sl = modinfo->deps; *sl != NULL; sl++) {
273 if (strcmp(module_name, *sl) == 0) {
274 /* another module depends on us */
275 export_symbols = true;
282 for (i = 0; i < n_dirs; i++) {
283 char *fname = g_strdup_printf("%s/%s%s",
284 dirs[i], module_name, CONFIG_HOST_DSOSUF);
285 int ret = access(fname, F_OK);
286 if (ret != 0 && (errno == ENOENT || errno == ENOTDIR)) {
288 * if we don't find the module in this dir, try the next one.
289 * If we don't find it in any dir, that can be fine too: user
290 * did not install the module. We will return 0 in this case
291 * with no error set.
293 g_free(fname);
294 continue;
295 } else if (ret != 0) {
296 /* most common is EACCES here */
297 error_setg_errno(errp, errno, "error trying to access %s", fname);
298 } else if (module_load_dso(fname, export_symbols, errp)) {
299 rv = 1; /* module successfully loaded */
301 g_free(fname);
302 goto out;
304 rv = 0; /* module not found */
306 out:
307 if (rv <= 0) {
308 g_hash_table_remove(loaded_modules, module_name);
309 g_free(module_name);
311 for (i = 0; i < n_dirs; i++) {
312 g_free(dirs[i]);
314 return rv;
317 static bool module_loaded_qom_all;
319 int module_load_qom(const char *type, Error **errp)
321 const QemuModinfo *modinfo;
322 const char **sl;
323 int rv = 0;
325 if (!type) {
326 error_setg(errp, "%s", "type is NULL");
327 return -1;
330 trace_module_lookup_object_type(type);
331 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
332 if (!modinfo->objs) {
333 continue;
335 if (!module_check_arch(modinfo)) {
336 continue;
338 for (sl = modinfo->objs; *sl != NULL; sl++) {
339 if (strcmp(type, *sl) == 0) {
340 if (rv > 0) {
341 error_setg(errp, "multiple modules providing '%s'", type);
342 return -1;
344 rv = module_load("", modinfo->name, errp);
345 if (rv < 0) {
346 return rv;
351 return rv;
354 void module_load_qom_all(void)
356 const QemuModinfo *modinfo;
357 Error *local_err = NULL;
359 if (module_loaded_qom_all) {
360 return;
363 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
364 if (!modinfo->objs) {
365 continue;
367 if (!module_check_arch(modinfo)) {
368 continue;
370 if (module_load("", modinfo->name, &local_err) < 0) {
371 error_report_err(local_err);
374 module_loaded_qom_all = true;
377 void qemu_load_module_for_opts(const char *group)
379 const QemuModinfo *modinfo;
380 const char **sl;
382 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
383 if (!modinfo->opts) {
384 continue;
386 for (sl = modinfo->opts; *sl != NULL; sl++) {
387 if (strcmp(group, *sl) == 0) {
388 Error *local_err = NULL;
389 if (module_load("", modinfo->name, &local_err) < 0) {
390 error_report_err(local_err);
397 #else
399 void module_allow_arch(const char *arch) {}
400 void qemu_load_module_for_opts(const char *group) {}
401 int module_load(const char *prefix, const char *name, Error **errp) { return 2; }
402 int module_load_qom(const char *type, Error **errp) { return 2; }
403 void module_load_qom_all(void) {}
405 #endif