modules: dependencies infrastructure

Allow modules depending on other modules.

module_load_file() gets the option to export symbols (by not adding the
G_MODULE_BIND_LOCAL flag).

module_load_one() will check the module dependency list to figure (a)
whenever are other modules must be loaded first, or (b) the module
should export the symbols.

The dependencies are specificed as static list in the source code for
now as I expect the list will stay small.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 20201019075224.14803-11-kraxel@redhat.com
This commit is contained in:
Gerd Hoffmann 2020-10-19 09:52:20 +02:00
parent 9ed345a14e
commit 6f13fa7a98
1 changed files with 27 additions and 5 deletions

View File

@ -110,7 +110,7 @@ void module_call_init(module_init_type type)
}
#ifdef CONFIG_MODULES
static int module_load_file(const char *fname, bool mayfail)
static int module_load_file(const char *fname, bool mayfail, bool export_symbols)
{
GModule *g_module;
void (*sym)(void);
@ -118,7 +118,7 @@ static int module_load_file(const char *fname, bool mayfail)
int len = strlen(fname);
int suf_len = strlen(dsosuf);
ModuleEntry *e, *next;
int ret;
int ret, flags;
if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) {
/* wrong suffix */
@ -132,7 +132,11 @@ static int module_load_file(const char *fname, bool mayfail)
assert(QTAILQ_EMPTY(&dso_init_list));
g_module = g_module_open(fname, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
flags = G_MODULE_BIND_LAZY;
if (!export_symbols) {
flags |= G_MODULE_BIND_LOCAL;
}
g_module = g_module_open(fname, flags);
if (!g_module) {
if (!mayfail) {
fprintf(stderr, "Failed to open module: %s\n",
@ -167,6 +171,12 @@ static int module_load_file(const char *fname, bool mayfail)
out:
return ret;
}
static const struct {
const char *name;
const char *dep;
} module_deps[] = {
};
#endif
bool module_load_one(const char *prefix, const char *lib_name, bool mayfail)
@ -182,7 +192,8 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail)
char *dirs[5];
char *module_name;
int i = 0, n_dirs = 0;
int ret;
int ret, dep;
bool export_symbols = false;
static GHashTable *loaded_modules;
if (!g_module_supported()) {
@ -196,6 +207,17 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail)
module_name = g_strdup_printf("%s%s", prefix, lib_name);
for (dep = 0; dep < ARRAY_SIZE(module_deps); dep++) {
if (strcmp(module_name, module_deps[dep].name) == 0) {
/* we depend on another module */
module_load_one("", module_deps[dep].dep, false);
}
if (strcmp(module_name, module_deps[dep].dep) == 0) {
/* another module depends on us */
export_symbols = true;
}
}
if (!g_hash_table_add(loaded_modules, module_name)) {
g_free(module_name);
return true;
@ -220,7 +242,7 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail)
for (i = 0; i < n_dirs; i++) {
fname = g_strdup_printf("%s/%s%s",
dirs[i], module_name, CONFIG_HOST_DSOSUF);
ret = module_load_file(fname, mayfail);
ret = module_load_file(fname, mayfail, export_symbols);
g_free(fname);
fname = NULL;
/* Try loading until loaded a module file */