On i386, ARM and MIPS, warn_sec_mismatch() sometimes fails to show usefull symbol name. This is because empty 'refsym' due to 0 r_addend value. This patch is to adjust r_addend value, consulting with apply_relocate() routine in kernel code. Without this patch: MODPOST vmlinux WARNING: init/built-in.o - Section mismatch: reference to .init.text: from .text between 'rest_init' (at offset 0xf4) and 'try_name' WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap' WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap' With this patch: MODPOST vmlinux WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap' WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap' Now modpost can detect "kernel_init" name (and whitelist it) and show "set_up_list3s" name.
Unified · Split
| @@ -384,6 +384,7 @@ static int parse_elf(struct elf_info *info, const char *filename) · 383 unmodified lines | ||
| 384 | 384 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); |
| 385 | 385 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); |
| 386 | 386 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); |
| 387 | + sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); | |
| 387 | 388 | } |
| 388 | 389 | /* Find symbol table. */ |
| 389 | 390 | for (i = 1; i < hdr->e_shnum; i++) { |
| @@ -773,6 +774,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, · 383 unmodified lines | ||
| 773 | 774 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
| 774 | 775 | if (sym->st_shndx != relsym->st_shndx) |
| 775 | 776 | continue; |
| 777 | + if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) | |
| 778 | + continue; | |
| 776 | 779 | if (sym->st_value == addr) |
| 777 | 780 | return sym; |
| 778 | 781 | } |
| @@ -910,6 +913,68 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, · 131 unmodified lines | ||
| 910 | 913 | } |
| 911 | 914 | } |
| 912 | 915 | |
| 916 | +static void addend_386_rel(struct elf_info *elf, int section, Elf_Rela *r) | |
| 917 | +{ | |
| 918 | + Elf_Shdr *sechdrs = elf->sechdrs; | |
| 919 | + unsigned int r_typ; | |
| 920 | + unsigned int *location; | |
| 921 | + | |
| 922 | + r_typ = ELF_R_TYPE(r->r_info); | |
| 923 | + location = (void *)elf->hdr + | |
| 924 | + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | |
| 925 | + switch (r_typ) { | |
| 926 | + case R_386_32: | |
| 927 | + r->r_addend = TO_NATIVE(*location); | |
| 928 | + break; | |
| 929 | + case R_386_PC32: | |
| 930 | + r->r_addend = TO_NATIVE(*location) + 4; | |
| 931 | + break; | |
| 932 | + } | |
| 933 | +} | |
| 934 | + | |
| 935 | +static void addend_arm_rel(struct elf_info *elf, int section, Elf_Rela *r) | |
| 936 | +{ | |
| 937 | + Elf_Shdr *sechdrs = elf->sechdrs; | |
| 938 | + unsigned int r_typ; | |
| 939 | + unsigned int *location; | |
| 940 | + | |
| 941 | + r_typ = ELF_R_TYPE(r->r_info); | |
| 942 | + location = (void *)elf->hdr + | |
| 943 | + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | |
| 944 | + switch (r_typ) { | |
| 945 | + case R_ARM_ABS32: | |
| 946 | + r->r_addend = TO_NATIVE(*location); | |
| 947 | + break; | |
| 948 | + case R_ARM_PC24: | |
| 949 | + r->r_addend = ((TO_NATIVE(*location) & 0x00ffffff) << 2) + 8; | |
| 950 | + break; | |
| 951 | + } | |
| 952 | +} | |
| 953 | + | |
| 954 | +static int addend_mips_rel(struct elf_info *elf, int section, Elf_Rela *r) | |
| 955 | +{ | |
| 956 | + Elf_Shdr *sechdrs = elf->sechdrs; | |
| 957 | + unsigned int r_typ; | |
| 958 | + unsigned int *location; | |
| 959 | + unsigned int inst; | |
| 960 | + | |
| 961 | + r_typ = ELF_R_TYPE(r->r_info); | |
| 962 | + if (r_typ == R_MIPS_HI16) | |
| 963 | + return 1; /* skip this */ | |
| 964 | + location = (void *)elf->hdr + | |
| 965 | + sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | |
| 966 | + inst = TO_NATIVE(*location); | |
| 967 | + switch (r_typ) { | |
| 968 | + case R_MIPS_LO16: | |
| 969 | + r->r_addend = ((inst & 0xffff) ^ 0x8000) - 0x8000; | |
| 970 | + break; | |
| 971 | + case R_MIPS_26: | |
| 972 | + r->r_addend = (inst & 0x03ffffff) << 2; | |
| 973 | + break; | |
| 974 | + } | |
| 975 | + return 0; | |
| 976 | +} | |
| 977 | + | |
| 913 | 978 | /** |
| 914 | 979 | * A module includes a number of sections that are discarded |
| 915 | 980 | * either when loaded or when used as built-in. |
| @@ -953,8 +1018,11 @@ static void check_sec_ref(struct module *mod, const char *modname, · 37 unmodified lines | ||
| 953 | 1018 | r.r_offset = TO_NATIVE(rela->r_offset); |
| 954 | 1019 | #if KERNEL_ELFCLASS == ELFCLASS64 |
| 955 | 1020 | if (hdr->e_machine == EM_MIPS) { |
| 1021 | + unsigned int r_typ; | |
| 956 | 1022 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); |
| 957 | 1023 | r_sym = TO_NATIVE(r_sym); |
| 1024 | + r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | |
| 1025 | + r.r_info = ELF64_R_INFO(r_sym, r_typ); | |
| 958 | 1026 | } else { |
| 959 | 1027 | r.r_info = TO_NATIVE(rela->r_info); |
| 960 | 1028 | r_sym = ELF_R_SYM(r.r_info); |
| @@ -987,8 +1055,11 @@ static void check_sec_ref(struct module *mod, const char *modname, · 26 unmodified lines | ||
| 987 | 1055 | r.r_offset = TO_NATIVE(rel->r_offset); |
| 988 | 1056 | #if KERNEL_ELFCLASS == ELFCLASS64 |
| 989 | 1057 | if (hdr->e_machine == EM_MIPS) { |
| 1058 | + unsigned int r_typ; | |
| 990 | 1059 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); |
| 991 | 1060 | r_sym = TO_NATIVE(r_sym); |
| 1061 | + r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | |
| 1062 | + r.r_info = ELF64_R_INFO(r_sym, r_typ); | |
| 992 | 1063 | } else { |
| 993 | 1064 | r.r_info = TO_NATIVE(rel->r_info); |
| 994 | 1065 | r_sym = ELF_R_SYM(r.r_info); |
| @@ -998,6 +1069,14 @@ static void check_sec_ref(struct module *mod, const char *modname, · 3 unmodified lines | ||
| 998 | 1069 | r_sym = ELF_R_SYM(r.r_info); |
| 999 | 1070 | #endif |
| 1000 | 1071 | r.r_addend = 0; |
| 1072 | + if (hdr->e_machine == EM_386) | |
| 1073 | + addend_386_rel(elf, i, &r); | |
| 1074 | + else if (hdr->e_machine == EM_ARM) | |
| 1075 | + addend_arm_rel(elf, i, &r); | |
| 1076 | + else if (hdr->e_machine == EM_MIPS) { | |
| 1077 | + if (addend_mips_rel(elf, i, &r)) | |
| 1078 | + continue; | |
| 1079 | + } | |
| 1001 | 1080 | sym = elf->symtab_start + r_sym; |
| 1002 | 1081 | /* Skip special sections */ |
| 1003 | 1082 | if (sym->st_shndx >= SHN_LORESERVE) |
| @@ -60,6 +60,9 @@ typedef union · 59 unmodified lines | ||
| 60 | 60 | #define ELF64_MIPS_R_SYM(i) \ |
| 61 | 61 | ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) |
| 62 | 62 | |
| 63 | +#define ELF64_MIPS_R_TYPE(i) \ | |
| 64 | + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) | |
| 65 | + | |
| 63 | 66 | #if KERNEL_ELFDATA != HOST_ELFDATA |
| 64 | 67 | |
| 65 | 68 | static inline void __endian(const void *src, void *dest, unsigned int size) |