Unverified Commit 5ab23c79 authored by Alexey Gladkov's avatar Alexey Gladkov Committed by Nathan Chancellor
Browse files

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.

Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
Signed-off-by: default avatarAlexey Gladkov <legion@kernel.org>
Tested-by: default avatarStephen Rothwell <sfr@canb.auug.org.au>
Reviewed-by: default avatarNicolas Schier <nsc@kernel.org>
Link: https://patch.msgid.link/28d4da3b0e3fc8474142746bcf469e03752c3208.1758182101.git.legion@kernel.org


Signed-off-by: default avatarNathan Chancellor <nathan@kernel.org>
parent 83fb4938
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -256,14 +256,10 @@ struct module_kobject *lookup_or_create_module_kobject(const char *name);
	__PASTE(type,			\
	__PASTE(__, name)))))

#ifdef MODULE
/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name)					\
static typeof(name) __mod_device_table(type, name)			\
  __attribute__ ((used, alias(__stringify(name))))
#else  /* !MODULE */
#define MODULE_DEVICE_TABLE(type, name)
#endif

/* Version of form [<epoch>:]<version>[-<extra-version>].
 * Or for CVS/RCS ID version, everything but the number is stripped.
+3 −1
Original line number Diff line number Diff line
@@ -89,11 +89,13 @@ endif
remove-section-y                                   := .modinfo
remove-section-$(CONFIG_ARCH_VMLINUX_NEEDS_RELOCS) += '.rel*'

remove-symbols := -w --strip-symbol='__mod_device_table__*'

# To avoid warnings: "empty loadable segment detected at ..." from GNU objcopy,
# it is necessary to remove the PT_LOAD flag from the segment.
quiet_cmd_strip_relocs = OBJCOPY $@
      cmd_strip_relocs = $(OBJCOPY) $(patsubst %,--set-section-flags %=noload,$(remove-section-y)) $< $@; \
                         $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $@
                         $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $(remove-symbols) $@

targets += vmlinux
vmlinux: vmlinux.unstripped FORCE
+3 −0
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@
# EXPORT_SYMBOL (namespace)
/ __kstrtabns_/d

# MODULE_DEVICE_TABLE (symbol name)
/ __mod_device_table__/d

# ---------------------------------------------------------------------------
# Ignored suffixes
#  (do not forget '$' after each pattern)
+18 −1
Original line number Diff line number Diff line
@@ -1477,7 +1477,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
	void *symval;
	char *zeros = NULL;
	const char *type, *name, *modname;
	size_t typelen;
	size_t typelen, modnamelen;
	static const char *prefix = "__mod_device_table__";

	/* We're looking for a section relative symbol */
@@ -1500,6 +1500,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
	type = strstr(modname, "__");
	if (!type)
		return;
	modnamelen = type - modname;
	type += strlen("__");

	name = strstr(type, "__");
@@ -1526,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);
}
+15 −0
Original line number Diff line number Diff line
@@ -2067,11 +2067,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");

	add_exported_symbols(&buf, mod);

	buf_printf(&buf,
		   "#include <linux/module.h>\n"
		   "#undef __MODULE_INFO_PREFIX\n"
		   "#define __MODULE_INFO_PREFIX\n");

	list_for_each_entry_safe(alias, next, &mod->aliases, node) {
		buf_printf(&buf, "MODULE_INFO(%s.alias, \"%s\");\n",
			   alias->builtin_modname, alias->str);
		list_del(&alias->node);
		free(alias->builtin_modname);
		free(alias);
	}

	write_if_changed(&buf, ".vmlinux.export.c");
	free(buf.p);
}
Loading