From 6f13fa7a9825e85e35927cbb51a992e158798424 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 19 Oct 2020 09:52:20 +0200
Subject: modules: dependencies infrastructure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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
---
 util/module.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/util/module.c b/util/module.c
index f0ed05f..0c0f258 100644
--- a/util/module.c
+++ b/util/module.c
@@ -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 */
-- 
cgit v1.1