Bug 1529549
| Summary: | glibc 2.26.9000 pthread problems with giac on i386 | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Frederic Han <frederic.han> | 
| Component: | glibc | Assignee: | Florian Weimer <fweimer> | 
| Status: | CLOSED RAWHIDE | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | 
| Severity: | medium | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | rawhide | CC: | anto.trande, aoliva, arjun, codonell, dj, fweimer, law, mfabian, pfrankli, rth, siddhesh | 
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | i386 | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | glibc-2.26.9000-35.fc28 | Doc Type: | If docs needed, set a value | 
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2018-01-12 10:18:54 UTC | Type: | Bug | 
| Regression: | --- | Mount Type: | --- | 
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | 1529979 | ||
| Bug Blocks: | |||
| 
        
          Description
        
        
          Frederic Han
        
        
        
        
        
          2017-12-28 16:53:52 UTC
        
       The crash seems to be happening in a destructor during unwinding:
0xf6906ce6 in _Unwind_ForcedUnwind (exc=<optimized out>, stop=<optimized out>, stop_argument=<optimized out>) at ../../../libgcc/unwind.inc:212
212     }
0xf6906ce8      212     }
0xf78c62c5 in std::imvector<giac::gen>::begin (this=<optimized out>) at vector.h:205
205     vector.h: No such file or directory.
giac::in_thread_eval (arg=0x56721e10) at global.cc:3544
3544    global.cc: No such file or directory.
0xf78c62ca      3544    in global.cc
0xf78c62cc      3544    in global.cc
0xf78c62cf      3544    in global.cc
0xf71cdf10 in giac::gen::~gen()@plt () from /lib/libgiac.so.0
0x56878790 in ?? ()
Upon entry into the PLT stub, the value of ebx appears to be invalid:
Dump of assembler code for function _ZN4giac3genD1Ev@plt:
=> 0xf71cdf10 <+0>:     jmp    *0x15dc(%ebx)
   0xf71cdf16 <+6>:     push   $0x2ba0
   0xf71cdf1b <+11>:    jmp    0xf71c87c0
(gdb) print/x $ebx
$2 = 0xf4d892a0
(gdb) print/x $ebx + 0x15dc
$3 = 0xf4d8a87c
This does not match the address of the .got:
        0xf7fa4fb4 - 0xf7facfec is .got in /lib/libgiac.so.0
In the exception handler landing pad, %ebx is restored from %esi:
   0xf78c62c5 <+533>:   mov    %eax,%edi
   0xf78c62c7 <+535>:   mov    -0x60(%ebp),%eax
   0xf78c62ca <+538>:   mov    %esi,%ebx
   0xf78c62cc <+540>:   mov    %eax,(%esp)
   0xf78c62cf <+543>:   call   0xf71cdf10 <_ZN4giac3genD1Ev@plt>
