aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/file2alias.c17
-rw-r--r--scripts/mod/mk_elfconfig.c4
-rw-r--r--scripts/mod/modpost.c698
-rw-r--r--scripts/mod/modpost.h25
-rw-r--r--scripts/mod/sumversion.c32
5 files changed, 607 insertions, 169 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index c164b230ad6f..84e21201f3c0 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -34,7 +34,7 @@ typedef uint16_t __u16;
34typedef unsigned char __u8; 34typedef unsigned char __u8;
35 35
36/* Big exception to the "don't include kernel headers into userspace, which 36/* Big exception to the "don't include kernel headers into userspace, which
37 * even potentially has different endianness and word sizes, since 37 * even potentially has different endianness and word sizes, since
38 * we handle those differences explicitly below */ 38 * we handle those differences explicitly below */
39#include "../../include/linux/mod_devicetable.h" 39#include "../../include/linux/mod_devicetable.h"
40#include "../../include/linux/input.h" 40#include "../../include/linux/input.h"
@@ -153,8 +153,8 @@ static void do_usb_table(void *symval, unsigned long size,
153 const unsigned long id_size = sizeof(struct usb_device_id); 153 const unsigned long id_size = sizeof(struct usb_device_id);
154 154
155 if (size % id_size || size < id_size) { 155 if (size % id_size || size < id_size) {
156 fprintf(stderr, "*** Warning: %s ids %lu bad size " 156 warn("%s ids %lu bad size "
157 "(each on %lu)\n", mod->name, size, id_size); 157 "(each on %lu)\n", mod->name, size, id_size);
158 } 158 }
159 /* Leave last one: it's the terminator. */ 159 /* Leave last one: it's the terminator. */
160 size -= id_size; 160 size -= id_size;
@@ -217,9 +217,8 @@ static int do_pci_entry(const char *filename,
217 if ((baseclass_mask != 0 && baseclass_mask != 0xFF) 217 if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
218 || (subclass_mask != 0 && subclass_mask != 0xFF) 218 || (subclass_mask != 0 && subclass_mask != 0xFF)
219 || (interface_mask != 0 && interface_mask != 0xFF)) { 219 || (interface_mask != 0 && interface_mask != 0xFF)) {
220 fprintf(stderr, 220 warn("Can't handle masks in %s:%04X\n",
221 "*** Warning: Can't handle masks in %s:%04X\n", 221 filename, id->class_mask);
222 filename, id->class_mask);
223 return 0; 222 return 0;
224 } 223 }
225 224
@@ -229,7 +228,7 @@ static int do_pci_entry(const char *filename,
229 return 1; 228 return 1;
230} 229}
231 230
232/* looks like: "ccw:tNmNdtNdmN" */ 231/* looks like: "ccw:tNmNdtNdmN" */
233static int do_ccw_entry(const char *filename, 232static int do_ccw_entry(const char *filename,
234 struct ccw_device_id *id, char *alias) 233 struct ccw_device_id *id, char *alias)
235{ 234{
@@ -445,8 +444,8 @@ static void do_table(void *symval, unsigned long size,
445 int (*do_entry)(const char *, void *entry, char *alias) = function; 444 int (*do_entry)(const char *, void *entry, char *alias) = function;
446 445
447 if (size % id_size || size < id_size) { 446 if (size % id_size || size < id_size) {
448 fprintf(stderr, "*** Warning: %s ids %lu bad size " 447 warn("%s ids %lu bad size "
449 "(each on %lu)\n", mod->name, size, id_size); 448 "(each on %lu)\n", mod->name, size, id_size);
450 } 449 }
451 /* Leave last one: it's the terminator. */ 450 /* Leave last one: it's the terminator. */
452 size -= id_size; 451 size -= id_size;
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index de2aabf89fb3..3c92c83733f4 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -6,7 +6,7 @@
6int 6int
7main(int argc, char **argv) 7main(int argc, char **argv)
8{ 8{
9 unsigned char ei[EI_NIDENT]; 9 unsigned char ei[EI_NIDENT];
10 union { short s; char c[2]; } endian_test; 10 union { short s; char c[2]; } endian_test;
11 11
12 if (argc != 2) { 12 if (argc != 2) {
@@ -57,7 +57,7 @@ main(int argc, char **argv)
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");
60 else 60 else
61 printf("#define MODULE_SYMBOL_PREFIX \"\"\n"); 61 printf("#define MODULE_SYMBOL_PREFIX \"\"\n");
62 62
63 return 0; 63 return 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index b8b2a560b26b..0b92ddff26fd 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -2,7 +2,7 @@
2 * 2 *
3 * Copyright 2003 Kai Germaschewski 3 * Copyright 2003 Kai Germaschewski
4 * Copyright 2002-2004 Rusty Russell, IBM Corporation 4 * Copyright 2002-2004 Rusty Russell, IBM Corporation
5 * 5 * Copyright 2006 Sam Ravnborg
6 * Based in part on module-init-tools/depmod.c,file2alias 6 * Based in part on module-init-tools/depmod.c,file2alias
7 * 7 *
8 * This software may be used and distributed according to the terms 8 * This software may be used and distributed according to the terms
@@ -20,9 +20,10 @@ int modversions = 0;
20int have_vmlinux = 0; 20int have_vmlinux = 0;
21/* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 21/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
22static int all_versions = 0; 22static int all_versions = 0;
23/* If we are modposting external module set to 1 */
24static int external_module = 0;
23 25
24void 26void fatal(const char *fmt, ...)
25fatal(const char *fmt, ...)
26{ 27{
27 va_list arglist; 28 va_list arglist;
28 29
@@ -35,8 +36,7 @@ fatal(const char *fmt, ...)
35 exit(1); 36 exit(1);
36} 37}
37 38
38void 39void warn(const char *fmt, ...)
39warn(const char *fmt, ...)
40{ 40{
41 va_list arglist; 41 va_list arglist;
42 42
@@ -47,6 +47,18 @@ warn(const char *fmt, ...)
47 va_end(arglist); 47 va_end(arglist);
48} 48}
49 49
50static int is_vmlinux(const char *modname)
51{
52 const char *myname;
53
54 if ((myname = strrchr(modname, '/')))
55 myname++;
56 else
57 myname = modname;
58
59 return strcmp(myname, "vmlinux") == 0;
60}
61
50void *do_nofail(void *ptr, const char *expr) 62void *do_nofail(void *ptr, const char *expr)
51{ 63{
52 if (!ptr) { 64 if (!ptr) {
@@ -59,8 +71,7 @@ void *do_nofail(void *ptr, const char *expr)
59 71
60static struct module *modules; 72static struct module *modules;
61 73
62struct module * 74static struct module *find_module(char *modname)
63find_module(char *modname)
64{ 75{
65 struct module *mod; 76 struct module *mod;
66 77
@@ -70,12 +81,11 @@ find_module(char *modname)
70 return mod; 81 return mod;
71} 82}
72 83
73struct module * 84static struct module *new_module(char *modname)
74new_module(char *modname)
75{ 85{
76 struct module *mod; 86 struct module *mod;
77 char *p, *s; 87 char *p, *s;
78 88
79 mod = NOFAIL(malloc(sizeof(*mod))); 89 mod = NOFAIL(malloc(sizeof(*mod)));
80 memset(mod, 0, sizeof(*mod)); 90 memset(mod, 0, sizeof(*mod));
81 p = NOFAIL(strdup(modname)); 91 p = NOFAIL(strdup(modname));
@@ -104,6 +114,10 @@ struct symbol {
104 unsigned int crc; 114 unsigned int crc;
105 int crc_valid; 115 int crc_valid;
106 unsigned int weak:1; 116 unsigned int weak:1;
117 unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
118 unsigned int kernel:1; /* 1 if symbol is from kernel
119 * (only for external modules) **/
120 unsigned int preloaded:1; /* 1 if symbol from Module.symvers */
107 char name[0]; 121 char name[0];
108}; 122};
109 123
@@ -122,11 +136,12 @@ static inline unsigned int tdb_hash(const char *name)
122 return (1103515243 * value + 12345); 136 return (1103515243 * value + 12345);
123} 137}
124 138
125/* Allocate a new symbols for use in the hash of exported symbols or 139/**
126 * the list of unresolved symbols per module */ 140 * Allocate a new symbols for use in the hash of exported symbols or
127 141 * the list of unresolved symbols per module
128struct symbol * 142 **/
129alloc_symbol(const char *name, unsigned int weak, struct symbol *next) 143static struct symbol *alloc_symbol(const char *name, unsigned int weak,
144 struct symbol *next)
130{ 145{
131 struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); 146 struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
132 147
@@ -138,9 +153,7 @@ alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
138} 153}
139 154
140/* For the hash of exported symbols */ 155/* For the hash of exported symbols */
141 156static struct symbol *new_symbol(const char *name, struct module *module)
142void
143new_symbol(const char *name, struct module *module, unsigned int *crc)
144{ 157{
145 unsigned int hash; 158 unsigned int hash;
146 struct symbol *new; 159 struct symbol *new;
@@ -148,14 +161,10 @@ new_symbol(const char *name, struct module *module, unsigned int *crc)
148 hash = tdb_hash(name) % SYMBOL_HASH_SIZE; 161 hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
149 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); 162 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
150 new->module = module; 163 new->module = module;
151 if (crc) { 164 return new;
152 new->crc = *crc;
153 new->crc_valid = 1;
154 }
155} 165}
156 166
157struct symbol * 167static struct symbol *find_symbol(const char *name)
158find_symbol(const char *name)
159{ 168{
160 struct symbol *s; 169 struct symbol *s;
161 170
@@ -170,25 +179,42 @@ find_symbol(const char *name)
170 return NULL; 179 return NULL;
171} 180}
172 181
173/* Add an exported symbol - it may have already been added without a 182/**
174 * CRC, in this case just update the CRC */ 183 * Add an exported symbol - it may have already been added without a
175void 184 * CRC, in this case just update the CRC
176add_exported_symbol(const char *name, struct module *module, unsigned int *crc) 185 **/
186static struct symbol *sym_add_exported(const char *name, struct module *mod)
177{ 187{
178 struct symbol *s = find_symbol(name); 188 struct symbol *s = find_symbol(name);
179 189
180 if (!s) { 190 if (!s) {
181 new_symbol(name, module, crc); 191 s = new_symbol(name, mod);
182 return; 192 } else {
183 } 193 if (!s->preloaded) {
184 if (crc) { 194 warn("%s: '%s' exported twice. Previous export "
185 s->crc = *crc; 195 "was in %s%s\n", mod->name, name,
186 s->crc_valid = 1; 196 s->module->name,
197 is_vmlinux(s->module->name) ?"":".ko");
198 }
187 } 199 }
200 s->preloaded = 0;
201 s->vmlinux = is_vmlinux(mod->name);
202 s->kernel = 0;
203 return s;
204}
205
206static void sym_update_crc(const char *name, struct module *mod,
207 unsigned int crc)
208{
209 struct symbol *s = find_symbol(name);
210
211 if (!s)
212 s = new_symbol(name, mod);
213 s->crc = crc;
214 s->crc_valid = 1;
188} 215}
189 216
190void * 217void *grab_file(const char *filename, unsigned long *size)
191grab_file(const char *filename, unsigned long *size)
192{ 218{
193 struct stat st; 219 struct stat st;
194 void *map; 220 void *map;
@@ -207,13 +233,12 @@ grab_file(const char *filename, unsigned long *size)
207 return map; 233 return map;
208} 234}
209 235
210/* 236/**
211 Return a copy of the next line in a mmap'ed file. 237 * Return a copy of the next line in a mmap'ed file.
212 spaces in the beginning of the line is trimmed away. 238 * spaces in the beginning of the line is trimmed away.
213 Return a pointer to a static buffer. 239 * Return a pointer to a static buffer.
214*/ 240 **/
215char* 241char* get_next_line(unsigned long *pos, void *file, unsigned long size)
216get_next_line(unsigned long *pos, void *file, unsigned long size)
217{ 242{
218 static char line[4096]; 243 static char line[4096];
219 int skip = 1; 244 int skip = 1;
@@ -243,14 +268,12 @@ get_next_line(unsigned long *pos, void *file, unsigned long size)
243 return NULL; 268 return NULL;
244} 269}
245 270
246void 271void release_file(void *file, unsigned long size)
247release_file(void *file, unsigned long size)
248{ 272{
249 munmap(file, size); 273 munmap(file, size);
250} 274}
251 275
252void 276static void parse_elf(struct elf_info *info, const char *filename)
253parse_elf(struct elf_info *info, const char *filename)
254{ 277{
255 unsigned int i; 278 unsigned int i;
256 Elf_Ehdr *hdr = info->hdr; 279 Elf_Ehdr *hdr = info->hdr;
@@ -297,14 +320,13 @@ parse_elf(struct elf_info *info, const char *filename)
297 continue; 320 continue;
298 321
299 info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; 322 info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
300 info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset 323 info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
301 + sechdrs[i].sh_size; 324 + sechdrs[i].sh_size;
302 info->strtab = (void *)hdr + 325 info->strtab = (void *)hdr +
303 sechdrs[sechdrs[i].sh_link].sh_offset; 326 sechdrs[sechdrs[i].sh_link].sh_offset;
304 } 327 }
305 if (!info->symtab_start) { 328 if (!info->symtab_start) {
306 fprintf(stderr, "modpost: %s no symtab?\n", filename); 329 fatal("%s has no symtab?\n", filename);
307 abort();
308 } 330 }
309 /* Fix endianness in symbols */ 331 /* Fix endianness in symbols */
310 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { 332 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
@@ -316,36 +338,31 @@ parse_elf(struct elf_info *info, const char *filename)
316 return; 338 return;
317 339
318 truncated: 340 truncated:
319 fprintf(stderr, "modpost: %s is truncated.\n", filename); 341 fatal("%s is truncated.\n", filename);
320 abort();
321} 342}
322 343
323void 344static void parse_elf_finish(struct elf_info *info)
324parse_elf_finish(struct elf_info *info)
325{ 345{
326 release_file(info->hdr, info->size); 346 release_file(info->hdr, info->size);
327} 347}
328 348
329#define CRC_PFX "__crc_" 349#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
330#define KSYMTAB_PFX "__ksymtab_" 350#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
331 351
332void 352static void handle_modversions(struct module *mod, struct elf_info *info,
333handle_modversions(struct module *mod, struct elf_info *info, 353 Elf_Sym *sym, const char *symname)
334 Elf_Sym *sym, const char *symname)
335{ 354{
336 unsigned int crc; 355 unsigned int crc;
337 356
338 switch (sym->st_shndx) { 357 switch (sym->st_shndx) {
339 case SHN_COMMON: 358 case SHN_COMMON:
340 fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n", 359 warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
341 symname, mod->name);
342 break; 360 break;
343 case SHN_ABS: 361 case SHN_ABS:
344 /* CRC'd symbol */ 362 /* CRC'd symbol */
345 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { 363 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
346 crc = (unsigned int) sym->st_value; 364 crc = (unsigned int) sym->st_value;
347 add_exported_symbol(symname + strlen(CRC_PFX), 365 sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
348 mod, &crc);
349 } 366 }
350 break; 367 break;
351 case SHN_UNDEF: 368 case SHN_UNDEF:
@@ -370,15 +387,15 @@ handle_modversions(struct module *mod, struct elf_info *info,
370 /* Ignore register directives. */ 387 /* Ignore register directives. */
371 if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) 388 if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
372 break; 389 break;
373 if (symname[0] == '.') { 390 if (symname[0] == '.') {
374 char *munged = strdup(symname); 391 char *munged = strdup(symname);
375 munged[0] = '_'; 392 munged[0] = '_';
376 munged[1] = toupper(munged[1]); 393 munged[1] = toupper(munged[1]);
377 symname = munged; 394 symname = munged;
378 } 395 }
379 } 396 }
380#endif 397#endif
381 398
382 if (memcmp(symname, MODULE_SYMBOL_PREFIX, 399 if (memcmp(symname, MODULE_SYMBOL_PREFIX,
383 strlen(MODULE_SYMBOL_PREFIX)) == 0) 400 strlen(MODULE_SYMBOL_PREFIX)) == 0)
384 mod->unres = alloc_symbol(symname + 401 mod->unres = alloc_symbol(symname +
@@ -389,8 +406,7 @@ handle_modversions(struct module *mod, struct elf_info *info,
389 default: 406 default:
390 /* All exported symbols */ 407 /* All exported symbols */
391 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { 408 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
392 add_exported_symbol(symname + strlen(KSYMTAB_PFX), 409 sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
393 mod, NULL);
394 } 410 }
395 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) 411 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
396 mod->has_init = 1; 412 mod->has_init = 1;
@@ -400,20 +416,9 @@ handle_modversions(struct module *mod, struct elf_info *info,
400 } 416 }
401} 417}
402 418
403int 419/**
404is_vmlinux(const char *modname) 420 * Parse tag=value strings from .modinfo section
405{ 421 **/
406 const char *myname;
407
408 if ((myname = strrchr(modname, '/')))
409 myname++;
410 else
411 myname = modname;
412
413 return strcmp(myname, "vmlinux") == 0;
414}
415
416/* Parse tag=value strings from .modinfo section */
417static char *next_string(char *string, unsigned long *secsize) 422static char *next_string(char *string, unsigned long *secsize)
418{ 423{
419 /* Skip non-zero chars */ 424 /* Skip non-zero chars */
@@ -446,8 +451,418 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
446 return NULL; 451 return NULL;
447} 452}
448 453
449void 454/**
450read_symbols(char *modname) 455 * Test if string s ends in string sub
456 * return 0 if match
457 **/
458static int strrcmp(const char *s, const char *sub)
459{
460 int slen, sublen;
461
462 if (!s || !sub)
463 return 1;
464
465 slen = strlen(s);
466 sublen = strlen(sub);
467
468 if ((slen == 0) || (sublen == 0))
469 return 1;
470
471 if (sublen > slen)
472 return 1;
473
474 return memcmp(s + slen - sublen, sub, sublen);
475}
476
477/**
478 * Whitelist to allow certain references to pass with no warning.
479 * Pattern 1:
480 * If a module parameter is declared __initdata and permissions=0
481 * then this is legal despite the warning generated.
482 * We cannot see value of permissions here, so just ignore
483 * this pattern.
484 * The pattern is identified by:
485 * tosec = .init.data
486 * fromsec = .data*
487 * atsym =__param*
488 *
489 * Pattern 2:
490 * Many drivers utilise a *_driver container with references to
491 * add, remove, probe functions etc.
492 * These functions may often be marked __init and we do not want to
493 * warn here.
494 * the pattern is identified by:
495 * tosec = .init.text | .exit.text
496 * fromsec = .data
497 * atsym = *_driver, *_ops, *_probe, *probe_one
498 **/
499static int secref_whitelist(const char *tosec, const char *fromsec,
500 const char *atsym)
501{
502 int f1 = 1, f2 = 1;
503 const char **s;
504 const char *pat2sym[] = {
505 "_driver",
506 "_ops",
507 "_probe",
508 "_probe_one",
509 NULL
510 };
511
512 /* Check for pattern 1 */
513 if (strcmp(tosec, ".init.data") != 0)
514 f1 = 0;
515 if (strncmp(fromsec, ".data", strlen(".data")) != 0)
516 f1 = 0;
517 if (strncmp(atsym, "__param", strlen("__param")) != 0)
518 f1 = 0;
519
520 if (f1)
521 return f1;
522
523 /* Check for pattern 2 */
524 if ((strcmp(tosec, ".init.text") != 0) &&
525 (strcmp(tosec, ".exit.text") != 0))
526 f2 = 0;
527 if (strcmp(fromsec, ".data") != 0)
528 f2 = 0;
529
530 for (s = pat2sym; *s; s++)
531 if (strrcmp(atsym, *s) == 0)
532 f1 = 1;
533
534 return f1 && f2;
535}
536
537/**
538 * Find symbol based on relocation record info.
539 * In some cases the symbol supplied is a valid symbol so
540 * return refsym. If st_name != 0 we assume this is a valid symbol.
541 * In other cases the symbol needs to be looked up in the symbol table
542 * based on section and address.
543 * **/
544static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
545 Elf_Sym *relsym)
546{
547 Elf_Sym *sym;
548
549 if (relsym->st_name != 0)
550 return relsym;
551 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
552 if (sym->st_shndx != relsym->st_shndx)
553 continue;
554 if (sym->st_value == addr)
555 return sym;
556 }
557 return NULL;
558}
559
560/*
561 * Find symbols before or equal addr and after addr - in the section sec.
562 * If we find two symbols with equal offset prefer one with a valid name.
563 * The ELF format may have a better way to detect what type of symbol
564 * it is, but this works for now.
565 **/
566static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
567 const char *sec,
568 Elf_Sym **before, Elf_Sym **after)
569{
570 Elf_Sym *sym;
571 Elf_Ehdr *hdr = elf->hdr;
572 Elf_Addr beforediff = ~0;
573 Elf_Addr afterdiff = ~0;
574 const char *secstrings = (void *)hdr +
575 elf->sechdrs[hdr->e_shstrndx].sh_offset;
576
577 *before = NULL;
578 *after = NULL;
579
580 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
581 const char *symsec;
582
583 if (sym->st_shndx >= SHN_LORESERVE)
584 continue;
585 symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
586 if (strcmp(symsec, sec) != 0)
587 continue;
588 if (sym->st_value <= addr) {
589 if ((addr - sym->st_value) < beforediff) {
590 beforediff = addr - sym->st_value;
591 *before = sym;
592 }
593 else if ((addr - sym->st_value) == beforediff) {
594 /* equal offset, valid name? */
595 const char *name = elf->strtab + sym->st_name;
596 if (name && strlen(name))
597 *before = sym;
598 }
599 }
600 else
601 {
602 if ((sym->st_value - addr) < afterdiff) {
603 afterdiff = sym->st_value - addr;
604 *after = sym;
605 }
606 else if ((sym->st_value - addr) == afterdiff) {
607 /* equal offset, valid name? */
608 const char *name = elf->strtab + sym->st_name;
609 if (name && strlen(name))
610 *after = sym;
611 }
612 }
613 }
614}
615
616/**
617 * Print a warning about a section mismatch.
618 * Try to find symbols near it so user can find it.
619 * Check whitelist before warning - it may be a false positive.
620 **/
621static void warn_sec_mismatch(const char *modname, const char *fromsec,
622 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
623{
624 const char *refsymname = "";
625 Elf_Sym *before, *after;
626 Elf_Sym *refsym;
627 Elf_Ehdr *hdr = elf->hdr;
628 Elf_Shdr *sechdrs = elf->sechdrs;
629 const char *secstrings = (void *)hdr +
630 sechdrs[hdr->e_shstrndx].sh_offset;
631 const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name;
632
633 find_symbols_between(elf, r.r_offset, fromsec, &before, &after);
634
635 refsym = find_elf_symbol(elf, r.r_addend, sym);
636 if (refsym && strlen(elf->strtab + refsym->st_name))
637 refsymname = elf->strtab + refsym->st_name;
638
639 /* check whitelist - we may ignore it */
640 if (before &&
641 secref_whitelist(secname, fromsec, elf->strtab + before->st_name))
642 return;
643
644 if (before && after) {
645 warn("%s - Section mismatch: reference to %s:%s from %s "
646 "between '%s' (at offset 0x%llx) and '%s'\n",
647 modname, secname, refsymname, fromsec,
648 elf->strtab + before->st_name,
649 (long long)r.r_offset,
650 elf->strtab + after->st_name);
651 } else if (before) {
652 warn("%s - Section mismatch: reference to %s:%s from %s "
653 "after '%s' (at offset 0x%llx)\n",
654 modname, secname, refsymname, fromsec,
655 elf->strtab + before->st_name,
656 (long long)r.r_offset);
657 } else if (after) {
658 warn("%s - Section mismatch: reference to %s:%s from %s "
659 "before '%s' (at offset -0x%llx)\n",
660 modname, secname, refsymname, fromsec,
661 elf->strtab + before->st_name,
662 (long long)r.r_offset);
663 } else {
664 warn("%s - Section mismatch: reference to %s:%s from %s "
665 "(offset 0x%llx)\n",
666 modname, secname, fromsec, refsymname,
667 (long long)r.r_offset);
668 }
669}
670
671/**
672 * A module includes a number of sections that are discarded
673 * either when loaded or when used as built-in.
674 * For loaded modules all functions marked __init and all data
675 * marked __initdata will be discarded when the module has been intialized.
676 * Likewise for modules used built-in the sections marked __exit
677 * are discarded because __exit marked function are supposed to be called
678 * only when a moduel is unloaded which never happes for built-in modules.
679 * The check_sec_ref() function traverses all relocation records
680 * to find all references to a section that reference a section that will
681 * be discarded and warns about it.
682 **/
683static void check_sec_ref(struct module *mod, const char *modname,
684 struct elf_info *elf,
685 int section(const char*),
686 int section_ref_ok(const char *))
687{
688 int i;
689 Elf_Sym *sym;
690 Elf_Ehdr *hdr = elf->hdr;
691 Elf_Shdr *sechdrs = elf->sechdrs;
692 const char *secstrings = (void *)hdr +
693 sechdrs[hdr->e_shstrndx].sh_offset;
694
695 /* Walk through all sections */
696 for (i = 0; i < hdr->e_shnum; i++) {
697 Elf_Rela *rela;
698 Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
699 Elf_Rela *stop = (void*)start + sechdrs[i].sh_size;
700 const char *name = secstrings + sechdrs[i].sh_name +
701 strlen(".rela");
702 /* We want to process only relocation sections and not .init */
703 if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
704 continue;
705
706 for (rela = start; rela < stop; rela++) {
707 Elf_Rela r;
708 const char *secname;
709 r.r_offset = TO_NATIVE(rela->r_offset);
710 r.r_info = TO_NATIVE(rela->r_info);
711 r.r_addend = TO_NATIVE(rela->r_addend);
712 sym = elf->symtab_start + ELF_R_SYM(r.r_info);
713 /* Skip special sections */
714 if (sym->st_shndx >= SHN_LORESERVE)
715 continue;
716
717 secname = secstrings + sechdrs[sym->st_shndx].sh_name;
718 if (section(secname))
719 warn_sec_mismatch(modname, name, elf, sym, r);
720 }
721 }
722}
723
724/**
725 * Functions used only during module init is marked __init and is stored in
726 * a .init.text section. Likewise data is marked __initdata and stored in
727 * a .init.data section.
728 * If this section is one of these sections return 1
729 * See include/linux/init.h for the details
730 **/
731static int init_section(const char *name)
732{
733 if (strcmp(name, ".init") == 0)
734 return 1;
735 if (strncmp(name, ".init.", strlen(".init.")) == 0)
736 return 1;
737 return 0;
738}
739
740/**
741 * Identify sections from which references to a .init section is OK.
742 *
743 * Unfortunately references to read only data that referenced .init
744 * sections had to be excluded. Almost all of these are false
745 * positives, they are created by gcc. The downside of excluding rodata
746 * is that there really are some user references from rodata to
747 * init code, e.g. drivers/video/vgacon.c:
748 *
749 * const struct consw vga_con = {
750 * con_startup: vgacon_startup,
751 *
752 * where vgacon_startup is __init. If you want to wade through the false
753 * positives, take out the check for rodata.
754 **/
755static int init_section_ref_ok(const char *name)
756{
757 const char **s;
758 /* Absolute section names */
759 const char *namelist1[] = {
760 ".init",
761 ".opd", /* see comment [OPD] at exit_section_ref_ok() */
762 ".toc1", /* used by ppc64 */
763 ".stab",
764 ".rodata",
765 ".text.lock",
766 "__bug_table", /* used by powerpc for BUG() */
767 ".pci_fixup_header",
768 ".pci_fixup_final",
769 ".pdr",
770 "__param",
771 NULL
772 };
773 /* Start of section names */
774 const char *namelist2[] = {
775 ".init.",
776 ".altinstructions",
777 ".eh_frame",
778 ".debug",
779 NULL
780 };
781 /* part of section name */
782 const char *namelist3 [] = {
783 ".unwind", /* sample: IA_64.unwind.init.text */
784 NULL
785 };
786
787 for (s = namelist1; *s; s++)
788 if (strcmp(*s, name) == 0)
789 return 1;
790 for (s = namelist2; *s; s++)
791 if (strncmp(*s, name, strlen(*s)) == 0)
792 return 1;
793 for (s = namelist3; *s; s++)
794 if (strstr(name, *s) != NULL)
795 return 1;
796 return 0;
797}
798
799/*
800 * Functions used only during module exit is marked __exit and is stored in
801 * a .exit.text section. Likewise data is marked __exitdata and stored in
802 * a .exit.data section.
803 * If this section is one of these sections return 1
804 * See include/linux/init.h for the details
805 **/
806static int exit_section(const char *name)
807{
808 if (strcmp(name, ".exit.text") == 0)
809 return 1;
810 if (strcmp(name, ".exit.data") == 0)
811 return 1;
812 return 0;
813
814}
815
816/*
817 * Identify sections from which references to a .exit section is OK.
818 *
819 * [OPD] Keith Ownes <kaos@sgi.com> commented:
820 * For our future {in}sanity, add a comment that this is the ppc .opd
821 * section, not the ia64 .opd section.
822 * ia64 .opd should not point to discarded sections.
823 **/
824static int exit_section_ref_ok(const char *name)
825{
826 const char **s;
827 /* Absolute section names */
828 const char *namelist1[] = {
829 ".exit.text",
830 ".exit.data",
831 ".init.text",
832 ".opd", /* See comment [OPD] */
833 ".toc1", /* used by ppc64 */
834 ".altinstructions",
835 ".pdr",
836 "__bug_table", /* used by powerpc for BUG() */
837 ".exitcall.exit",
838 ".eh_frame",
839 ".stab",
840 NULL
841 };
842 /* Start of section names */
843 const char *namelist2[] = {
844 ".debug",
845 NULL
846 };
847 /* part of section name */
848 const char *namelist3 [] = {
849 ".unwind", /* Sample: IA_64.unwind.exit.text */
850 NULL
851 };
852
853 for (s = namelist1; *s; s++)
854 if (strcmp(*s, name) == 0)
855 return 1;
856 for (s = namelist2; *s; s++)
857 if (strncmp(*s, name, strlen(*s)) == 0)
858 return 1;
859 for (s = namelist3; *s; s++)
860 if (strstr(name, *s) != NULL)
861 return 1;
862 return 0;
863}
864
865static void read_symbols(char *modname)
451{ 866{
452 const char *symname; 867 const char *symname;
453 char *version; 868 char *version;
@@ -462,9 +877,7 @@ read_symbols(char *modname)
462 /* When there's no vmlinux, don't print warnings about 877 /* When there's no vmlinux, don't print warnings about
463 * unresolved symbols (since there'll be too many ;) */ 878 * unresolved symbols (since there'll be too many ;) */
464 if (is_vmlinux(modname)) { 879 if (is_vmlinux(modname)) {
465 unsigned int fake_crc = 0;
466 have_vmlinux = 1; 880 have_vmlinux = 1;
467 add_exported_symbol("struct_module", mod, &fake_crc);
468 mod->skip = 1; 881 mod->skip = 1;
469 } 882 }
470 883
@@ -474,6 +887,8 @@ read_symbols(char *modname)
474 handle_modversions(mod, &info, sym, symname); 887 handle_modversions(mod, &info, sym, symname);
475 handle_moddevtable(mod, &info, sym, symname); 888 handle_moddevtable(mod, &info, sym, symname);
476 } 889 }
890 check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok);
891 check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok);
477 892
478 version = get_modinfo(info.modinfo, info.modinfo_len, "version"); 893 version = get_modinfo(info.modinfo, info.modinfo_len, "version");
479 if (version) 894 if (version)
@@ -499,21 +914,20 @@ read_symbols(char *modname)
499 * following helper, then compare to the file on disk and 914 * following helper, then compare to the file on disk and
500 * only update the later if anything changed */ 915 * only update the later if anything changed */
501 916
502void __attribute__((format(printf, 2, 3))) 917void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
503buf_printf(struct buffer *buf, const char *fmt, ...) 918 const char *fmt, ...)
504{ 919{
505 char tmp[SZ]; 920 char tmp[SZ];
506 int len; 921 int len;
507 va_list ap; 922 va_list ap;
508 923
509 va_start(ap, fmt); 924 va_start(ap, fmt);
510 len = vsnprintf(tmp, SZ, fmt, ap); 925 len = vsnprintf(tmp, SZ, fmt, ap);
511 buf_write(buf, tmp, len); 926 buf_write(buf, tmp, len);
512 va_end(ap); 927 va_end(ap);
513} 928}
514 929
515void 930void buf_write(struct buffer *buf, const char *s, int len)
516buf_write(struct buffer *buf, const char *s, int len)
517{ 931{
518 if (buf->size - buf->pos < len) { 932 if (buf->size - buf->pos < len) {
519 buf->size += len + SZ; 933 buf->size += len + SZ;
@@ -523,10 +937,10 @@ buf_write(struct buffer *buf, const char *s, int len)
523 buf->pos += len; 937 buf->pos += len;
524} 938}
525 939
526/* Header for the generated file */ 940/**
527 941 * Header for the generated file
528void 942 **/
529add_header(struct buffer *b, struct module *mod) 943static void add_header(struct buffer *b, struct module *mod)
530{ 944{
531 buf_printf(b, "#include <linux/module.h>\n"); 945 buf_printf(b, "#include <linux/module.h>\n");
532 buf_printf(b, "#include <linux/vermagic.h>\n"); 946 buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -546,10 +960,10 @@ add_header(struct buffer *b, struct module *mod)
546 buf_printf(b, "};\n"); 960 buf_printf(b, "};\n");
547} 961}
548 962
549/* Record CRCs for unresolved symbols */ 963/**
550 964 * Record CRCs for unresolved symbols
551void 965 **/
552add_versions(struct buffer *b, struct module *mod) 966static void add_versions(struct buffer *b, struct module *mod)
553{ 967{
554 struct symbol *s, *exp; 968 struct symbol *s, *exp;
555 969
@@ -557,8 +971,8 @@ add_versions(struct buffer *b, struct module *mod)
557 exp = find_symbol(s->name); 971 exp = find_symbol(s->name);
558 if (!exp || exp->module == mod) { 972 if (!exp || exp->module == mod) {
559 if (have_vmlinux && !s->weak) 973 if (have_vmlinux && !s->weak)
560 fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " 974 warn("\"%s\" [%s.ko] undefined!\n",
561 "undefined!\n", s->name, mod->name); 975 s->name, mod->name);
562 continue; 976 continue;
563 } 977 }
564 s->module = exp->module; 978 s->module = exp->module;
@@ -579,8 +993,7 @@ add_versions(struct buffer *b, struct module *mod)
579 continue; 993 continue;
580 } 994 }
581 if (!s->crc_valid) { 995 if (!s->crc_valid) {
582 fprintf(stderr, "*** Warning: \"%s\" [%s.ko] " 996 warn("\"%s\" [%s.ko] has no CRC!\n",
583 "has no CRC!\n",
584 s->name, mod->name); 997 s->name, mod->name);
585 continue; 998 continue;
586 } 999 }
@@ -590,8 +1003,8 @@ add_versions(struct buffer *b, struct module *mod)
590 buf_printf(b, "};\n"); 1003 buf_printf(b, "};\n");
591} 1004}
592 1005
593void 1006static void add_depends(struct buffer *b, struct module *mod,
594add_depends(struct buffer *b, struct module *mod, struct module *modules) 1007 struct module *modules)
595{ 1008{
596 struct symbol *s; 1009 struct symbol *s;
597 struct module *m; 1010 struct module *m;
@@ -621,8 +1034,7 @@ add_depends(struct buffer *b, struct module *mod, struct module *modules)
621 buf_printf(b, "\";\n"); 1034 buf_printf(b, "\";\n");
622} 1035}
623 1036
624void 1037static void add_srcversion(struct buffer *b, struct module *mod)
625add_srcversion(struct buffer *b, struct module *mod)
626{ 1038{
627 if (mod->srcversion[0]) { 1039 if (mod->srcversion[0]) {
628 buf_printf(b, "\n"); 1040 buf_printf(b, "\n");
@@ -631,8 +1043,7 @@ add_srcversion(struct buffer *b, struct module *mod)
631 } 1043 }
632} 1044}
633 1045
634void 1046static void write_if_changed(struct buffer *b, const char *fname)
635write_if_changed(struct buffer *b, const char *fname)
636{ 1047{
637 char *tmp; 1048 char *tmp;
638 FILE *file; 1049 FILE *file;
@@ -676,8 +1087,7 @@ write_if_changed(struct buffer *b, const char *fname)
676 fclose(file); 1087 fclose(file);
677} 1088}
678 1089
679void 1090static void read_dump(const char *fname, unsigned int kernel)
680read_dump(const char *fname)
681{ 1091{
682 unsigned long size, pos = 0; 1092 unsigned long size, pos = 0;
683 void *file = grab_file(fname, &size); 1093 void *file = grab_file(fname, &size);
@@ -691,6 +1101,7 @@ read_dump(const char *fname)
691 char *symname, *modname, *d; 1101 char *symname, *modname, *d;
692 unsigned int crc; 1102 unsigned int crc;
693 struct module *mod; 1103 struct module *mod;
1104 struct symbol *s;
694 1105
695 if (!(symname = strchr(line, '\t'))) 1106 if (!(symname = strchr(line, '\t')))
696 goto fail; 1107 goto fail;
@@ -711,15 +1122,30 @@ read_dump(const char *fname)
711 mod = new_module(NOFAIL(strdup(modname))); 1122 mod = new_module(NOFAIL(strdup(modname)));
712 mod->skip = 1; 1123 mod->skip = 1;
713 } 1124 }
714 add_exported_symbol(symname, mod, &crc); 1125 s = sym_add_exported(symname, mod);
1126 s->kernel = kernel;
1127 s->preloaded = 1;
1128 sym_update_crc(symname, mod, crc);
715 } 1129 }
716 return; 1130 return;
717fail: 1131fail:
718 fatal("parse error in symbol dump file\n"); 1132 fatal("parse error in symbol dump file\n");
719} 1133}
720 1134
721void 1135/* For normal builds always dump all symbols.
722write_dump(const char *fname) 1136 * For external modules only dump symbols
1137 * that are not read from kernel Module.symvers.
1138 **/
1139static int dump_sym(struct symbol *sym)
1140{
1141 if (!external_module)
1142 return 1;
1143 if (sym->vmlinux || sym->kernel)
1144 return 0;
1145 return 1;
1146}
1147
1148static void write_dump(const char *fname)
723{ 1149{
724 struct buffer buf = { }; 1150 struct buffer buf = { };
725 struct symbol *symbol; 1151 struct symbol *symbol;
@@ -728,34 +1154,33 @@ write_dump(const char *fname)
728 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { 1154 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
729 symbol = symbolhash[n]; 1155 symbol = symbolhash[n];
730 while (symbol) { 1156 while (symbol) {
731 symbol = symbol->next; 1157 if (dump_sym(symbol))
732 } 1158 buf_printf(&buf, "0x%08x\t%s\t%s\n",
733 } 1159 symbol->crc, symbol->name,
734 1160 symbol->module->name);
735 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
736 symbol = symbolhash[n];
737 while (symbol) {
738 buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
739 symbol->name, symbol->module->name);
740 symbol = symbol->next; 1161 symbol = symbol->next;
741 } 1162 }
742 } 1163 }
743 write_if_changed(&buf, fname); 1164 write_if_changed(&buf, fname);
744} 1165}
745 1166
746int 1167int main(int argc, char **argv)
747main(int argc, char **argv)
748{ 1168{
749 struct module *mod; 1169 struct module *mod;
750 struct buffer buf = { }; 1170 struct buffer buf = { };
751 char fname[SZ]; 1171 char fname[SZ];
752 char *dump_read = NULL, *dump_write = NULL; 1172 char *kernel_read = NULL, *module_read = NULL;
1173 char *dump_write = NULL;
753 int opt; 1174 int opt;
754 1175
755 while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { 1176 while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
756 switch(opt) { 1177 switch(opt) {
757 case 'i': 1178 case 'i':
758 dump_read = optarg; 1179 kernel_read = optarg;
1180 break;
1181 case 'I':
1182 module_read = optarg;
1183 external_module = 1;
759 break; 1184 break;
760 case 'm': 1185 case 'm':
761 modversions = 1; 1186 modversions = 1;
@@ -771,8 +1196,10 @@ main(int argc, char **argv)
771 } 1196 }
772 } 1197 }
773 1198
774 if (dump_read) 1199 if (kernel_read)
775 read_dump(dump_read); 1200 read_dump(kernel_read, 1);
1201 if (module_read)
1202 read_dump(module_read, 0);
776 1203
777 while (optind < argc) { 1204 while (optind < argc) {
778 read_symbols(argv[optind++]); 1205 read_symbols(argv[optind++]);
@@ -799,4 +1226,3 @@ main(int argc, char **argv)
799 1226
800 return 0; 1227 return 0;
801} 1228}
802
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 7334d839145d..b14255c72a37 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -13,20 +13,30 @@
13 13
14#if KERNEL_ELFCLASS == ELFCLASS32 14#if KERNEL_ELFCLASS == ELFCLASS32
15 15
16#define Elf_Ehdr Elf32_Ehdr 16#define Elf_Ehdr Elf32_Ehdr
17#define Elf_Shdr Elf32_Shdr 17#define Elf_Shdr Elf32_Shdr
18#define Elf_Sym Elf32_Sym 18#define Elf_Sym Elf32_Sym
19#define Elf_Addr Elf32_Addr
20#define Elf_Section Elf32_Section
19#define ELF_ST_BIND ELF32_ST_BIND 21#define ELF_ST_BIND ELF32_ST_BIND
20#define ELF_ST_TYPE ELF32_ST_TYPE 22#define ELF_ST_TYPE ELF32_ST_TYPE
21 23
24#define Elf_Rela Elf32_Rela
25#define ELF_R_SYM ELF32_R_SYM
26#define ELF_R_TYPE ELF32_R_TYPE
22#else 27#else
23 28
24#define Elf_Ehdr Elf64_Ehdr 29#define Elf_Ehdr Elf64_Ehdr
25#define Elf_Shdr Elf64_Shdr 30#define Elf_Shdr Elf64_Shdr
26#define Elf_Sym Elf64_Sym 31#define Elf_Sym Elf64_Sym
32#define Elf_Addr Elf64_Addr
33#define Elf_Section Elf64_Section
27#define ELF_ST_BIND ELF64_ST_BIND 34#define ELF_ST_BIND ELF64_ST_BIND
28#define ELF_ST_TYPE ELF64_ST_TYPE 35#define ELF_ST_TYPE ELF64_ST_TYPE
29 36
37#define Elf_Rela Elf64_Rela
38#define ELF_R_SYM ELF64_R_SYM
39#define ELF_R_TYPE ELF64_R_TYPE
30#endif 40#endif
31 41
32#if KERNEL_ELFDATA != HOST_ELFDATA 42#if KERNEL_ELFDATA != HOST_ELFDATA
@@ -91,17 +101,22 @@ struct elf_info {
91 unsigned int modinfo_len; 101 unsigned int modinfo_len;
92}; 102};
93 103
104/* file2alias.c */
94void handle_moddevtable(struct module *mod, struct elf_info *info, 105void handle_moddevtable(struct module *mod, struct elf_info *info,
95 Elf_Sym *sym, const char *symname); 106 Elf_Sym *sym, const char *symname);
96
97void add_moddevtable(struct buffer *buf, struct module *mod); 107void add_moddevtable(struct buffer *buf, struct module *mod);
98 108
109/* sumversion.c */
99void maybe_frob_rcs_version(const char *modfilename, 110void maybe_frob_rcs_version(const char *modfilename,
100 char *version, 111 char *version,
101 void *modinfo, 112 void *modinfo,
102 unsigned long modinfo_offset); 113 unsigned long modinfo_offset);
103void get_src_version(const char *modname, char sum[], unsigned sumlen); 114void get_src_version(const char *modname, char sum[], unsigned sumlen);
104 115
116/* from modpost.c */
105void *grab_file(const char *filename, unsigned long *size); 117void *grab_file(const char *filename, unsigned long *size);
106char* get_next_line(unsigned long *pos, void *file, unsigned long size); 118char* get_next_line(unsigned long *pos, void *file, unsigned long size);
107void release_file(void *file, unsigned long size); 119void release_file(void *file, unsigned long size);
120
121void fatal(const char *fmt, ...);
122void warn(const char *fmt, ...);
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 43271a1ca01e..8a2875689e4d 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -316,8 +316,7 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
316 316
317 file = grab_file(cmd, &flen); 317 file = grab_file(cmd, &flen);
318 if (!file) { 318 if (!file) {
319 fprintf(stderr, "Warning: could not find %s for %s\n", 319 warn("could not find %s for %s\n", cmd, objfile);
320 cmd, objfile);
321 goto out; 320 goto out;
322 } 321 }
323 322
@@ -355,9 +354,8 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md)
355 /* Check if this file is in same dir as objfile */ 354 /* Check if this file is in same dir as objfile */
356 if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { 355 if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
357 if (!parse_file(line, md)) { 356 if (!parse_file(line, md)) {
358 fprintf(stderr, 357 warn("could not open %s: %s\n",
359 "Warning: could not open %s: %s\n", 358 line, strerror(errno));
360 line, strerror(errno));
361 goto out_file; 359 goto out_file;
362 } 360 }
363 361
@@ -383,8 +381,11 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
383 struct md4_ctx md; 381 struct md4_ctx md;
384 char *sources, *end, *fname; 382 char *sources, *end, *fname;
385 const char *basename; 383 const char *basename;
386 char filelist[strlen(getenv("MODVERDIR")) + strlen("/") + 384 char filelist[PATH_MAX + 1];
387 strlen(modname) - strlen(".o") + strlen(".mod") + 1 ]; 385 char *modverdir = getenv("MODVERDIR");
386
387 if (!modverdir)
388 modverdir = ".";
388 389
389 /* Source files for module are in .tmp_versions/modname.mod, 390 /* Source files for module are in .tmp_versions/modname.mod,
390 after the first line. */ 391 after the first line. */
@@ -392,28 +393,25 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
392 basename = strrchr(modname, '/') + 1; 393 basename = strrchr(modname, '/') + 1;
393 else 394 else
394 basename = modname; 395 basename = modname;
395 sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"), 396 sprintf(filelist, "%s/%.*s.mod", modverdir,
396 (int) strlen(basename) - 2, basename); 397 (int) strlen(basename) - 2, basename);
397 398
398 file = grab_file(filelist, &len); 399 file = grab_file(filelist, &len);
399 if (!file) { 400 if (!file) {
400 fprintf(stderr, "Warning: could not find versions for %s\n", 401 warn("could not find versions for %s\n", filelist);
401 filelist);
402 return; 402 return;
403 } 403 }
404 404
405 sources = strchr(file, '\n'); 405 sources = strchr(file, '\n');
406 if (!sources) { 406 if (!sources) {
407 fprintf(stderr, "Warning: malformed versions file for %s\n", 407 warn("malformed versions file for %s\n", modname);
408 modname);
409 goto release; 408 goto release;
410 } 409 }
411 410
412 sources++; 411 sources++;
413 end = strchr(sources, '\n'); 412 end = strchr(sources, '\n');
414 if (!end) { 413 if (!end) {
415 fprintf(stderr, "Warning: bad ending versions file for %s\n", 414 warn("bad ending versions file for %s\n", modname);
416 modname);
417 goto release; 415 goto release;
418 } 416 }
419 *end = '\0'; 417 *end = '\0';
@@ -438,19 +436,19 @@ static void write_version(const char *filename, const char *sum,
438 436
439 fd = open(filename, O_RDWR); 437 fd = open(filename, O_RDWR);
440 if (fd < 0) { 438 if (fd < 0) {
441 fprintf(stderr, "Warning: changing sum in %s failed: %s\n", 439 warn("changing sum in %s failed: %s\n",
442 filename, strerror(errno)); 440 filename, strerror(errno));
443 return; 441 return;
444 } 442 }
445 443
446 if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { 444 if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
447 fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n", 445 warn("changing sum in %s:%lu failed: %s\n",
448 filename, offset, strerror(errno)); 446 filename, offset, strerror(errno));
449 goto out; 447 goto out;
450 } 448 }
451 449
452 if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { 450 if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
453 fprintf(stderr, "Warning: writing sum in %s failed: %s\n", 451 warn("writing sum in %s failed: %s\n",
454 filename, strerror(errno)); 452 filename, strerror(errno));
455 goto out; 453 goto out;
456 } 454 }