aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/mod/modpost.c73
-rw-r--r--scripts/mod/modpost.h3
2 files changed, 76 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3645e980da71..b83cddb8dca9 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -374,6 +374,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
374 hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); 374 hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
375 hdr->e_shnum = TO_NATIVE(hdr->e_shnum); 375 hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
376 hdr->e_machine = TO_NATIVE(hdr->e_machine); 376 hdr->e_machine = TO_NATIVE(hdr->e_machine);
377 hdr->e_type = TO_NATIVE(hdr->e_type);
377 sechdrs = (void *)hdr + hdr->e_shoff; 378 sechdrs = (void *)hdr + hdr->e_shoff;
378 info->sechdrs = sechdrs; 379 info->sechdrs = sechdrs;
379 380
@@ -384,6 +385,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
384 sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); 385 sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
385 sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); 386 sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
386 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); 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 /* Find symbol table. */ 391 /* Find symbol table. */
389 for (i = 1; i < hdr->e_shnum; i++) { 392 for (i = 1; i < hdr->e_shnum; i++) {
@@ -753,6 +756,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
753 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 756 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
754 if (sym->st_shndx != relsym->st_shndx) 757 if (sym->st_shndx != relsym->st_shndx)
755 continue; 758 continue;
759 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
760 continue;
756 if (sym->st_value == addr) 761 if (sym->st_value == addr)
757 return sym; 762 return sym;
758 } 763 }
@@ -895,6 +900,58 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
895 } 900 }
896} 901}
897 902
903static 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
913static 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
932static 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 * A module includes a number of sections that are discarded 956 * A module includes a number of sections that are discarded
900 * either when loaded or when used as built-in. 957 * either when loaded or when used as built-in.
@@ -938,8 +995,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
938 r.r_offset = TO_NATIVE(rela->r_offset); 995 r.r_offset = TO_NATIVE(rela->r_offset);
939#if KERNEL_ELFCLASS == ELFCLASS64 996#if KERNEL_ELFCLASS == ELFCLASS64
940 if (hdr->e_machine == EM_MIPS) { 997 if (hdr->e_machine == EM_MIPS) {
998 unsigned int r_typ;
941 r_sym = ELF64_MIPS_R_SYM(rela->r_info); 999 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
942 r_sym = TO_NATIVE(r_sym); 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 } else { 1003 } else {
944 r.r_info = TO_NATIVE(rela->r_info); 1004 r.r_info = TO_NATIVE(rela->r_info);
945 r_sym = ELF_R_SYM(r.r_info); 1005 r_sym = ELF_R_SYM(r.r_info);
@@ -972,8 +1032,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
972 r.r_offset = TO_NATIVE(rel->r_offset); 1032 r.r_offset = TO_NATIVE(rel->r_offset);
973#if KERNEL_ELFCLASS == ELFCLASS64 1033#if KERNEL_ELFCLASS == ELFCLASS64
974 if (hdr->e_machine == EM_MIPS) { 1034 if (hdr->e_machine == EM_MIPS) {
1035 unsigned int r_typ;
975 r_sym = ELF64_MIPS_R_SYM(rel->r_info); 1036 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
976 r_sym = TO_NATIVE(r_sym); 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 } else { 1040 } else {
978 r.r_info = TO_NATIVE(rel->r_info); 1041 r.r_info = TO_NATIVE(rel->r_info);
979 r_sym = ELF_R_SYM(r.r_info); 1042 r_sym = ELF_R_SYM(r.r_info);
@@ -983,6 +1046,16 @@ static void check_sec_ref(struct module *mod, const char *modname,
983 r_sym = ELF_R_SYM(r.r_info); 1046 r_sym = ELF_R_SYM(r.r_info);
984#endif 1047#endif
985 r.r_addend = 0; 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 sym = elf->symtab_start + r_sym; 1059 sym = elf->symtab_start + r_sym;
987 /* Skip special sections */ 1060 /* Skip special sections */
988 if (sym->st_shndx >= SHN_LORESERVE) 1061 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)