]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
modpost: add support for generating namespace dependencies
authorMatthias Maennich <maennich@google.com>
Fri, 6 Sep 2019 10:32:31 +0000 (11:32 +0100)
committerJessica Yu <jeyu@kernel.org>
Tue, 10 Sep 2019 08:30:38 +0000 (10:30 +0200)
This patch adds an option to modpost to generate a <module>.ns_deps file
per module, containing the namespace dependencies for that module.

E.g. if the linked module my-module.ko would depend on the symbol
myfunc.MY_NS in the namespace MY_NS, the my-module.ns_deps file created
by modpost would contain the entry MY_NS to express the namespace
dependency of my-module imposed by using the symbol myfunc.

These files can subsequently be used by static analysis tools (like
coccinelle scripts) to address issues with missing namespace imports. A
later patch of this series will introduce such a script 'nsdeps' and a
corresponding make target to automatically add missing
MODULE_IMPORT_NS() definitions to the module's sources. For that it uses
the information provided in the generated .ns_deps files.

Co-developed-by: Martijn Coenen <maco@android.com>
Signed-off-by: Martijn Coenen <maco@android.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
.gitignore
Makefile
scripts/mod/modpost.c
scripts/mod/modpost.h

index 2030c7a4d2f8c4d5d3764990c7b4a7b6855bb10b..9ee63aa2a3fbf53d0534a110f04b8e913dd92078 100644 (file)
@@ -32,6 +32,7 @@
 *.lzo
 *.mod
 *.mod.c
+*.ns_deps
 *.o
 *.o.*
 *.order
index 0cbe8717bdb30f87d01d53033a6261b428387044..0cdb957ae2c349892b774f299da243511834b668 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1669,7 +1669,7 @@ clean: $(clean-dirs)
                -o -name '*.ko.*' \
                -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
                -o -name '*.dwo' -o -name '*.lst' \
-               -o -name '*.su' -o -name '*.mod' \
+               -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \
                -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
                -o -name '*.lex.c' -o -name '*.tab.[ch]' \
                -o -name '*.asn1.[ch]' \
index c2d49afaea1c3bbc5c9752096d9079814248a6dc..be72da25fe7caa0395fbc18209aee7a3755dd4fc 100644 (file)
@@ -38,6 +38,8 @@ static int sec_mismatch_count = 0;
 static int sec_mismatch_fatal = 0;
 /* ignore missing files */
 static int ignore_missing_files;
+/* write namespace dependencies */
+static int write_namespace_deps;
 
 enum export {
        export_plain,      export_unused,     export_gpl,
@@ -2176,10 +2178,15 @@ static int check_exports(struct module *mod)
                else
                        basename = mod->name;
 
-               if (exp->namespace &&
-                   !module_imports_namespace(mod, exp->namespace)) {
-                       warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
-                            basename, exp->name, exp->namespace);
+               if (exp->namespace) {
+                       add_namespace(&mod->required_namespaces,
+                                     exp->namespace);
+
+                       if (!write_namespace_deps &&
+                           !module_imports_namespace(mod, exp->namespace)) {
+                               warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
+                                    basename, exp->name, exp->namespace);
+                       }
                }
 
                if (!mod->gpl_compatible)
@@ -2484,6 +2491,31 @@ static void write_dump(const char *fname)
        free(buf.p);
 }
 
+static void write_namespace_deps_files(void)
+{
+       struct module *mod;
+       struct namespace_list *ns;
+       struct buffer ns_deps_buf = {};
+
+       for (mod = modules; mod; mod = mod->next) {
+               char fname[PATH_MAX];
+
+               if (mod->skip)
+                       continue;
+
+               ns_deps_buf.pos = 0;
+
+               for (ns = mod->required_namespaces; ns; ns = ns->next)
+                       buf_printf(&ns_deps_buf, "%s\n", ns->namespace);
+
+               if (ns_deps_buf.pos == 0)
+                       continue;
+
+               sprintf(fname, "%s.ns_deps", mod->name);
+               write_if_changed(&ns_deps_buf, fname);
+       }
+}
+
 struct ext_sym_list {
        struct ext_sym_list *next;
        const char *file;
@@ -2500,7 +2532,7 @@ int main(int argc, char **argv)
        struct ext_sym_list *extsym_iter;
        struct ext_sym_list *extsym_start = NULL;
 
-       while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awE")) != -1) {
+       while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) {
                switch (opt) {
                case 'i':
                        kernel_read = optarg;
@@ -2541,6 +2573,9 @@ int main(int argc, char **argv)
                case 'E':
                        sec_mismatch_fatal = 1;
                        break;
+               case 'd':
+                       write_namespace_deps = 1;
+                       break;
                default:
                        exit(1);
                }
@@ -2575,6 +2610,9 @@ int main(int argc, char **argv)
 
                err |= check_modname_len(mod);
                err |= check_exports(mod);
+               if (write_namespace_deps)
+                       continue;
+
                add_header(&buf, mod);
                add_intree_flag(&buf, !external_module);
                add_retpoline(&buf);
@@ -2587,6 +2625,12 @@ int main(int argc, char **argv)
                sprintf(fname, "%s.mod.c", mod->name);
                write_if_changed(&buf, fname);
        }
+
+       if (write_namespace_deps) {
+               write_namespace_deps_files();
+               return 0;
+       }
+
        if (dump_write)
                write_dump(dump_write);
        if (sec_mismatch_count && sec_mismatch_fatal)
index 9626bf3e74247d5f22b4c76b636f3f38d97a3578..92a926d375d287c0629facef7de45cee938aa99c 100644 (file)
@@ -126,6 +126,8 @@ struct module {
        struct buffer dev_table_buf;
        char         srcversion[25];
        int is_dot_o;
+       // Required namespace dependencies
+       struct namespace_list *required_namespaces;
        // Actual imported namespaces
        struct namespace_list *imported_namespaces;
 };