| @@ -321,13 +321,10 @@ static void *sym_get_data_by_offset(const struct elf_info *info, · 320 unmodified lines |
| 321 | { | 321 | { |
| 322 | Elf_Shdr *sechdr = &info->sechdrs[secindex]; | 322 | Elf_Shdr *sechdr = &info->sechdrs[secindex]; |
| 323 | | 323 | |
| 324 | if (info->hdr->e_type != ET_REL) | | |
| 325 | offset -= sechdr->sh_addr; | | |
| 326 | | | |
| 327 | return (void *)info->hdr + sechdr->sh_offset + offset; | 324 | return (void *)info->hdr + sechdr->sh_offset + offset; |
| 328 | } | 325 | } |
| 329 | | 326 | |
| 330 | static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) | 327 | void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) |
| 331 | { | 328 | { |
| 332 | return sym_get_data_by_offset(info, get_secindex(info, sym), | 329 | return sym_get_data_by_offset(info, get_secindex(info, sym), |
| 333 | sym->st_value); | 330 | sym->st_value); |
| @@ -339,8 +336,16 @@ static const char *sech_name(const struct elf_info *info, Elf_Shdr *sechdr) · 5 unmodified lines |
| 339 | sechdr->sh_name); | 336 | sechdr->sh_name); |
| 340 | } | 337 | } |
| 341 | | 338 | |
| 342 | static const char *sec_name(const struct elf_info *info, int secindex) | 339 | static const char *sec_name(const struct elf_info *info, unsigned int secindex) |
| 343 | { | 340 | { |
| | 341 | /* |
| | 342 | * If sym->st_shndx is a special section index, there is no |
| | 343 | * corresponding section header. |
| | 344 | * Return "" if the index is out of range of info->sechdrs[] array. |
| | 345 | */ |
| | 346 | if (secindex >= info->num_sections) |
| | 347 | return ""; |
| | 348 | |
| 344 | return sech_name(info, &info->sechdrs[secindex]); | 349 | return sech_name(info, &info->sechdrs[secindex]); |
| 345 | } | 350 | } |
| 346 | | 351 | |
| @@ -466,6 +471,10 @@ static int parse_elf(struct elf_info *info, const char *filename) · 119 unmodified lines |
| 466 | sechdrs = (void *)hdr + hdr->e_shoff; | 471 | sechdrs = (void *)hdr + hdr->e_shoff; |
| 467 | info->sechdrs = sechdrs; | 472 | info->sechdrs = sechdrs; |
| 468 | | 473 | |
| | 474 | /* modpost only works for relocatable objects */ |
| | 475 | if (hdr->e_type != ET_REL) |
| | 476 | fatal("%s: not relocatable object.", filename); |
| | 477 | |
| 469 | /* Check if file offset is correct */ | 478 | /* Check if file offset is correct */ |
| 470 | if (hdr->e_shoff > info->size) { | 479 | if (hdr->e_shoff > info->size) { |
| 471 | fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n", | 480 | fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n", |
| @@ -737,12 +746,18 @@ static bool match(const char *string, const char *const patterns[]) · 265 unmodified lines |
| 737 | return false; | 746 | return false; |
| 738 | } | 747 | } |
| 739 | | 748 | |
| | 749 | /* useful to pass patterns to match() directly */ |
| | 750 | #define PATTERNS(...) \ |
| | 751 | ({ \ |
| | 752 | static const char *const patterns[] = {__VA_ARGS__, NULL}; \ |
| | 753 | patterns; \ |
| | 754 | }) |
| | 755 | |
| 740 | /* sections that we do not want to do full section mismatch check on */ | 756 | /* sections that we do not want to do full section mismatch check on */ |
| 741 | static const char *const section_white_list[] = | 757 | static const char *const section_white_list[] = |
| 742 | { | 758 | { |
| 743 | ".comment*", | 759 | ".comment*", |
| 744 | ".debug*", | 760 | ".debug*", |
| 745 | ".cranges", /* sh64 */ | | |
| 746 | ".zdebug*", /* Compressed debug sections. */ | 761 | ".zdebug*", /* Compressed debug sections. */ |
| 747 | ".GCC.command.line", /* record-gcc-switches */ | 762 | ".GCC.command.line", /* record-gcc-switches */ |
| 748 | ".mdebug*", /* alpha, score, mips etc. */ | 763 | ".mdebug*", /* alpha, score, mips etc. */ |
| @@ -830,28 +845,12 @@ static const char *const init_data_sections[] = · 81 unmodified lines |
| 830 | /* all init sections */ | 845 | /* all init sections */ |
| 831 | static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; | 846 | static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; |
| 832 | | 847 | |
| 833 | /* All init and exit sections (code + data) */ | | |
| 834 | static const char *const init_exit_sections[] = | | |
| 835 | {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; | | |
| 836 | | | |
| 837 | /* all text sections */ | 848 | /* all text sections */ |
| 838 | static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; | 849 | static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; |
| 839 | | 850 | |
| 840 | /* data section */ | 851 | /* data section */ |
| 841 | static const char *const data_sections[] = { DATA_SECTIONS, NULL }; | 852 | static const char *const data_sections[] = { DATA_SECTIONS, NULL }; |
| 842 | | 853 | |
| 843 | | | |
| 844 | /* symbols in .data that may refer to init/exit sections */ | | |
| 845 | #define DEFAULT_SYMBOL_WHITE_LIST \ | | |
| 846 | "*driver", \ | | |
| 847 | "*_template", /* scsi uses *_template a lot */ \ | | |
| 848 | "*_timer", /* arm uses ops structures named _timer a lot */ \ | | |
| 849 | "*_sht", /* scsi also used *_sht to some extent */ \ | | |
| 850 | "*_ops", \ | | |
| 851 | "*_probe", \ | | |
| 852 | "*_probe_one", \ | | |
| 853 | "*_console" | | |
| 854 | | | |
| 855 | static const char *const head_sections[] = { ".head.text*", NULL }; | 854 | static const char *const head_sections[] = { ".head.text*", NULL }; |
| 856 | static const char *const linker_symbols[] = | 855 | static const char *const linker_symbols[] = |
| 857 | { "__init_begin", "_sinittext", "_einittext", NULL }; | 856 | { "__init_begin", "_sinittext", "_einittext", NULL }; |
| @@ -883,9 +882,6 @@ enum mismatch { · 25 unmodified lines |
| 883 | * | 882 | * |
| 884 | * @mismatch: Type of mismatch. | 883 | * @mismatch: Type of mismatch. |
| 885 | * | 884 | * |
| 886 | * @symbol_white_list: Do not match a relocation to a symbol in this list | | |
| 887 | * even if it is targeting a section in @bad_to_sec. | | |
| 888 | * | | |
| 889 | * @handler: Specific handler to call when a match is found. If NULL, | 885 | * @handler: Specific handler to call when a match is found. If NULL, |
| 890 | * default_mismatch_handler() will be called. | 886 | * default_mismatch_handler() will be called. |
| 891 | * | 887 | * |
| @@ -895,7 +891,6 @@ struct sectioncheck { · 3 unmodified lines |
| 895 | const char *bad_tosec[20]; | 891 | const char *bad_tosec[20]; |
| 896 | const char *good_tosec[20]; | 892 | const char *good_tosec[20]; |
| 897 | enum mismatch mismatch; | 893 | enum mismatch mismatch; |
| 898 | const char *symbol_white_list[20]; | | |
| 899 | void (*handler)(const char *modname, struct elf_info *elf, | 894 | void (*handler)(const char *modname, struct elf_info *elf, |
| 900 | const struct sectioncheck* const mismatch, | 895 | const struct sectioncheck* const mismatch, |
| 901 | Elf_Rela *r, Elf_Sym *sym, const char *fromsec); | 896 | Elf_Rela *r, Elf_Sym *sym, const char *fromsec); |
| @@ -915,75 +910,61 @@ static const struct sectioncheck sectioncheck[] = { · 13 unmodified lines |
| 915 | .fromsec = { TEXT_SECTIONS, NULL }, | 910 | .fromsec = { TEXT_SECTIONS, NULL }, |
| 916 | .bad_tosec = { ALL_INIT_SECTIONS, NULL }, | 911 | .bad_tosec = { ALL_INIT_SECTIONS, NULL }, |
| 917 | .mismatch = TEXT_TO_ANY_INIT, | 912 | .mismatch = TEXT_TO_ANY_INIT, |
| 918 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 919 | }, | 913 | }, |
| 920 | { | 914 | { |
| 921 | .fromsec = { DATA_SECTIONS, NULL }, | 915 | .fromsec = { DATA_SECTIONS, NULL }, |
| 922 | .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, | 916 | .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, |
| 923 | .mismatch = DATA_TO_ANY_INIT, | 917 | .mismatch = DATA_TO_ANY_INIT, |
| 924 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 925 | }, | 918 | }, |
| 926 | { | 919 | { |
| 927 | .fromsec = { DATA_SECTIONS, NULL }, | 920 | .fromsec = { DATA_SECTIONS, NULL }, |
| 928 | .bad_tosec = { INIT_SECTIONS, NULL }, | 921 | .bad_tosec = { INIT_SECTIONS, NULL }, |
| 929 | .mismatch = DATA_TO_ANY_INIT, | 922 | .mismatch = DATA_TO_ANY_INIT, |
| 930 | .symbol_white_list = { | | |
| 931 | "*_template", "*_timer", "*_sht", "*_ops", | | |
| 932 | "*_probe", "*_probe_one", "*_console", NULL | | |
| 933 | }, | | |
| 934 | }, | 923 | }, |
| 935 | { | 924 | { |
| 936 | .fromsec = { TEXT_SECTIONS, NULL }, | 925 | .fromsec = { TEXT_SECTIONS, NULL }, |
| 937 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, | 926 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, |
| 938 | .mismatch = TEXT_TO_ANY_EXIT, | 927 | .mismatch = TEXT_TO_ANY_EXIT, |
| 939 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 940 | }, | 928 | }, |
| 941 | { | 929 | { |
| 942 | .fromsec = { DATA_SECTIONS, NULL }, | 930 | .fromsec = { DATA_SECTIONS, NULL }, |
| 943 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, | 931 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, |
| 944 | .mismatch = DATA_TO_ANY_EXIT, | 932 | .mismatch = DATA_TO_ANY_EXIT, |
| 945 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 946 | }, | 933 | }, |
| 947 | /* Do not reference init code/data from meminit code/data */ | 934 | /* Do not reference init code/data from meminit code/data */ |
| 948 | { | 935 | { |
| 949 | .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, | 936 | .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, |
| 950 | .bad_tosec = { INIT_SECTIONS, NULL }, | 937 | .bad_tosec = { INIT_SECTIONS, NULL }, |
| 951 | .mismatch = XXXINIT_TO_SOME_INIT, | 938 | .mismatch = XXXINIT_TO_SOME_INIT, |
| 952 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 953 | }, | 939 | }, |
| 954 | /* Do not reference exit code/data from memexit code/data */ | 940 | /* Do not reference exit code/data from memexit code/data */ |
| 955 | { | 941 | { |
| 956 | .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, | 942 | .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, |
| 957 | .bad_tosec = { EXIT_SECTIONS, NULL }, | 943 | .bad_tosec = { EXIT_SECTIONS, NULL }, |
| 958 | .mismatch = XXXEXIT_TO_SOME_EXIT, | 944 | .mismatch = XXXEXIT_TO_SOME_EXIT, |
| 959 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 960 | }, | 945 | }, |
| 961 | /* Do not use exit code/data from init code */ | 946 | /* Do not use exit code/data from init code */ |
| 962 | { | 947 | { |
| 963 | .fromsec = { ALL_INIT_SECTIONS, NULL }, | 948 | .fromsec = { ALL_INIT_SECTIONS, NULL }, |
| 964 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, | 949 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, |
| 965 | .mismatch = ANY_INIT_TO_ANY_EXIT, | 950 | .mismatch = ANY_INIT_TO_ANY_EXIT, |
| 966 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 967 | }, | 951 | }, |
| 968 | /* Do not use init code/data from exit code */ | 952 | /* Do not use init code/data from exit code */ |
| 969 | { | 953 | { |
| 970 | .fromsec = { ALL_EXIT_SECTIONS, NULL }, | 954 | .fromsec = { ALL_EXIT_SECTIONS, NULL }, |
| 971 | .bad_tosec = { ALL_INIT_SECTIONS, NULL }, | 955 | .bad_tosec = { ALL_INIT_SECTIONS, NULL }, |
| 972 | .mismatch = ANY_EXIT_TO_ANY_INIT, | 956 | .mismatch = ANY_EXIT_TO_ANY_INIT, |
| 973 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 974 | }, | 957 | }, |
| 975 | { | 958 | { |
| 976 | .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, | 959 | .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, |
| 977 | .bad_tosec = { INIT_SECTIONS, NULL }, | 960 | .bad_tosec = { INIT_SECTIONS, NULL }, |
| 978 | .mismatch = ANY_INIT_TO_ANY_EXIT, | 961 | .mismatch = ANY_INIT_TO_ANY_EXIT, |
| 979 | .symbol_white_list = { NULL }, | | |
| 980 | }, | 962 | }, |
| 981 | /* Do not export init/exit functions or data */ | 963 | /* Do not export init/exit functions or data */ |
| 982 | { | 964 | { |
| 983 | .fromsec = { "___ksymtab*", NULL }, | 965 | .fromsec = { "___ksymtab*", NULL }, |
| 984 | .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, | 966 | .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, |
| 985 | .mismatch = EXPORT_TO_INIT_EXIT, | 967 | .mismatch = EXPORT_TO_INIT_EXIT, |
| 986 | .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, | | |
| 987 | }, | 968 | }, |
| 988 | { | 969 | { |
| 989 | .fromsec = { "__ex_table", NULL }, | 970 | .fromsec = { "__ex_table", NULL }, |
| @@ -1044,15 +1025,6 @@ static const struct sectioncheck *section_mismatch( · 54 unmodified lines |
| 1044 | * fromsec = .data* | 1025 | * fromsec = .data* |
| 1045 | * atsym = __param_ops_* | 1026 | * atsym = __param_ops_* |
| 1046 | * | 1027 | * |
| 1047 | * Pattern 2: | | |
| 1048 | * Many drivers utilise a *driver container with references to | | |
| 1049 | * add, remove, probe functions etc. | | |
| 1050 | * the pattern is identified by: | | |
| 1051 | * tosec = init or exit section | | |
| 1052 | * fromsec = data section | | |
| 1053 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, | | |
| 1054 | * *probe_one, *_console, *_timer | | |
| 1055 | * | | |
| 1056 | * Pattern 3: | 1028 | * Pattern 3: |
| 1057 | * Whitelist all references from .head.text to any init section | 1029 | * Whitelist all references from .head.text to any init section |
| 1058 | * | 1030 | * |
| @@ -1101,10 +1073,22 @@ static int secref_whitelist(const struct sectioncheck *mismatch, · 42 unmodified lines |
| 1101 | strstarts(fromsym, "__param_ops_")) | 1073 | strstarts(fromsym, "__param_ops_")) |
| 1102 | return 0; | 1074 | return 0; |
| 1103 | | 1075 | |
| 1104 | /* Check for pattern 2 */ | 1076 | /* symbols in data sections that may refer to any init/exit sections */ |
| 1105 | if (match(tosec, init_exit_sections) && | 1077 | if (match(fromsec, PATTERNS(DATA_SECTIONS)) && |
| 1106 | match(fromsec, data_sections) && | 1078 | match(tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) && |
| 1107 | match(fromsym, mismatch->symbol_white_list)) | 1079 | match(fromsym, PATTERNS("*_template", // scsi uses *_template a lot |
| | 1080 | "*_timer", // arm uses ops structures named _timer a lot |
| | 1081 | "*_sht", // scsi also used *_sht to some extent |
| | 1082 | "*_ops", |
| | 1083 | "*_probe", |
| | 1084 | "*_probe_one", |
| | 1085 | "*_console"))) |
| | 1086 | return 0; |
| | 1087 | |
| | 1088 | /* symbols in data sections that may refer to meminit/exit sections */ |
| | 1089 | if (match(fromsec, PATTERNS(DATA_SECTIONS)) && |
| | 1090 | match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS, ALL_EXIT_SECTIONS)) && |
| | 1091 | match(fromsym, PATTERNS("*driver"))) |
| 1108 | return 0; | 1092 | return 0; |
| 1109 | | 1093 | |
| 1110 | /* Check for pattern 3 */ | 1094 | /* Check for pattern 3 */ |
| @@ -1230,42 +1214,6 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, · 119 unmodified lines |
| 1230 | return near; | 1214 | return near; |
| 1231 | } | 1215 | } |
| 1232 | | 1216 | |
| 1233 | /* | | |
| 1234 | * Convert a section name to the function/data attribute | | |
| 1235 | * .init.text => __init | | |
| 1236 | * .memexitconst => __memconst | | |
| 1237 | * etc. | | |
| 1238 | * | | |
| 1239 | * The memory of returned value has been allocated on a heap. The user of this | | |
| 1240 | * method should free it after usage. | | |
| 1241 | */ | | |
| 1242 | static char *sec2annotation(const char *s) | | |
| 1243 | { | | |
| 1244 | if (match(s, init_exit_sections)) { | | |
| 1245 | char *p = NOFAIL(malloc(20)); | | |
| 1246 | char *r = p; | | |
| 1247 | | | |
| 1248 | *p++ = '_'; | | |
| 1249 | *p++ = '_'; | | |
| 1250 | if (*s == '.') | | |
| 1251 | s++; | | |
| 1252 | while (*s && *s != '.') | | |
| 1253 | *p++ = *s++; | | |
| 1254 | *p = '\0'; | | |
| 1255 | if (*s == '.') | | |
| 1256 | s++; | | |
| 1257 | if (strstr(s, "rodata") != NULL) | | |
| 1258 | strcat(p, "const "); | | |
| 1259 | else if (strstr(s, "data") != NULL) | | |
| 1260 | strcat(p, "data "); | | |
| 1261 | else | | |
| 1262 | strcat(p, " "); | | |
| 1263 | return r; | | |
| 1264 | } else { | | |
| 1265 | return NOFAIL(strdup("")); | | |
| 1266 | } | | |
| 1267 | } | | |
| 1268 | | | |
| 1269 | static int is_function(Elf_Sym *sym) | 1217 | static int is_function(Elf_Sym *sym) |
| 1270 | { | 1218 | { |
| 1271 | if (sym) | 1219 | if (sym) |
| @@ -1274,19 +1222,6 @@ static int is_function(Elf_Sym *sym) · 2 unmodified lines |
| 1274 | return -1; | 1222 | return -1; |
| 1275 | } | 1223 | } |
| 1276 | | 1224 | |
| 1277 | static void print_section_list(const char * const list[20]) | | |
| 1278 | { | | |
| 1279 | const char *const *s = list; | | |
| 1280 | | | |
| 1281 | while (*s) { | | |
| 1282 | fprintf(stderr, "%s", *s); | | |
| 1283 | s++; | | |
| 1284 | if (*s) | | |
| 1285 | fprintf(stderr, ", "); | | |
| 1286 | } | | |
| 1287 | fprintf(stderr, "\n"); | | |
| 1288 | } | | |
| 1289 | | | |
| 1290 | static inline void get_pretty_name(int is_func, const char** name, const char** name_p) | 1225 | static inline void get_pretty_name(int is_func, const char** name, const char** name_p) |
| 1291 | { | 1226 | { |
| 1292 | switch (is_func) { | 1227 | switch (is_func) { |
| @@ -1304,141 +1239,31 @@ static inline void get_pretty_name(int is_func, const char** name, const char** · 11 unmodified lines |
| 1304 | static void report_sec_mismatch(const char *modname, | 1239 | static void report_sec_mismatch(const char *modname, |
| 1305 | const struct sectioncheck *mismatch, | 1240 | const struct sectioncheck *mismatch, |
| 1306 | const char *fromsec, | 1241 | const char *fromsec, |
| 1307 | unsigned long long fromaddr, | | |
| 1308 | const char *fromsym, | 1242 | const char *fromsym, |
| 1309 | int from_is_func, | 1243 | const char *tosec, const char *tosym) |
| 1310 | const char *tosec, const char *tosym, | | |
| 1311 | int to_is_func) | | |
| 1312 | { | 1244 | { |
| 1313 | const char *from, *from_p; | | |
| 1314 | const char *to, *to_p; | | |
| 1315 | char *prl_from; | | |
| 1316 | char *prl_to; | | |
| 1317 | | | |
| 1318 | sec_mismatch_count++; | 1245 | sec_mismatch_count++; |
| 1319 | | 1246 | |
| 1320 | get_pretty_name(from_is_func, &from, &from_p); | | |
| 1321 | get_pretty_name(to_is_func, &to, &to_p); | | |
| 1322 | | | |
| 1323 | warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " | | |
| 1324 | "to the %s %s:%s%s\n", | | |
| 1325 | modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, | | |
| 1326 | tosym, to_p); | | |
| 1327 | | | |
| 1328 | switch (mismatch->mismatch) { | 1247 | switch (mismatch->mismatch) { |
| 1329 | case TEXT_TO_ANY_INIT: | 1248 | case TEXT_TO_ANY_INIT: |
| 1330 | prl_from = sec2annotation(fromsec); | 1249 | case DATA_TO_ANY_INIT: |
| 1331 | prl_to = sec2annotation(tosec); | | |
| 1332 | fprintf(stderr, | | |
| 1333 | "The function %s%s() references\n" | | |
| 1334 | "the %s %s%s%s.\n" | | |
| 1335 | "This is often because %s lacks a %s\n" | | |
| 1336 | "annotation or the annotation of %s is wrong.\n", | | |
| 1337 | prl_from, fromsym, | | |
| 1338 | to, prl_to, tosym, to_p, | | |
| 1339 | fromsym, prl_to, tosym); | | |
| 1340 | free(prl_from); | | |
| 1341 | free(prl_to); | | |
| 1342 | break; | | |
| 1343 | case DATA_TO_ANY_INIT: { | | |
| 1344 | prl_to = sec2annotation(tosec); | | |
| 1345 | fprintf(stderr, | | |
| 1346 | "The variable %s references\n" | | |
| 1347 | "the %s %s%s%s\n" | | |
| 1348 | "If the reference is valid then annotate the\n" | | |
| 1349 | "variable with __init* or __refdata (see linux/init.h) " | | |
| 1350 | "or name the variable:\n", | | |
| 1351 | fromsym, to, prl_to, tosym, to_p); | | |
| 1352 | print_section_list(mismatch->symbol_white_list); | | |
| 1353 | free(prl_to); | | |
| 1354 | break; | | |
| 1355 | } | | |
| 1356 | case TEXT_TO_ANY_EXIT: | 1250 | case TEXT_TO_ANY_EXIT: |
| 1357 | prl_to = sec2annotation(tosec); | 1251 | case DATA_TO_ANY_EXIT: |
| 1358 | fprintf(stderr, | | |
| 1359 | "The function %s() references a %s in an exit section.\n" | | |
| 1360 | "Often the %s %s%s has valid usage outside the exit section\n" | | |
| 1361 | "and the fix is to remove the %sannotation of %s.\n", | | |
| 1362 | fromsym, to, to, tosym, to_p, prl_to, tosym); | | |
| 1363 | free(prl_to); | | |
| 1364 | break; | | |
| 1365 | case DATA_TO_ANY_EXIT: { | | |
| 1366 | prl_to = sec2annotation(tosec); | | |
| 1367 | fprintf(stderr, | | |
| 1368 | "The variable %s references\n" | | |
| 1369 | "the %s %s%s%s\n" | | |
| 1370 | "If the reference is valid then annotate the\n" | | |
| 1371 | "variable with __exit* (see linux/init.h) or " | | |
| 1372 | "name the variable:\n", | | |
| 1373 | fromsym, to, prl_to, tosym, to_p); | | |
| 1374 | print_section_list(mismatch->symbol_white_list); | | |
| 1375 | free(prl_to); | | |
| 1376 | break; | | |
| 1377 | } | | |
| 1378 | case XXXINIT_TO_SOME_INIT: | 1252 | case XXXINIT_TO_SOME_INIT: |
| 1379 | case XXXEXIT_TO_SOME_EXIT: | 1253 | case XXXEXIT_TO_SOME_EXIT: |
| 1380 | prl_from = sec2annotation(fromsec); | | |
| 1381 | prl_to = sec2annotation(tosec); | | |
| 1382 | fprintf(stderr, | | |
| 1383 | "The %s %s%s%s references\n" | | |
| 1384 | "a %s %s%s%s.\n" | | |
| 1385 | "If %s is only used by %s then\n" | | |
| 1386 | "annotate %s with a matching annotation.\n", | | |
| 1387 | from, prl_from, fromsym, from_p, | | |
| 1388 | to, prl_to, tosym, to_p, | | |
| 1389 | tosym, fromsym, tosym); | | |
| 1390 | free(prl_from); | | |
| 1391 | free(prl_to); | | |
| 1392 | break; | | |
| 1393 | case ANY_INIT_TO_ANY_EXIT: | 1254 | case ANY_INIT_TO_ANY_EXIT: |
| 1394 | prl_from = sec2annotation(fromsec); | | |
| 1395 | prl_to = sec2annotation(tosec); | | |
| 1396 | fprintf(stderr, | | |
| 1397 | "The %s %s%s%s references\n" | | |
| 1398 | "a %s %s%s%s.\n" | | |
| 1399 | "This is often seen when error handling " | | |
| 1400 | "in the init function\n" | | |
| 1401 | "uses functionality in the exit path.\n" | | |
| 1402 | "The fix is often to remove the %sannotation of\n" | | |
| 1403 | "%s%s so it may be used outside an exit section.\n", | | |
| 1404 | from, prl_from, fromsym, from_p, | | |
| 1405 | to, prl_to, tosym, to_p, | | |
| 1406 | prl_to, tosym, to_p); | | |
| 1407 | free(prl_from); | | |
| 1408 | free(prl_to); | | |
| 1409 | break; | | |
| 1410 | case ANY_EXIT_TO_ANY_INIT: | 1255 | case ANY_EXIT_TO_ANY_INIT: |
| 1411 | prl_from = sec2annotation(fromsec); | 1256 | warn("%s: section mismatch in reference: %s (section: %s) -> %s (section: %s)\n", |
| 1412 | prl_to = sec2annotation(tosec); | 1257 | modname, fromsym, fromsec, tosym, tosec); |
| 1413 | fprintf(stderr, | | |
| 1414 | "The %s %s%s%s references\n" | | |
| 1415 | "a %s %s%s%s.\n" | | |
| 1416 | "This is often seen when error handling " | | |
| 1417 | "in the exit function\n" | | |
| 1418 | "uses functionality in the init path.\n" | | |
| 1419 | "The fix is often to remove the %sannotation of\n" | | |
| 1420 | "%s%s so it may be used outside an init section.\n", | | |
| 1421 | from, prl_from, fromsym, from_p, | | |
| 1422 | to, prl_to, tosym, to_p, | | |
| 1423 | prl_to, tosym, to_p); | | |
| 1424 | free(prl_from); | | |
| 1425 | free(prl_to); | | |
| 1426 | break; | 1258 | break; |
| 1427 | case EXPORT_TO_INIT_EXIT: | 1259 | case EXPORT_TO_INIT_EXIT: |
| 1428 | prl_to = sec2annotation(tosec); | 1260 | warn("%s: EXPORT_SYMBOL used for init/exit symbol: %s (section: %s)\n", |
| 1429 | fprintf(stderr, | 1261 | modname, tosym, tosec); |
| 1430 | "The symbol %s is exported and annotated %s\n" | | |
| 1431 | "Fix this by removing the %sannotation of %s " | | |
| 1432 | "or drop the export.\n", | | |
| 1433 | tosym, prl_to, prl_to, tosym); | | |
| 1434 | free(prl_to); | | |
| 1435 | break; | 1262 | break; |
| 1436 | case EXTABLE_TO_NON_TEXT: | 1263 | case EXTABLE_TO_NON_TEXT: |
| 1437 | fatal("There's a special handler for this mismatch type, " | 1264 | fatal("There's a special handler for this mismatch type, we should never get here.\n"); |
| 1438 | "we should never get here."); | | |
| 1439 | break; | 1265 | break; |
| 1440 | } | 1266 | } |
| 1441 | fprintf(stderr, "\n"); | | |
| 1442 | } | 1267 | } |
| 1443 | | 1268 | |
| 1444 | static void default_mismatch_handler(const char *modname, struct elf_info *elf, | 1269 | static void default_mismatch_handler(const char *modname, struct elf_info *elf, |
| @@ -1454,9 +1279,6 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, · 9 unmodified lines |
| 1454 | from = find_elf_symbol2(elf, r->r_offset, fromsec); | 1279 | from = find_elf_symbol2(elf, r->r_offset, fromsec); |
| 1455 | fromsym = sym_name(elf, from); | 1280 | fromsym = sym_name(elf, from); |
| 1456 | | 1281 | |
| 1457 | if (strstarts(fromsym, "reference___initcall")) | | |
| 1458 | return; | | |
| 1459 | | | |
| 1460 | tosec = sec_name(elf, get_secindex(elf, sym)); | 1282 | tosec = sec_name(elf, get_secindex(elf, sym)); |
| 1461 | to = find_elf_symbol(elf, r->r_addend, sym); | 1283 | to = find_elf_symbol(elf, r->r_addend, sym); |
| 1462 | tosym = sym_name(elf, to); | 1284 | tosym = sym_name(elf, to); |
| @@ -1465,9 +1287,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf, · 2 unmodified lines |
| 1465 | if (secref_whitelist(mismatch, | 1287 | if (secref_whitelist(mismatch, |
| 1466 | fromsec, fromsym, tosec, tosym)) { | 1288 | fromsec, fromsym, tosec, tosym)) { |
| 1467 | report_sec_mismatch(modname, mismatch, | 1289 | report_sec_mismatch(modname, mismatch, |
| 1468 | fromsec, r->r_offset, fromsym, | 1290 | fromsec, fromsym, tosec, tosym); |
| 1469 | is_function(from), tosec, tosym, | | |
| 1470 | is_function(to)); | | |
| 1471 | } | 1291 | } |
| 1472 | } | 1292 | } |
| 1473 | | 1293 | |
| @@ -1623,9 +1443,6 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) · 149 unmodified lines |
| 1623 | break; | 1443 | break; |
| 1624 | case R_386_PC32: | 1444 | case R_386_PC32: |
| 1625 | r->r_addend = TO_NATIVE(*location) + 4; | 1445 | r->r_addend = TO_NATIVE(*location) + 4; |
| 1626 | /* For CONFIG_RELOCATABLE=y */ | | |
| 1627 | if (elf->hdr->e_type == ET_EXEC) | | |
| 1628 | r->r_addend += r->r_offset; | | |
| 1629 | break; | 1446 | break; |
| 1630 | } | 1447 | } |
| 1631 | return 0; | 1448 | return 0; |
| @@ -1718,8 +1535,7 @@ static void section_rela(const char *modname, struct elf_info *elf, · 86 unmodified lines |
| 1718 | Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; | 1535 | Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; |
| 1719 | Elf_Rela *stop = (void *)start + sechdr->sh_size; | 1536 | Elf_Rela *stop = (void *)start + sechdr->sh_size; |
| 1720 | | 1537 | |
| 1721 | fromsec = sech_name(elf, sechdr); | 1538 | fromsec = sec_name(elf, sechdr->sh_info); |
| 1722 | fromsec += strlen(".rela"); | | |
| 1723 | /* if from section (name) is know good then skip it */ | 1539 | /* if from section (name) is know good then skip it */ |
| 1724 | if (match(fromsec, section_white_list)) | 1540 | if (match(fromsec, section_white_list)) |
| 1725 | return; | 1541 | return; |
| @@ -1771,8 +1587,7 @@ static void section_rel(const char *modname, struct elf_info *elf, · 45 unmodified lines |
| 1771 | Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; | 1587 | Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; |
| 1772 | Elf_Rel *stop = (void *)start + sechdr->sh_size; | 1588 | Elf_Rel *stop = (void *)start + sechdr->sh_size; |
| 1773 | | 1589 | |
| 1774 | fromsec = sech_name(elf, sechdr); | 1590 | fromsec = sec_name(elf, sechdr->sh_info); |
| 1775 | fromsec += strlen(".rel"); | | |
| 1776 | /* if from section (name) is know good then skip it */ | 1591 | /* if from section (name) is know good then skip it */ |
| 1777 | if (match(fromsec, section_white_list)) | 1592 | if (match(fromsec, section_white_list)) |
| 1778 | return; | 1593 | return; |