Skip to contentSkip to conversation

Add generated modalias to modules.builtin.modinfo

PATCH Applied Alexey Gladkov 6 participants 34 messages Apr 26, 2025 – May 12, 2025

Subsystems (6)

v1 of 8 Applied Latest is v8 →

lore
Share & tools
lore
#0 lore raw

cover Add generated modalias to modules.builtin.modinfo

The modules.builtin.modinfo file is used by userspace (kmod to be specific) to get information about builtin modules. Among other information about the module, information about module aliases is stored. This is very important to determine that a particular modalias will be handled by a module that is inside the kernel.

There are several mechanisms for creating modalias for modules:

The first is to explicitly specify the MODULE_ALIAS of the macro. In this case, the aliases go into the '.modinfo' section of the module if it is compiled separately or into vmlinux.o if it is builtin into the kernel.

The second is the use of MODULE_DEVICE_TABLE followed by the use of the modpost utility. In this case, vmlinux.o no longer has this information and does not get it into modules.builtin.modinfo.

For example:

$ modinfo pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30
modinfo: ERROR: Module pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30 not found.
$ modinfo xhci_pci
name:           xhci_pci
filename:       (builtin)
license:        GPL
file:           drivers/usb/host/xhci-pci
description:    xHCI PCI Host Controller Driver

The builtin module is missing alias "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 add the generated by modpost modalias to modules.builtin.modinfo.

Fortunately modpost already generates .vmlinux.export.c for exported symbols. It is possible to use this file to create a '.modinfo' section for builtin modules. The modules.builtin.modinfo file becomes a composite file. One part is extracted from vmlinux.o, the other part from .vmlinux.export.o.

Alexey Gladkov (7):
mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE
scsi: Define MODULE_DEVICE_TABLE only if necessary
modules: Add macros to specify modinfo prefix
modpost: Make mod_device_table aliases more unique
modpost: Create modalias for builtin modules
kbuild: Move modules.builtin.modinfo to another makefile
kbuild: Create modules.builtin.modinfo for modpost results

 drivers/mfd/stmpe-spi.c     |  2 +-
 drivers/scsi/BusLogic.c     |  2 +-
 include/linux/module.h      | 21 +++++++++++-----
 include/linux/moduleparam.h |  7 ++++--
 scripts/Makefile.vmlinux    | 50 +++++++++++++++++++++++++++++++++++++
 scripts/Makefile.vmlinux_o  | 26 +------------------
 scripts/mod/file2alias.c    | 31 +++++++++++++++++++----
 scripts/mod/modpost.c       | 21 +++++++++++++---
 scripts/mod/modpost.h       |  7 +++++-
 9 files changed, 123 insertions(+), 44 deletions(-)
Signature · 1 line
2.49.0
#1 lore raw

PATCH 1/7 mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE

The name used in the macro does not exist.

drivers/mfd/stmpe-spi.c:132:26: error: use of undeclared identifier 'stmpe_id'
132 | MODULE_DEVICE_TABLE(spi, stmpe_id);
| ^
1 error generated.

Fixes e789995d5c61 ("mfd: Add support for STMPE SPI interface")
Cc Lee Jones <[email protected]>
Cc Maxime Coquelin <[email protected]>
Cc Alexandre Torgue <[email protected]>
---
 drivers/mfd/stmpe-spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mfd/stmpe-spi.c +1 -1
index 792236f56399..b9cc85ea2c40 100644
@@ -129,7 +129,7 @@ static const struct spi_device_id stmpe_spi_id[] = {
 	{ "stmpe2403", STMPE2403 },
 	{ }
 };