Upon entry to pthread_exit, both ebx and esi have the correct value:
Thread 2 "icas" hit Breakpoint 1, __pthread_exit (value=value@entry=0x0) at pthread_exit.c:25
25      {
(gdb) print/x $ebx
$1 = 0xf7fa4fb4
(gdb) info symb 0xf7fa4fb4
_GLOBAL_OFFSET_TABLE_ in section .got of /lib/libgiac.so.0
(gdb) print/x $esi
$2 = 0xf7fa4fb4
This means that either the exception handling information is faulty or not correctly processed by the libgcc unwinder, or glibc incorrectly clobbers register contents.
Does not reproduce with glibc-2.26.9000-27.fc28.i686. Seems to be caused by -fstack-clash-protection. Yuck. Looks like __pthread_unwind is miscompiled.  Compiling nptl/unwind.c with -fno-stack-clash-protection fixes this.
(gdb) disassemble __pthread_unwind
Dump of assembler code for function __pthread_unwind:
   0xf6879790 <+0>:     push   %esi
   0xf6879791 <+1>:     push   %ebx
   0xf6879792 <+2>:     push   %esi
   0xf6879793 <+3>:     pop    %esi
   0xf6879794 <+4>:     call   0xf68712dd <__x86.get_pc_thunk.dx>
   0xf6879799 <+9>:     add    $0x71867,%edx
   0xf687979f <+15>:    sub    $0x4,%esp
   0xf68797a2 <+18>:    mov    %eax,%esi
   0xf68797a4 <+20>:    mov    0x38f4(%edx),%eax
   0xf68797aa <+26>:    test   %eax,%eax
   0xf68797ac <+28>:    jne    0xf68797cd <__pthread_unwind+61>
   0xf68797ae <+30>:    mov    $0x14,%eax
   0xf68797b3 <+35>:    call   *%gs:0x10
   0xf68797ba <+42>:    mov    $0x9,%ecx
   0xf68797bf <+47>:    mov    %eax,%ebx
   0xf68797c1 <+49>:    mov    $0x25,%eax
   0xf68797c6 <+54>:    call   *%gs:0x10
   0xf68797cd <+61>:    mov    0x38e0(%edx),%edx
   0xf68797d3 <+67>:    mov    %esi,%eax
   0xf68797d5 <+69>:    ror    $0x9,%edx
   0xf68797d8 <+72>:    xor    %gs:0x18,%edx
   0xf68797df <+79>:    call   *%edx
End of assembler dump.
CFI data:
000000b0 0000002c 000000b4 FDE cie=00000000 pc=00000180..000001d1
  DW_CFA_advance_loc: 1 to 00000181
  DW_CFA_def_cfa_offset: 8
  DW_CFA_offset: r6 (esi) at cfa-8
  DW_CFA_advance_loc: 1 to 00000182
  DW_CFA_def_cfa_offset: 12
  DW_CFA_offset: r3 (ebx) at cfa-12
  DW_CFA_advance_loc: 1 to 00000183
  DW_CFA_def_cfa_offset: 16
  DW_CFA_offset: r6 (esi) at cfa-16
  DW_CFA_advance_loc: 1 to 00000184
  DW_CFA_restore: r6 (esi)
  DW_CFA_def_cfa_offset: 12
  DW_CFA_advance_loc: 14 to 00000192
  DW_CFA_def_cfa_offset: 20
  DW_CFA_advance_loc: 51 to 000001c5
  DW_CFA_def_cfa_offset: 24
  DW_CFA_advance_loc: 1 to 000001c6
  DW_CFA_def_cfa_offset: 28
  DW_CFA_advance_loc: 1 to 000001c7
  DW_CFA_def_cfa_offset: 32
GCC produces this assembly:
        .globl  __GI___pthread_unwind
        .hidden __GI___pthread_unwind
        .type   __GI___pthread_unwind, @function
__GI___pthread_unwind:
.LFB55:
        .loc 1 112 0
        .cfi_startproc
.LVL27:
        pushl   %esi
        .cfi_def_cfa_offset 8
        .cfi_offset 6, -8
        pushl   %ebx
        .cfi_def_cfa_offset 12
        .cfi_offset 3, -12
        pushl   %esi
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        popl    %esi
        .cfi_restore 6
        .cfi_def_cfa_offset 12
        call    __x86.get_pc_thunk.bx
        addl    $_GLOBAL_OFFSET_TABLE_, %ebx
        subl    $8, %esp
        .cfi_def_cfa_offset 20
        .loc 1 112 0
        movl    %eax, %esi
.LVL28:
        .loc 1 118 0
        xorl    %edx, %edx
.LBB21:
        .loc 1 114 0
#APP
# 114 "unwind.c" 1
        movl %gs:8,%ecx
# 0 "" 2
.LVL29:
#NO_APP
.LBE21:
        .loc 1 118 0
        xorl    %eax, %eax
.LVL30:
#APP
# 118 "unwind.c" 1
        movl %eax,%gs:592
        movl %edx,%gs:596
# 0 "" 2
        .loc 1 119 0
#NO_APP
        leal    unwind_cleanup@GOTOFF(%ebx), %eax
#APP
# 119 "unwind.c" 1
        movl %eax,%gs:600
# 0 "" 2
        .loc 1 121 0
#NO_APP
        leal    unwind_stop@GOTOFF(%ebx), %eax
        addl    $592, %ecx
.LVL31:
        pushl   %esi
        .cfi_def_cfa_offset 24
        pushl   %eax
        .cfi_def_cfa_offset 28
        pushl   %ecx
        .cfi_def_cfa_offset 32
        call    _Unwind_ForcedUnwind@PLT
.LVL32:
        .loc 1 125 0
        call    abort@PLT
.LVL33:
        .cfi_endproc
.LFE55:
        .size   __GI___pthread_unwind, .-__GI___pthread_unwind
        .globl  __pthread_unwind
        .set    __pthread_unwind,__GI___pthread_unwind
I wonder if the push/pop combination of %esi causes the problem because it could obscure the earlier saved value of %esi, so that the unwinder is not able to restore it anymore.
I'm now pretty confident this is a GCC bug. I posted a test case upstream: https://sourceware.org/ml/libc-alpha/2017-12/msg00987.html Fixed by the rebuild in glibc-2.26.9000-35.fc28. |