aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-02-17 16:42:02 -0500
committerSam Ravnborg <sam@mars.ravnborg.org>2006-02-19 03:51:20 -0500
commitb39927cf4cc5a9123d2b157ffd396884cb8156eb (patch)
tree8e372f4b8fa678de7239a125ff4653f136a9dc66 /scripts
parenta67dc21a38055ec2d8d85b2f64d98091748569b3 (diff)
kbuild: check for section mismatch during modpost stage
Section mismatch is identified as references to .init* sections from non .init sections. And likewise references to .exit.* sections outside .exit sections. .init.* sections are discarded after a module is initialized and references to .init.* sections are oops candidates. .exit.* sections are discarded when a module is built-in and thus references to .exit are also oops candidates. The checks were possible to do using 'make buildcheck' which called the two perl scripts: reference_discarded.pl and reference_init.pl. This patch just moves the same functionality inside modpost and the scripts are then obsoleted. They will though be kept for a while so users can do double checks - but note that some .o files are skipped by the perl scripts so result is not 1:1. All credit for the concept goes to Keith Owens who implemented the original perl scrips - this patch just moves it to modpost. Compared to the perl script the implmentation in modpost will be run for each kernel build - thus catching the error much sooner, but the downside is that the individual .o file are not always identified. Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/mod/modpost.c258
-rw-r--r--scripts/mod/modpost.h10
2 files changed, 268 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index d901095ea8..a7360c379c 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -451,6 +451,262 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
451 return NULL; 451 return NULL;
452} 452}
453 453
454/*
455 * Find symbols before or equal addr and after addr - in the section sec
456 **/
457static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
458 const char *sec,
459 Elf_Sym **before, Elf_Sym **after)
460{
461 Elf_Sym *sym;
462 Elf_Ehdr *hdr = elf->hdr;
463 Elf_Addr beforediff = ~0;
464 Elf_Addr afterdiff = ~0;
465 const char *secstrings = (void *)hdr +
466 elf->sechdrs[hdr->e_shstrndx].sh_offset;
467
468 *before = NULL;
469 *after = NULL;
470
471 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
472 const char *symsec;
473
474 if (sym->st_shndx >= SHN_LORESERVE)
475 continue;
476 symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name;
477 if (strcmp(symsec, sec) != 0)
478 continue;
479 if (sym->st_value <= addr) {
480 if ((addr - sym->st_value) < beforediff) {
481 beforediff = addr - sym->st_value;
482 *before = sym;
483 }
484 }
485 else
486 {
487 if ((sym->st_value - addr) < afterdiff) {
488 afterdiff = sym->st_value - addr;
489 *after = sym;
490 }
491 }
492 }
493}
494
495/**
496 * Print a warning about a section mismatch.
497 * Try to find symbols near it so user can find it.
498 **/
499static void warn_sec_mismatch(const char *modname, const char *fromsec,
500 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
501{
502 Elf_Sym *before;
503 Elf_Sym *after;
504 Elf_Ehdr *hdr = elf->hdr;
505 Elf_Shdr *sechdrs = elf->sechdrs;
506 const char *secstrings = (void *)hdr +
507 sechdrs[hdr->e_shstrndx].sh_offset;
508 const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name;
509
510 find_symbols_between(elf, r.r_offset, fromsec, &before, &after);
511
512 if (before && after) {
513 warn("%s - Section mismatch: reference to %s from %s "
514 "between '%s' (at offset 0x%lx) and '%s'\n",
515 modname, secname, fromsec,
516 elf->strtab + before->st_name,
517 (long)(r.r_offset - before->st_value),
518 elf->strtab + after->st_name);
519 } else if (before) {
520 warn("%s - Section mismatch: reference to %s from %s "
521 "after '%s' (at offset 0x%lx)\n",
522 modname, secname, fromsec,
523 elf->strtab + before->st_name,
524 (long)(r.r_offset - before->st_value));
525 } else if (after) {
526 warn("%s - Section mismatch: reference to %s from %s "
527 "before '%s' (at offset -0x%lx)\n",
528 modname, secname, fromsec,
529 elf->strtab + before->st_name,
530 (long)(before->st_value - r.r_offset));
531 } else {
532 warn("%s - Section mismatch: reference to %s from %s "
533 "(offset 0x%lx)\n",
534 modname, secname, fromsec, (long)r.r_offset);
535 }
536}
537
538/**
539 * A module includes a number of sections that are discarded
540 * either when loaded or when used as built-in.
541 * For loaded modules all functions marked __init and all data
542 * marked __initdata will be discarded when the module has been intialized.
543 * Likewise for modules used built-in the sections marked __exit
544 * are discarded because __exit marked function are supposed to be called
545 * only when a moduel is unloaded which never happes for built-in modules.
546 * The check_sec_ref() function traverses all relocation records
547 * to find all references to a section that reference a section that will
548 * be discarded and warns about it.
549 **/
550static void check_sec_ref(struct module *mod, const char *modname,
551 struct elf_info *elf,
552 int section(const char*),
553 int section_ref_ok(const char *))
554{
555 int i;
556 Elf_Sym *sym;
557 Elf_Ehdr *hdr = elf->hdr;
558 Elf_Shdr *sechdrs = elf->sechdrs;
559 const char *secstrings = (void *)hdr +
560 sechdrs[hdr->e_shstrndx].sh_offset;
561
562 /* Walk through all sections */
563 for (i = 0; i < hdr->e_shnum; i++) {
564 const char *name = secstrings + sechdrs[i].sh_name +
565 strlen(".rela");
566 /* We want to process only relocation sections and not .init */
567 if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
568 continue;
569 Elf_Rela *rela;
570 Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
571 Elf_Rela *stop = (void*)start + sechdrs[i].sh_size;
572
573 for (rela = start; rela < stop; rela++) {
574 Elf_Rela r;
575 const char *secname;
576 r.r_offset = TO_NATIVE(rela->r_offset);
577 r.r_info = TO_NATIVE(rela->r_info);
578 sym = elf->symtab_start + ELF_R_SYM(r.r_info);
579 secname = secstrings + sechdrs[sym->st_shndx].sh_name;
580 /* Skip special sections */
581 if (sym->st_shndx >= SHN_LORESERVE)
582 continue;
583
584 if (section(secname))
585 warn_sec_mismatch(modname, name, elf, sym, r);
586 }
587 }
588}
589
590/**
591 * Functions used only during module init is marked __init and is stored in
592 * a .init.text section. Likewise data is marked __initdata and stored in
593 * a .init.data section.
594 * If this section is one of these sections return 1
595 * See include/linux/init.h for the details
596 **/
597static int init_section(const char *name)
598{
599 if (strcmp(name, ".init") == 0)
600 return 1;
601 if (strncmp(name, ".init.", strlen(".init.")) == 0)
602 return 1;
603 return 0;
604}
605
606/**
607 * Identify sections from which references to a .init section is OK.
608 *
609 * Unfortunately references to read only data that referenced .init
610 * sections had to be excluded. Almost all of these are false
611 * positives, they are created by gcc. The downside of excluding rodata
612 * is that there really are some user references from rodata to
613 * init code, e.g. drivers/video/vgacon.c:
614 *
615 * const struct consw vga_con = {
616 * con_startup: vgacon_startup,
617 *
618 * where vgacon_startup is __init. If you want to wade through the false
619 * positives, take out the check for rodata.
620 **/
621static int init_section_ref_ok(const char *name)
622{
623 const char **s;
624 /* Absolute section names */
625 const char *namelist1[] = {
626 ".init",
627 ".stab",
628 ".rodata",
629 ".text.lock",
630 ".pci_fixup_header",
631 ".pci_fixup_final",
632 ".pdr",
633 "__param",
634 NULL
635 };
636 /* Start of section names */
637 const char *namelist2[] = {
638 ".init.",
639 ".altinstructions",
640 ".eh_frame",
641 ".debug",
642 NULL
643 };
644
645 for (s = namelist1; *s; s++)
646 if (strcmp(*s, name) == 0)
647 return 1;
648 for (s = namelist2; *s; s++)
649 if (strncmp(*s, name, strlen(*s)) == 0)
650 return 1;
651 return 0;
652}
653
654/*
655 * Functions used only during module exit is marked __exit and is stored in
656 * a .exit.text section. Likewise data is marked __exitdata and stored in
657 * a .exit.data section.
658 * If this section is one of these sections return 1
659 * See include/linux/init.h for the details
660 **/