This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug dynamic-link/17868] New: powerpc: ifuncmain6pie failure with GCC 4.9


https://sourceware.org/bugzilla/show_bug.cgi?id=17868

            Bug ID: 17868
           Summary: powerpc: ifuncmain6pie failure with GCC 4.9
           Product: glibc
           Version: 2.20
            Status: NEW
          Severity: normal
          Priority: P2
         Component: dynamic-link
          Assignee: unassigned at sourceware dot org
          Reporter: azanella at linux dot vnet.ibm.com

Since GLIBC release 2.20, the testcase elf/ifuncmain6pie fails when building
with GCC 4.9+. e.

The which basically check if some IFUNC is being relocated correctly in a
shared library.  The failures is:

$ ./testrun.sh elf/ifuncmain6pie
Illegal instruction (core dumped)

And debugging it I found that the issue seems to be the value used in IFUNC
relocation address at:

* sysdeps/powerpc/powerpc64/dl-machine.h:

606 /* Call function at address VALUE (an OPD entry) to resolve ifunc relocs. 
*/
607 auto inline Elf64_Addr __attribute__ ((always_inline))
608 resolve_ifunc (Elf64_Addr value,
609                const struct link_map *map, const struct link_map *sym_map)
610 {
611 #if _CALL_ELF != 2
612 #ifndef RESOLVE_CONFLICT_FIND_MAP
613   /* The function we are calling may not yet have its opd entry relocated. 
*/
614   Elf64_FuncDesc opd;
615   if (map != sym_map
616 # if !defined RTLD_BOOTSTRAP && defined SHARED
617       /* Bootstrap map doesn't have l_relocated set for it.  */
618       && sym_map != &GL(dl_rtld_map)
619 # endif
620       && !sym_map->l_relocated)
621     {
622       Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
623       opd.fd_func = func->fd_func + sym_map->l_addr;
624       opd.fd_toc = func->fd_toc + sym_map->l_addr;
625       opd.fd_aux = func->fd_aux;
626       value = (Elf64_Addr) &opd;
627     }
628 #endif
629 #endif
630   return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
631 }

The function is a always inline one and GLIBC can not be built without
optimization, so took me some time to figure out where exactly it was being
called and the issues.

On GCC 4.9 the problems is on line 630. the 'value' is a bogus one, leading to
a memory area that contains no code and thus issuing an invalid instruction.
At first I though it would be a GLIBC or a linker issue, but debugging it does
not seem so. The 'resolve_ifunc' is being called at:

* sysdeps/powerpc/powerpc64/dl-machine.h:

633 /* Perform the relocation specified by RELOC and SYM (which is fully
634    resolved).  MAP is the object containing the reloc.  */
635 auto inline void __attribute__ ((always_inline))
636 elf_machine_rela (struct link_map *map,
637                   const Elf64_Rela *reloc,
638                   const Elf64_Sym *sym,
639                   const struct r_found_version *version,
640                   void *const reloc_addr_arg,
641                   int skip_ifunc)
642 {
643   Elf64_Addr *const reloc_addr = reloc_addr_arg;
644   const int r_type = ELF64_R_TYPE (reloc->r_info);
645   const Elf64_Sym *const refsym = sym;
646   union unaligned
647     {
648       uint16_t u2;
649       uint32_t u4;
650       uint64_t u8;
651     } __attribute__ ((__packed__));
652 
653   if (r_type == R_PPC64_RELATIVE)
654     {
655       *reloc_addr = map->l_addr + reloc->r_addend;
656       return;
657     }
658 
659   if (__glibc_unlikely (r_type == R_PPC64_NONE))
660     return;
661 
662   /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
663      and STT_GNU_IFUNC.  */
664   struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
665   Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr +
sym->st_value)
666                       + reloc->r_addend);

And I identified the assembly generated and registers being used. Below, both
assembly starts at the 'resolve_ifunc' tests:

615   if (map != sym_map
616 # if !defined RTLD_BOOTSTRAP && defined SHARED
617       /* Bootstrap map doesn't have l_relocated set for it.  */
618       && sym_map != &GL(dl_rtld_map)
619 # endif
620       && !sym_map->l_relocated)


GCC 4.8:

(gdb) x/28i $pc-48
   0x2f30180c <_dl_relocate_object+8956>:       cmpwi   cr7,r9,0
   0x2f301810 <_dl_relocate_object+8960>:       beq-    cr7,0x2f2ff87c
<_dl_relocate_object+876>
   0x2f301814 <_dl_relocate_object+8964>:       bne-    cr3,0x2f2ff87c
<_dl_relocate_object+876>
   0x2f301818 <_dl_relocate_object+8968>:       cmpld   cr7,r29,r23
   0x2f30181c <_dl_relocate_object+8972>:       beq     cr7,0x2f301864
<_dl_relocate_object+9044>
   0x2f301820 <_dl_relocate_object+8976>:       nop
   0x2f301824 <_dl_relocate_object+8980>:       ld      r8,-32624(r2)
   0x2f301828 <_dl_relocate_object+8984>:       cmpd    cr7,r23,r8
   0x2f30182c <_dl_relocate_object+8988>:       beq     cr7,0x2f301864
<_dl_relocate_object+9044>
   0x2f301830 <_dl_relocate_object+8992>:       ld      r9,816(r23)
   0x2f301834 <_dl_relocate_object+8996>:       rldicl. r7,r9,35,63
   0x2f301838 <_dl_relocate_object+9000>:       bne     0x2f301864
