@@ -374,6 +374,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
374374 hdr -> e_shstrndx = TO_NATIVE (hdr -> e_shstrndx );
375375 hdr -> e_shnum = TO_NATIVE (hdr -> e_shnum );
376376 hdr -> e_machine = TO_NATIVE (hdr -> e_machine );
377+ hdr -> e_type = TO_NATIVE (hdr -> e_type );
377378 sechdrs = (void * )hdr + hdr -> e_shoff ;
378379 info -> sechdrs = sechdrs ;
379380
@@ -384,6 +385,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
384385 sechdrs [i ].sh_size = TO_NATIVE (sechdrs [i ].sh_size );
385386 sechdrs [i ].sh_link = TO_NATIVE (sechdrs [i ].sh_link );
386387 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 );
387390 }
388391 /* Find symbol table. */
389392 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,
753756 for (sym = elf -> symtab_start ; sym < elf -> symtab_stop ; sym ++ ) {
754757 if (sym -> st_shndx != relsym -> st_shndx )
755758 continue ;
759+ if (ELF_ST_TYPE (sym -> st_info ) == STT_SECTION )
760+ continue ;
756761 if (sym -> st_value == addr )
757762 return sym ;
758763 }
@@ -895,6 +900,58 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
895900 }
896901}
897902
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+
898955/**
899956 * A module includes a number of sections that are discarded
900957 * either when loaded or when used as built-in.
@@ -938,8 +995,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
938995 r .r_offset = TO_NATIVE (rela -> r_offset );
939996#if KERNEL_ELFCLASS == ELFCLASS64
940997 if (hdr -> e_machine == EM_MIPS ) {
998+ unsigned int r_typ ;
941999 r_sym = ELF64_MIPS_R_SYM (rela -> r_info );
9421000 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 );
9431003 } else {
9441004 r .r_info = TO_NATIVE (rela -> r_info );
9451005 r_sym = ELF_R_SYM (r .r_info );
@@ -972,8 +1032,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
9721032 r .r_offset = TO_NATIVE (rel -> r_offset );
9731033#if KERNEL_ELFCLASS == ELFCLASS64
9741034 if (hdr -> e_machine == EM_MIPS ) {
1035+ unsigned int r_typ ;
9751036 r_sym = ELF64_MIPS_R_SYM (rel -> r_info );
9761037 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 );
9771040 } else {
9781041 r .r_info = TO_NATIVE (rel -> r_info );
9791042 r_sym = ELF_R_SYM (r .r_info );
@@ -983,6 +1046,16 @@ static void check_sec_ref(struct module *mod, const char *modname,
9831046 r_sym = ELF_R_SYM (r .r_info );
9841047#endif
9851048 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+ }
9861059 sym = elf -> symtab_start + r_sym ;
9871060 /* Skip special sections */
9881061 if (sym -> st_shndx >= SHN_LORESERVE )
0 commit comments