aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/mod/modpost.c73
1 files changed, 38 insertions, 35 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 7dfd0395c5b0..e4099cd5f085 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -605,6 +605,26 @@ static int strrcmp(const char *s, const char *sub)
605 return memcmp(s + slen - sublen, sub, sublen); 605 return memcmp(s + slen - sublen, sub, sublen);
606} 606}
607 607
608static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
609{
610 return elf->strtab + sym->st_name;
611}
612
613static const char *sec_name(struct elf_info *elf, int shndx)
614{
615 Elf_Shdr *sechdrs = elf->sechdrs;
616 return (void *)elf->hdr +
617 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
618 sechdrs[shndx].sh_name;
619}
620
621static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
622{
623 return (void *)elf->hdr +
624 elf->sechdrs[elf->hdr->e_shstrndx].sh_offset +
625 sechdr->sh_name;
626}
627
608/* if sym is empty or point to a string 628/* if sym is empty or point to a string
609 * like ".[0-9]+" then return 1. 629 * like ".[0-9]+" then return 1.
610 * This is the optional prefix added by ld to some sections 630 * This is the optional prefix added by ld to some sections
@@ -943,17 +963,14 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
943{ 963{
944 Elf_Sym *sym; 964 Elf_Sym *sym;
945 Elf_Sym *near = NULL; 965 Elf_Sym *near = NULL;
946 Elf_Ehdr *hdr = elf->hdr;
947 Elf_Addr distance = ~0; 966 Elf_Addr distance = ~0;
948 const char *secstrings = (void *)hdr +
949 elf->sechdrs[hdr->e_shstrndx].sh_offset;
950 967
951 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 968 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
952 const char *symsec; 969 const char *symsec;
953 970
954 if (sym->st_shndx >= SHN_LORESERVE) 971 if (sym->st_shndx >= SHN_LORESERVE)
955 continue; 972 continue;
956 symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name; 973 symsec = sec_name(elf, sym->st_shndx);
957 if (strcmp(symsec, sec) != 0) 974 if (strcmp(symsec, sec) != 0)
958 continue; 975 continue;
959 if (!is_valid_name(elf, sym)) 976 if (!is_valid_name(elf, sym))
@@ -978,24 +995,21 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
978static void warn_sec_mismatch(const char *modname, const char *fromsec, 995static void warn_sec_mismatch(const char *modname, const char *fromsec,
979 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) 996 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
980{ 997{
981 const char *refsymname = "";
982 Elf_Sym *where; 998 Elf_Sym *where;
983 Elf_Sym *refsym; 999 Elf_Sym *refsym;
984 Elf_Ehdr *hdr = elf->hdr; 1000 const char *refsymname = "";
985 Elf_Shdr *sechdrs = elf->sechdrs; 1001 const char *secname;
986 const char *secstrings = (void *)hdr +
987 sechdrs[hdr->e_shstrndx].sh_offset;
988 const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name;
989 1002
1003 secname = sec_name(elf, sym->st_shndx);
990 where = find_elf_symbol2(elf, r.r_offset, fromsec); 1004 where = find_elf_symbol2(elf, r.r_offset, fromsec);
991 1005
992 refsym = find_elf_symbol(elf, r.r_addend, sym); 1006 refsym = find_elf_symbol(elf, r.r_addend, sym);
993 if (refsym && strlen(elf->strtab + refsym->st_name)) 1007 if (refsym && strlen(sym_name(elf, refsym)))
994 refsymname = elf->strtab + refsym->st_name; 1008 refsymname = sym_name(elf, refsym);
995 1009
996 /* check whitelist - we may ignore it */ 1010 /* check whitelist - we may ignore it */
997 if (secref_whitelist(modname, secname, fromsec, 1011 if (secref_whitelist(modname, secname, fromsec,
998 where ? elf->strtab + where->st_name : "", 1012 where ? sym_name(elf, where) : "",
999 refsymname)) 1013 refsymname))
1000 return; 1014 return;
1001 1015
@@ -1003,7 +1017,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
1003 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " 1017 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
1004 "in '%s'\n", 1018 "in '%s'\n",
1005 modname, fromsec, (unsigned long long)r.r_offset, 1019 modname, fromsec, (unsigned long long)r.r_offset,
1006 secname, refsymname, elf->strtab + where->st_name); 1020 secname, refsymname, sym_name(elf, where));
1007 } else { 1021 } else {
1008 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n", 1022 warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
1009 modname, fromsec, (unsigned long long)r.r_offset, 1023 modname, fromsec, (unsigned long long)r.r_offset,
@@ -1095,14 +1109,10 @@ static void section_rela(const char *modname, struct elf_info *elf,
1095 const char *fromsec; 1109 const char *fromsec;
1096 const char * tosec; 1110 const char * tosec;
1097 1111
1098 Elf_Ehdr *hdr = elf->hdr; 1112 Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
1099 Elf_Rela *start = (void *)hdr + sechdr->sh_offset;
1100 Elf_Rela *stop = (void *)start + sechdr->sh_size; 1113 Elf_Rela *stop = (void *)start + sechdr->sh_size;
1101 1114
1102 const char *secstrings = (void *)hdr + 1115 fromsec = sech_name(elf, sechdr);
1103 elf->sechdrs[hdr->e_shstrndx].sh_offset;
1104
1105 fromsec = secstrings + sechdr->sh_name;
1106 fromsec += strlen(".rela"); 1116 fromsec += strlen(".rela");
1107 /* if from section (name) is know good then skip it */ 1117 /* if from section (name) is know good then skip it */
1108 if (match(fromsec, section_white_list)) 1118 if (match(fromsec, section_white_list))
@@ -1111,7 +1121,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
1111 for (rela = start; rela < stop; rela++) { 1121 for (rela = start; rela < stop; rela++) {
1112 r.r_offset = TO_NATIVE(rela->r_offset); 1122 r.r_offset = TO_NATIVE(rela->r_offset);
1113#if KERNEL_ELFCLASS == ELFCLASS64 1123#if KERNEL_ELFCLASS == ELFCLASS64
1114 if (hdr->e_machine == EM_MIPS) { 1124 if (elf->hdr->e_machine == EM_MIPS) {
1115 unsigned int r_typ; 1125 unsigned int r_typ;
1116 r_sym = ELF64_MIPS_R_SYM(rela->r_info); 1126 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
1117 r_sym = TO_NATIVE(r_sym); 1127 r_sym = TO_NATIVE(r_sym);
@@ -1131,8 +1141,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
1131 if (sym->st_shndx >= SHN_LORESERVE) 1141 if (sym->st_shndx >= SHN_LORESERVE)
1132 continue; 1142 continue;
1133 1143
1134 tosec = secstrings + 1144 tosec = sec_name(elf, sym->st_shndx);
1135 elf->sechdrs[sym->st_shndx].sh_name;
1136 if (section_mismatch(fromsec, tosec)) 1145 if (section_mismatch(fromsec, tosec))
1137 warn_sec_mismatch(modname, fromsec, elf, sym, r); 1146 warn_sec_mismatch(modname, fromsec, elf, sym, r);
1138 } 1147 }
@@ -1148,14 +1157,10 @@ static void section_rel(const char *modname, struct elf_info *elf,
1148 const char *fromsec; 1157 const char *fromsec;
1149 const char * tosec; 1158 const char * tosec;
1150 1159
1151 Elf_Ehdr *hdr = elf->hdr; 1160 Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
1152 Elf_Rel *start = (void *)hdr + sechdr->sh_offset;
1153 Elf_Rel *stop = (void *)start + sechdr->sh_size; 1161 Elf_Rel *stop = (void *)start + sechdr->sh_size;
1154 1162
1155 const char *secstrings = (void *)hdr + 1163 fromsec = sech_name(elf, sechdr);
1156 elf->sechdrs[hdr->e_shstrndx].sh_offset;
1157
1158 fromsec = secstrings + sechdr->sh_name;
1159 fromsec += strlen(".rel"); 1164 fromsec += strlen(".rel");
1160 /* if from section (name) is know good then skip it */ 1165 /* if from section (name) is know good then skip it */
1161 if (match(fromsec, section_white_list)) 1166 if (match(fromsec, section_white_list))
@@ -1164,7 +1169,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
1164 for (rel = start; rel < stop; rel++) { 1169 for (rel = start; rel < stop; rel++) {
1165 r.r_offset = TO_NATIVE(rel->r_offset); 1170 r.r_offset = TO_NATIVE(rel->r_offset);
1166#if KERNEL_ELFCLASS == ELFCLASS64 1171#if KERNEL_ELFCLASS == ELFCLASS64
1167 if (hdr->e_machine == EM_MIPS) { 1172 if (elf->hdr->e_machine == EM_MIPS) {
1168 unsigned int r_typ; 1173 unsigned int r_typ;
1169 r_sym = ELF64_MIPS_R_SYM(rel->r_info); 1174 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
1170 r_sym = TO_NATIVE(r_sym); 1175 r_sym = TO_NATIVE(r_sym);
@@ -1179,7 +1184,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
1179 r_sym = ELF_R_SYM(r.r_info); 1184 r_sym = ELF_R_SYM(r.r_info);
1180#endif 1185#endif
1181 r.r_addend = 0; 1186 r.r_addend = 0;
1182 switch (hdr->e_machine) { 1187 switch (elf->hdr->e_machine) {
1183 case EM_386: 1188 case EM_386:
1184 if (addend_386_rel(elf, sechdr, &r)) 1189 if (addend_386_rel(elf, sechdr, &r))
1185 continue; 1190 continue;
@@ -1198,8 +1203,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
1198 if (sym->st_shndx >= SHN_LORESERVE) 1203 if (sym->st_shndx >= SHN_LORESERVE)
1199 continue; 1204 continue;
1200 1205
1201 tosec = secstrings + 1206 tosec = sec_name(elf, sym->st_shndx);
1202 elf->sechdrs[sym->st_shndx].sh_name;
1203 if (section_mismatch(fromsec, tosec)) 1207 if (section_mismatch(fromsec, tosec))
1204 warn_sec_mismatch(modname, fromsec, elf, sym, r); 1208 warn_sec_mismatch(modname, fromsec, elf, sym, r);
1205 } 1209 }
@@ -1221,11 +1225,10 @@ static void check_sec_ref(struct module *mod, const char *modname,
1221 struct elf_info *elf) 1225 struct elf_info *elf)
1222{ 1226{
1223 int i; 1227 int i;
1224 Elf_Ehdr *hdr = elf->hdr;
1225 Elf_Shdr *sechdrs = elf->sechdrs; 1228 Elf_Shdr *sechdrs = elf->sechdrs;
1226 1229
1227 /* Walk through all sections */ 1230 /* Walk through all sections */
1228 for (i = 0; i < hdr->e_shnum; i++) { 1231 for (i = 0; i < elf->hdr->e_shnum; i++) {
1229 /* We want to process only relocation sections and not .init */ 1232 /* We want to process only relocation sections and not .init */
1230 if (sechdrs[i].sh_type == SHT_RELA) 1233 if (sechdrs[i].sh_type == SHT_RELA)
1231 section_rela(modname, elf, &elf->sechdrs[i]); 1234 section_rela(modname, elf, &elf->sechdrs[i]);