Commit fc7d5e32 authored by Matthew Maurer's avatar Matthew Maurer Committed by Masahiro Yamada
Browse files

modpost: Produce extended MODVERSIONS information



Generate both the existing modversions format and the new extended one
when running modpost. Presence of this metadata in the final .ko is
guarded by CONFIG_EXTENDED_MODVERSIONS.

We no longer generate an error on long symbols in modpost if
CONFIG_EXTENDED_MODVERSIONS is set, as they can now be appropriately
encoded in the extended section. These symbols will be skipped in the
previous encoding. An error will still be generated if
CONFIG_EXTENDED_MODVERSIONS is not set.

Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
Signed-off-by: default avatarMatthew Maurer <mmaurer@google.com>
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
parent 54ac1ac8
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -207,6 +207,16 @@ config ASM_MODVERSIONS
	  assembly. This can be enabled only when the target architecture
	  supports it.

config EXTENDED_MODVERSIONS
	bool "Extended Module Versioning Support"
	depends on MODVERSIONS
	help
	  This enables extended MODVERSIONs support, allowing long symbol
	  names to be versioned.

	  The most likely reason you would enable this is to enable Rust
	  support. If unsure, say N.

config MODULE_SRCVERSION_ALL
	bool "Source checksum for all modules"
	help
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ MODPOST = $(objtree)/scripts/mod/modpost
modpost-args =										\
	$(if $(CONFIG_MODULES),-M)							\
	$(if $(CONFIG_MODVERSIONS),-m)							\
	$(if $(CONFIG_EXTENDED_MODVERSIONS),-x)						\
	$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a)					\
	$(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E)					\
	$(if $(KBUILD_MODPOST_WARN),-w)							\
+58 −4
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ static bool module_enabled;
static bool modversions;
/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
static bool all_versions;
/* Is CONFIG_EXTENDED_MODVERSIONS set? */
static bool extended_modversions;
/* If we are modposting external module set to 1 */
static bool external_module;
/* Only warn about unresolved symbols */
@@ -1805,6 +1807,49 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)
	}
}

/**
 * Record CRCs for unresolved symbols, supporting long names
 */
static void add_extended_versions(struct buffer *b, struct module *mod)
{
	struct symbol *s;

	if (!extended_modversions)
		return;

	buf_printf(b, "\n");
	buf_printf(b, "static const u32 ____version_ext_crcs[]\n");
	buf_printf(b, "__used __section(\"__version_ext_crcs\") = {\n");
	list_for_each_entry(s, &mod->unresolved_symbols, list) {
		if (!s->module)
			continue;
		if (!s->crc_valid) {
			warn("\"%s\" [%s.ko] has no CRC!\n",
				s->name, mod->name);
			continue;
		}
		buf_printf(b, "\t0x%08x,\n", s->crc);
	}
	buf_printf(b, "};\n");

	buf_printf(b, "static const char ____version_ext_names[]\n");
	buf_printf(b, "__used __section(\"__version_ext_names\") =\n");
	list_for_each_entry(s, &mod->unresolved_symbols, list) {
		if (!s->module)
			continue;
		if (!s->crc_valid)
			/*
			 * We already warned on this when producing the crc
			 * table.
			 * We need to skip its name too, as the indexes in
			 * both tables need to align.
			 */
			continue;
		buf_printf(b, "\t\"%s\\0\"\n", s->name);
	}
	buf_printf(b, ";\n");
}

/**
 * Record CRCs for unresolved symbols
 **/
@@ -1828,10 +1873,15 @@ static void add_versions(struct buffer *b, struct module *mod)
			continue;
		}
		if (strlen(s->name) >= MODULE_NAME_LEN) {
			if (extended_modversions) {
				/* this symbol will only be in the extended info */
				continue;
			} else {
				error("too long symbol \"%s\" [%s.ko]\n",
				      s->name, mod->name);
				break;
			}
		}
		buf_printf(b, "\t{ 0x%08x, \"%s\" },\n",
			   s->crc, s->name);
	}
@@ -1961,6 +2011,7 @@ static void write_mod_c_file(struct module *mod)
	add_header(&buf, mod);
	add_exported_symbols(&buf, mod);
	add_versions(&buf, mod);
	add_extended_versions(&buf, mod);
	add_depends(&buf, mod);

	buf_printf(&buf, "\n");
@@ -2126,7 +2177,7 @@ int main(int argc, char **argv)
	LIST_HEAD(dump_lists);
	struct dump_list *dl, *dl2;

	while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:")) != -1) {
	while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:x")) != -1) {
		switch (opt) {
		case 'e':
			external_module = true;
@@ -2175,6 +2226,9 @@ int main(int argc, char **argv)
		case 'd':
			missing_namespace_deps = optarg;
			break;
		case 'x':
			extended_modversions = true;
			break;
		default:
			exit(1);
		}