diff options
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r-- | scripts/mod/modpost.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2fcdbc7a1ee5..ce7e0d17bae2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -384,6 +384,7 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
384 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); | 384 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); |
385 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); | 385 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); |
386 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); | 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 | /* Find symbol table. */ | 389 | /* Find symbol table. */ |
389 | for (i = 1; i < hdr->e_shnum; i++) { | 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, | |||
773 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | 774 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
774 | if (sym->st_shndx != relsym->st_shndx) | 775 | if (sym->st_shndx != relsym->st_shndx) |
775 | continue; | 776 | continue; |
777 | if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) | ||
778 | continue; | ||
776 | if (sym->st_value == addr) | 779 | if (sym->st_value == addr) |
777 | return sym; | 780 | return sym; |
778 | } | 781 | } |
@@ -910,6 +913,68 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
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 | * A module includes a number of sections that are discarded | 979 | * A module includes a number of sections that are discarded |
915 | * either when loaded or when used as built-in. | 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, | |||
953 | r.r_offset = TO_NATIVE(rela->r_offset); | 1018 | r.r_offset = TO_NATIVE(rela->r_offset); |
954 | #if KERNEL_ELFCLASS == ELFCLASS64 | 1019 | #if KERNEL_ELFCLASS == ELFCLASS64 |
955 | if (hdr->e_machine == EM_MIPS) { | 1020 | if (hdr->e_machine == EM_MIPS) { |
1021 | unsigned int r_typ; | ||
956 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | 1022 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); |
957 | r_sym = TO_NATIVE(r_sym); | 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 | } else { | 1026 | } else { |
959 | r.r_info = TO_NATIVE(rela->r_info); | 1027 | r.r_info = TO_NATIVE(rela->r_info); |
960 | r_sym = ELF_R_SYM(r.r_info); | 1028 | r_sym = ELF_R_SYM(r.r_info); |
@@ -987,8 +1055,11 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
987 | r.r_offset = TO_NATIVE(rel->r_offset); | 1055 | r.r_offset = TO_NATIVE(rel->r_offset); |
988 | #if KERNEL_ELFCLASS == ELFCLASS64 | 1056 | #if KERNEL_ELFCLASS == ELFCLASS64 |
989 | if (hdr->e_machine == EM_MIPS) { | 1057 | if (hdr->e_machine == EM_MIPS) { |
1058 | unsigned int r_typ; | ||
990 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | 1059 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); |
991 | r_sym = TO_NATIVE(r_sym); | 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 | } else { | 1063 | } else { |
993 | r.r_info = TO_NATIVE(rel->r_info); | 1064 | r.r_info = TO_NATIVE(rel->r_info); |
994 | r_sym = ELF_R_SYM(r.r_info); | 1065 | r_sym = ELF_R_SYM(r.r_info); |
@@ -998,6 +1069,14 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
998 | r_sym = ELF_R_SYM(r.r_info); | 1069 | r_sym = ELF_R_SYM(r.r_info); |
999 | #endif | 1070 | #endif |
1000 | r.r_addend = 0; | 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 | sym = elf->symtab_start + r_sym; | 1080 | sym = elf->symtab_start + r_sym; |
1002 | /* Skip special sections */ | 1081 | /* Skip special sections */ |
1003 | if (sym->st_shndx >= SHN_LORESERVE) | 1082 | if (sym->st_shndx >= SHN_LORESERVE) |