diff options
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 56 |
1 files changed, 16 insertions, 40 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 730b321680cd..7dfd0395c5b0 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -938,20 +938,16 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) | |||
938 | * The ELF format may have a better way to detect what type of symbol | 938 | * The ELF format may have a better way to detect what type of symbol |
939 | * it is, but this works for now. | 939 | * it is, but this works for now. |
940 | **/ | 940 | **/ |
941 | static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, | 941 | static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, |
942 | const char *sec, | 942 | const char *sec) |
943 | Elf_Sym **before, Elf_Sym **after) | ||
944 | { | 943 | { |
945 | Elf_Sym *sym; | 944 | Elf_Sym *sym; |
945 | Elf_Sym *near = NULL; | ||
946 | Elf_Ehdr *hdr = elf->hdr; | 946 | Elf_Ehdr *hdr = elf->hdr; |
947 | Elf_Addr beforediff = ~0; | 947 | Elf_Addr distance = ~0; |
948 | Elf_Addr afterdiff = ~0; | ||
949 | const char *secstrings = (void *)hdr + | 948 | const char *secstrings = (void *)hdr + |
950 | elf->sechdrs[hdr->e_shstrndx].sh_offset; | 949 | elf->sechdrs[hdr->e_shstrndx].sh_offset; |
951 | 950 | ||
952 | *before = NULL; | ||
953 | *after = NULL; | ||
954 | |||
955 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | 951 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
956 | const char *symsec; | 952 | const char *symsec; |
957 | 953 | ||
@@ -963,20 +959,15 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, | |||
963 | if (!is_valid_name(elf, sym)) | 959 | if (!is_valid_name(elf, sym)) |
964 | continue; | 960 | continue; |
965 | if (sym->st_value <= addr) { | 961 | if (sym->st_value <= addr) { |
966 | if ((addr - sym->st_value) < beforediff) { | 962 | if ((addr - sym->st_value) < distance) { |
967 | beforediff = addr - sym->st_value; | 963 | distance = addr - sym->st_value; |
968 | *before = sym; | 964 | near = sym; |
969 | } else if ((addr - sym->st_value) == beforediff) { | 965 | } else if ((addr - sym->st_value) == distance) { |
970 | *before = sym; | 966 | near = sym; |
971 | } | 967 | } |
972 | } else { | ||
973 | if ((sym->st_value - addr) < afterdiff) { | ||
974 | afterdiff = sym->st_value - addr; | ||
975 | *after = sym; | ||
976 | } else if ((sym->st_value - addr) == afterdiff) | ||
977 | *after = sym; | ||
978 | } | 968 | } |
979 | } | 969 | } |
970 | return near; | ||
980 | } | 971 | } |
981 | 972 | ||
982 | /** | 973 | /** |
@@ -988,7 +979,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
988 | struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) | 979 | struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) |
989 | { | 980 | { |
990 | const char *refsymname = ""; | 981 | const char *refsymname = ""; |
991 | Elf_Sym *before, *after; | 982 | Elf_Sym *where; |
992 | Elf_Sym *refsym; | 983 | Elf_Sym *refsym; |
993 | Elf_Ehdr *hdr = elf->hdr; | 984 | Elf_Ehdr *hdr = elf->hdr; |
994 | Elf_Shdr *sechdrs = elf->sechdrs; | 985 | Elf_Shdr *sechdrs = elf->sechdrs; |
@@ -996,7 +987,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
996 | sechdrs[hdr->e_shstrndx].sh_offset; | 987 | sechdrs[hdr->e_shstrndx].sh_offset; |
997 | const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; | 988 | const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; |
998 | 989 | ||
999 | find_symbols_between(elf, r.r_offset, fromsec, &before, &after); | 990 | where = find_elf_symbol2(elf, r.r_offset, fromsec); |
1000 | 991 | ||
1001 | refsym = find_elf_symbol(elf, r.r_addend, sym); | 992 | refsym = find_elf_symbol(elf, r.r_addend, sym); |
1002 | if (refsym && strlen(elf->strtab + refsym->st_name)) | 993 | if (refsym && strlen(elf->strtab + refsym->st_name)) |
@@ -1004,30 +995,15 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
1004 | 995 | ||
1005 | /* check whitelist - we may ignore it */ | 996 | /* check whitelist - we may ignore it */ |
1006 | if (secref_whitelist(modname, secname, fromsec, | 997 | if (secref_whitelist(modname, secname, fromsec, |
1007 | before ? elf->strtab + before->st_name : "", | 998 | where ? elf->strtab + where->st_name : "", |
1008 | refsymname)) | 999 | refsymname)) |
1009 | return; | 1000 | return; |
1010 | 1001 | ||
1011 | if (before && after) { | 1002 | if (where) { |
1012 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | ||
1013 | "(between '%s' and '%s')\n", | ||
1014 | modname, fromsec, (unsigned long long)r.r_offset, | ||
1015 | secname, refsymname, | ||
1016 | elf->strtab + before->st_name, | ||
1017 | elf->strtab + after->st_name); | ||
1018 | } else if (before) { | ||
1019 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | ||
1020 | "(after '%s')\n", | ||
1021 | modname, fromsec, (unsigned long long)r.r_offset, | ||
1022 | secname, refsymname, | ||
1023 | elf->strtab + before->st_name); | ||
1024 | } else if (after) { | ||
1025 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | 1003 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " |
1026 | "before '%s' (at offset -0x%llx)\n", | 1004 | "in '%s'\n", |
1027 | modname, fromsec, (unsigned long long)r.r_offset, | 1005 | modname, fromsec, (unsigned long long)r.r_offset, |
1028 | secname, refsymname, | 1006 | secname, refsymname, elf->strtab + where->st_name); |
1029 | elf->strtab + after->st_name, | ||
1030 | (unsigned long long)r.r_offset); | ||
1031 | } else { | 1007 | } else { |
1032 | 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", |
1033 | modname, fromsec, (unsigned long long)r.r_offset, | 1009 | modname, fromsec, (unsigned long long)r.r_offset, |