Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

modpost: add support for generating namespace dependencies

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>

authored by

Matthias Maennich and committed by
Jessica Yu
1d082773 8e2adc6a

+53 -6
+1
.gitignore
··· 32 32 *.lzo 33 33 *.mod 34 34 *.mod.c 35 + *.ns_deps 35 36 *.o 36 37 *.o.* 37 38 *.order
+1 -1
Makefile
··· 1669 1669 -o -name '*.ko.*' \ 1670 1670 -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ 1671 1671 -o -name '*.dwo' -o -name '*.lst' \ 1672 - -o -name '*.su' -o -name '*.mod' \ 1672 + -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ 1673 1673 -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ 1674 1674 -o -name '*.lex.c' -o -name '*.tab.[ch]' \ 1675 1675 -o -name '*.asn1.[ch]' \
+49 -5
scripts/mod/modpost.c
··· 38 38 static int sec_mismatch_fatal = 0; 39 39 /* ignore missing files */ 40 40 static int ignore_missing_files; 41 + /* write namespace dependencies */ 42 + static int write_namespace_deps; 41 43 42 44 enum export { 43 45 export_plain, export_unused, export_gpl, ··· 2178 2176 else 2179 2177 basename = mod->name; 2180 2178 2181 - if (exp->namespace && 2182 - !module_imports_namespace(mod, exp->namespace)) { 2183 - warn("module %s uses symbol %s from namespace %s, but does not import it.\n", 2184 - basename, exp->name, exp->namespace); 2179 + if (exp->namespace) { 2180 + add_namespace(&mod->required_namespaces, 2181 + exp->namespace); 2182 + 2183 + if (!write_namespace_deps && 2184 + !module_imports_namespace(mod, exp->namespace)) { 2185 + warn("module %s uses symbol %s from namespace %s, but does not import it.\n", 2186 + basename, exp->name, exp->namespace); 2187 + } 2185 2188 } 2186 2189 2187 2190 if (!mod->gpl_compatible) ··· 2491 2484 free(buf.p); 2492 2485 } 2493 2486 2487 + static void write_namespace_deps_files(void) 2488 + { 2489 + struct module *mod; 2490 + struct namespace_list *ns; 2491 + struct buffer ns_deps_buf = {}; 2492 + 2493 + for (mod = modules; mod; mod = mod->next) { 2494 + char fname[PATH_MAX]; 2495 + 2496 + if (mod->skip) 2497 + continue; 2498 + 2499 + ns_deps_buf.pos = 0; 2500 + 2501 + for (ns = mod->required_namespaces; ns; ns = ns->next) 2502 + buf_printf(&ns_deps_buf, "%s\n", ns->namespace); 2503 + 2504 + if (ns_deps_buf.pos == 0) 2505 + continue; 2506 + 2507 + sprintf(fname, "%s.ns_deps", mod->name); 2508 + write_if_changed(&ns_deps_buf, fname); 2509 + } 2510 + } 2511 + 2494 2512 struct ext_sym_list { 2495 2513 struct ext_sym_list *next; 2496 2514 const char *file; ··· 2532 2500 struct ext_sym_list *extsym_iter; 2533 2501 struct ext_sym_list *extsym_start = NULL; 2534 2502 2535 - while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awE")) != -1) { 2503 + while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) { 2536 2504 switch (opt) { 2537 2505 case 'i': 2538 2506 kernel_read = optarg; ··· 2573 2541 case 'E': 2574 2542 sec_mismatch_fatal = 1; 2575 2543 break; 2544 + case 'd': 2545 + write_namespace_deps = 1; 2546 + break; 2576 2547 default: 2577 2548 exit(1); 2578 2549 } ··· 2610 2575 2611 2576 err |= check_modname_len(mod); 2612 2577 err |= check_exports(mod); 2578 + if (write_namespace_deps) 2579 + continue; 2580 + 2613 2581 add_header(&buf, mod); 2614 2582 add_intree_flag(&buf, !external_module); 2615 2583 add_retpoline(&buf); ··· 2625 2587 sprintf(fname, "%s.mod.c", mod->name); 2626 2588 write_if_changed(&buf, fname); 2627 2589 } 2590 + 2591 + if (write_namespace_deps) { 2592 + write_namespace_deps_files(); 2593 + return 0; 2594 + } 2595 + 2628 2596 if (dump_write) 2629 2597 write_dump(dump_write); 2630 2598 if (sec_mismatch_count && sec_mismatch_fatal)
+2
scripts/mod/modpost.h
··· 126 126 struct buffer dev_table_buf; 127 127 char srcversion[25]; 128 128 int is_dot_o; 129 + // Required namespace dependencies 130 + struct namespace_list *required_namespaces; 129 131 // Actual imported namespaces 130 132 struct namespace_list *imported_namespaces; 131 133 };