include/asm-generic/vmlinux.lds.h | 2 +- include/crypto/algapi.h | 4 +- include/linux/module.h | 3 -- include/linux/moduleparam.h | 9 ++-- include/net/tcp.h | 4 +- scripts/Makefile.vmlinux | 73 +++++++++++++++++++++---------- scripts/Makefile.vmlinux_o | 26 +---------- scripts/mksysmap | 3 ++ 8 files changed, 63 insertions(+), 61 deletions(-)
Currently, modules.builtin.modinfo is generated from vmlinux.o, which occurs before modpost. So, we cannot include modpost-processed data into modules.builtin.modinfo. This patch set allows to generate modules.builtin.modinfo from vmlinux.unstripped. I think this patch set will be useful to clean up this: https://lore.kernel.org/linux-kbuild/cover.1748335606.git.legion@kernel.org/T/#m98813857abf2101bdf67f1b8529a44f5c7f4746d The original approach generates modules.builtin.modinfo from two files and then cancatenates them into a single file. I prefer generating modules.builtin.modinfo from a single point. I think 1/4 is a good cleanup regardless of modules.builtin.modinfo Masahiro Yamada (4): module: remove meaningless 'name' parameter from __MODULE_INFO() kbuild: always create intermediate vmlinux.unstripped kbuild: keep .modinfo section in vmlinux.unstripped kbuild: extract modules.builtin.modinfo from vmlinux.unstripped include/asm-generic/vmlinux.lds.h | 2 +- include/crypto/algapi.h | 4 +- include/linux/module.h | 3 -- include/linux/moduleparam.h | 9 ++-- include/net/tcp.h | 4 +- scripts/Makefile.vmlinux | 73 +++++++++++++++++++++---------- scripts/Makefile.vmlinux_o | 26 +---------- scripts/mksysmap | 3 ++ 8 files changed, 63 insertions(+), 61 deletions(-) -- 2.43.0
If these changes will be applied, the patchset [1] that adds the modpost generated aliases to modules.builtin.modinfo will look much smaller. [1] https://lore.kernel.org/all/cover.1748335606.git.legion@kernel.org/T/#m515563dbddb2f2fcd10b0f198db69aee533db088 Alexey Gladkov (3): scsi: Always define blogic_pci_tbl structure modpost: Add modname to mod_device_table alias modpost: Create modalias for builtin modules drivers/scsi/BusLogic.c | 2 -- include/linux/module.h | 18 +++++++++++------- rust/kernel/device_id.rs | 8 ++++---- scripts/Makefile.vmlinux | 5 ++++- scripts/mksysmap | 3 +++ scripts/mod/file2alias.c | 34 ++++++++++++++++++++++++++++++---- scripts/mod/modpost.c | 17 ++++++++++++++++- scripts/mod/modpost.h | 2 ++ 8 files changed, 70 insertions(+), 19 deletions(-) -- 2.49.0
The blogic_pci_tbl structure is used by the MODULE_DEVICE_TABLE macro.
There is no longer a need to protect it with the MODULE condition, since
this no longer causes the compiler to warn about an unused variable.
Cc: Khalid Aziz <khalid@gonehiking.org>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Suggested-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Alexey Gladkov <legion@kernel.org>
---
drivers/scsi/BusLogic.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 1f100270cd38..08e12a3d6703 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -3715,7 +3715,6 @@ static void __exit blogic_exit(void)
__setup("BusLogic=", blogic_setup);
-#ifdef MODULE
/*static const struct pci_device_id blogic_pci_tbl[] = {
{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -3731,7 +3730,6 @@ static const struct pci_device_id blogic_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
{0, },
};
-#endif
MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
module_init(blogic_init);
--
2.49.0
At this point, if a symbol is compiled as part of the kernel,
information about which module the symbol belongs to is lost.
To save this it is possible to add the module name to the alias name.
It's not very pretty, but it's possible for now.
Signed-off-by: Alexey Gladkov <legion@kernel.org>
---
include/linux/module.h | 14 +++++++++++---
rust/kernel/device_id.rs | 8 ++++----
scripts/mod/file2alias.c | 18 ++++++++++++++----
3 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 24fe6b865e9c..e0f826fab2ac 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -243,11 +243,19 @@ struct module_kobject *lookup_or_create_module_kobject(const char *name);
/* What your module does. */
#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
+/* Format: __mod_device_table__kmod_<modname>__<type>__<name> */
+#define __mod_device_table(type, name) \
+ __PASTE(__mod_device_table__, \
+ __PASTE(__KBUILD_MODNAME, \
+ __PASTE(__, \
+ __PASTE(type, \
+ __PASTE(__, name)))))
+
#ifdef MODULE
/* Creates an alias so file2alias.c can find device table. */
-#define MODULE_DEVICE_TABLE(type, name) \
-extern typeof(name) __mod_device_table__##type##__##name \
- __attribute__ ((unused, alias(__stringify(name))))
+#define MODULE_DEVICE_TABLE(type, name) \
+static typeof(name) __mod_device_table(type, name) \
+ __attribute__ ((used, alias(__stringify(name))))
#else /* !MODULE */
#define MODULE_DEVICE_TABLE(type, name)
#endif
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index 0a4eb56d98f2..365d8f544844 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -154,10 +154,10 @@ macro_rules! module_device_table {
($table_type: literal, $module_table_name:ident, $table_name:ident) => {
#[rustfmt::skip]
#[export_name =
- concat!("__mod_device_table__", $table_type,
- "__", module_path!(),
- "_", line!(),
- "_", stringify!($table_name))
+ concat!("__mod_device_table__", line!(),
+ "__kmod_", module_path!(),
+ "__", $table_type,
+ "__", stringify!($table_name))
]
static $module_table_name: [::core::mem::MaybeUninit<u8>; $table_name.raw_ids().size()] =
unsafe { ::core::mem::transmute_copy($table_name.raw_ids()) };
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 00586119a25b..13021266a18f 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1476,8 +1476,8 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
{
void *symval;
char *zeros = NULL;
- const char *type, *name;
- size_t typelen;
+ const char *type, *name, *modname;
+ size_t typelen, modnamelen;
static const char *prefix = "__mod_device_table__";
/* We're looking for a section relative symbol */
@@ -1488,10 +1488,20 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
return;
- /* All our symbols are of form __mod_device_table__<type>__<name>. */
+ /* All our symbols are of form __mod_device_table__kmod_<modname>__<type>__<name>. */
if (!strstarts(symname, prefix))
return;
- type = symname + strlen(prefix);
+
+ modname = strstr(symname, "__kmod_");
+ if (!modname)
+ return;
+ modname += strlen("__kmod_");
+
+ type = strstr(modname, "__");
+ if (!type)
+ return;
+ modnamelen = type - modname;
+ type += strlen("__");
name = strstr(type, "__");
if (!name)
--
2.49.0
For some modules, modalias is generated using the modpost utility and
the section is added to the module file.
When a module is added inside vmlinux, modpost does not generate
modalias for such modules and the information is lost.
As a result kmod (which uses modules.builtin.modinfo in userspace)
cannot determine that modalias is handled by a builtin kernel module.
$ cat /sys/devices/pci0000:00/0000:00:14.0/modalias
pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30
$ modinfo xhci_pci
name: xhci_pci
filename: (builtin)
license: GPL
file: drivers/usb/host/xhci-pci
description: xHCI PCI Host Controller Driver
Missing modalias "pci:v*d*sv*sd*bc0Csc03i30*" which will be generated by
modpost if the module is built separately.
To fix this it is necessary to generate the same modalias for vmlinux as
for the individual modules. Fortunately '.vmlinux.export.o' is already
generated from which '.modinfo' can be extracted in the same way as for
vmlinux.o.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Alexey Gladkov <legion@kernel.org>
---
include/linux/module.h | 4 ----
scripts/Makefile.vmlinux | 5 ++++-
scripts/mksysmap | 3 +++
scripts/mod/file2alias.c | 16 ++++++++++++++++
scripts/mod/modpost.c | 17 ++++++++++++++++-
scripts/mod/modpost.h | 2 ++
6 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index e0f826fab2ac..3aeee5d0a77c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -251,14 +251,10 @@ struct module_kobject *lookup_or_create_module_kobject(const char *name);
__PASTE(type, \
__PASTE(__, name)))))
-#ifdef MODULE
/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name) \
static typeof(name) __mod_device_table(type, name) \
__attribute__ ((used, alias(__stringify(name))))
-#else /* !MODULE */
-#define MODULE_DEVICE_TABLE(type, name)
-#endif
/* Version of form [<epoch>:]<version>[-<extra-version>].
* Or for CVS/RCS ID version, everything but the number is stripped.
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index fdab5aa90215..fcc188d26ead 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -89,8 +89,11 @@ endif
remove-section-y := .modinfo
remove-section-$(CONFIG_ARCH_VMLINUX_NEEDS_RELOCS) += '.rel*'
+remove-symbols := -w --strip-symbol='__mod_device_table__*'
+
quiet_cmd_strip_relocs = OBJCOPY $@
- cmd_strip_relocs = $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $< $@
+ cmd_strip_relocs = $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) \
+ $(remove-symbols) $< $@
targets += vmlinux
vmlinux: vmlinux.unstripped FORCE
diff --git a/scripts/mksysmap b/scripts/mksysmap
index a607a0059d11..c4531eacde20 100755
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
@@ -59,6 +59,9 @@
# EXPORT_SYMBOL (namespace)
/ __kstrtabns_/d
+# MODULE_DEVICE_TABLE (symbol name)
+/ __mod_device_table__/d
+
# ---------------------------------------------------------------------------
# Ignored suffixes
# (do not forget '$' after each pattern)
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 13021266a18f..7da9735e7ab3 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1527,5 +1527,21 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
}
}
+ if (mod->is_vmlinux) {
+ struct module_alias *alias;
+
+ /*
+ * If this is vmlinux, record the name of the builtin module.
+ * Traverse the linked list in the reverse order, and set the
+ * builtin_modname unless it has already been set in the
+ * previous call.
+ */
+ list_for_each_entry_reverse(alias, &mod->aliases, node) {
+ if (alias->builtin_modname)
+ break;
+ alias->builtin_modname = xstrndup(modname, modnamelen);
+ }
+ }
+
free(zeros);
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index be89921d60b6..67668b159444 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2021,11 +2021,26 @@ static void write_if_changed(struct buffer *b, const char *fname)
static void write_vmlinux_export_c_file(struct module *mod)
{
struct buffer buf = { };
+ struct module_alias *alias, *next;
buf_printf(&buf,
- "#include <linux/export-internal.h>\n");
+ "#include <linux/export-internal.h>\n"
+ "#include <linux/module.h>\n");
add_exported_symbols(&buf, mod);
+
+ buf_printf(&buf,
+ "#undef __MODULE_INFO_PREFIX\n"
+ "#define __MODULE_INFO_PREFIX\n");
+
+ list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+ buf_printf(&buf, "MODULE_INFO(%s.alias, \"%s\");\n",
+ alias->builtin_modname, alias->str);
+ list_del(&alias->node);
+ free(alias->builtin_modname);
+ free(alias);
+ }
+
write_if_changed(&buf, ".vmlinux.export.c");
free(buf.p);
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 9133e4c3803f..2aecb8f25c87 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -99,10 +99,12 @@ buf_write(struct buffer *buf, const char *s, int len);
* struct module_alias - auto-generated MODULE_ALIAS()
*
* @node: linked to module::aliases
+ * @modname: name of the builtin module (only for vmlinux)
* @str: a string for MODULE_ALIAS()
*/
struct module_alias {
struct list_head node;
+ char *builtin_modname;
char str[];
};
--
2.49.0
On Fri, Jun 06, 2025 at 01:10:22PM +0900, Masahiro Yamada wrote: > > Currently, modules.builtin.modinfo is generated from vmlinux.o, which > occurs before modpost. So, we cannot include modpost-processed data > into modules.builtin.modinfo. > > This patch set allows to generate modules.builtin.modinfo from > vmlinux.unstripped. > > I think this patch set will be useful to clean up this: > > https://lore.kernel.org/linux-kbuild/cover.1748335606.git.legion@kernel.org/T/#m98813857abf2101bdf67f1b8529a44f5c7f4746d > > The original approach generates modules.builtin.modinfo from two files > and then cancatenates them into a single file. > > I prefer generating modules.builtin.modinfo from a single point. > > I think 1/4 is a good cleanup regardless of modules.builtin.modinfo > > > Masahiro Yamada (4): > module: remove meaningless 'name' parameter from __MODULE_INFO() > kbuild: always create intermediate vmlinux.unstripped > kbuild: keep .modinfo section in vmlinux.unstripped > kbuild: extract modules.builtin.modinfo from vmlinux.unstripped > > include/asm-generic/vmlinux.lds.h | 2 +- > include/crypto/algapi.h | 4 +- > include/linux/module.h | 3 -- > include/linux/moduleparam.h | 9 ++-- > include/net/tcp.h | 4 +- > scripts/Makefile.vmlinux | 73 +++++++++++++++++++++---------- > scripts/Makefile.vmlinux_o | 26 +---------- > scripts/mksysmap | 3 ++ > 8 files changed, 63 insertions(+), 61 deletions(-) Hm. It doesn't work for me :( I haven't been able to figure out what's wrong yet. make[3]: *** No rule to make target 'vmlinux', needed by 'arch/x86/boot/compressed/../voffset.h'. Stop. make[2]: *** [arch/x86/boot/Makefile:96: arch/x86/boot/compressed/vmlinux] Error 2 make[1]: *** [arch/x86/Makefile:320: bzImage] Error 2 make: *** [Makefile:248: __sub-make] Error 2 -- Rgrds, legion
© 2016 - 2025 Red Hat, Inc.