diff options
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/.gitignore | 1 | ||||
| -rw-r--r-- | scripts/mod/Makefile | 13 | ||||
| -rw-r--r-- | scripts/mod/devicetable-offsets.c | 12 | ||||
| -rw-r--r-- | scripts/mod/file2alias.c | 122 | ||||
| -rw-r--r-- | scripts/mod/mk_elfconfig.c | 1 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 264 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 2 | ||||
| -rw-r--r-- | scripts/mod/sumversion.c | 6 |
8 files changed, 262 insertions, 159 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/Makefile b/scripts/mod/Makefile index 9415b566336..c11212ff351 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -15,8 +15,8 @@ endef quiet_cmd_offsets = GEN $@ define cmd_offsets (set -e; \ - echo "#ifndef __DEVICEVTABLE_OFFSETS_H__"; \ - echo "#define __DEVICEVTABLE_OFFSETS_H__"; \ + echo "#ifndef __DEVICETABLE_OFFSETS_H__"; \ + echo "#define __DEVICETABLE_OFFSETS_H__"; \ echo "/*"; \ echo " * DO NOT MODIFY."; \ echo " *"; \ @@ -29,13 +29,10 @@ define cmd_offsets echo "#endif" ) > $@ endef -# We use internal kbuild rules to avoid the "is up to date" message from make -scripts/mod/devicetable-offsets.s: scripts/mod/devicetable-offsets.c FORCE - $(Q)mkdir -p $(dir $@) - $(call if_changed_dep,cc_s_c) +$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s + $(call if_changed,offsets) -$(obj)/$(devicetable-offsets-file): scripts/mod/devicetable-offsets.s - $(call cmd,offsets) +targets += $(devicetable-offsets-file) devicetable-offsets.s # dependencies on generated files need to be listed explicitly diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index b45260bfeaa..f282516acc7 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -174,5 +174,17 @@ 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); + + DEVID(rio_device_id); + DEVID_FIELD(rio_device_id, did); + DEVID_FIELD(rio_device_id, vid); + DEVID_FIELD(rio_device_id, asm_did); + DEVID_FIELD(rio_device_id, asm_vid); + return 0; } diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 771ac17f635..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; }; @@ -79,10 +79,12 @@ struct devtable **__start___devtable, **__stop___devtable; extern struct devtable *__start___devtable[], *__stop___devtable[]; #endif /* __MACH__ */ -#if __GNUC__ == 3 && __GNUC_MINOR__ < 3 -# define __used __attribute__((__unused__)) -#else -# define __used __attribute__((__used__)) +#if !defined(__used) +# if __GNUC__ == 3 && __GNUC_MINOR__ < 3 +# define __used __attribute__((__unused__)) +# else +# define __used __attribute__((__used__)) +# endif #endif /* Define a variable f that holds the value of field f of struct devid @@ -144,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); @@ -208,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)) @@ -641,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); @@ -1108,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. @@ -1122,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); @@ -1133,6 +1134,48 @@ 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) +{ + DEF_FIELD_ADDR(symval, mei_cl_device_id, name); + + sprintf(alias, MEI_CL_MODULE_PREFIX "%s", *name); + + return 1; +} +ADD_TO_DEVTABLE("mei", mei_cl_device_id, do_mei_entry); + +/* Looks like: rapidio:vNdNavNadN */ +static int do_rio_entry(const char *filename, + void *symval, char *alias) +{ + DEF_FIELD(symval, rio_device_id, did); + DEF_FIELD(symval, rio_device_id, vid); + DEF_FIELD(symval, rio_device_id, asm_did); + DEF_FIELD(symval, rio_device_id, asm_vid); + + strcpy(alias, "rapidio:"); + ADD(alias, "v", vid != RIO_ANY_ID, vid); + ADD(alias, "d", did != RIO_ANY_ID, did); + ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid); + ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did); + + add_wildcard(alias); + return 1; +} +ADD_TO_DEVTABLE("rapidio", rio_device_id, do_rio_entry); + /* Does namelen bytes of name exactly match the symbol? */ static bool sym_is(const char *name, unsigned namelen, const char *symbol) { @@ -1172,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 */ @@ -1183,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; @@ -1193,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 78b30c1548e..9d9c5b905b3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -15,17 +15,13 @@ #include <stdio.h> #include <ctype.h> #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" - -/* Some toolchains use a `_' prefix for all user symbols. */ -#ifdef CONFIG_SYMBOL_PREFIX -#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX -#else -#define MODULE_SYMBOL_PREFIX "" -#endif - +#include "../../include/linux/export.h" /* Are we using CONFIG_MODVERSIONS? */ int modversions = 0; @@ -42,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, @@ -85,6 +83,14 @@ PRINTF void merror(const char *fmt, ...) va_end(arglist); } +static inline bool strends(const char *str, const char *postfix) +{ + if (strlen(str) < strlen(postfix)) + return false; + + return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; +} + static int is_vmlinux(const char *modname) { const char *myname; @@ -120,22 +126,20 @@ static struct module *find_module(char *modname) return mod; } -static struct module *new_module(char *modname) +static struct module *new_module(const char *modname) { struct module *mod; - char *p, *s; + char *p; mod = NOFAIL(malloc(sizeof(*mod))); memset(mod, 0, sizeof(*mod)); p = NOFAIL(strdup(modname)); /* strip trailing .o */ - s = strrchr(p, '.'); - if (s != NULL) - if (strcmp(s, ".o") == 0) { - *s = '\0'; - mod->is_dot_o = 1; - } + if (strends(p, ".o")) { + p[strlen(p) - 2] = '\0'; + mod->is_dot_o = 1; + } /* add to list */ mod->name = p; @@ -160,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]; }; @@ -312,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; } } @@ -328,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; } @@ -406,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); } @@ -562,7 +574,7 @@ static void parse_elf_finish(struct elf_info *info) static int ignore_undef_symbol(struct elf_info *info, const char *symname) { /* ignore __this_module, it will be resolved shortly */ - if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) + if (strcmp(symname, VMLINUX_SYMBOL_STR(__this_module)) == 0) return 1; /* ignore global offset table */ if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) @@ -572,19 +584,23 @@ 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; } -#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_" -#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" +#define CRC_PFX VMLINUX_SYMBOL_STR(__crc_) +#define KSYMTAB_PFX VMLINUX_SYMBOL_STR(__ksymtab_) static void handle_modversions(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname) @@ -598,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 */ @@ -637,14 +655,15 @@ static void handle_modversions(struct module *mod, struct elf_info *info, } #endif - if (memcmp(symname, MODULE_SYMBOL_PREFIX, - strlen(MODULE_SYMBOL_PREFIX)) == 0) { - mod->unres = - alloc_symbol(symname + - strlen(MODULE_SYMBOL_PREFIX), - ELF_ST_BIND(sym->st_info) == STB_WEAK, - mod->unres); - } +#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX + if (symname[0] != '_') + break; + else + symname++; +#endif + mod->unres = alloc_symbol(symname, + ELF_ST_BIND(sym->st_info) == STB_WEAK, + mod->unres); break; default: /* All exported symbols */ @@ -652,9 +671,9 @@ static void handle_modversions(struct module *mod, struct elf_info *info, sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, export); } - if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) + if (strcmp(symname, VMLINUX_SYMBOL_STR(init_module)) == 0) mod->has_init = 1; - if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0) + if (strcmp(symname, VMLINUX_SYMBOL_STR(cleanup_module)) == 0) mod->has_cleanup = 1; break; } @@ -819,6 +838,7 @@ static const char *section_white_list[] = { ".comment*", ".debug*", + ".cranges", /* sh64 */ ".zdebug*", /* Compressed debug sections. */ ".GCC-command-line", /* mn10300 */ ".GCC.command.line", /* record-gcc-switches, non mn10300 */ @@ -832,6 +852,7 @@ static const char *section_white_list[] = ".xt.lit", /* xtensa */ ".arcextmap*", /* arc */ ".gnu.linkonce.arcext*", /* arc : modules */ + ".gnu.lto*", NULL }; @@ -841,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); @@ -859,37 +880,34 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_INIT_DATA_SECTIONS \ - ".init.setup$", ".init.rodata$", \ - ".cpuinit.rodata$", ".meminit.rodata$", \ - ".init.data$", ".cpuinit.data$", ".meminit.data$" + ".init.setup$", ".init.rodata$", ".meminit.rodata$", \ + ".init.data$", ".meminit.data$" #define ALL_EXIT_DATA_SECTIONS \ - ".exit.data$", ".cpuexit.data$", ".memexit.data$" + ".exit.data$", ".memexit.data$" #define ALL_INIT_TEXT_SECTIONS \ - ".init.text$", ".cpuinit.text$", ".meminit.text$" + ".init.text$", ".meminit.text$" #define ALL_EXIT_TEXT_SECTIONS \ - ".exit.text$", ".cpuexit.text$", ".memexit.text$" + ".exit.text$", ".memexit.text$" #define ALL_PCI_INIT_SECTIONS \ ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ ".pci_fixup_enable$", ".pci_fixup_resume$", \ ".pci_fixup_resume_early$", ".pci_fixup_suspend$" -#define ALL_XXXINIT_SECTIONS CPU_INIT_SECTIONS, MEM_INIT_SECTIONS -#define ALL_XXXEXIT_SECTIONS CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS +#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS +#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS #define DATA_SECTIONS ".data$", ".data.rel$" -#define TEXT_SECTIONS ".text$" +#define TEXT_SECTIONS ".text$", ".text.unlikely$" #define INIT_SECTIONS ".init.*" -#define CPU_INIT_SECTIONS ".cpuinit.*" #define MEM_INIT_SECTIONS ".meminit.*" #define EXIT_SECTIONS ".exit.*" -#define CPU_EXIT_SECTIONS ".cpuexit.*" #define MEM_EXIT_SECTIONS ".memexit.*" /* init data sections */ @@ -977,48 +995,20 @@ const struct sectioncheck sectioncheck[] = { .mismatch = DATA_TO_ANY_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference init code/data from cpuinit/meminit code/data */ +/* Do not reference init code/data from meminit code/data */ { .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference cpuinit code/data from meminit code/data */ -{ - .fromsec = { MEM_INIT_SECTIONS, NULL }, - .tosec = { CPU_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_SOME_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference meminit code/data from cpuinit code/data */ -{ - .fromsec = { CPU_INIT_SECTIONS, NULL }, - .tosec = { MEM_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_SOME_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference exit code/data from cpuexit/memexit code/data */ +/* Do not reference exit code/data from memexit code/data */ { .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .tosec = { EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference cpuexit code/data from memexit code/data */ -{ - .fromsec = { MEM_EXIT_SECTIONS, NULL }, - .tosec = { CPU_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_SOME_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference memexit code/data from cpuexit code/data */ -{ - .fromsec = { CPU_EXIT_SECTIONS, NULL }, - .tosec = { MEM_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_SOME_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, /* Do not use exit code/data from init code */ { .fromsec = { ALL_INIT_SECTIONS, NULL }, @@ -1087,8 +1077,6 @@ static const struct sectioncheck *section_mismatch( * Pattern 2: * Many drivers utilise a *driver container with references to * add, remove, probe functions etc. - * These functions may often be marked __cpuinit and we do not want to - * warn here. * the pattern is identified by: * tosec = init or exit section * fromsec = data section @@ -1247,7 +1235,6 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, /* * Convert a section name to the function/data attribute * .init.text => __init - * .cpuinit.data => __cpudata * .memexitconst => __memconst * etc. * @@ -1309,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; @@ -1454,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; @@ -1472,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)) { @@ -1519,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); @@ -1527,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; @@ -1567,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; @@ -1611,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; @@ -1681,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; @@ -1697,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; @@ -1735,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); @@ -1762,6 +1779,27 @@ static void read_symbols(char *modname) mod->unres = alloc_symbol("module_layout", 0, mod->unres); } +static void read_symbols_from_files(const char *filename) +{ + FILE *in = stdin; + char fname[PATH_MAX]; + + if (strcmp(filename, "-") != 0) { + in = fopen(filename, "r"); + if (!in) + fatal("Can't open filenames file %s: %m", filename); + } + + while (fgets(fname, PATH_MAX, in) != NULL) { + if (strends(fname, "\n")) + fname[strlen(fname)-1] = '\0'; + read_symbols(fname); + } + + if (in != stdin) + fclose(in); +} + #define SZ 500 /* We first write the generated file into memory using the @@ -1863,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) @@ -1907,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; } } @@ -1934,7 +1972,8 @@ static int add_versions(struct buffer *b, struct module *mod) s->name, mod->name); continue; } - buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name); + buf_printf(b, "\t{ %#8x, __VMLINUX_SYMBOL_STR(%s) },\n", + s->crc, s->name); } buf_printf(b, "};\n"); @@ -2074,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"); } @@ -2122,13 +2163,13 @@ int main(int argc, char **argv) struct module *mod; struct buffer buf = { }; char *kernel_read = NULL, *module_read = NULL; - char *dump_write = NULL; + char *dump_write = NULL, *files_source = NULL; int opt; int err; struct ext_sym_list *extsym_iter; struct ext_sym_list *extsym_start = NULL; - while ((opt = getopt(argc, argv, "i:I:e:msSo:awM:K:")) != -1) { + while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:")) != -1) { switch (opt) { case 'i': kernel_read = optarg; @@ -2148,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; @@ -2160,6 +2204,9 @@ int main(int argc, char **argv) case 'S': sec_mismatch_verbose = 0; break; + case 'T': + files_source = optarg; + break; case 'w': warn_unresolved = 1; break; @@ -2182,6 +2229,9 @@ int main(int argc, char **argv) while (optind < argc) read_symbols(argv[optind++]); + if (files_source) + read_symbols_from_files(files_source); + for (mod = modules; mod; mod = mod->next) { if (mod->skip) continue; 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); |
