diff options
-rw-r--r-- | scripts/mod/modpost.c | 104 |
1 files changed, 52 insertions, 52 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e4099cd5f085..0a80acafd212 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -607,7 +607,10 @@ static int strrcmp(const char *s, const char *sub) | |||
607 | 607 | ||
608 | static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) | 608 | static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) |
609 | { | 609 | { |
610 | return elf->strtab + sym->st_name; | 610 | if (sym) |
611 | return elf->strtab + sym->st_name; | ||
612 | else | ||
613 | return ""; | ||
611 | } | 614 | } |
612 | 615 | ||
613 | static const char *sec_name(struct elf_info *elf, int shndx) | 616 | static const char *sec_name(struct elf_info *elf, int shndx) |
@@ -812,7 +815,6 @@ static int section_mismatch(const char *fromsec, const char *tosec) | |||
812 | return 0; | 815 | return 0; |
813 | } | 816 | } |
814 | 817 | ||
815 | |||
816 | /** | 818 | /** |
817 | * Whitelist to allow certain references to pass with no warning. | 819 | * Whitelist to allow certain references to pass with no warning. |
818 | * | 820 | * |
@@ -856,36 +858,35 @@ static int section_mismatch(const char *fromsec, const char *tosec) | |||
856 | * refsymname = __init_begin, _sinittext, _einittext | 858 | * refsymname = __init_begin, _sinittext, _einittext |
857 | * | 859 | * |
858 | **/ | 860 | **/ |
859 | static int secref_whitelist(const char *modname, const char *tosec, | 861 | static int secref_whitelist(const char *fromsec, const char *fromsym, |
860 | const char *fromsec, const char *atsym, | 862 | const char *tosec, const char *tosym) |
861 | const char *refsymname) | ||
862 | { | 863 | { |
863 | /* Check for pattern 0 */ | 864 | /* Check for pattern 0 */ |
864 | if (match(fromsec, initref_sections)) | 865 | if (match(fromsec, initref_sections)) |
865 | return 1; | 866 | return 0; |
866 | 867 | ||
867 | /* Check for pattern 1 */ | 868 | /* Check for pattern 1 */ |
868 | if (match(tosec, init_data_sections) && | 869 | if (match(tosec, init_data_sections) && |
869 | match(fromsec, data_sections) && | 870 | match(fromsec, data_sections) && |
870 | (strncmp(atsym, "__param", strlen("__param")) == 0)) | 871 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) |
871 | return 1; | 872 | return 0; |
872 | 873 | ||
873 | /* Check for pattern 2 */ | 874 | /* Check for pattern 2 */ |
874 | if (match(tosec, init_exit_sections) && | 875 | if (match(tosec, init_exit_sections) && |
875 | match(fromsec, data_sections) && | 876 | match(fromsec, data_sections) && |
876 | match(atsym, symbol_white_list)) | 877 | match(fromsym, symbol_white_list)) |
877 | return 1; | 878 | return 0; |
878 | 879 | ||
879 | /* Check for pattern 3 */ | 880 | /* Check for pattern 3 */ |
880 | if (match(fromsec, head_sections) && | 881 | if (match(fromsec, head_sections) && |
881 | match(tosec, init_sections)) | 882 | match(tosec, init_sections)) |
882 | return 1; | 883 | return 0; |
883 | 884 | ||
884 | /* Check for pattern 4 */ | 885 | /* Check for pattern 4 */ |
885 | if (match(refsymname, linker_symbols)) | 886 | if (match(tosym, linker_symbols)) |
886 | return 1; | 887 | return 0; |
887 | 888 | ||
888 | return 0; | 889 | return 1; |
889 | } | 890 | } |
890 | 891 | ||
891 | /** | 892 | /** |
@@ -987,41 +988,49 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, | |||
987 | return near; | 988 | return near; |
988 | } | 989 | } |
989 | 990 | ||
990 | /** | 991 | /* |
991 | * Print a warning about a section mismatch. | 992 | * Print a warning about a section mismatch. |
992 | * Try to find symbols near it so user can find it. | 993 | * Try to find symbols near it so user can find it. |
993 | * Check whitelist before warning - it may be a false positive. | 994 | * Check whitelist before warning - it may be a false positive. |
994 | **/ | 995 | */ |
995 | static void warn_sec_mismatch(const char *modname, const char *fromsec, | 996 | static void report_sec_mismatch(const char *modname, |
996 | struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) | 997 | const char *fromsec, |
998 | unsigned long long fromaddr, | ||
999 | const char *fromsym, | ||
1000 | const char *tosec, const char *tosym) | ||
997 | { | 1001 | { |
998 | Elf_Sym *where; | 1002 | if (strlen(tosym)) { |
999 | Elf_Sym *refsym; | ||
1000 | const char *refsymname = ""; | ||
1001 | const char *secname; | ||
1002 | |||
1003 | secname = sec_name(elf, sym->st_shndx); | ||
1004 | where = find_elf_symbol2(elf, r.r_offset, fromsec); | ||
1005 | |||
1006 | refsym = find_elf_symbol(elf, r.r_addend, sym); | ||
1007 | if (refsym && strlen(sym_name(elf, refsym))) | ||
1008 | refsymname = sym_name(elf, refsym); | ||
1009 | |||
1010 | /* check whitelist - we may ignore it */ | ||
1011 | if (secref_whitelist(modname, secname, fromsec, | ||
1012 | where ? sym_name(elf, where) : "", | ||
1013 | refsymname)) | ||
1014 | return; | ||
1015 | |||
1016 | if (where) { | ||
1017 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | 1003 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " |
1018 | "in '%s'\n", | 1004 | "in '%s'\n", |
1019 | modname, fromsec, (unsigned long long)r.r_offset, | 1005 | modname, fromsec, fromaddr, |
1020 | secname, refsymname, sym_name(elf, where)); | 1006 | tosec, tosym, fromsym); |
1021 | } else { | 1007 | } else { |
1022 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n", | 1008 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n", |
1023 | modname, fromsec, (unsigned long long)r.r_offset, | 1009 | modname, fromsec, fromaddr, |
1024 | secname, refsymname); | 1010 | tosec, tosym); |
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | static void check_section_mismatch(const char *modname, struct elf_info *elf, | ||
1015 | Elf_Rela *r, Elf_Sym *sym, const char *fromsec) | ||
1016 | { | ||
1017 | const char *tosec; | ||
1018 | |||
1019 | tosec = sec_name(elf, sym->st_shndx); | ||
1020 | if (section_mismatch(fromsec, tosec)) { | ||
1021 | const char *fromsym; | ||
1022 | const char *tosym; | ||
1023 | |||
1024 | fromsym = sym_name(elf, | ||
1025 | find_elf_symbol2(elf, r->r_offset, fromsec)); | ||
1026 | tosym = sym_name(elf, | ||
1027 | find_elf_symbol(elf, r->r_addend, sym)); | ||
1028 | |||
1029 | /* check whitelist - we may ignore it */ | ||
1030 | if (secref_whitelist(fromsec, fromsym, tosec, tosym)) { | ||
1031 | report_sec_mismatch(modname, fromsec, r->r_offset, | ||
1032 | fromsym, tosec, tosym); | ||
1033 | } | ||
1025 | } | 1034 | } |
1026 | } | 1035 | } |
1027 | 1036 | ||
@@ -1107,7 +1116,6 @@ static void section_rela(const char *modname, struct elf_info *elf, | |||
1107 | Elf_Rela r; | 1116 | Elf_Rela r; |
1108 | unsigned int r_sym; | 1117 | unsigned int r_sym; |
1109 | const char *fromsec; | 1118 | const char *fromsec; |
1110 | const char * tosec; | ||
1111 | 1119 | ||
1112 | Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; | 1120 | Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; |
1113 | Elf_Rela *stop = (void *)start + sechdr->sh_size; | 1121 | Elf_Rela *stop = (void *)start + sechdr->sh_size; |
@@ -1117,7 +1125,6 @@ static void section_rela(const char *modname, struct elf_info *elf, | |||
1117 | /* if from section (name) is know good then skip it */ | 1125 | /* if from section (name) is know good then skip it */ |
1118 | if (match(fromsec, section_white_list)) | 1126 | if (match(fromsec, section_white_list)) |
1119 | return; | 1127 | return; |
1120 | |||
1121 | for (rela = start; rela < stop; rela++) { | 1128 | for (rela = start; rela < stop; rela++) { |
1122 | r.r_offset = TO_NATIVE(rela->r_offset); | 1129 | r.r_offset = TO_NATIVE(rela->r_offset); |
1123 | #if KERNEL_ELFCLASS == ELFCLASS64 | 1130 | #if KERNEL_ELFCLASS == ELFCLASS64 |
@@ -1140,10 +1147,7 @@ static void section_rela(const char *modname, struct elf_info *elf, | |||
1140 | /* Skip special sections */ | 1147 | /* Skip special sections */ |
1141 | if (sym->st_shndx >= SHN_LORESERVE) | 1148 | if (sym->st_shndx >= SHN_LORESERVE) |
1142 | continue; | 1149 | continue; |
1143 | 1150 | check_section_mismatch(modname, elf, &r, sym, fromsec); | |
1144 | tosec = sec_name(elf, sym->st_shndx); | ||
1145 | if (section_mismatch(fromsec, tosec)) | ||
1146 | warn_sec_mismatch(modname, fromsec, elf, sym, r); | ||
1147 | } | 1151 | } |
1148 | } | 1152 | } |
1149 | 1153 | ||
@@ -1155,7 +1159,6 @@ static void section_rel(const char *modname, struct elf_info *elf, | |||
1155 | Elf_Rela r; | 1159 | Elf_Rela r; |
1156 | unsigned int r_sym; | 1160 | unsigned int r_sym; |
1157 | const char *fromsec; | 1161 | const char *fromsec; |
1158 | const char * tosec; | ||
1159 | 1162 | ||
1160 | Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; | 1163 | Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; |
1161 | Elf_Rel *stop = (void *)start + sechdr->sh_size; | 1164 | Elf_Rel *stop = (void *)start + sechdr->sh_size; |
@@ -1202,10 +1205,7 @@ static void section_rel(const char *modname, struct elf_info *elf, | |||
1202 | /* Skip special sections */ | 1205 | /* Skip special sections */ |
1203 | if (sym->st_shndx >= SHN_LORESERVE) | 1206 | if (sym->st_shndx >= SHN_LORESERVE) |
1204 | continue; | 1207 | continue; |
1205 | 1208 | check_section_mismatch(modname, elf, &r, sym, fromsec); | |
1206 | tosec = sec_name(elf, sym->st_shndx); | ||
1207 | if (section_mismatch(fromsec, tosec)) | ||
1208 | warn_sec_mismatch(modname, fromsec, elf, sym, r); | ||
1209 | } | 1209 | } |
1210 | } | 1210 | } |
1211 | 1211 | ||