diff options
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/.gitignore | 1 | ||||
| -rw-r--r-- | scripts/mod/devicetable-offsets.c | 3 | ||||
| -rw-r--r-- | scripts/mod/file2alias.c | 80 | ||||
| -rw-r--r-- | scripts/mod/mk_elfconfig.c | 1 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 117 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 2 | ||||
| -rw-r--r-- | scripts/mod/sumversion.c | 6 | 
7 files changed, 138 insertions, 72 deletions
diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore index 33bae0df4de..3bd11b60317 100644 --- a/scripts/mod/.gitignore +++ b/scripts/mod/.gitignore @@ -2,4 +2,3 @@ elfconfig.h  mk_elfconfig  modpost  devicetable-offsets.h - diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index bb5d115ca67..f282516acc7 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -174,6 +174,9 @@ int main(void)  	DEVID_FIELD(x86_cpu_id, model);  	DEVID_FIELD(x86_cpu_id, vendor); +	DEVID(cpu_feature); +	DEVID_FIELD(cpu_feature, feature); +  	DEVID(mei_cl_device_id);  	DEVID_FIELD(mei_cl_device_id, name); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 23708636b05..e614ef689ee 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -42,7 +42,7 @@ typedef unsigned char	__u8;  /* This array collects all instances that use the generic do_table */  struct devtable { -	const char *device_id; /* name of table, __mod_<name>_device_table. */ +	const char *device_id; /* name of table, __mod_<name>__*_device_table. */  	unsigned long id_size;  	void *function;  }; @@ -146,7 +146,8 @@ static void device_id_check(const char *modname, const char *device_id,  	if (size % id_size || size < id_size) {  		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " -		      "of the size of section __mod_%s_device_table=%lu.\n" +		      "of the size of " +		      "section __mod_%s__<identifier>_device_table=%lu.\n"  		      "Fix definition of struct %s_device_id "  		      "in mod_devicetable.h\n",  		      modname, device_id, id_size, device_id, size, device_id); @@ -210,8 +211,8 @@ static void do_usb_entry(void *symval,  				range_lo < 0x9 ? "[%X-9" : "[%X",  				range_lo);  			sprintf(alias + strlen(alias), -				range_hi > 0xA ? "a-%X]" : "%X]", -				range_lo); +				range_hi > 0xA ? "A-%X]" : "%X]", +				range_hi);  		}  	}  	if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) @@ -643,28 +644,26 @@ ADD_TO_DEVTABLE("pcmcia", pcmcia_device_id, do_pcmcia_entry);  static int do_of_entry (const char *filename, void *symval, char *alias)  { -    int len; -    char *tmp; -    DEF_FIELD_ADDR(symval, of_device_id, name); -    DEF_FIELD_ADDR(symval, of_device_id, type); -    DEF_FIELD_ADDR(symval, of_device_id, compatible); - -    len = sprintf (alias, "of:N%sT%s", -                    (*name)[0] ? *name : "*", -                    (*type)[0] ? *type : "*"); - -    if (compatible[0]) -        sprintf (&alias[len], "%sC%s", -                     (*type)[0] ? "*" : "", -                     *compatible); - -    /* Replace all whitespace with underscores */ -    for (tmp = alias; tmp && *tmp; tmp++) -        if (isspace (*tmp)) -            *tmp = '_'; - -    add_wildcard(alias); -    return 1; +	int len; +	char *tmp; +	DEF_FIELD_ADDR(symval, of_device_id, name); +	DEF_FIELD_ADDR(symval, of_device_id, type); +	DEF_FIELD_ADDR(symval, of_device_id, compatible); + +	len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*", +		      (*type)[0] ? *type : "*"); + +	if (compatible[0]) +		sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "", +			*compatible); + +	/* Replace all whitespace with underscores */ +	for (tmp = alias; tmp && *tmp; tmp++) +		if (isspace (*tmp)) +			*tmp = '_'; + +	add_wildcard(alias); +	return 1;  }  ADD_TO_DEVTABLE("of", of_device_id, do_of_entry); @@ -1110,7 +1109,7 @@ static int do_amba_entry(const char *filename,  }  ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry); -/* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* +/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*   * All fields are numbers. It would be nicer to use strings for vendor   * and feature, but getting those out of the build system here is too   * complicated. @@ -1124,10 +1123,10 @@ static int do_x86cpu_entry(const char *filename, void *symval,  	DEF_FIELD(symval, x86_cpu_id, model);  	DEF_FIELD(symval, x86_cpu_id, vendor); -	strcpy(alias, "x86cpu:"); -	ADD(alias, "vendor:",  vendor != X86_VENDOR_ANY, vendor); -	ADD(alias, ":family:", family != X86_FAMILY_ANY, family); -	ADD(alias, ":model:",  model  != X86_MODEL_ANY,  model); +	strcpy(alias, "cpu:type:x86,"); +	ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); +	ADD(alias, "fam", family != X86_FAMILY_ANY, family); +	ADD(alias, "mod", model  != X86_MODEL_ANY,  model);  	strcat(alias, ":feature:*");  	if (feature != X86_FEATURE_ANY)  		sprintf(alias + strlen(alias), "%04X*", feature); @@ -1135,6 +1134,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,  }  ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry); +/* LOOKS like cpu:type:*:feature:*FEAT* */ +static int do_cpu_entry(const char *filename, void *symval, char *alias) +{ +	DEF_FIELD(symval, cpu_feature, feature); + +	sprintf(alias, "cpu:type:*:feature:*%04X*", feature); +	return 1; +} +ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry); +  /* Looks like: mei:S */  static int do_mei_entry(const char *filename, void *symval,  			char *alias) @@ -1206,7 +1215,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,  {  	void *symval;  	char *zeros = NULL; -	const char *name; +	const char *name, *identifier;  	unsigned int namelen;  	/* We're looking for a section relative symbol */ @@ -1217,7 +1226,7 @@ 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 <prefix>__mod_XXX_device_table. */ +	/* All our symbols are of form <prefix>__mod_<name>__<identifier>_device_table. */  	name = strstr(symname, "__mod_");  	if (!name)  		return; @@ -1227,7 +1236,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,  		return;  	if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))  		return; -	namelen -= strlen("_device_table"); +	identifier = strstr(name, "__"); +	if (!identifier) +		return; +	namelen = identifier - name;  	/* Handle all-NULL symbols allocated into .bss */  	if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c index 639bca7ba55..a4fd71d71d6 100644 --- a/scripts/mod/mk_elfconfig.c +++ b/scripts/mod/mk_elfconfig.c @@ -54,4 +54,3 @@ main(int argc, char **argv)  	return 0;  } - diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8247979e8f6..9d9c5b905b3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -17,6 +17,7 @@  #include <string.h>  #include <limits.h>  #include <stdbool.h> +#include <errno.h>  #include "modpost.h"  #include "../../include/generated/autoconf.h"  #include "../../include/linux/license.h" @@ -37,6 +38,8 @@ static int warn_unresolved = 0;  /* How a symbol is exported */  static int sec_mismatch_count = 0;  static int sec_mismatch_verbose = 1; +/* ignore missing files */ +static int ignore_missing_files;  enum export {  	export_plain,      export_unused,     export_gpl, @@ -161,7 +164,7 @@ struct symbol {  	unsigned int vmlinux:1;    /* 1 if symbol is defined in vmlinux */  	unsigned int kernel:1;     /* 1 if symbol is from kernel  				    *  (only for external modules) **/ -	unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */ +	unsigned int preloaded:1;  /* 1 if symbol from Module.symvers, or crc */  	enum export  export;       /* Type of export */  	char name[0];  }; @@ -313,7 +316,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,  			     s->module->name,  			     is_vmlinux(s->module->name) ?"":".ko");  		} else { -			/* In case Modules.symvers was out of date */ +			/* In case Module.symvers was out of date */  			s->module = mod;  		}  	} @@ -329,8 +332,11 @@ static void sym_update_crc(const char *name, struct module *mod,  {  	struct symbol *s = find_symbol(name); -	if (!s) +	if (!s) {  		s = new_symbol(name, mod, export); +		/* Don't complain when we find it later. */ +		s->preloaded = 1; +	}  	s->crc = crc;  	s->crc_valid = 1;  } @@ -407,6 +413,11 @@ static int parse_elf(struct elf_info *info, const char *filename)  	hdr = grab_file(filename, &info->size);  	if (!hdr) { +		if (ignore_missing_files) { +			fprintf(stderr, "%s: %s (ignored)\n", filename, +				strerror(errno)); +			return 0; +		}  		perror(filename);  		exit(1);  	} @@ -573,12 +584,16 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)  		if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||  		    strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||  		    strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 || -		    strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0) +		    strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0 || +		    strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || +		    strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)  			return 1;  	if (info->hdr->e_machine == EM_PPC64)  		/* Special register function linked on all modules during final link of .ko */  		if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || -		    strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0) +		    strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 || +		    strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || +		    strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)  			return 1;  	/* Do not ignore this symbol */  	return 0; @@ -599,17 +614,19 @@ static void handle_modversions(struct module *mod, struct elf_info *info,  	else  		export = export_from_sec(info, get_secindex(info, sym)); +	/* CRC'd symbol */ +	if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { +		crc = (unsigned int) sym->st_value; +		sym_update_crc(symname + strlen(CRC_PFX), mod, crc, +				export); +	} +  	switch (sym->st_shndx) {  	case SHN_COMMON: -		warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); -		break; -	case SHN_ABS: -		/* CRC'd symbol */ -		if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { -			crc = (unsigned int) sym->st_value; -			sym_update_crc(symname + strlen(CRC_PFX), mod, crc, -					export); -		} +		if (!strncmp(symname, "__gnu_lto_", sizeof("__gnu_lto_")-1)) { +			/* Should warn here, but modpost runs before the linker */ +		} else +			warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);  		break;  	case SHN_UNDEF:  		/* undefined symbol */ @@ -835,6 +852,7 @@ static const char *section_white_list[] =  	".xt.lit",         /* xtensa */  	".arcextmap*",			/* arc */  	".gnu.linkonce.arcext*",	/* arc : modules */ +	".gnu.lto*",  	NULL  }; @@ -844,7 +862,7 @@ static const char *section_white_list[] =   * without "ax" / "aw".   */  static void check_section(const char *modname, struct elf_info *elf, -                          Elf_Shdr *sechdr) +			  Elf_Shdr *sechdr)  {  	const char *sec = sech_name(elf, sechdr); @@ -1278,12 +1296,12 @@ static void print_section_list(const char * const list[20])   */  static void report_sec_mismatch(const char *modname,  				const struct sectioncheck *mismatch, -                                const char *fromsec, -                                unsigned long long fromaddr, -                                const char *fromsym, -                                int from_is_func, -                                const char *tosec, const char *tosym, -                                int to_is_func) +				const char *fromsec, +				unsigned long long fromaddr, +				const char *fromsym, +				int from_is_func, +				const char *tosec, const char *tosym, +				int to_is_func)  {  	const char *from, *from_p;  	const char *to, *to_p; @@ -1423,7 +1441,7 @@ static void report_sec_mismatch(const char *modname,  }  static void check_section_mismatch(const char *modname, struct elf_info *elf, -                                   Elf_Rela *r, Elf_Sym *sym, const char *fromsec) +				   Elf_Rela *r, Elf_Sym *sym, const char *fromsec)  {  	const char *tosec;  	const struct sectioncheck *mismatch; @@ -1441,6 +1459,10 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf,  		to = find_elf_symbol(elf, r->r_addend, sym);  		tosym = sym_name(elf, to); +		if (!strncmp(fromsym, "reference___initcall", +				sizeof("reference___initcall")-1)) +			return; +  		/* check whitelist - we may ignore it */  		if (secref_whitelist(mismatch,  					fromsec, fromsym, tosec, tosym)) { @@ -1488,6 +1510,16 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  #define R_ARM_JUMP24	29  #endif +#ifndef	R_ARM_THM_CALL +#define	R_ARM_THM_CALL		10 +#endif +#ifndef	R_ARM_THM_JUMP24 +#define	R_ARM_THM_JUMP24	30 +#endif +#ifndef	R_ARM_THM_JUMP19 +#define	R_ARM_THM_JUMP19	51 +#endif +  static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  {  	unsigned int r_typ = ELF_R_TYPE(r->r_info); @@ -1496,15 +1528,18 @@ static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  	case R_ARM_ABS32:  		/* From ARM ABI: (S + A) | T */  		r->r_addend = (int)(long) -		              (elf->symtab_start + ELF_R_SYM(r->r_info)); +			      (elf->symtab_start + ELF_R_SYM(r->r_info));  		break;  	case R_ARM_PC24:  	case R_ARM_CALL:  	case R_ARM_JUMP24: +	case R_ARM_THM_CALL: +	case R_ARM_THM_JUMP24: +	case R_ARM_THM_JUMP19:  		/* From ARM ABI: ((S + A) | T) - P */  		r->r_addend = (int)(long)(elf->hdr + -		              sechdr->sh_offset + -		              (r->r_offset - sechdr->sh_addr)); +			      sechdr->sh_offset + +			      (r->r_offset - sechdr->sh_addr));  		break;  	default:  		return 1; @@ -1536,7 +1571,7 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  }  static void section_rela(const char *modname, struct elf_info *elf, -                         Elf_Shdr *sechdr) +			 Elf_Shdr *sechdr)  {  	Elf_Sym  *sym;  	Elf_Rela *rela; @@ -1580,7 +1615,7 @@ static void section_rela(const char *modname, struct elf_info *elf,  }  static void section_rel(const char *modname, struct elf_info *elf, -                        Elf_Shdr *sechdr) +			Elf_Shdr *sechdr)  {  	Elf_Sym *sym;  	Elf_Rel *rel; @@ -1650,7 +1685,7 @@ static void section_rel(const char *modname, struct elf_info *elf,   * be discarded and warns about it.   **/  static void check_sec_ref(struct module *mod, const char *modname, -                          struct elf_info *elf) +			  struct elf_info *elf)  {  	int i;  	Elf_Shdr *sechdrs = elf->sechdrs; @@ -1666,6 +1701,19 @@ static void check_sec_ref(struct module *mod, const char *modname,  	}  } +static char *remove_dot(char *s) +{ +	char *end; +	int n = strcspn(s, "."); + +	if (n > 0 && s[n] != 0) { +		strtoul(s + n + 1, &end, 10); +		if  (end > s + n + 1 && (*end == '.' || *end == 0)) +			s[n] = 0; +	} +	return s; +} +  static void read_symbols(char *modname)  {  	const char *symname; @@ -1704,7 +1752,7 @@ static void read_symbols(char *modname)  	}  	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { -		symname = info.strtab + sym->st_name; +		symname = remove_dot(info.strtab + sym->st_name);  		handle_modversions(mod, &info, sym, symname);  		handle_moddevtable(mod, &info, sym, symname); @@ -1853,7 +1901,7 @@ static void add_header(struct buffer *b, struct module *mod)  	buf_printf(b, "\n");  	buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");  	buf_printf(b, "\n"); -	buf_printf(b, "struct module __this_module\n"); +	buf_printf(b, "__visible struct module __this_module\n");  	buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");  	buf_printf(b, "\t.name = KBUILD_MODNAME,\n");  	if (mod->has_init) @@ -1897,7 +1945,7 @@ static int add_versions(struct buffer *b, struct module *mod)  					     s->name, mod->name);  				} else {  					merror("\"%s\" [%s.ko] undefined!\n", -					          s->name, mod->name); +					       s->name, mod->name);  					err = 1;  				}  			} @@ -2065,8 +2113,10 @@ static void read_dump(const char *fname, unsigned int kernel)  		s->preloaded = 1;  		sym_update_crc(symname, mod, crc, export_no(export));  	} +	release_file(file, size);  	return;  fail: +	release_file(file, size);  	fatal("parse error in symbol dump file\n");  } @@ -2119,7 +2169,7 @@ int main(int argc, char **argv)  	struct ext_sym_list *extsym_iter;  	struct ext_sym_list *extsym_start = NULL; -	while ((opt = getopt(argc, argv, "i:I:e:msST:o:awM:K:")) != -1) { +	while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:")) != -1) {  		switch (opt) {  		case 'i':  			kernel_read = optarg; @@ -2139,6 +2189,9 @@ int main(int argc, char **argv)  		case 'm':  			modversions = 1;  			break; +		case 'n': +			ignore_missing_files = 1; +			break;  		case 'o':  			dump_write = optarg;  			break; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 51207e4d5f8..168b43dc0a5 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -127,7 +127,7 @@ struct elf_info {  	Elf_Section  export_gpl_sec;  	Elf_Section  export_unused_gpl_sec;  	Elf_Section  export_gpl_future_sec; -	const char   *strtab; +	char         *strtab;  	char	     *modinfo;  	unsigned int modinfo_len; diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 9dfcd6d988d..944418da9fe 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -214,7 +214,7 @@ static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)  	mctx->block[14] = mctx->byte_count << 3;  	mctx->block[15] = mctx->byte_count >> 29;  	le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - -	                  sizeof(uint64_t)) / sizeof(uint32_t)); +			  sizeof(uint64_t)) / sizeof(uint32_t));  	md4_transform(mctx->hash, mctx->block);  	cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t)); @@ -367,7 +367,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)  			break;  		/* Terminate line at first space, to get rid of final ' \' */  		while (*p) { -                       if (isspace(*p)) { +			if (isspace(*p)) {  				*p = '\0';  				break;  			} @@ -416,7 +416,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)  		basename = strrchr(modname, '/') + 1;  	else  		basename = modname; -	sprintf(filelist, "%s/%.*s.mod", modverdir, +	snprintf(filelist, sizeof(filelist), "%s/%.*s.mod", modverdir,  		(int) strlen(basename) - 2, basename);  	file = grab_file(filelist, &len);  | 