-MODULE_DEVICE_TABLE(spi, stmpe_id);
+MODULE_DEVICE_TABLE(spi, stmpe_spi_id);
 
 static struct spi_driver stmpe_spi_driver = {
 	.driver = {
Signature · 1 line
2.49.0
Reviewed-by on v1 1/7
#2 lore raw

Re: [PATCH v1 1/7] mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE

Quoted 6 lines · Alexey Gladkov

The name used in the macro does not exist.

drivers/mfd/stmpe-spi.c:132:26: error: use of undeclared identifier 'stmpe_id'
132 | MODULE_DEVICE_TABLE(spi, stmpe_id);
| ^
1 error generated.

P.S. You can trim the error messages to relevant parts, e.g. "1 error generated" is really redundant and not needed to store in git history.

Quoted 1 line

Best regards,
Krzysztof

maintainer
#3 lore raw

Re: [PATCH v1 1/7] mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE

Quoted 9 lines · Krzysztof Kozlowski
Quoted 6 lines · Alexey Gladkov

The name used in the macro does not exist.

drivers/mfd/stmpe-spi.c:132:26: error: use of undeclared identifier 'stmpe_id'
132 | MODULE_DEVICE_TABLE(spi, stmpe_id);
| ^
1 error generated.

Quoted 4 lines

P.S. You can trim the error messages to relevant parts, e.g. "1 error generated" is really redundant and not needed to store in git history.

Trimmed on apply, thanks.

Signature · 1 line
Lee Jones [李琼斯]
maintainer Applied
#4 lore raw

Re: (subset) [PATCH v1 1/7] mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE

In reply to Alexey Gladkov
Quoted 8 lines · Alexey Gladkov

The name used in the macro does not exist.

drivers/mfd/stmpe-spi.c:132:26: error: use of undeclared identifier 'stmpe_id'
132 | MODULE_DEVICE_TABLE(spi, stmpe_id);
| ^
1 error generated.

[...]

Applied, thanks!

[1/7] mfd: stmpe-spi: Correct the name used in MODULE_DEVICE_TABLE

      commit: 7e5d7dcd96e29bb30fe7b105c53ae63a8edcd3e1

--
Lee Jones [李琼斯]

#5 lore raw

PATCH 2/7 scsi: Define MODULE_DEVICE_TABLE only if necessary

In reply to Alexey Gladkov

Define MODULE_DEVICE_TABLE only if a structure is defined for it.

drivers/scsi/BusLogic.c:3735:26: error: use of undeclared identifier 'blogic_pci_tbl'
3735 | MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
| ^
1 error generated.

Fixes 1079a2d251f2 ("[SCSI] BusLogic: stop using check_region")
Cc Khalid Aziz <[email protected]>
Cc "James E.J. Bottomley" <[email protected]>
Cc "Martin K. Petersen" <[email protected]>
---
 drivers/scsi/BusLogic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/BusLogic.c +1 -1
index 1f100270cd38..8ce2ac9293a3 100644
@@ -3731,8 +3731,8 @@ 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);
+#endif
 
 module_init(blogic_init);
 module_exit(blogic_exit);
Signature · 1 line
2.49.0
#6 lore raw

PATCH 3/7 modules: Add macros to specify modinfo prefix

In reply to Alexey Gladkov

The __MODULE_INFO macros always use __MODULE_INFO_PREFIX. The only way to use a different prefix is to override __MODULE_INFO_PREFIX, which is not very useful.

The new macro will be used in file2alias.c to generate modalias for builtin modules.

---
 include/linux/module.h      | 3 +++
 include/linux/moduleparam.h | 7 +++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
include/linux/module.h +3 -0
index d94b196d5a34..e987fd62c734 100644
@@ -168,6 +168,9 @@ extern void cleanup_module(void);
 /* For userspace: you can also call me... */
 #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
 
+#define MODULE_ALIAS_MODNAME(_modname, _alias) \
+	__MODULE_INFO_WITH_PREFIX(_modname ".", alias, alias, _alias)
+
 /* Soft module dependencies. See man modprobe.d for details.
  * Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
  */
include/linux/moduleparam.h +5 -2
index bfb85fd13e1f..3f819fc67c43 100644
@@ -20,10 +20,13 @@
 /* Chosen so that structs with an unsigned long line up. */
 #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
 
-#define __MODULE_INFO(tag, name, info)					  \
+#define __MODULE_INFO_WITH_PREFIX(prefix, tag, name, info)		  \
 	static const char __UNIQUE_ID(name)[]				  \
 		__used __section(".modinfo") __aligned(1)		  \
-		= __MODULE_INFO_PREFIX __stringify(tag) "=" info
+		= prefix __stringify(tag) "=" info
+
+#define __MODULE_INFO(tag, name, info)					  \
+	__MODULE_INFO_WITH_PREFIX(__MODULE_INFO_PREFIX, tag, name, info)
 
 #define __MODULE_PARM_TYPE(name, _type)					  \
 	__MODULE_INFO(parmtype, name##type, #name ":" _type)
Signature · 1 line
2.49.0
#7 lore raw

PATCH 4/7 modpost: Make mod_device_table aliases more unique

In reply to Alexey Gladkov

In order to avoid symbol conflicts if they appear in the same binary, a more unique alias identifier can be generated.

---
 include/linux/module.h   | 14 ++++++++++++--
 scripts/mod/file2alias.c | 18 ++++++++++++++----
 2 files changed, 26 insertions(+), 6 deletions(-)
include/linux/module.h +12 -2
index e987fd62c734..7250b4a527ec 100644
@@ -247,10 +247,20 @@ extern void cleanup_module(void);
 /* What your module does. */
 #define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
 
+/* Format: __mod_device_table__<counter>__kmod_<modname>__<type>__<name> */
+#define __mod_device_table(type, name)	\
+	__PASTE(__mod_device_table__,	\
+	__PASTE(__COUNTER__,		\
+	__PASTE(__,			\
+	__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		\
+#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)
scripts/mod/file2alias.c +14 -4
index 00586119a25b..dff1799a4c79 100644
@@ -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__<counter>__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)
Signature · 1 line
2.49.0
#8 lore raw

PATCH 5/7 modpost: Create modalias for builtin modules

In reply to Alexey Gladkov

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.

---
 include/linux/module.h   |  4 ----
 scripts/mod/file2alias.c | 13 ++++++++++++-
 scripts/mod/modpost.c    | 21 ++++++++++++++++++---
 scripts/mod/modpost.h    |  7 ++++++-
 4 files changed, 36 insertions(+), 9 deletions(-)
include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +12 -1
index dff1799a4c79..0fa3f031b904 100644
@@ -1471,7 +1471,8 @@ static const struct devtable devtable[] = {
 /* Create MODULE_ALIAS() statements.
  * At this time, we cannot write the actual output C source yet,
  * so we write into the mod->dev_table_buf buffer. */
-void handle_moddevtable(struct module *mod, struct elf_info *info,
+void handle_moddevtable(struct list_head *modules,
+			struct module *mod, struct elf_info *info,
 			Elf_Sym *sym, const char *symname)
 {
 	void *symval;
@@ -1509,6 +1510,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 	typelen = name - type;
 	name += strlen("__");
 
+	if (mod->is_vmlinux) {
+		struct module *builtin_mod;
+
+		builtin_mod = new_module(modname, modnamelen);
+		builtin_mod->is_vmlinux = mod->is_vmlinux;
+		builtin_mod->dump_file = MODULE_BUILTIN_FNAME;
+
+		mod = builtin_mod;
+	}
+
 	/* Handle all-NULL symbols allocated into .bss */
 	if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
 		zeros = calloc(1, sym->st_size);
scripts/mod/modpost.c +18 -3
index be89921d60b6..10e1987fc0e3 100644
@@ -183,7 +183,7 @@ static struct module *find_module(const char *filename, const char *modname)
 	return NULL;
 }
 
-static struct module *new_module(const char *name, size_t namelen)
+struct module *new_module(const char *name, size_t namelen)
 {
 	struct module *mod;
 
@@ -1610,7 +1610,7 @@ static void read_symbols(const char *modname)
 		symname = remove_dot(info.strtab + sym->st_name);
 
 		handle_symbol(mod, &info, sym, symname);
-		handle_moddevtable(mod, &info, sym, symname);
+		handle_moddevtable(&modules, mod, &info, sym, symname);
 	}
 
 	check_sec_ref(mod, &info);
@@ -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);
+
+	list_for_each_entry(mod, &modules, list) {
+		if (!mod->is_vmlinux || !mod->dump_file ||
+		    strcmp(mod->dump_file, MODULE_BUILTIN_FNAME))
+			continue;
+		list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+			buf_printf(&buf, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+					mod->name, alias->str);
+			list_del(&alias->node);
+			free(alias);
+		}
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
scripts/mod/modpost.h +6 -1
index 9133e4c3803f..85e48f7dd837 100644
@@ -199,6 +199,10 @@ static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym)
 	return !is_mapping_symbol(name);
 }
 
+#define MODULE_BUILTIN_FNAME "(builtin)"
+
+struct module *new_module(const char *name, size_t namelen);
+
 /* symsearch.c */
 void symsearch_init(struct elf_info *elf);
 void symsearch_finish(struct elf_info *elf);
@@ -207,7 +211,8 @@ Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
 				Elf_Addr min_distance);
 
 /* file2alias.c */
-void handle_moddevtable(struct module *mod, struct elf_info *info,
+void handle_moddevtable(struct list_head *modules,
+			struct module *mod, struct elf_info *info,
 			Elf_Sym *sym, const char *symname);
 
 /* sumversion.c */
Signature · 1 line
2.49.0
#9 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

kernel test robot noticed the following build errors:

Hi Alexey,

kernel test robot noticed the following build errors:

[auto build test ERROR on masahiroy-kbuild/for-next]
[also build test ERROR on masahiroy-kbuild/fixes lee-mfd/for-mfd-next mkp-scsi/for-next jejb-scsi/for-next linus/master v6.15-rc3 next-20250424] [cannot apply to mcgrof/modules-next lee-mfd/for-mfd-fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexey-Gladkov/mfd-stmpe-spi-Correct-the-name-used-in-MODULE_DEVICE_TABLE/20250427-002149
base:   https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git for-next
patch link:    https://lore.kernel.org/r/bb0d887760a474e5e7f9db0e9933eee81a5d9ea3.1745591072.git.legion%40kernel.org
patch subject: [PATCH v1 5/7] modpost: Create modalias for builtin modules
config: alpha-defconfig (https://download.01.org/0day-ci/archive/20250428/[email protected]/config)
compiler: alpha-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250428/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

{standard input}: Assembler messages:

>> {standard input}:79363: Error: symbol `__kstrtab___memset' is already defined
>> {standard input}:79365: Error: symbol `__kstrtabns___memset' is already defined

{standard input}:79370: Error: symbol `__ksymtab___memset' is already defined

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
maintainer
#10 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

In reply to Alexey Gladkov
Quoted 59 lines · Alexey Gladkov

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.

---
 include/linux/module.h   |  4 ----
 scripts/mod/file2alias.c | 13 ++++++++++++-
 scripts/mod/modpost.c    | 21 ++++++++++++++++++---
 scripts/mod/modpost.h    |  7 ++++++-
 4 files changed, 36 insertions(+), 9 deletions(-)
include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +0 -0
index dff1799a4c79..0fa3f031b904 100644

scripts/mod/file2alias.c static const struct devtable devtable[] = { · line 1478

Quoted 9 lines
scripts/mod/file2alias.c +2 -1
@@ -1471,7 +1471,8 @@ static const struct devtable devtable[] = {
 /* Create MODULE_ALIAS() statements.
  * At this time, we cannot write the actual output C source yet,
  * so we write into the mod->dev_table_buf buffer. */
-void handle_moddevtable(struct module *mod, struct elf_info *info,
+void handle_moddevtable(struct list_head *modules,
+			struct module *mod, struct elf_info *info,
 			Elf_Sym *sym, const char *symname)
 {
 	void *symval;

The new modules parameter is unused.

scripts/mod/file2alias.c void handle_moddevtable(struct module *mod, struct elf_info *info, · line 1518

Quoted 10 lines
scripts/mod/file2alias.c +6 -0
@@ -1509,6 +1510,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 	typelen = name - type;
 	name += strlen("__");
 
+	if (mod->is_vmlinux) {
+		struct module *builtin_mod;
+
+		builtin_mod = new_module(modname, modnamelen);
+		builtin_mod->is_vmlinux = mod->is_vmlinux;
+		builtin_mod->dump_file = MODULE_BUILTIN_FNAME;

The module.dump_file member is described in scripts/mod/modpost.h as "path to the .symvers file if loaded from a file". However, that is not the case here.

Similarly, the module struct in scripts/mod/modpost.h is commented as "represent a module (vmlinux or *.ko)", but this patch expands its scope to also include builtin modules.

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

Signature · 2 lines
Thanks,
Petr
#11 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

Quoted 63 lines · Petr Pavlu
Quoted 62 lines · Alexey Gladkov

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.

---
 include/linux/module.h   |  4 ----
 scripts/mod/file2alias.c | 13 ++++++++++++-
 scripts/mod/modpost.c    | 21 ++++++++++++++++++---
 scripts/mod/modpost.h    |  7 ++++++-
 4 files changed, 36 insertions(+), 9 deletions(-)
include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +0 -0
index dff1799a4c79..0fa3f031b904 100644
@@ -1471,7 +1471,8 @@ static const struct devtable devtable[] = {
 /* Create MODULE_ALIAS() statements.
  * At this time, we cannot write the actual output C source yet,
  * so we write into the mod->dev_table_buf buffer. */
Quoted 8 lines

scripts/mod/file2alias.c static const struct devtable devtable[] = { · line 1478

Quoted 6 lines
scripts/mod/file2alias.c +2 -1
-void handle_moddevtable(struct module *mod, struct elf_info *info,
+void handle_moddevtable(struct list_head *modules,
+			struct module *mod, struct elf_info *info,
 			Elf_Sym *sym, const char *symname)
 {
 	void *symval;

The new modules parameter is unused.

Indeed. It is no longer needed after the optimization. Thank you.

Quoted 15 lines

scripts/mod/file2alias.c void handle_moddevtable(struct module *mod, struct elf_info *info, · line 1518

Quoted 10 lines
scripts/mod/file2alias.c +6 -0
@@ -1509,6 +1510,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 	typelen = name - type;
 	name += strlen("__");
 
+	if (mod->is_vmlinux) {
+		struct module *builtin_mod;
+
+		builtin_mod = new_module(modname, modnamelen);
+		builtin_mod->is_vmlinux = mod->is_vmlinux;
+		builtin_mod->dump_file = MODULE_BUILTIN_FNAME;

The module.dump_file member is described in scripts/mod/modpost.h as "path to the .symvers file if loaded from a file". However, that is not the case here.

Quoted 3 lines

Similarly, the module struct in scripts/mod/modpost.h is commented as "represent a module (vmlinux or *.ko)", but this patch expands its scope to also include builtin modules.

Well, an alternative would be to add a separate flag. I used dump_file because it allows you to exclude such "builtin" modules from processing in write_dump(), write_namespace_deps_files(), etc.

But yes, I agree that it's an abuse.

Quoted 6 lines

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

It is possible to extend struct module_alias and add the module name. The problem is that alias is added by module_alias_printf() and we will have to add the module name to the arguments to each do_entry handler in addition to struct module where there is already a name (but in our case it is vmlinux).

I can do that if you think it's a better way.

Signature · 1 line
Rgrds, legion
#12 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

Quoted 7 lines · Alexey Gladkov
Quoted 6 lines

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

Quoted 7 lines

It is possible to extend struct module_alias and add the module name. The problem is that alias is added by module_alias_printf() and we will have to add the module name to the arguments to each do_entry handler in addition to struct module where there is already a name (but in our case it is vmlinux).

I can do that if you think it's a better way.

If I don't add separate entries for each builtin module, the patch will look like this:

include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +109 -71

612 lines not on this page · raw message

scripts/mod/modpost.c +11 -1
index be89921d60b6..f97f2565c1e2 100644
@@ -2021,11 +2021,21 @@ 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);
+
+	list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+		buf_printf(&buf, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+				alias->modname, alias->alias);
+		list_del(&alias->node);
+		free(alias);
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
scripts/mod/modpost.h +2 -0
index 9133e4c3803f..e08646632e19 100644
@@ -103,6 +103,8 @@ buf_write(struct buffer *buf, const char *s, int len);
  */
 struct module_alias {
 	struct list_head node;
+	const char *modname;
+	const char *alias;
 	char str[];
 };
 
Signature · 1 line
Rgrds, legion
maintainer
#13 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

Quoted 14 lines · Alexey Gladkov
Quoted 13 lines · Alexey Gladkov
Quoted 6 lines

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

It is possible to extend struct module_alias and add the module name. The problem is that alias is added by module_alias_printf() and we will have to add the module name to the arguments to each do_entry handler in addition to struct module where there is already a name (but in our case it is vmlinux).

Quoted 5 lines
Quoted 1 line

I can do that if you think it's a better way.

If I don't add separate entries for each builtin module, the patch will look like this:
[...]

I see, that didn't turn out as well as I envisioned. One more approach would be to track builtin modules separately. A patch is below. I'm not sure if it's better.

include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +6 -2
index dff1799a4c79..28a4c045f66c 100644
@@ -1471,8 +1471,8 @@ static const struct devtable devtable[] = {
 /* Create MODULE_ALIAS() statements.
  * At this time, we cannot write the actual output C source yet,
  * so we write into the mod->dev_table_buf buffer. */
-void handle_moddevtable(struct module *mod, struct elf_info *info,
-			Elf_Sym *sym, const char *symname)
+void handle_moddevtable(struct module *mod, struct elf_info *info, Elf_Sym *sym,
+			const char *symname)
 {
 	void *symval;
 	char *zeros = NULL;
@@ -1509,6 +1509,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
 	typelen = name - type;
 	name += strlen("__");
 
+	if (mod->is_vmlinux)
+		// XXX Check if the module doesn't already exist?
+		mod = new_module(modname, modnamelen, true);
+
 	/* Handle all-NULL symbols allocated into .bss */
 	if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
 		zeros = calloc(1, sym->st_size);
scripts/mod/modpost.c +24 -6
index be89921d60b6..f39e3456e021 100644
@@ -168,9 +168,12 @@ 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);
 
+/* A list of all builtin modules we processed */
+LIST_HEAD(builtin_modules);
+
 static struct module *find_module(const char *filename, const char *modname)
 {
 	struct module *mod;
@@ -183,7 +186,7 @@ static struct module *find_module(const char *filename, const char *modname)
 	return NULL;
 }
 
-static struct module *new_module(const char *name, size_t namelen)
+struct module *new_module(const char *name, size_t namelen, bool is_builtin)
 {
 	struct module *mod;
 
@@ -207,7 +210,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;
 }
@@ -1573,7 +1579,7 @@ static void read_symbols(const char *modname)
 	}
 
 	/* strip trailing .o */
-	mod = new_module(modname, strlen(modname) - strlen(".o"));
+	mod = new_module(modname, strlen(modname) - strlen(".o"), false);
 
 	/* save .no_trim_symbol section for later use */
 	if (info.no_trim_symbol_len) {
@@ -2021,11 +2027,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 <linux/export-internal.h>\n");
+		   "#include <linux/export-internal.h>\n"
+		   "#include <linux/module.h>\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, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+					mod->name, alias->str);
+			list_del(&alias->node);
+			free(alias);
+		}
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
@@ -2114,7 +2132,7 @@ static void read_dump(const char *fname)
 
 		mod = find_module(fname, modname);
 		if (!mod) {
-			mod = new_module(modname, strlen(modname));
+			mod = new_module(modname, strlen(modname), false);
 			mod->dump_file = fname;
 		}
 		s = sym_add_exported(symname, mod, gpl_only, namespace);
scripts/mod/modpost.h +3 -1
index 9133e4c3803f..f2b6d25f00ff 100644
@@ -107,7 +107,7 @@ struct module_alias {
 };
 
 /**
- * struct module - represent a module (vmlinux or *.ko)
+ * struct module - represent a module (vmlinux, a builtin module, or *.ko)
  *
  * @dump_file: path to the .symvers file if loaded from a file
  * @aliases: list head for module_aliases
@@ -199,6 +199,8 @@ static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym)
 	return !is_mapping_symbol(name);
 }
 
+struct module *new_module(const char *name, size_t namelen, bool is_builtin);
+
 /* symsearch.c */
 void symsearch_init(struct elf_info *elf);
 void symsearch_finish(struct elf_info *elf);
Signature · 2 lines
Cheers,
Petr
#14 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

Quoted 17 lines · Petr Pavlu
Quoted 16 lines · Alexey Gladkov
Quoted 14 lines · Alexey Gladkov
Quoted 6 lines

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

It is possible to extend struct module_alias and add the module name. The problem is that alias is added by module_alias_printf() and we will have to add the module name to the arguments to each do_entry handler in addition to struct module where there is already a name (but in our case it is vmlinux).

I can do that if you think it's a better way.

Quoted 7 lines
Quoted 3 lines

If I don't add separate entries for each builtin module, the patch will look like this:
[...]

I see, that didn't turn out as well as I envisioned. One more approach would be to track builtin modules separately. A patch is below. I'm not sure if it's better.

I'm not sure I get it. What do you mean when you say I need to track builtin modules separately ?

Signature · 1 line
Rgrds, legion
maintainer
#15 lore raw

Re: [PATCH v1 5/7] modpost: Create modalias for builtin modules

Quoted 22 lines · Alexey Gladkov
Quoted 21 lines · Petr Pavlu
Quoted 19 lines · Alexey Gladkov
Quoted 7 lines · Alexey Gladkov
Quoted 6 lines

I'm not sure it's best to overload this data in this way. I think mixing actual files and "logical" modules in the modules list is somewhat confusing.

An alternative would be to keep a single module struct for vmlinux and record the discovered aliases under it?

Quoted 7 lines

It is possible to extend struct module_alias and add the module name. The problem is that alias is added by module_alias_printf() and we will have to add the module name to the arguments to each do_entry handler in addition to struct module where there is already a name (but in our case it is vmlinux).

I can do that if you think it's a better way.

If I don't add separate entries for each builtin module, the patch will look like this:
[...]

Quoted 6 lines
Quoted 3 lines

I see, that didn't turn out as well as I envisioned. One more approach would be to track builtin modules separately. A patch is below. I'm not sure if it's better.

I'm not sure I get it. What do you mean when you say I need to track builtin modules separately ?

The patch that I sent in my reply introduces a new list called builtin_modules. This is what I meant by tracking builtin modules separately. This implementation has the advantage of not conceptually mixing the modules and allows the function write_vmlinux_export_c_file() to directly use the new list.

On the other hand, keeping everything in one list and introducing a flag for builtin modules (or maybe replacing module.is_vmlinux with some module.type enum) allows functions that take only a module pointer to know which module they are dealing with, which I imagine could be useful.

I don't have a clear preference, as long as we avoid misusing module.dump_file.

Signature · 2 lines
Thanks,
Petr
#16 lore raw

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/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.

---

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(-)
include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +5 -0
index dff1799a4c79..be221923f582 100644
@@ -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);
scripts/mod/modpost.c +27 -8
index be89921d60b6..db3c172d4528 100644
@@ -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 <linux/export-internal.h>\n");
+		   "#include <linux/export-internal.h>\n"
+		   "#include <linux/module.h>\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, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+					mod->name, alias->str);
+			list_del(&alias->node);
+			free(alias);
+		}
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
@@ -2112,7 +2131,7 @@ static void read_dump(const char *fname)
 			continue;
 		}
 
-		mod = find_module(fname, modname);
+		mod = find_module(fname, modname, strlen(modname));
 		if (!mod) {
 			mod = new_module(modname, strlen(modname));
 			mod->dump_file = fname;
scripts/mod/modpost.h +14 -1
index 9133e4c3803f..1d0dd4ee944a 100644
@@ -107,7 +107,7 @@ struct module_alias {
 };
 
 /**
- * struct module - represent a module (vmlinux or *.ko)
+ * struct module - represent a module (vmlinux, a builtin module, or *.ko)
  *
  * @dump_file: path to the .symvers file if loaded from a file
  * @aliases: list head for module_aliases
@@ -199,6 +199,19 @@ static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym)
 	return !is_mapping_symbol(name);
 }
 
+struct module *find_module(const char *filename, const char *name, size_t namelen);
+struct module *create_module(const char *name, size_t namelen, bool is_builtin);
+
+static inline struct module *new_module(const char *name, size_t namelen)
+{
+	return create_module(name, namelen, false);
+}
+
+static inline struct module *new_builtin_module(const char *name, size_t namelen)
+{
+	return create_module(name, namelen, true);
+}
+
 /* symsearch.c */
 void symsearch_init(struct elf_info *elf);
 void symsearch_finish(struct elf_info *elf);
Signature · 1 line
2.49.0
#17 lore raw

Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules

Quoted 90 lines · Alexey Gladkov

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.

---

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(-)
include/linux/module.h +0 -4
index 7250b4a527ec..6225793ddcd4 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +5 -0
index dff1799a4c79..be221923f582 100644
@@ -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);
scripts/mod/modpost.c +3 -2
index be89921d60b6..db3c172d4528 100644
@@ -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);

scripts/mod/modpost.c char *get_line(char **stringp) · line 183

Quoted 10 lines
scripts/mod/modpost.c +4 -2
+
+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.

Quoted 93 lines
scripts/mod/modpost.c +20 -4
+		    !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 <linux/export-internal.h>\n");
+		   "#include <linux/export-internal.h>\n"
+		   "#include <linux/module.h>\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, "MODULE_ALIAS_MODNAME(\"%s\", \"%s\");\n",
+					mod->name, alias->str);
+			list_del(&alias->node);
+			free(alias);
+		}
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
@@ -2112,7 +2131,7 @@ static void read_dump(const char *fname)
 			continue;
 		}
 
-		mod = find_module(fname, modname);
+		mod = find_module(fname, modname, strlen(modname));
 		if (!mod) {
 			mod = new_module(modname, strlen(modname));
 			mod->dump_file = fname;
scripts/mod/modpost.h +14 -1
index 9133e4c3803f..1d0dd4ee944a 100644
@@ -107,7 +107,7 @@ struct module_alias {
 };
 
 /**
- * struct module - represent a module (vmlinux or *.ko)
+ * struct module - represent a module (vmlinux, a builtin module, or *.ko)
  *
  * @dump_file: path to the .symvers file if loaded from a file
  * @aliases: list head for module_aliases
@@ -199,6 +199,19 @@ static inline bool is_valid_name(struct elf_info *elf, Elf_Sym *sym)
 	return !is_mapping_symbol(name);
 }
 
+struct module *find_module(const char *filename, const char *name, size_t namelen);
+struct module *create_module(const char *name, size_t namelen, bool is_builtin);
+
+static inline struct module *new_module(const char *name, size_t namelen)
+{
+	return create_module(name, namelen, false);
+}
+
+static inline struct module *new_builtin_module(const char *name, size_t namelen)
+{
+	return create_module(name, namelen, true);
+}
+
 /* symsearch.c */
 void symsearch_init(struct elf_info *elf);
 void symsearch_finish(struct elf_info *elf);
Signature · 1 line
2.49.0
Signature · 1 line
Rgrds, legion
#18 lore raw

Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules

In reply to Alexey Gladkov
Quoted 37 lines · Alexey Gladkov

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.

---

v2: As Petr Pavlu suggested, I separated the builtin modules from the external
modules. I've also added a search for duplicate modules.

Quoted 6 lines
---
 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.

Signature · 2 lines
Best Regards
Masahiro Yamada

From 28b8431db696b15a5812d6ca0a7372a30e060cfb Mon Sep 17 00:00:00 2001
From: Masahiro Yamada <[email protected]>
Date: Fri, 9 May 2025 00:22:46 +0900
Subject: [PATCH] Another simple implementation

---
 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(-)
include/linux/module.h +0 -4
index 01fceca47a5b..17e69e4a1802 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +16 -0
index dff1799a4c79..d42f2c742fd6 100644
@@ -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);
 }
scripts/mod/modpost.c +13 -1
index be89921d60b6..285b6c20c760 100644
@@ -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 <linux/export-internal.h>\n");
+		   "#include <linux/export-internal.h>\n"
+		   "#include <linux/module.h>\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);
 }
scripts/mod/modpost.h +2 -0
index 9133e4c3803f..2aecb8f25c87 100644
@@ -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[];
 };
 
Signature · 1 line
2.43.0
#19 lore raw

Re: [PATCH v2 5/7] modpost: Create modalias for builtin modules

Quoted 46 lines · Masahiro Yamada
Quoted 37 lines · Alexey Gladkov

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.

---

v2: As Petr Pavlu suggested, I separated the builtin modules from the external
modules. I've also added a search for duplicate modules.

Quoted 6 lines
---
 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(-)
Quoted 3 lines

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!

Signature · 1 line
Rgrds, legion
#20 lore raw

PATCH 6/7 kbuild: Move modules.builtin.modinfo to another makefile

In reply to Alexey Gladkov

The creation of modules.builtin.modinfo is going to depend on .vmlinux.export.o so it is worth moving its creation closer to it.

---
 scripts/Makefile.vmlinux   | 26 ++++++++++++++++++++++++++
 scripts/Makefile.vmlinux_o | 26 +-------------------------
 2 files changed, 27 insertions(+), 25 deletions(-)
scripts/Makefile.vmlinux +26 -0
index b0a6cd5b818c..033c22c807b5 100644
@@ -97,6 +97,32 @@ ifdef CONFIG_BUILDTIME_TABLE_SORT
 vmlinux: scripts/sorttable
 endif
 
+# module.builtin.modinfo
+# ---------------------------------------------------------------------------
+__default: modules.builtin.modinfo
+
+OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
+
+targets += modules.builtin.modinfo
+modules.builtin.modinfo: vmlinux.o FORCE
+	$(call if_changed,objcopy)
+
+# module.builtin
+# ---------------------------------------------------------------------------
+__default: modules.builtin
+
+# The second line aids cases where multiple modules share the same object.
+
+quiet_cmd_modules_builtin = GEN     $@
+      cmd_modules_builtin = \
+	tr '\0' '\n' < $< | \
+	sed -n 's/^[[:alnum:]:_]*\.file=//p' | \
+	tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$$/.ko/' > $@
+
+targets += modules.builtin
+modules.builtin: modules.builtin.modinfo FORCE
+	$(call if_changed,modules_builtin)
+
 # module.builtin.ranges
 # ---------------------------------------------------------------------------
 ifdef CONFIG_BUILTIN_MODULE_RANGES
scripts/Makefile.vmlinux_o +1 -25
index 938c7457717e..23c8751285d7 100644
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 PHONY := __default
-__default: vmlinux.o modules.builtin.modinfo modules.builtin
+__default: vmlinux.o
 
 include include/config/auto.conf
 include $(srctree)/scripts/Kbuild.include
@@ -73,30 +73,6 @@ vmlinux.o: $(initcalls-lds) vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
 
 targets += vmlinux.o
 
-# module.builtin.modinfo
-# ---------------------------------------------------------------------------
-
-OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
-
-targets += modules.builtin.modinfo
-modules.builtin.modinfo: vmlinux.o FORCE
-	$(call if_changed,objcopy)
-
-# module.builtin
-# ---------------------------------------------------------------------------
-
-# The second line aids cases where multiple modules share the same object.
-
-quiet_cmd_modules_builtin = GEN     $@
-      cmd_modules_builtin = \
-	tr '\0' '\n' < $< | \
-	sed -n 's/^[[:alnum:]:_]*\.file=//p' | \
-	tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$$/.ko/' > $@
-
-targets += modules.builtin
-modules.builtin: modules.builtin.modinfo FORCE
-	$(call if_changed,modules_builtin)
-
 # Add FORCE to the prerequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
 
Signature · 1 line
2.49.0
#21 lore raw

PATCH 7/7 kbuild: Create modules.builtin.modinfo for modpost results

In reply to Alexey Gladkov

Create modules.builtin.modinfo as a combination of modinfo from vmlinux and the result of generating modalias by modpost.

---
 scripts/Makefile.vmlinux | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)
scripts/Makefile.vmlinux +27 -3
index 033c22c807b5..7a3a21040c4c 100644
@@ -70,6 +70,18 @@ endif
 ifdef CONFIG_MODULES
 targets += .vmlinux.export.o
 $(vmlinux-final): .vmlinux.export.o
+
+# .module.builtin.modinfo.modpost
+# ---------------------------------------------------------------------------
+__default: .modules.builtin.modinfo.modpost
+
+OBJCOPYFLAGS_.modules.builtin.modinfo.modpost := -j .modinfo -O binary
+
+targets += .modules.builtin.modinfo.modpost
+.modules.builtin.modinfo.modpost: .vmlinux.export.o FORCE
+	$(call if_changed,objcopy)
+
+modules.builtin.modinfo: .modules.builtin.modinfo.modpost
 endif
 
 ifdef CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX
@@ -97,15 +109,27 @@ ifdef CONFIG_BUILDTIME_TABLE_SORT
 vmlinux: scripts/sorttable
 endif
 
+# .module.builtin.modinfo.vmlinux
+# ---------------------------------------------------------------------------
+__default: .modules.builtin.modinfo.vmlinux
+
+OBJCOPYFLAGS_.modules.builtin.modinfo.vmlinux := -j .modinfo -O binary
+
+targets += .modules.builtin.modinfo.vmlinux
+.modules.builtin.modinfo.vmlinux: vmlinux.o FORCE
+	$(call if_changed,objcopy)
+
 # module.builtin.modinfo
 # ---------------------------------------------------------------------------
 __default: modules.builtin.modinfo
 
-OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
+quiet_cmd_modules_builtin_modinfo = GEN     $@
+      cmd_modules_builtin_modinfo = \
+	cat $< $(wildcard .modules.builtin.modinfo.modpost) > $@
 
 targets += modules.builtin.modinfo
-modules.builtin.modinfo: vmlinux.o FORCE
-	$(call if_changed,objcopy)
+modules.builtin.modinfo: .modules.builtin.modinfo.vmlinux FORCE
+	$(call if_changed,modules_builtin_modinfo)
 
 # module.builtin
 # ---------------------------------------------------------------------------
Signature · 1 line
2.49.0
maintainer
#22 lore raw
In reply to Alexey Gladkov
Quoted 28 lines · Alexey Gladkov

The modules.builtin.modinfo file is used by userspace (kmod to be specific) to get information about builtin modules. Among other information about the module, information about module aliases is stored. This is very important to determine that a particular modalias will be handled by a module that is inside the kernel.

There are several mechanisms for creating modalias for modules:

The first is to explicitly specify the MODULE_ALIAS of the macro. In this case, the aliases go into the '.modinfo' section of the module if it is compiled separately or into vmlinux.o if it is builtin into the kernel.

The second is the use of MODULE_DEVICE_TABLE followed by the use of the modpost utility. In this case, vmlinux.o no longer has this information and does not get it into modules.builtin.modinfo.

For example:

$ modinfo pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30
modinfo: ERROR: Module pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30 not found.
$ modinfo xhci_pci
name:           xhci_pci
filename:       (builtin)
license:        GPL
file:           drivers/usb/host/xhci-pci
description:    xHCI PCI Host Controller Driver
Quoted 2 lines

The builtin module is missing alias "pci:v*d*sv*sd*bc0Csc03i30*" which will be generated by modpost if the module is built separately.

Could you explain what is currently broken because the device-table alias information isn't available? I think adding this information is reasonable, both for consistency and so kmod can display accurate information, but is there more that I'm missing?

Signature · 2 lines
Thanks,
Petr
#23 lore raw
Quoted 29 lines · Petr Pavlu
Quoted 28 lines · Alexey Gladkov

The modules.builtin.modinfo file is used by userspace (kmod to be specific) to get information about builtin modules. Among other information about the module, information about module aliases is stored. This is very important to determine that a particular modalias will be handled by a module that is inside the kernel.

There are several mechanisms for creating modalias for modules:

The first is to explicitly specify the MODULE_ALIAS of the macro. In this case, the aliases go into the '.modinfo' section of the module if it is compiled separately or into vmlinux.o if it is builtin into the kernel.

The second is the use of MODULE_DEVICE_TABLE followed by the use of the modpost utility. In this case, vmlinux.o no longer has this information and does not get it into modules.builtin.modinfo.

For example:

$ modinfo pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30
modinfo: ERROR: Module pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30 not found.
$ modinfo xhci_pci
name:           xhci_pci
filename:       (builtin)
license:        GPL
file:           drivers/usb/host/xhci-pci
description:    xHCI PCI Host Controller Driver
Quoted 7 lines
Quoted 2 lines

The builtin module is missing alias "pci:v*d*sv*sd*bc0Csc03i30*" which will be generated by modpost if the module is built separately.

Could you explain what is currently broken because the device-table alias information isn't available? I think adding this information is reasonable, both for consistency and so kmod can display accurate information, but is there more that I'm missing?

Yes. Right now, aliases that are generated by modpost are not available for kmod because it's not in the modules.builtin.modinfo.

Signature · 1 line
Rgrds, legion
#24 lore raw

v2 cover Add generated modalias to modules.builtin.modinfo

In reply to Alexey Gladkov

The modules.builtin.modinfo file is used by userspace (kmod to be specific) to get information about builtin modules. Among other information about the module, information about module aliases is stored. This is very important to determine that a particular modalias will be handled by a module that is inside the kernel.

There are several mechanisms for creating modalias for modules:

The first is to explicitly specify the MODULE_ALIAS of the macro. In this case, the aliases go into the '.modinfo' section of the module if it is compiled separately or into vmlinux.o if it is builtin into the kernel.

The second is the use of MODULE_DEVICE_TABLE followed by the use of the modpost utility. In this case, vmlinux.o no longer has this information and does not get it into modules.builtin.modinfo.

For example:

$ modinfo pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30
modinfo: ERROR: Module pci:v00008086d0000A36Dsv00001043sd00008694bc0Csc03i30 not found.
$ modinfo xhci_pci
name:           xhci_pci
filename:       (builtin)
license:        GPL
file:           drivers/usb/host/xhci-pci
description:    xHCI PCI Host Controller Driver

The builtin module is missing alias "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 add the generated by modpost modalias to modules.builtin.modinfo.

Fortunately modpost already generates .vmlinux.export.c for exported symbols. It is possible to use this file to create a '.modinfo' section for builtin modules. The modules.builtin.modinfo file becomes a composite file. One part is extracted from vmlinux.o, the other part from .vmlinux.export.o.

Notes:
- v2:
* Drop patch for mfd because it was already applied and is in linux-next.
* The generation of aliases for builtin modules has been redone as suggested by Masahiro Yamada.
* Rebase to v6.15-rc5-136-g9c69f8884904
* v1: https://lore.kernel.org/all/[email protected]/

Alexey Gladkov (6):
scsi: Define MODULE_DEVICE_TABLE only if necessary
modules: Add macros to specify modinfo prefix
modpost: Make mod_device_table aliases more unique
modpost: Create modalias for builtin modules
kbuild: Move modules.builtin.modinfo to another makefile
kbuild: Create modules.builtin.modinfo for modpost results

 drivers/scsi/BusLogic.c     |  2 +-
 include/linux/module.h      | 21 +++++++++++-----
 include/linux/moduleparam.h |  7 ++++--
 scripts/Makefile.vmlinux    | 50 +++++++++++++++++++++++++++++++++++++
 scripts/Makefile.vmlinux_o  | 26 +------------------
 scripts/mod/file2alias.c    | 34 ++++++++++++++++++++++---
 scripts/mod/modpost.c       | 13 +++++++++-
 scripts/mod/modpost.h       |  2 ++
 8 files changed, 116 insertions(+), 39 deletions(-)
Signature · 1 line
2.49.0
#25 lore raw

PATCH v2 1/6 scsi: Define MODULE_DEVICE_TABLE only if necessary

In reply to Alexey Gladkov

Define MODULE_DEVICE_TABLE only if a structure is defined for it.

drivers/scsi/BusLogic.c:3735:26: error: use of undeclared identifier 'blogic_pci_tbl'
3735 | MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);

Fixes 1079a2d251f2 ("[SCSI] BusLogic: stop using check_region")
Cc Khalid Aziz <[email protected]>
Cc "James E.J. Bottomley" <[email protected]>
Cc "Martin K. Petersen" <[email protected]>
---
 drivers/scsi/BusLogic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/BusLogic.c +1 -1
index 1f100270cd38..8ce2ac9293a3 100644
@@ -3731,8 +3731,8 @@ 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);
+#endif
 
 module_init(blogic_init);
 module_exit(blogic_exit);
Signature · 1 line
2.49.0
#26 lore raw

PATCH v2 2/6 modules: Add macros to specify modinfo prefix

In reply to Alexey Gladkov

The __MODULE_INFO macros always use __MODULE_INFO_PREFIX. The only way to use a different prefix is to override __MODULE_INFO_PREFIX, which is not very useful.

The new macro will be used in file2alias.c to generate modalias for builtin modules.

---
 include/linux/module.h      | 3 +++
 include/linux/moduleparam.h | 7 +++++--
 2 files changed, 8 insertions(+), 2 deletions(-)
include/linux/module.h +3 -0
index b3329110d668..de0da7c7cf03 100644
@@ -170,6 +170,9 @@ struct module_kobject *lookup_or_create_module_kobject(const char *name);
 /* For userspace: you can also call me... */
 #define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
 
+#define MODULE_ALIAS_MODNAME(_modname, _alias) \
+	__MODULE_INFO_WITH_PREFIX(_modname ".", alias, alias, _alias)
+
 /* Soft module dependencies. See man modprobe.d for details.
  * Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
  */
include/linux/moduleparam.h +5 -2
index bfb85fd13e1f..3f819fc67c43 100644
@@ -20,10 +20,13 @@
 /* Chosen so that structs with an unsigned long line up. */
 #define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
 
-#define __MODULE_INFO(tag, name, info)					  \
+#define __MODULE_INFO_WITH_PREFIX(prefix, tag, name, info)		  \
 	static const char __UNIQUE_ID(name)[]				  \
 		__used __section(".modinfo") __aligned(1)		  \
-		= __MODULE_INFO_PREFIX __stringify(tag) "=" info
+		= prefix __stringify(tag) "=" info
+
+#define __MODULE_INFO(tag, name, info)					  \
+	__MODULE_INFO_WITH_PREFIX(__MODULE_INFO_PREFIX, tag, name, info)
 
 #define __MODULE_PARM_TYPE(name, _type)					  \
 	__MODULE_INFO(parmtype, name##type, #name ":" _type)
Signature · 1 line
2.49.0
maintainer Reviewed-by on v2 2/6
#27 lore raw

Re: [PATCH v2 2/6] modules: Add macros to specify modinfo prefix

Quoted 8 lines · Alexey Gladkov

The __MODULE_INFO macros always use __MODULE_INFO_PREFIX. The only way to use a different prefix is to override __MODULE_INFO_PREFIX, which is not very useful.

The new macro will be used in file2alias.c to generate modalias for builtin modules.

-- Petr

#28 lore raw

PATCH v2 3/6 modpost: Make mod_device_table aliases more unique

In reply to Alexey Gladkov

In order to avoid symbol conflicts if they appear in the same binary, a more unique alias identifier can be generated.

---
 include/linux/module.h   | 14 ++++++++++++--
 scripts/mod/file2alias.c | 18 ++++++++++++++----
 2 files changed, 26 insertions(+), 6 deletions(-)
include/linux/module.h +12 -2
index de0da7c7cf03..01fceca47a5b 100644
@@ -249,10 +249,20 @@ 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__<counter>__kmod_<modname>__<type>__<name> */
+#define __mod_device_table(type, name)	\
+	__PASTE(__mod_device_table__,	\
+	__PASTE(__COUNTER__,		\
+	__PASTE(__,			\
+	__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		\
+#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)
scripts/mod/file2alias.c +14 -4
index 00586119a25b..dff1799a4c79 100644
@@ -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__<counter>__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)
Signature · 1 line
2.49.0
#30 lore raw

PATCH v2 4/6 modpost: Create modalias for builtin modules

In reply to Alexey Gladkov

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.

---
 include/linux/module.h   |  4 ----
 scripts/mod/file2alias.c | 16 ++++++++++++++++
 scripts/mod/modpost.c    | 13 ++++++++++++-
 scripts/mod/modpost.h    |  2 ++
 4 files changed, 30 insertions(+), 5 deletions(-)
include/linux/module.h +0 -4
index 01fceca47a5b..17e69e4a1802 100644
@@ -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 [<epoch>:]<version>[-<extra-version>].
  * Or for CVS/RCS ID version, everything but the number is stripped.
scripts/mod/file2alias.c +16 -0
index dff1799a4c79..d42f2c742fd6 100644
@@ -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);
 }
scripts/mod/modpost.c +12 -1
index be89921d60b6..c7c601c6f82d 100644
@@ -2021,11 +2021,22 @@ 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);
+
+	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);
+		free(alias->builtin_modname);
+		free(alias);
+	}
+
 	write_if_changed(&buf, ".vmlinux.export.c");
 	free(buf.p);
 }
scripts/mod/modpost.h +2 -0
index 9133e4c3803f..2aecb8f25c87 100644
@@ -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[];
 };
 
Signature · 1 line
2.49.0
maintainer Reviewed-by on v2 4/6
#31 lore raw

Re: [PATCH v2 4/6] modpost: Create modalias for builtin modules

Quoted 22 lines · Alexey Gladkov

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.

Quoted 7 lines

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.

-- Petr

#32 lore raw

PATCH v2 5/6 kbuild: Move modules.builtin.modinfo to another makefile

In reply to Alexey Gladkov

The creation of modules.builtin.modinfo is going to depend on .vmlinux.export.o so it is worth moving its creation closer to it.

---
 scripts/Makefile.vmlinux   | 26 ++++++++++++++++++++++++++
 scripts/Makefile.vmlinux_o | 26 +-------------------------
 2 files changed, 27 insertions(+), 25 deletions(-)
scripts/Makefile.vmlinux +26 -0
index b0a6cd5b818c..033c22c807b5 100644
@@ -97,6 +97,32 @@ ifdef CONFIG_BUILDTIME_TABLE_SORT
 vmlinux: scripts/sorttable
 endif
 
+# module.builtin.modinfo
+# ---------------------------------------------------------------------------
+__default: modules.builtin.modinfo
+
+OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
+
+targets += modules.builtin.modinfo
+modules.builtin.modinfo: vmlinux.o FORCE
+	$(call if_changed,objcopy)
+
+# module.builtin
+# ---------------------------------------------------------------------------
+__default: modules.builtin
+
+# The second line aids cases where multiple modules share the same object.
+
+quiet_cmd_modules_builtin = GEN     $@
+      cmd_modules_builtin = \
+	tr '\0' '\n' < $< | \
+	sed -n 's/^[[:alnum:]:_]*\.file=//p' | \
+	tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$$/.ko/' > $@
+
+targets += modules.builtin
+modules.builtin: modules.builtin.modinfo FORCE
+	$(call if_changed,modules_builtin)
+
 # module.builtin.ranges
 # ---------------------------------------------------------------------------
 ifdef CONFIG_BUILTIN_MODULE_RANGES
scripts/Makefile.vmlinux_o +1 -25
index 938c7457717e..23c8751285d7 100644
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 PHONY := __default
-__default: vmlinux.o modules.builtin.modinfo modules.builtin
+__default: vmlinux.o
 
 include include/config/auto.conf
 include $(srctree)/scripts/Kbuild.include
@@ -73,30 +73,6 @@ vmlinux.o: $(initcalls-lds) vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
 
 targets += vmlinux.o
 
-# module.builtin.modinfo
-# ---------------------------------------------------------------------------
-
-OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
-
-targets += modules.builtin.modinfo
-modules.builtin.modinfo: vmlinux.o FORCE
-	$(call if_changed,objcopy)
-
-# module.builtin
-# ---------------------------------------------------------------------------
-
-# The second line aids cases where multiple modules share the same object.
-
-quiet_cmd_modules_builtin = GEN     $@
-      cmd_modules_builtin = \
-	tr '\0' '\n' < $< | \
-	sed -n 's/^[[:alnum:]:_]*\.file=//p' | \
-	tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$$/.ko/' > $@
-
-targets += modules.builtin
-modules.builtin: modules.builtin.modinfo FORCE
-	$(call if_changed,modules_builtin)
-
 # Add FORCE to the prerequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
 
Signature · 1 line
2.49.0
#33 lore raw

PATCH v2 6/6 kbuild: Create modules.builtin.modinfo for modpost results

In reply to Alexey Gladkov

Create modules.builtin.modinfo as a combination of modinfo from vmlinux and the result of generating modalias by modpost.

---
 scripts/Makefile.vmlinux | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)
scripts/Makefile.vmlinux +27 -3
index 033c22c807b5..7a3a21040c4c 100644
@@ -70,6 +70,18 @@ endif
 ifdef CONFIG_MODULES
 targets += .vmlinux.export.o
 $(vmlinux-final): .vmlinux.export.o
+
+# .module.builtin.modinfo.modpost
+# ---------------------------------------------------------------------------
+__default: .modules.builtin.modinfo.modpost
+
+OBJCOPYFLAGS_.modules.builtin.modinfo.modpost := -j .modinfo -O binary
+
+targets += .modules.builtin.modinfo.modpost
+.modules.builtin.modinfo.modpost: .vmlinux.export.o FORCE
+	$(call if_changed,objcopy)
+
+modules.builtin.modinfo: .modules.builtin.modinfo.modpost
 endif
 
 ifdef CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX
@@ -97,15 +109,27 @@ ifdef CONFIG_BUILDTIME_TABLE_SORT
 vmlinux: scripts/sorttable
 endif
 
+# .module.builtin.modinfo.vmlinux
+# ---------------------------------------------------------------------------
+__default: .modules.builtin.modinfo.vmlinux
+
+OBJCOPYFLAGS_.modules.builtin.modinfo.vmlinux := -j .modinfo -O binary
+
+targets += .modules.builtin.modinfo.vmlinux
+.modules.builtin.modinfo.vmlinux: vmlinux.o FORCE
+	$(call if_changed,objcopy)
+
 # module.builtin.modinfo
 # ---------------------------------------------------------------------------
 __default: modules.builtin.modinfo
 
-OBJCOPYFLAGS_modules.builtin.modinfo := -j .modinfo -O binary
+quiet_cmd_modules_builtin_modinfo = GEN     $@
+      cmd_modules_builtin_modinfo = \
+	cat $< $(wildcard .modules.builtin.modinfo.modpost) > $@
 
 targets += modules.builtin.modinfo
-modules.builtin.modinfo: vmlinux.o FORCE
-	$(call if_changed,objcopy)
+modules.builtin.modinfo: .modules.builtin.modinfo.vmlinux FORCE
+	$(call if_changed,modules_builtin_modinfo)
 
 # module.builtin
 # ---------------------------------------------------------------------------
Signature · 1 line
2.49.0