Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules
On Fri, May 09, 2025 at 12:42:39AM +0900, Masahiro Yamada wrote: > On Mon, May 5, 2025 at 6:39 PM Alexey Gladkov wrote: > > > > 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/pci:00/:00:14.0/modalias > > pci:v8086dA36Dsv1043sd8694bc0Csc03i30 > > > > $ 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: Alexey Gladkov > > --- > > > > v2: As Petr Pavlu suggested, I separated the builtin modules from the > > external > > modules. I've also added a search for duplicate modules. > > > > > > > --- > > include/linux/module.h | 4 > > scripts/mod/file2alias.c | 5 + > > scripts/mod/modpost.c| 35 +++ > > scripts/mod/modpost.h| 15 ++- > > 4 files changed, 46 insertions(+), 13 deletions(-) > > > I can implement this with less code change. > > I attached my patch. That is a good point. I'm gonna do it this way. Thanks! -- Rgrds, legion
Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules
On Mon, May 5, 2025 at 6:39 PM Alexey Gladkov wrote:
>
> 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/pci:00/:00:14.0/modalias
> pci:v8086dA36Dsv1043sd8694bc0Csc03i30
>
> $ 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: Alexey Gladkov
> ---
>
> v2: As Petr Pavlu suggested, I separated the builtin modules from the external
> modules. I've also added a search for duplicate modules.
>
> ---
> include/linux/module.h | 4
> scripts/mod/file2alias.c | 5 +
> scripts/mod/modpost.c| 35 +++
> scripts/mod/modpost.h| 15 ++-
> 4 files changed, 46 insertions(+), 13 deletions(-)
I can implement this with less code change.
I attached my patch.
--
Best Regards
Masahiro Yamada
From 28b8431db696b15a5812d6ca0a7372a30e060cfb Mon Sep 17 00:00:00 2001
From: Masahiro Yamada
Date: Fri, 9 May 2025 00:22:46 +0900
Subject: [PATCH] Another simple implementation
Signed-off-by: Masahiro Yamada
---
include/linux/module.h | 4
scripts/mod/file2alias.c | 16
scripts/mod/modpost.c| 14 +-
scripts/mod/modpost.h| 2 ++
4 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 01fceca47a5b..17e69e4a1802 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -259,14 +259,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) \
extern typeof(name) __mod_device_table(type, name) \
__attribute__ ((unused, alias(__stringify(name
-#else /* !MODULE */
-#define MODULE_DEVICE_TABLE(type, name)
-#endif
/* Version of form [:][-].
* Or for CVS/RCS ID version, everything but the number is stripped.
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index dff1799a4c79..d42f2c742fd6 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..285b6c20c760 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2021,11 +2021,23 @@ 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 \n");
+ "#include \n"
+ "#include \n");
add_exported_symbols(&buf, mod);
+
+ list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+ buf_printf(&buf, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+ alias->builtin_modname, alias->str);
+ list_del(&alias->node);
+ printf("builtin modname = %s\n", alias->builtin_modname);
+ 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.43.0
Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules
On Mon, May 05, 2025 at 11:38:29AM +0200, Alexey Gladkov wrote:
> 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/pci:00/:00:14.0/modalias
> pci:v8086dA36Dsv1043sd8694bc0Csc03i30
>
> $ 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: Alexey Gladkov
> ---
>
> v2: As Petr Pavlu suggested, I separated the builtin modules from the external
> modules. I've also added a search for duplicate modules.
>
> ---
> include/linux/module.h | 4
> scripts/mod/file2alias.c | 5 +
> scripts/mod/modpost.c| 35 +++
> scripts/mod/modpost.h| 15 ++-
> 4 files changed, 46 insertions(+), 13 deletions(-)
>
> diff --git a/include/linux/module.h b/include/linux/module.h
> index 7250b4a527ec..6225793ddcd4 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -257,14 +257,10 @@ extern void cleanup_module(void);
> __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
> -#else /* !MODULE */
> -#define MODULE_DEVICE_TABLE(type, name)
> -#endif
>
> /* Version of form [:][-].
> * Or for CVS/RCS ID version, everything but the number is stripped.
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index dff1799a4c79..be221923f582 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -1509,6 +1509,11 @@ void handle_moddevtable(struct module *mod, struct
> elf_info *info,
> typelen = name - type;
> name += strlen("__");
>
> + if (mod->is_vmlinux) {
> + mod = find_module(NULL, modname, modnamelen);
> + mod = mod ?: new_builtin_module(modname, modnamelen);
> + }
> +
> /* Handle all-NULL symbols allocated into .bss */
> if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
> zeros = calloc(1, sym->st_size);
> diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
> index be89921d60b6..db3c172d4528 100644
> --- a/scripts/mod/modpost.c
> +++ b/scripts/mod/modpost.c
> @@ -168,22 +168,26 @@ char *get_line(char **stringp)
> return orig;
> }
>
> -/* A list of all modules we processed */
> +/* A list of all modules (vmlinux or *.ko) we processed */
> LIST_HEAD(modules);
>
> -static struct module *find_module(const char *filename, const char *modname)
> +/* A list of all builtin modules we processed */
> +LIST_HEAD(builtin_modules);
> +
> +struct module *find_module(const char *filename, const char *name, size_t
> namelen)
> {
> struct module *mod;
>
> list_for_each_entry(mod, &modules, list) {
> - if (!strcmp(mod->dump_file, filename) &&
> - !strcmp(mod->name, modname))
> + if ((mod->dump_file && !strcmp(mod->dump_file, filename)) &&
> + namelen != strlen(mod->name) &&
Of course there has to be an '==' here. I'll fix it if this patch fits.
> + !strncmp(mod->name, name, namelen))
> return mod;
> }
> return NULL;
> }
>
> -static struct module *new_module(const char *name, size_t namelen)
> +struct module *create_module(const char *name, size_t namelen, bool
> is_builtin)
> {
> struct module *mod;
>
> @@ -207,7 +211,10 @@ static struct module *new_module(const char *name,
> size_t namelen)
>*/
> mod->is_gpl_compatible = true;
>
> - list_add_tail(&mod->list, &modules);
> + if (is_builtin)
> + list_add_tail(&mod->list, &builtin_modules);
> + else
> + list_add_tail(&mod->list, &modules);
>
> return mod;
> }
> @@ -2021,11 +2028,23 @@ 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_p
[PATCH v2 5/7] modpost: Create modalias for builtin modules
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/pci:00/:00:14.0/modalias
pci:v8086dA36Dsv1043sd8694bc0Csc03i30
$ 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: Alexey Gladkov
---
v2: As Petr Pavlu suggested, I separated the builtin modules from the external
modules. I've also added a search for duplicate modules.
---
include/linux/module.h | 4
scripts/mod/file2alias.c | 5 +
scripts/mod/modpost.c| 35 +++
scripts/mod/modpost.h| 15 ++-
4 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 7250b4a527ec..6225793ddcd4 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -257,14 +257,10 @@ extern void cleanup_module(void);
__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
-#else /* !MODULE */
-#define MODULE_DEVICE_TABLE(type, name)
-#endif
/* Version of form [:][-].
* Or for CVS/RCS ID version, everything but the number is stripped.
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index dff1799a4c79..be221923f582 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1509,6 +1509,11 @@ void handle_moddevtable(struct module *mod, struct
elf_info *info,
typelen = name - type;
name += strlen("__");
+ if (mod->is_vmlinux) {
+ mod = find_module(NULL, modname, modnamelen);
+ mod = mod ?: new_builtin_module(modname, modnamelen);
+ }
+
/* Handle all-NULL symbols allocated into .bss */
if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
zeros = calloc(1, sym->st_size);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index be89921d60b6..db3c172d4528 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -168,22 +168,26 @@ char *get_line(char **stringp)
return orig;
}
-/* A list of all modules we processed */
+/* A list of all modules (vmlinux or *.ko) we processed */
LIST_HEAD(modules);
-static struct module *find_module(const char *filename, const char *modname)
+/* A list of all builtin modules we processed */
+LIST_HEAD(builtin_modules);
+
+struct module *find_module(const char *filename, const char *name, size_t
namelen)
{
struct module *mod;
list_for_each_entry(mod, &modules, list) {
- if (!strcmp(mod->dump_file, filename) &&
- !strcmp(mod->name, modname))
+ if ((mod->dump_file && !strcmp(mod->dump_file, filename)) &&
+ namelen != strlen(mod->name) &&
+ !strncmp(mod->name, name, namelen))
return mod;
}
return NULL;
}
-static struct module *new_module(const char *name, size_t namelen)
+struct module *create_module(const char *name, size_t namelen, bool is_builtin)
{
struct module *mod;
@@ -207,7 +211,10 @@ static struct module *new_module(const char *name, size_t
namelen)
*/
mod->is_gpl_compatible = true;
- list_add_tail(&mod->list, &modules);
+ if (is_builtin)
+ list_add_tail(&mod->list, &builtin_modules);
+ else
+ list_add_tail(&mod->list, &modules);
return mod;
}
@@ -2021,11 +2028,23 @@ 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 \n");
+ "#include \n"
+ "#include \n");
add_exported_symbols(&buf, mod);
+
+ list_for_each_entry(mod, &builtin_modules, list) {
+ list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+ buf_printf(&buf,

