diff options
Diffstat (limited to 'scripts/mod/modpost.c')
| -rw-r--r-- | scripts/mod/modpost.c | 62 | 
1 files changed, 58 insertions, 4 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index dc907014108b..38ff3dd4a9a1 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -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 */ @@ -1806,6 +1808,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   **/  static void add_versions(struct buffer *b, struct module *mod) @@ -1828,9 +1873,14 @@ static void add_versions(struct buffer *b, struct module *mod)  			continue;  		}  		if (strlen(s->name) >= MODULE_NAME_LEN) { -			error("too long symbol \"%s\" [%s.ko]\n", -			      s->name, mod->name); -			break; +			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);  		}  | 
