diff options
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/mk_elfconfig.c | 6 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 219 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 6 |
3 files changed, 209 insertions, 22 deletions
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c index 3c92c83733f4..725d61c0fb43 100644 --- a/scripts/mod/mk_elfconfig.c +++ b/scripts/mod/mk_elfconfig.c | |||
| @@ -28,7 +28,7 @@ main(int argc, char **argv) | |||
| 28 | printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); | 28 | printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); |
| 29 | break; | 29 | break; |
| 30 | default: | 30 | default: |
| 31 | abort(); | 31 | exit(1); |
| 32 | } | 32 | } |
| 33 | switch (ei[EI_DATA]) { | 33 | switch (ei[EI_DATA]) { |
| 34 | case ELFDATA2LSB: | 34 | case ELFDATA2LSB: |
| @@ -38,7 +38,7 @@ main(int argc, char **argv) | |||
| 38 | printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); | 38 | printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); |
| 39 | break; | 39 | break; |
| 40 | default: | 40 | default: |
| 41 | abort(); | 41 | exit(1); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | if (sizeof(unsigned long) == 4) { | 44 | if (sizeof(unsigned long) == 4) { |
| @@ -53,7 +53,7 @@ main(int argc, char **argv) | |||
| 53 | else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) | 53 | else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) |
| 54 | printf("#define HOST_ELFDATA ELFDATA2LSB\n"); | 54 | printf("#define HOST_ELFDATA ELFDATA2LSB\n"); |
| 55 | else | 55 | else |
| 56 | abort(); | 56 | exit(1); |
| 57 | 57 | ||
| 58 | if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) | 58 | if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) |
| 59 | printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); | 59 | printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index d0f86ed43f7a..dfde0e87a765 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <ctype.h> | 14 | #include <ctype.h> |
| 15 | #include "modpost.h" | 15 | #include "modpost.h" |
| 16 | #include "../../include/linux/license.h" | ||
| 16 | 17 | ||
| 17 | /* Are we using CONFIG_MODVERSIONS? */ | 18 | /* Are we using CONFIG_MODVERSIONS? */ |
| 18 | int modversions = 0; | 19 | int modversions = 0; |
| @@ -22,6 +23,11 @@ int have_vmlinux = 0; | |||
| 22 | static int all_versions = 0; | 23 | static int all_versions = 0; |
| 23 | /* If we are modposting external module set to 1 */ | 24 | /* If we are modposting external module set to 1 */ |
| 24 | static int external_module = 0; | 25 | static int external_module = 0; |
| 26 | /* How a symbol is exported */ | ||
| 27 | enum export { | ||
| 28 | export_plain, export_unused, export_gpl, | ||
| 29 | export_unused_gpl, export_gpl_future, export_unknown | ||
| 30 | }; | ||
| 25 | 31 | ||
| 26 | void fatal(const char *fmt, ...) | 32 | void fatal(const char *fmt, ...) |
| 27 | { | 33 | { |
| @@ -97,6 +103,7 @@ static struct module *new_module(char *modname) | |||
| 97 | 103 | ||
| 98 | /* add to list */ | 104 | /* add to list */ |
| 99 | mod->name = p; | 105 | mod->name = p; |
| 106 | mod->gpl_compatible = -1; | ||
| 100 | mod->next = modules; | 107 | mod->next = modules; |
| 101 | modules = mod; | 108 | modules = mod; |
| 102 | 109 | ||
| @@ -118,6 +125,7 @@ struct symbol { | |||
| 118 | unsigned int kernel:1; /* 1 if symbol is from kernel | 125 | unsigned int kernel:1; /* 1 if symbol is from kernel |
| 119 | * (only for external modules) **/ | 126 | * (only for external modules) **/ |
| 120 | unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ | 127 | unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ |
| 128 | enum export export; /* Type of export */ | ||
| 121 | char name[0]; | 129 | char name[0]; |
| 122 | }; | 130 | }; |
| 123 | 131 | ||
| @@ -153,7 +161,8 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak, | |||
| 153 | } | 161 | } |
| 154 | 162 | ||
| 155 | /* For the hash of exported symbols */ | 163 | /* For the hash of exported symbols */ |
| 156 | static struct symbol *new_symbol(const char *name, struct module *module) | 164 | static struct symbol *new_symbol(const char *name, struct module *module, |
| 165 | enum export export) | ||
| 157 | { | 166 | { |
| 158 | unsigned int hash; | 167 | unsigned int hash; |
| 159 | struct symbol *new; | 168 | struct symbol *new; |
| @@ -161,6 +170,7 @@ static struct symbol *new_symbol(const char *name, struct module *module) | |||
| 161 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; | 170 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; |
| 162 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); | 171 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); |
| 163 | new->module = module; | 172 | new->module = module; |
| 173 | new->export = export; | ||
| 164 | return new; | 174 | return new; |
| 165 | } | 175 | } |
| 166 | 176 | ||
| @@ -179,16 +189,63 @@ static struct symbol *find_symbol(const char *name) | |||
| 179 | return NULL; | 189 | return NULL; |
| 180 | } | 190 | } |
| 181 | 191 | ||
| 192 | static struct { | ||
| 193 | const char *str; | ||
| 194 | enum export export; | ||
| 195 | } export_list[] = { | ||
| 196 | { .str = "EXPORT_SYMBOL", .export = export_plain }, | ||
| 197 | { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, | ||
| 198 | { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, | ||
| 199 | { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, | ||
| 200 | { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, | ||
| 201 | { .str = "(unknown)", .export = export_unknown }, | ||
| 202 | }; | ||
| 203 | |||
| 204 | |||
| 205 | static const char *export_str(enum export ex) | ||
| 206 | { | ||
| 207 | return export_list[ex].str; | ||
| 208 | } | ||
| 209 | |||
| 210 | static enum export export_no(const char * s) | ||
| 211 | { | ||
| 212 | int i; | ||
| 213 | if (!s) | ||
| 214 | return export_unknown; | ||
| 215 | for (i = 0; export_list[i].export != export_unknown; i++) { | ||
| 216 | if (strcmp(export_list[i].str, s) == 0) | ||
| 217 | return export_list[i].export; | ||
| 218 | } | ||
| 219 | return export_unknown; | ||
| 220 | } | ||
| 221 | |||
| 222 | static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) | ||
| 223 | { | ||
| 224 | if (sec == elf->export_sec) | ||
| 225 | return export_plain; | ||
| 226 | else if (sec == elf->export_unused_sec) | ||
| 227 | return export_unused; | ||
| 228 | else if (sec == elf->export_gpl_sec) | ||
| 229 | return export_gpl; | ||
| 230 | else if (sec == elf->export_unused_gpl_sec) | ||
| 231 | return export_unused_gpl; | ||
| 232 | else if (sec == elf->export_gpl_future_sec) | ||
| 233 | return export_gpl_future; | ||
| 234 | else | ||
| 235 | return export_unknown; | ||
| 236 | } | ||
| 237 | |||
| 182 | /** | 238 | /** |
| 183 | * Add an exported symbol - it may have already been added without a | 239 | * Add an exported symbol - it may have already been added without a |
| 184 | * CRC, in this case just update the CRC | 240 | * CRC, in this case just update the CRC |
| 185 | **/ | 241 | **/ |
| 186 | static struct symbol *sym_add_exported(const char *name, struct module *mod) | 242 | static struct symbol *sym_add_exported(const char *name, struct module *mod, |
| 243 | enum export export) | ||
| 187 | { | 244 | { |
| 188 | struct symbol *s = find_symbol(name); | 245 | struct symbol *s = find_symbol(name); |
| 189 | 246 | ||
| 190 | if (!s) { | 247 | if (!s) { |
| 191 | s = new_symbol(name, mod); | 248 | s = new_symbol(name, mod, export); |
| 192 | } else { | 249 | } else { |
| 193 | if (!s->preloaded) { | 250 | if (!s->preloaded) { |
| 194 | warn("%s: '%s' exported twice. Previous export " | 251 | warn("%s: '%s' exported twice. Previous export " |
| @@ -200,16 +257,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod) | |||
| 200 | s->preloaded = 0; | 257 | s->preloaded = 0; |
| 201 | s->vmlinux = is_vmlinux(mod->name); | 258 | s->vmlinux = is_vmlinux(mod->name); |
| 202 | s->kernel = 0; | 259 | s->kernel = 0; |
| 260 | s->export = export; | ||
| 203 | return s; | 261 | return s; |
| 204 | } | 262 | } |
| 205 | 263 | ||
| 206 | static void sym_update_crc(const char *name, struct module *mod, | 264 | static void sym_update_crc(const char *name, struct module *mod, |
| 207 | unsigned int crc) | 265 | unsigned int crc, enum export export) |
| 208 | { | 266 | { |
| 209 | struct symbol *s = find_symbol(name); | 267 | struct symbol *s = find_symbol(name); |
| 210 | 268 | ||
| 211 | if (!s) | 269 | if (!s) |
| 212 | s = new_symbol(name, mod); | 270 | s = new_symbol(name, mod, export); |
| 213 | s->crc = crc; | 271 | s->crc = crc; |
| 214 | s->crc_valid = 1; | 272 | s->crc_valid = 1; |
| 215 | } | 273 | } |
| @@ -283,7 +341,7 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
| 283 | hdr = grab_file(filename, &info->size); | 341 | hdr = grab_file(filename, &info->size); |
| 284 | if (!hdr) { | 342 | if (!hdr) { |
| 285 | perror(filename); | 343 | perror(filename); |
| 286 | abort(); | 344 | exit(1); |
| 287 | } | 345 | } |
| 288 | info->hdr = hdr; | 346 | info->hdr = hdr; |
| 289 | if (info->size < sizeof(*hdr)) | 347 | if (info->size < sizeof(*hdr)) |
| @@ -309,13 +367,25 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
| 309 | for (i = 1; i < hdr->e_shnum; i++) { | 367 | for (i = 1; i < hdr->e_shnum; i++) { |
| 310 | const char *secstrings | 368 | const char *secstrings |
| 311 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 369 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
| 370 | const char *secname; | ||
| 312 | 371 | ||
| 313 | if (sechdrs[i].sh_offset > info->size) | 372 | if (sechdrs[i].sh_offset > info->size) |
| 314 | goto truncated; | 373 | goto truncated; |
| 315 | if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) { | 374 | secname = secstrings + sechdrs[i].sh_name; |
| 375 | if (strcmp(secname, ".modinfo") == 0) { | ||
| 316 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; | 376 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; |
| 317 | info->modinfo_len = sechdrs[i].sh_size; | 377 | info->modinfo_len = sechdrs[i].sh_size; |
| 318 | } | 378 | } else if (strcmp(secname, "__ksymtab") == 0) |
| 379 | info->export_sec = i; | ||
| 380 | else if (strcmp(secname, "__ksymtab_unused") == 0) | ||
| 381 | info->export_unused_sec = i; | ||
| 382 | else if (strcmp(secname, "__ksymtab_gpl") == 0) | ||
| 383 | info->export_gpl_sec = i; | ||
| 384 | else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) | ||
| 385 | info->export_unused_gpl_sec = i; | ||
| 386 | else if (strcmp(secname, "__ksymtab_gpl_future") == 0) | ||
| 387 | info->export_gpl_future_sec = i; | ||
| 388 | |||
| 319 | if (sechdrs[i].sh_type != SHT_SYMTAB) | 389 | if (sechdrs[i].sh_type != SHT_SYMTAB) |
| 320 | continue; | 390 | continue; |
| 321 | 391 | ||
| @@ -353,6 +423,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 353 | Elf_Sym *sym, const char *symname) | 423 | Elf_Sym *sym, const char *symname) |
| 354 | { | 424 | { |
| 355 | unsigned int crc; | 425 | unsigned int crc; |
| 426 | enum export export = export_from_sec(info, sym->st_shndx); | ||
| 356 | 427 | ||
| 357 | switch (sym->st_shndx) { | 428 | switch (sym->st_shndx) { |
| 358 | case SHN_COMMON: | 429 | case SHN_COMMON: |
| @@ -362,7 +433,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 362 | /* CRC'd symbol */ | 433 | /* CRC'd symbol */ |
| 363 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { | 434 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { |
| 364 | crc = (unsigned int) sym->st_value; | 435 | crc = (unsigned int) sym->st_value; |
| 365 | sym_update_crc(symname + strlen(CRC_PFX), mod, crc); | 436 | sym_update_crc(symname + strlen(CRC_PFX), mod, crc, |
| 437 | export); | ||
| 366 | } | 438 | } |
| 367 | break; | 439 | break; |
| 368 | case SHN_UNDEF: | 440 | case SHN_UNDEF: |
| @@ -406,7 +478,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 406 | default: | 478 | default: |
| 407 | /* All exported symbols */ | 479 | /* All exported symbols */ |
| 408 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { | 480 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { |
| 409 | sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); | 481 | sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, |
| 482 | export); | ||
| 410 | } | 483 | } |
| 411 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) | 484 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) |
| 412 | mod->has_init = 1; | 485 | mod->has_init = 1; |
| @@ -437,13 +510,18 @@ static char *next_string(char *string, unsigned long *secsize) | |||
| 437 | return string; | 510 | return string; |
| 438 | } | 511 | } |
| 439 | 512 | ||
| 440 | static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | 513 | static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, |
| 441 | const char *tag) | 514 | const char *tag, char *info) |
| 442 | { | 515 | { |
| 443 | char *p; | 516 | char *p; |
| 444 | unsigned int taglen = strlen(tag); | 517 | unsigned int taglen = strlen(tag); |
| 445 | unsigned long size = modinfo_len; | 518 | unsigned long size = modinfo_len; |
| 446 | 519 | ||
| 520 | if (info) { | ||
| 521 | size -= info - (char *)modinfo; | ||
| 522 | modinfo = next_string(info, &size); | ||
| 523 | } | ||
| 524 | |||
| 447 | for (p = modinfo; p; p = next_string(p, &size)) { | 525 | for (p = modinfo; p; p = next_string(p, &size)) { |
| 448 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') | 526 | if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') |
| 449 | return p + taglen + 1; | 527 | return p + taglen + 1; |
| @@ -451,6 +529,13 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | |||
| 451 | return NULL; | 529 | return NULL; |
| 452 | } | 530 | } |
| 453 | 531 | ||
| 532 | static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | ||
| 533 | const char *tag) | ||
| 534 | |||
| 535 | { | ||
| 536 | return get_next_modinfo(modinfo, modinfo_len, tag, NULL); | ||
| 537 | } | ||
| 538 | |||
| 454 | /** | 539 | /** |
| 455 | * Test if string s ends in string sub | 540 | * Test if string s ends in string sub |
| 456 | * return 0 if match | 541 | * return 0 if match |
| @@ -821,6 +906,10 @@ static int init_section_ref_ok(const char *name) | |||
| 821 | ".pci_fixup_final", | 906 | ".pci_fixup_final", |
| 822 | ".pdr", | 907 | ".pdr", |
| 823 | "__param", | 908 | "__param", |
| 909 | "__ex_table", | ||
| 910 | ".fixup", | ||
| 911 | ".smp_locks", | ||
| 912 | ".plt", /* seen on ARCH=um build on x86_64. Harmless */ | ||
| 824 | NULL | 913 | NULL |
| 825 | }; | 914 | }; |
| 826 | /* Start of section names */ | 915 | /* Start of section names */ |
| @@ -846,6 +935,8 @@ static int init_section_ref_ok(const char *name) | |||
| 846 | for (s = namelist3; *s; s++) | 935 | for (s = namelist3; *s; s++) |
| 847 | if (strstr(name, *s) != NULL) | 936 | if (strstr(name, *s) != NULL) |
| 848 | return 1; | 937 | return 1; |
| 938 | if (strrcmp(name, ".init") == 0) | ||
| 939 | return 1; | ||
| 849 | return 0; | 940 | return 0; |
| 850 | } | 941 | } |
| 851 | 942 | ||
| @@ -892,6 +983,10 @@ static int exit_section_ref_ok(const char *name) | |||
| 892 | ".exitcall.exit", | 983 | ".exitcall.exit", |
| 893 | ".eh_frame", | 984 | ".eh_frame", |
| 894 | ".stab", | 985 | ".stab", |
| 986 | "__ex_table", | ||
| 987 | ".fixup", | ||
| 988 | ".smp_locks", | ||
| 989 | ".plt", /* seen on ARCH=um build on x86_64. Harmless */ | ||
| 895 | NULL | 990 | NULL |
| 896 | }; | 991 | }; |
| 897 | /* Start of section names */ | 992 | /* Start of section names */ |
| @@ -921,6 +1016,7 @@ static void read_symbols(char *modname) | |||
| 921 | { | 1016 | { |
| 922 | const char *symname; | 1017 | const char *symname; |
| 923 | char *version; | 1018 | char *version; |
| 1019 | char *license; | ||
| 924 | struct module *mod; | 1020 | struct module *mod; |
| 925 | struct elf_info info = { }; | 1021 | struct elf_info info = { }; |
| 926 | Elf_Sym *sym; | 1022 | Elf_Sym *sym; |
| @@ -936,6 +1032,18 @@ static void read_symbols(char *modname) | |||
| 936 | mod->skip = 1; | 1032 | mod->skip = 1; |
| 937 | } | 1033 | } |
| 938 | 1034 | ||
| 1035 | license = get_modinfo(info.modinfo, info.modinfo_len, "license"); | ||
| 1036 | while (license) { | ||
| 1037 | if (license_is_gpl_compatible(license)) | ||
| 1038 | mod->gpl_compatible = 1; | ||
| 1039 | else { | ||
| 1040 | mod->gpl_compatible = 0; | ||
| 1041 | break; | ||
| 1042 | } | ||
| 1043 | license = get_next_modinfo(info.modinfo, info.modinfo_len, | ||
| 1044 | "license", license); | ||
| 1045 | } | ||
| 1046 | |||
| 939 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { | 1047 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
| 940 | symname = info.strtab + sym->st_name; | 1048 | symname = info.strtab + sym->st_name; |
| 941 | 1049 | ||
| @@ -992,6 +1100,67 @@ void buf_write(struct buffer *buf, const char *s, int len) | |||
| 992 | buf->pos += len; | 1100 | buf->pos += len; |
| 993 | } | 1101 | } |
| 994 | 1102 | ||
| 1103 | static void check_for_gpl_usage(enum export exp, const char *m, const char *s) | ||
| 1104 | { | ||
| 1105 | const char *e = is_vmlinux(m) ?"":".ko"; | ||
| 1106 | |||
| 1107 | switch (exp) { | ||
| 1108 | case export_gpl: | ||
| 1109 | fatal("modpost: GPL-incompatible module %s%s " | ||
| 1110 | "uses GPL-only symbol '%s'\n", m, e, s); | ||
| 1111 | break; | ||
| 1112 | case export_unused_gpl: | ||
| 1113 | fatal("modpost: GPL-incompatible module %s%s " | ||
| 1114 | "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); | ||
| 1115 | break; | ||
| 1116 | case export_gpl_future: | ||
| 1117 | warn("modpost: GPL-incompatible module %s%s " | ||
| 1118 | "uses future GPL-only symbol '%s'\n", m, e, s); | ||
| 1119 | break; | ||
| 1120 | case export_plain: | ||
| 1121 | case export_unused: | ||
| 1122 | case export_unknown: | ||
| 1123 | /* ignore */ | ||
| 1124 | break; | ||
| 1125 | } | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | static void check_for_unused(enum export exp, const char* m, const char* s) | ||
| 1129 | { | ||
| 1130 | const char *e = is_vmlinux(m) ?"":".ko"; | ||
| 1131 | |||
| 1132 | switch (exp) { | ||
| 1133 | case export_unused: | ||
| 1134 | case export_unused_gpl: | ||
| 1135 | warn("modpost: module %s%s " | ||
| 1136 | "uses symbol '%s' marked UNUSED\n", m, e, s); | ||
| 1137 | break; | ||
| 1138 | default: | ||
| 1139 | /* ignore */ | ||
| 1140 | break; | ||
| 1141 | } | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | static void check_exports(struct module *mod) | ||
| 1145 | { | ||
| 1146 | struct symbol *s, *exp; | ||
| 1147 | |||
| 1148 | for (s = mod->unres; s; s = s->next) { | ||
| 1149 | const char *basename; | ||
| 1150 | exp = find_symbol(s->name); | ||
| 1151 | if (!exp || exp->module == mod) | ||
| 1152 | continue; | ||
| 1153 | basename = strrchr(mod->name, '/'); | ||
| 1154 | if (basename) | ||
| 1155 | basename++; | ||
| 1156 | else | ||
| 1157 | basename = mod->name; | ||
| 1158 | if (!mod->gpl_compatible) | ||
| 1159 | check_for_gpl_usage(exp->export, basename, exp->name); | ||
| 1160 | check_for_unused(exp->export, basename, exp->name); | ||
| 1161 | } | ||
| 1162 | } | ||
| 1163 | |||
| 995 | /** | 1164 | /** |
| 996 | * Header for the generated file | 1165 | * Header for the generated file |
| 997 | **/ | 1166 | **/ |
| @@ -1142,6 +1311,9 @@ static void write_if_changed(struct buffer *b, const char *fname) | |||
| 1142 | fclose(file); | 1311 | fclose(file); |
| 1143 | } | 1312 | } |
| 1144 | 1313 | ||
| 1314 | /* parse Module.symvers file. line format: | ||
| 1315 | * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something] | ||
| 1316 | **/ | ||
| 1145 | static void read_dump(const char *fname, unsigned int kernel) | 1317 | static void read_dump(const char *fname, unsigned int kernel) |
| 1146 | { | 1318 | { |
| 1147 | unsigned long size, pos = 0; | 1319 | unsigned long size, pos = 0; |
| @@ -1153,7 +1325,7 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1153 | return; | 1325 | return; |
| 1154 | 1326 | ||
| 1155 | while ((line = get_next_line(&pos, file, size))) { | 1327 | while ((line = get_next_line(&pos, file, size))) { |
| 1156 | char *symname, *modname, *d; | 1328 | char *symname, *modname, *d, *export, *end; |
| 1157 | unsigned int crc; | 1329 | unsigned int crc; |
| 1158 | struct module *mod; | 1330 | struct module *mod; |
| 1159 | struct symbol *s; | 1331 | struct symbol *s; |
| @@ -1164,8 +1336,10 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1164 | if (!(modname = strchr(symname, '\t'))) | 1336 | if (!(modname = strchr(symname, '\t'))) |
| 1165 | goto fail; | 1337 | goto fail; |
| 1166 | *modname++ = '\0'; | 1338 | *modname++ = '\0'; |
| 1167 | if (strchr(modname, '\t')) | 1339 | if ((export = strchr(modname, '\t')) != NULL) |
| 1168 | goto fail; | 1340 | *export++ = '\0'; |
| 1341 | if (export && ((end = strchr(export, '\t')) != NULL)) | ||
| 1342 | *end = '\0'; | ||
| 1169 | crc = strtoul(line, &d, 16); | 1343 | crc = strtoul(line, &d, 16); |
| 1170 | if (*symname == '\0' || *modname == '\0' || *d != '\0') | 1344 | if (*symname == '\0' || *modname == '\0' || *d != '\0') |
| 1171 | goto fail; | 1345 | goto fail; |
| @@ -1177,10 +1351,10 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1177 | mod = new_module(NOFAIL(strdup(modname))); | 1351 | mod = new_module(NOFAIL(strdup(modname))); |
| 1178 | mod->skip = 1; | 1352 | mod->skip = 1; |
| 1179 | } | 1353 | } |
| 1180 | s = sym_add_exported(symname, mod); | 1354 | s = sym_add_exported(symname, mod, export_no(export)); |
| 1181 | s->kernel = kernel; | 1355 | s->kernel = kernel; |
| 1182 | s->preloaded = 1; | 1356 | s->preloaded = 1; |
| 1183 | sym_update_crc(symname, mod, crc); | 1357 | sym_update_crc(symname, mod, crc, export_no(export)); |
| 1184 | } | 1358 | } |
| 1185 | return; | 1359 | return; |
| 1186 | fail: | 1360 | fail: |
| @@ -1210,9 +1384,10 @@ static void write_dump(const char *fname) | |||
| 1210 | symbol = symbolhash[n]; | 1384 | symbol = symbolhash[n]; |
| 1211 | while (symbol) { | 1385 | while (symbol) { |
| 1212 | if (dump_sym(symbol)) | 1386 | if (dump_sym(symbol)) |
| 1213 | buf_printf(&buf, "0x%08x\t%s\t%s\n", | 1387 | buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", |
| 1214 | symbol->crc, symbol->name, | 1388 | symbol->crc, symbol->name, |
| 1215 | symbol->module->name); | 1389 | symbol->module->name, |
| 1390 | export_str(symbol->export)); | ||
| 1216 | symbol = symbol->next; | 1391 | symbol = symbol->next; |
| 1217 | } | 1392 | } |
| 1218 | } | 1393 | } |
| @@ -1263,6 +1438,12 @@ int main(int argc, char **argv) | |||
| 1263 | for (mod = modules; mod; mod = mod->next) { | 1438 | for (mod = modules; mod; mod = mod->next) { |
| 1264 | if (mod->skip) | 1439 | if (mod->skip) |
| 1265 | continue; | 1440 | continue; |
| 1441 | check_exports(mod); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | for (mod = modules; mod; mod = mod->next) { | ||
| 1445 | if (mod->skip) | ||
| 1446 | continue; | ||
| 1266 | 1447 | ||
| 1267 | buf.pos = 0; | 1448 | buf.pos = 0; |
| 1268 | 1449 | ||
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 861d866fcd83..d398c61e55ef 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
| @@ -100,6 +100,7 @@ buf_write(struct buffer *buf, const char *s, int len); | |||
| 100 | struct module { | 100 | struct module { |
| 101 | struct module *next; | 101 | struct module *next; |
| 102 | const char *name; | 102 | const char *name; |
| 103 | int gpl_compatible; | ||
| 103 | struct symbol *unres; | 104 | struct symbol *unres; |
| 104 | int seen; | 105 | int seen; |
| 105 | int skip; | 106 | int skip; |
| @@ -115,6 +116,11 @@ struct elf_info { | |||
| 115 | Elf_Shdr *sechdrs; | 116 | Elf_Shdr *sechdrs; |
| 116 | Elf_Sym *symtab_start; | 117 | Elf_Sym *symtab_start; |
| 117 | Elf_Sym *symtab_stop; | 118 | Elf_Sym *symtab_stop; |
| 119 | Elf_Section export_sec; | ||
| 120 | Elf_Section export_unused_sec; | ||
| 121 | Elf_Section export_gpl_sec; | ||
| 122 | Elf_Section export_unused_gpl_sec; | ||
| 123 | Elf_Section export_gpl_future_sec; | ||
| 118 | const char *strtab; | 124 | const char *strtab; |
| 119 | char *modinfo; | 125 | char *modinfo; |
| 120 | unsigned int modinfo_len; | 126 | unsigned int modinfo_len; |
