aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod/modpost.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r--scripts/mod/modpost.c104
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
608static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) 608static 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
613static const char *sec_name(struct elf_info *elf, int shndx) 616static 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 **/
859static int secref_whitelist(const char *modname, const char *tosec, 861static 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 */
995static void warn_sec_mismatch(const char *modname, const char *fromsec, 996static 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
1014static 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