aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-02-26 16:18:11 -0500
committerSam Ravnborg <sam@mars.ravnborg.org>2006-02-26 16:18:11 -0500
commit4c8fbca5836aaafd165aa8732d92ab5d4f3a6841 (patch)
treef4a9d7f73a92d540ebf4a53e36ed19d160e2a4de /scripts/mod
parentcc006288fb538005a14ca4297250abbf0beeb0b9 (diff)
kbuild: whitelist false section mismatch warnings
In several cases the section mismatch check triggered false warnings. Following patch introduce a whitelist to 'false positives' are not warned of. Two types of patterns are recognised: 1) Typical case when a module parameter is _initdata 2) When a function pointer is assigned to a driver structure In both patterns we rely on the actual name of the variable assigned Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/modpost.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index de0a9ee1de16..663b1eff757b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -452,6 +452,89 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
452} 452}
453 453
454/** 454/**
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 (strcmp(fromsec, ".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/**
455 * Find symbol based on relocation record info. 538 * Find symbol based on relocation record info.
456 * In some cases the symbol supplied is a valid symbol so 539 * In some cases the symbol supplied is a valid symbol so
457 * return refsym. If st_name != 0 we assume this is a valid symbol. 540 * return refsym. If st_name != 0 we assume this is a valid symbol.
@@ -518,6 +601,7 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
518/** 601/**
519 * Print a warning about a section mismatch. 602 * Print a warning about a section mismatch.
520 * Try to find symbols near it so user can find it. 603 * Try to find symbols near it so user can find it.
604 * Check whitelist before warning - it may be a false positive.
521 **/ 605 **/
522static void warn_sec_mismatch(const char *modname, const char *fromsec, 606static void warn_sec_mismatch(const char *modname, const char *fromsec,
523 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) 607 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
@@ -536,6 +620,11 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
536 refsym = find_elf_symbol(elf, r.r_addend, sym); 620 refsym = find_elf_symbol(elf, r.r_addend, sym);
537 if (refsym && strlen(elf->strtab + refsym->st_name)) 621 if (refsym && strlen(elf->strtab + refsym->st_name))
538 refsymname = elf->strtab + refsym->st_name; 622 refsymname = elf->strtab + refsym->st_name;
623
624 /* check whitelist - we may ignore it */
625 if (before &&
626 secref_whitelist(secname, fromsec, elf->strtab + before->st_name))
627 return;
539 628
540 if (before && after) { 629 if (before && after) {
541 warn("%s - Section mismatch: reference to %s:%s from %s " 630 warn("%s - Section mismatch: reference to %s:%s from %s "