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. |