aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/mod/modpost.c79
-rw-r--r--scripts/mod/modpost.h3
2 files changed, 82 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
916static 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
935static 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
954static 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)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 0858caa9c03f..4156dd34c5de 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -60,6 +60,9 @@ typedef union
60#define ELF64_MIPS_R_SYM(i) \ 60#define ELF64_MIPS_R_SYM(i) \
61 ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) 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#if KERNEL_ELFDATA != HOST_ELFDATA 66#if KERNEL_ELFDATA != HOST_ELFDATA
64 67
65static inline void __endian(const void *src, void *dest, unsigned int size) 68static inline void __endian(const void *src, void *dest, unsigned int size)