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>
This commit is contained in:
parent
8e2adc6a00
commit
1d082773ff
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -32,6 +32,7 @@
|
||||||
*.lzo
|
*.lzo
|
||||||
*.mod
|
*.mod
|
||||||
*.mod.c
|
*.mod.c
|
||||||
|
*.ns_deps
|
||||||
*.o
|
*.o
|
||||||
*.o.*
|
*.o.*
|
||||||
*.order
|
*.order
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1669,7 +1669,7 @@ clean: $(clean-dirs)
|
||||||
-o -name '*.ko.*' \
|
-o -name '*.ko.*' \
|
||||||
-o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
|
-o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
|
||||||
-o -name '*.dwo' -o -name '*.lst' \
|
-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 '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
|
||||||
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
|
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
|
||||||
-o -name '*.asn1.[ch]' \
|
-o -name '*.asn1.[ch]' \
|
||||||
|
|
|
@ -38,6 +38,8 @@ static int sec_mismatch_count = 0;
|
||||||
static int sec_mismatch_fatal = 0;
|
static int sec_mismatch_fatal = 0;
|
||||||
/* ignore missing files */
|
/* ignore missing files */
|
||||||
static int ignore_missing_files;
|
static int ignore_missing_files;
|
||||||
|
/* write namespace dependencies */
|
||||||
|
static int write_namespace_deps;
|
||||||
|
|
||||||
enum export {
|
enum export {
|
||||||
export_plain, export_unused, export_gpl,
|
export_plain, export_unused, export_gpl,
|
||||||
|
@ -2176,10 +2178,15 @@ static int check_exports(struct module *mod)
|
||||||
else
|
else
|
||||||
basename = mod->name;
|
basename = mod->name;
|
||||||
|
|
||||||
if (exp->namespace &&
|
if (exp->namespace) {
|
||||||
!module_imports_namespace(mod, exp->namespace)) {
|
add_namespace(&mod->required_namespaces,
|
||||||
warn("module %s uses symbol %s from namespace %s, but does not import it.\n",
|
exp->namespace);
|
||||||
basename, exp->name, 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)
|
if (!mod->gpl_compatible)
|
||||||
|
@ -2484,6 +2491,31 @@ static void write_dump(const char *fname)
|
||||||
free(buf.p);
|
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 {
|
||||||
struct ext_sym_list *next;
|
struct ext_sym_list *next;
|
||||||
const char *file;
|
const char *file;
|
||||||
|
@ -2500,7 +2532,7 @@ int main(int argc, char **argv)
|
||||||
struct ext_sym_list *extsym_iter;
|
struct ext_sym_list *extsym_iter;
|
||||||
struct ext_sym_list *extsym_start = NULL;
|
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) {
|
switch (opt) {
|
||||||
case 'i':
|
case 'i':
|
||||||
kernel_read = optarg;
|
kernel_read = optarg;
|
||||||
|
@ -2541,6 +2573,9 @@ int main(int argc, char **argv)
|
||||||
case 'E':
|
case 'E':
|
||||||
sec_mismatch_fatal = 1;
|
sec_mismatch_fatal = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
write_namespace_deps = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -2575,6 +2610,9 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
err |= check_modname_len(mod);
|
err |= check_modname_len(mod);
|
||||||
err |= check_exports(mod);
|
err |= check_exports(mod);
|
||||||
|
if (write_namespace_deps)
|
||||||
|
continue;
|
||||||
|
|
||||||
add_header(&buf, mod);
|
add_header(&buf, mod);
|
||||||
add_intree_flag(&buf, !external_module);
|
add_intree_flag(&buf, !external_module);
|
||||||
add_retpoline(&buf);
|
add_retpoline(&buf);
|
||||||
|
@ -2587,6 +2625,12 @@ int main(int argc, char **argv)
|
||||||
sprintf(fname, "%s.mod.c", mod->name);
|
sprintf(fname, "%s.mod.c", mod->name);
|
||||||
write_if_changed(&buf, fname);
|
write_if_changed(&buf, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (write_namespace_deps) {
|
||||||
|
write_namespace_deps_files();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (dump_write)
|
if (dump_write)
|
||||||
write_dump(dump_write);
|
write_dump(dump_write);
|
||||||
if (sec_mismatch_count && sec_mismatch_fatal)
|
if (sec_mismatch_count && sec_mismatch_fatal)
|
||||||
|
|
|
@ -126,6 +126,8 @@ struct module {
|
||||||
struct buffer dev_table_buf;
|
struct buffer dev_table_buf;
|
||||||
char srcversion[25];
|
char srcversion[25];
|
||||||
int is_dot_o;
|
int is_dot_o;
|
||||||
|
// Required namespace dependencies
|
||||||
|
struct namespace_list *required_namespaces;
|
||||||
// Actual imported namespaces
|
// Actual imported namespaces
|
||||||
struct namespace_list *imported_namespaces;
|
struct namespace_list *imported_namespaces;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user