[PATCH v2 07/10] modpost: add support for generating namespace dependencies

From: Matthias Maennich
Date: Tue Aug 13 2019 - 08:19:39 EST


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@xxxxxxxxxxx>
Signed-off-by: Martijn Coenen <maco@xxxxxxxxxxx>
Signed-off-by: Matthias Maennich <maennich@xxxxxxxxxx>
---
scripts/mod/modpost.c | 61 +++++++++++++++++++++++++++++++++++++++----
scripts/mod/modpost.h | 2 ++
2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 538bb24ffee3..833a7e1bcbb5 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -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)
@@ -2481,6 +2488,38 @@ 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];
+ const char *basename;
+
+ 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;
+
+ basename = strrchr(mod->name, '/');
+ if (basename)
+ basename++;
+ else
+ basename = mod->name;
+
+ sprintf(fname, ".tmp_versions/%s.ns_deps", basename);
+ write_if_changed(&ns_deps_buf, fname);
+ }
+}
+
struct ext_sym_list {
struct ext_sym_list *next;
const char *file;
@@ -2497,7 +2536,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;
@@ -2538,6 +2577,9 @@ int main(int argc, char **argv)
case 'E':
sec_mismatch_fatal = 1;
break;
+ case 'd':
+ write_namespace_deps = 1;
+ break;
default:
exit(1);
}
@@ -2572,6 +2614,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);
@@ -2584,6 +2629,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)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 9626bf3e7424..92a926d375d2 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -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;
};
--
2.23.0.rc1.153.gdeed80330f-goog