<_dl_relocate_object+9044>
=> 0x2f30183c <_dl_relocate_object+9004>:       ld      r9,0(r23)
   0x2f301840 <_dl_relocate_object+9008>:       ld      r8,0(r10)
   0x2f301844 <_dl_relocate_object+9012>:       ld      r7,8(r10)
   0x2f301848 <_dl_relocate_object+9016>:       ld      r10,16(r10)
   0x2f30184c <_dl_relocate_object+9020>:       add     r8,r9,r8
   0x2f301850 <_dl_relocate_object+9024>:       add     r9,r7,r9
   0x2f301854 <_dl_relocate_object+9028>:       std     r8,176(r31)
   0x2f301858 <_dl_relocate_object+9032>:       std     r9,184(r31)
   0x2f30185c <_dl_relocate_object+9036>:       std     r10,192(r31)
   0x2f301860 <_dl_relocate_object+9040>:       addi    r10,r31,176
   0x2f301864 <_dl_relocate_object+9044>:       std     r2,40(r1)
   0x2f301868 <_dl_relocate_object+9048>:       addis   r8,r2,-1
   0x2f30186c <_dl_relocate_object+9052>:       ld      r3,26616(r8)
   0x2f301870 <_dl_relocate_object+9056>:       ld      r9,0(r10)
   0x2f301874 <_dl_relocate_object+9060>:       ld      r11,16(r10)
   0x2f301878 <_dl_relocate_object+9064>:       mtctr   r9

GCC 4.9:

(gdb) x/28i $pc-40
   0x495a0b40 <_dl_relocate_object+4608>:       cmpld   cr7,r29,r8
   0x495a0b44 <_dl_relocate_object+4612>:       beq     cr7,0x495a0b68
<_dl_relocate_object+4648>
   0x495a0b48 <_dl_relocate_object+4616>:       nop
   0x495a0b4c <_dl_relocate_object+4620>:       ld      r6,-32624(r2)
   0x495a0b50 <_dl_relocate_object+4624>:       cmpd    cr7,r8,r6
   0x495a0b54 <_dl_relocate_object+4628>:       beq     cr7,0x495a0b68
<_dl_relocate_object+4648>
   0x495a0b58 <_dl_relocate_object+4632>:       ld      r10,816(r8)
   0x495a0b5c <_dl_relocate_object+4636>:       rldicl. r7,r10,35,63
   0x495a0b60 <_dl_relocate_object+4640>:       bne     0x495a0b68
<_dl_relocate_object+4648>
   0x495a0b64 <_dl_relocate_object+4644>:       addi    r9,r31,176
=> 0x495a0b68 <_dl_relocate_object+4648>:       std     r2,40(r1)
   0x495a0b6c <_dl_relocate_object+4652>:       addis   r10,r2,-1
   0x495a0b70 <_dl_relocate_object+4656>:       ld      r3,26616(r10)
   0x495a0b74 <_dl_relocate_object+4660>:       ld      r10,0(r9)
   0x495a0b78 <_dl_relocate_object+4664>:       ld      r11,16(r9)
   0x495a0b7c <_dl_relocate_object+4668>:       std     r8,272(r31)
   0x495a0b80 <_dl_relocate_object+4672>:       mtctr   r10
   0x495a0b84 <_dl_relocate_object+4676>:       ld      r2,8(r9)
   0x495a0b88 <_dl_relocate_object+4680>:       bctrl

The GCC 4.8 does have the branch taken code

621     {
622       Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
623       opd.fd_func = func->fd_func + sym_map->l_addr;
624       opd.fd_toc = func->fd_toc + sym_map->l_addr;
625       opd.fd_aux = func->fd_aux;
626       value = (Elf64_Addr) &opd;
627     }

Correctly set:

=> 0x2f30183c <_dl_relocate_object+9004>:       ld      r9,0(r23)
   0x2f301840 <_dl_relocate_object+9008>:       ld      r8,0(r10)
   0x2f301844 <_dl_relocate_object+9012>:       ld      r7,8(r10)
   0x2f301848 <_dl_relocate_object+9016>:       ld      r10,16(r10)
   0x2f30184c <_dl_relocate_object+9020>:       add     r8,r9,r8
   0x2f301850 <_dl_relocate_object+9024>:       add     r9,r7,r9
   0x2f301854 <_dl_relocate_object+9028>:       std     r8,176(r31)
   0x2f301858 <_dl_relocate_object+9032>:       std     r9,184(r31)
   0x2f30185c <_dl_relocate_object+9036>:       std     r10,192(r31)
   0x2f301860 <_dl_relocate_object+9040>:       addi    r10,r31,176
   0x2f301864 <_dl_relocate_object+9044>:       std     r2,40(r1)
   0x2f301868 <_dl_relocate_object+9048>:       addis   r8,r2,-1
   0x2f30186c <_dl_relocate_object+9052>:       ld      r3,26616(r8)
   0x2f301870 <_dl_relocate_object+9056>:       ld      r9,0(r10)
   0x2f301874 <_dl_relocate_object+9060>:       ld      r11,16(r10)
   0x2f301878 <_dl_relocate_object+9064>:       mtctr   r9


GCC 4.9 seems to just omit it for some reason.  Also, if I calculate the
'opd.fd_func = func->fd_func + sym_map->l_addr;' using GCC 4.9 register state
I correctly the expected 'value' to call the IFUNC resolver function.

I was suggested to add an explicit dependency o value and opd variable to avoid
the code elimination from GCC:

diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h
b/sysdeps/powerpc/powerpc64/dl-machine.h
index 9448712..3b2746f 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -623,7 +623,7 @@ resolve_ifunc (Elf64_Addr value,
       opd.fd_func = func->fd_func + sym_map->l_addr;
       opd.fd_toc = func->fd_toc + sym_map->l_addr;
       opd.fd_aux = func->fd_aux;
-      value = (Elf64_Addr) &opd;
+      asm ("" : "=r" (value) : "0" (&opd), "X" (opd));
     }
 #endif
 #endif

The testcase passes with the fix.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]