aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod')
-rw-r--r--scripts/mod/modpost.c146
1 files changed, 60 insertions, 86 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 6c206b9212b1..986513dcd700 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -625,6 +625,7 @@ static int number_prefix(const char *sym)
625 625
626/* The pattern is an array of simple patterns. 626/* The pattern is an array of simple patterns.
627 * "foo" will match an exact string equal to "foo" 627 * "foo" will match an exact string equal to "foo"
628 * "*foo" will match a string that ends with "foo"
628 * "foo*" will match a string that begins with "foo" 629 * "foo*" will match a string that begins with "foo"
629 * "foo$" will match a string equal to "foo" or "foo.1" 630 * "foo$" will match a string equal to "foo" or "foo.1"
630 * where the '1' can be any number including several digits. 631 * where the '1' can be any number including several digits.
@@ -638,8 +639,13 @@ int match(const char *sym, const char * const pat[])
638 p = *pat++; 639 p = *pat++;
639 const char *endp = p + strlen(p) - 1; 640 const char *endp = p + strlen(p) - 1;
640 641
642 /* "*foo" */
643 if (*p == '*') {
644 if (strrcmp(sym, p + 1) == 0)
645 return 1;
646 }
641 /* "foo*" */ 647 /* "foo*" */
642 if (*endp == '*') { 648 else if (*endp == '*') {
643 if (strncmp(sym, p, strlen(p) - 1) == 0) 649 if (strncmp(sym, p, strlen(p) - 1) == 0)
644 return 1; 650 return 1;
645 } 651 }
@@ -660,54 +666,6 @@ int match(const char *sym, const char * const pat[])
660 return 0; 666 return 0;
661} 667}
662 668
663/*
664 * Functions used only during module init is marked __init and is stored in
665 * a .init.text section. Likewise data is marked __initdata and stored in
666 * a .init.data section.
667 * If this section is one of these sections return 1
668 * See include/linux/init.h for the details
669 */
670static int init_section(const char *name)
671{
672 if (strcmp(name, ".init") == 0)
673 return 1;
674 if (strncmp(name, ".init.", strlen(".init.")) == 0)
675 return 1;
676 return 0;
677}
678
679/*
680 * Functions used only during module exit is marked __exit and is stored in
681 * a .exit.text section. Likewise data is marked __exitdata and stored in
682 * a .exit.data section.
683 * If this section is one of these sections return 1
684 * See include/linux/init.h for the details
685 **/
686static int exit_section(const char *name)
687{
688 if (strcmp(name, ".exit.text") == 0)
689 return 1;
690 if (strcmp(name, ".exit.data") == 0)
691 return 1;
692 return 0;
693
694}
695
696/*
697 * Data sections are named like this:
698 * .data | .data.rel | .data.rel.*
699 * Return 1 if the specified section is a data section
700 */
701static int data_section(const char *name)
702{
703 if ((strcmp(name, ".data") == 0) ||
704 (strcmp(name, ".data.rel") == 0) ||
705 (strncmp(name, ".data.rel.", strlen(".data.rel.")) == 0))
706 return 1;
707 else
708 return 0;
709}
710
711/* sections that we do not want to do full section mismatch check on */ 669/* sections that we do not want to do full section mismatch check on */
712static const char *section_white_list[] = 670static const char *section_white_list[] =
713 { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL }; 671 { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
@@ -721,9 +679,50 @@ static const char *section_white_list[] =
721#define INIT_SECTIONS INIT_DATA_SECTIONS, INIT_TEXT_SECTIONS 679#define INIT_SECTIONS INIT_DATA_SECTIONS, INIT_TEXT_SECTIONS
722#define EXIT_SECTIONS EXIT_DATA_SECTIONS, EXIT_TEXT_SECTIONS 680#define EXIT_SECTIONS EXIT_DATA_SECTIONS, EXIT_TEXT_SECTIONS
723 681
724#define DATA_SECTIONS ".data$" 682#define DATA_SECTIONS ".data$", ".data.rel$"
725#define TEXT_SECTIONS ".text$" 683#define TEXT_SECTIONS ".text$"
726 684
685/* init data sections */
686static const char *init_data_sections[] = { INIT_DATA_SECTIONS, NULL };
687
688/* all init sections */
689static const char *init_sections[] = { INIT_SECTIONS, NULL };
690
691/* All init and exit sections (code + data) */
692static const char *init_exit_sections[] =
693 {INIT_SECTIONS, EXIT_SECTIONS, NULL };
694
695/* data section */
696static const char *data_sections[] = { DATA_SECTIONS, NULL };
697
698/* sections that may refer to an init/exit section with no warning */
699static const char *initref_sections[] =
700{
701 ".text.init.refok*",
702 ".exit.text.refok*",
703 ".data.init.refok*",
704 NULL
705};
706
707
708/* symbols in .data that may refer to init/exit sections */
709static const char *symbol_white_list[] =
710{
711 "*driver",
712 "*_template", /* scsi uses *_template a lot */
713 "*_timer", /* arm uses ops structures named _timer a lot */
714 "*_sht", /* scsi also used *_sht to some extent */
715 "*_ops",
716 "*_probe",
717 "*_probe_one",
718 "*_console",
719 NULL
720};
721
722static const char *head_sections[] = { ".head.text*", NULL };
723static const char *linker_symbols[] =
724 { "__init_begin", "_sinittext", "_einittext", NULL };
725
727struct sectioncheck { 726struct sectioncheck {
728 const char *fromsec[20]; 727 const char *fromsec[20];
729 const char *tosec[20]; 728 const char *tosec[20];
@@ -817,55 +816,30 @@ static int secref_whitelist(const char *modname, const char *tosec,
817 const char *fromsec, const char *atsym, 816 const char *fromsec, const char *atsym,
818 const char *refsymname) 817 const char *refsymname)
819{ 818{
820 const char **s;
821 const char *pat2sym[] = {
822 "driver",
823 "_template", /* scsi uses *_template a lot */
824 "_timer", /* arm uses ops structures named _timer a lot */
825 "_sht", /* scsi also used *_sht to some extent */
826 "_ops",
827 "_probe",
828 "_probe_one",
829 "_console",
830 NULL
831 };
832
833 const char *pat3refsym[] = {
834 "__init_begin",
835 "_sinittext",
836 "_einittext",
837 NULL
838 };
839
840 /* Check for pattern 0 */ 819 /* Check for pattern 0 */
841 if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) || 820 if (match(fromsec, initref_sections))
842 (strncmp(fromsec, ".exit.text.refok", strlen(".exit.text.refok")) == 0) ||
843 (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0))
844 return 1; 821 return 1;
845 822
846 /* Check for pattern 1 */ 823 /* Check for pattern 1 */
847 if ((strcmp(tosec, ".init.data") == 0) && 824 if (match(tosec, init_data_sections) &&
848 (strncmp(fromsec, ".data", strlen(".data")) == 0) && 825 match(fromsec, data_sections) &&
849 (strncmp(atsym, "__param", strlen("__param")) == 0)) 826 (strncmp(atsym, "__param", strlen("__param")) == 0))
850 return 1; 827 return 1;
851 828
852 /* Check for pattern 2 */ 829 /* Check for pattern 2 */
853 if ((init_section(tosec) || exit_section(tosec)) 830 if (match(tosec, init_exit_sections) &&
854 && data_section(fromsec)) 831 match(fromsec, data_sections) &&
855 for (s = pat2sym; *s; s++) 832 match(atsym, symbol_white_list))
856 if (strrcmp(atsym, *s) == 0) 833 return 1;
857 return 1;
858 834
859 /* Check for pattern 3 */ 835 /* Check for pattern 3 */
860 if ((strcmp(fromsec, ".text.head") == 0) && 836 if (match(fromsec, head_sections) &&
861 ((strcmp(tosec, ".init.data") == 0) || 837 match(tosec, init_sections))
862 (strcmp(tosec, ".init.text") == 0)))
863 return 1; 838 return 1;
864 839
865 /* Check for pattern 4 */ 840 /* Check for pattern 4 */
866 for (s = pat3refsym; *s; s++) 841 if (match(refsymname, linker_symbols))
867 if (strcmp(refsymname, *s) == 0) 842 return 1;
868 return 1;
869 843
870 return 0; 844 return 0;
871} 845}