Commit ae4ac12323c0ff80528cac3269151d580e23f923
Committed by
Sam Ravnborg
1 parent
b70e325cfe
Exists in
master
and in
39 other branches
kbuild: make better section mismatch reports on i386 and mips
On i386 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. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Showing 2 changed files with 76 additions and 0 deletions Side-by-side Diff
scripts/mod/modpost.c
... | ... | @@ -374,6 +374,7 @@ |
374 | 374 | hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); |
375 | 375 | hdr->e_shnum = TO_NATIVE(hdr->e_shnum); |
376 | 376 | hdr->e_machine = TO_NATIVE(hdr->e_machine); |
377 | + hdr->e_type = TO_NATIVE(hdr->e_type); | |
377 | 378 | sechdrs = (void *)hdr + hdr->e_shoff; |
378 | 379 | info->sechdrs = sechdrs; |
379 | 380 | |
... | ... | @@ -384,6 +385,8 @@ |
384 | 385 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); |
385 | 386 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); |
386 | 387 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); |
388 | + sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); | |
389 | + sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); | |
387 | 390 | } |
388 | 391 | /* Find symbol table. */ |
389 | 392 | for (i = 1; i < hdr->e_shnum; i++) { |
... | ... | @@ -753,6 +756,8 @@ |
753 | 756 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
754 | 757 | if (sym->st_shndx != relsym->st_shndx) |
755 | 758 | continue; |
759 | + if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) | |
760 | + continue; | |
756 | 761 | if (sym->st_value == addr) |
757 | 762 | return sym; |
758 | 763 | } |
... | ... | @@ -895,6 +900,58 @@ |
895 | 900 | } |
896 | 901 | } |
897 | 902 | |
903 | +static unsigned int *reloc_location(struct elf_info *elf, | |
904 | + int rsection, Elf_Rela *r) | |
905 | +{ | |
906 | + Elf_Shdr *sechdrs = elf->sechdrs; | |
907 | + int section = sechdrs[rsection].sh_info; | |
908 | + | |
909 | + return (void *)elf->hdr + sechdrs[section].sh_offset + | |
910 | + (r->r_offset - sechdrs[section].sh_addr); | |
911 | +} | |
912 | + | |
913 | +static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |
914 | +{ | |
915 | + unsigned int r_typ = ELF_R_TYPE(r->r_info); | |
916 | + unsigned int *location = reloc_location(elf, rsection, r); | |
917 | + | |
918 | + switch (r_typ) { | |
919 | + case R_386_32: | |
920 | + r->r_addend = TO_NATIVE(*location); | |
921 | + break; | |
922 | + case R_386_PC32: | |
923 | + r->r_addend = TO_NATIVE(*location) + 4; | |
924 | + /* For CONFIG_RELOCATABLE=y */ | |
925 | + if (elf->hdr->e_type == ET_EXEC) | |
926 | + r->r_addend += r->r_offset; | |
927 | + break; | |
928 | + } | |
929 | + return 0; | |
930 | +} | |
931 | + | |
932 | +static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |
933 | +{ | |
934 | + unsigned int r_typ = ELF_R_TYPE(r->r_info); | |
935 | + unsigned int *location = reloc_location(elf, rsection, r); | |
936 | + unsigned int inst; | |
937 | + | |
938 | + if (r_typ == R_MIPS_HI16) | |
939 | + return 1; /* skip this */ | |
940 | + inst = TO_NATIVE(*location); | |
941 | + switch (r_typ) { | |
942 | + case R_MIPS_LO16: | |
943 | + r->r_addend = inst & 0xffff; | |
944 | + break; | |
945 | + case R_MIPS_26: | |
946 | + r->r_addend = (inst & 0x03ffffff) << 2; | |
947 | + break; | |
948 | + case R_MIPS_32: | |
949 | + r->r_addend = inst; | |
950 | + break; | |
951 | + } | |
952 | + return 0; | |
953 | +} | |
954 | + | |
898 | 955 | /** |
899 | 956 | * A module includes a number of sections that are discarded |
900 | 957 | * either when loaded or when used as built-in. |
901 | 958 | |
... | ... | @@ -938,8 +995,11 @@ |
938 | 995 | r.r_offset = TO_NATIVE(rela->r_offset); |
939 | 996 | #if KERNEL_ELFCLASS == ELFCLASS64 |
940 | 997 | if (hdr->e_machine == EM_MIPS) { |
998 | + unsigned int r_typ; | |
941 | 999 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); |
942 | 1000 | r_sym = TO_NATIVE(r_sym); |
1001 | + r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | |
1002 | + r.r_info = ELF64_R_INFO(r_sym, r_typ); | |
943 | 1003 | } else { |
944 | 1004 | r.r_info = TO_NATIVE(rela->r_info); |
945 | 1005 | r_sym = ELF_R_SYM(r.r_info); |
946 | 1006 | |
... | ... | @@ -972,8 +1032,11 @@ |
972 | 1032 | r.r_offset = TO_NATIVE(rel->r_offset); |
973 | 1033 | #if KERNEL_ELFCLASS == ELFCLASS64 |
974 | 1034 | if (hdr->e_machine == EM_MIPS) { |
1035 | + unsigned int r_typ; | |
975 | 1036 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); |
976 | 1037 | r_sym = TO_NATIVE(r_sym); |
1038 | + r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | |
1039 | + r.r_info = ELF64_R_INFO(r_sym, r_typ); | |
977 | 1040 | } else { |
978 | 1041 | r.r_info = TO_NATIVE(rel->r_info); |
979 | 1042 | r_sym = ELF_R_SYM(r.r_info); |
... | ... | @@ -983,6 +1046,16 @@ |
983 | 1046 | r_sym = ELF_R_SYM(r.r_info); |
984 | 1047 | #endif |
985 | 1048 | r.r_addend = 0; |
1049 | + switch (hdr->e_machine) { | |
1050 | + case EM_386: | |
1051 | + if (addend_386_rel(elf, i, &r)) | |
1052 | + continue; | |
1053 | + break; | |
1054 | + case EM_MIPS: | |
1055 | + if (addend_mips_rel(elf, i, &r)) | |
1056 | + continue; | |
1057 | + break; | |
1058 | + } | |
986 | 1059 | sym = elf->symtab_start + r_sym; |
987 | 1060 | /* Skip special sections */ |
988 | 1061 | if (sym->st_shndx >= SHN_LORESERVE) |
scripts/mod/modpost.h
... | ... | @@ -60,6 +60,9 @@ |
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) |