[Bug malloc/32996] i386 TLS helper functions don't preserve XMM registers

hjl.tools at gmail dot com sourceware-bugzilla@sourceware.org
Sun Jun 8 09:25:12 GMT 2025


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

--- Comment #17 from H.J. Lu <hjl.tools at gmail dot com> ---
(In reply to dj@redhat.com from comment #11)
> Longer explanation:
> 
> In qbindingstorage.h we have:
> 
> class Q_CORE_EXPORT QBindingStorage
> {
>     mutable QBindingStorageData *d = nullptr;
> 
> And in qproperty.cc we have this:
> 
> QBindingStorage::QBindingStorage()
> {
>     bindingStatus = &QT_PREPEND_NAMESPACE(bindingStatus);
>     Q_ASSERT(bindingStatus);
> }
> 
> which compiles to this:
> 
>    0xf618a600 <_ZN15QBindingStorageC2Ev>:	endbr32
>    0xf618a604 <_ZN15QBindingStorageC2Ev+4>:	push   %ebx
>    0xf618a605 <_ZN15QBindingStorageC2Ev+5>:	pxor   %xmm0,%xmm0
>    0xf618a609 <_ZN15QBindingStorageC2Ev+9>:	call   0xf6051420
> <__x86.get_pc_thunk.bx>
>    0xf618a60e <_ZN15QBindingStorageC2Ev+14>:	add    $0x581ca6,%ebx
>    0xf618a614 <_ZN15QBindingStorageC2Ev+20>:	sub    $0x8,%esp
>    0xf618a617 <_ZN15QBindingStorageC2Ev+23>:	lea    0x34a4(,%ebx,1),%eax
>    0xf618a61e <_ZN15QBindingStorageC2Ev+30>:	call   0xf6006b30
> <___tls_get_addr@plt>
>    0xf618a623 <_ZN15QBindingStorageC2Ev+35>:	movd   %eax,%xmm1
>    0xf618a627 <_ZN15QBindingStorageC2Ev+39>:	mov    0x10(%esp),%eax
>    0xf618a62b <_ZN15QBindingStorageC2Ev+43>:	punpckldq %xmm1,%xmm0
>    0xf618a62f <_ZN15QBindingStorageC2Ev+47>:	movq   %xmm0,(%eax)
>    0xf618a633 <_ZN15QBindingStorageC2Ev+51>:	add    $0x8,%esp
>    0xf618a636 <_ZN15QBindingStorageC2Ev+54>:	pop    %ebx
>    0xf618a637 <_ZN15QBindingStorageC2Ev+55>:	ret
> 
> It sets XMM0 to 0x0, sets XMM1 to &::bindingStatus, merges XMM1 into
> XMM1, and stores that dword to this->d (initializing it to zero) and
> this->bindingStatus (initializing it to &::bindingstatus).
> 
> HOWEVER, __tls_get_addr doesn't seem to preserve XMM0 in all cases,
> specificially if it needs to extend the DTV:
> 
> #0  0xf769ad44 in _int_malloc (av=av@entry=0xf78257c0 <main_arena>,
> bytes=bytes@entry=104) at malloc.c:4230
> #1  0xf769bcd7 in __GI___libc_malloc (bytes=104) at malloc.c:3406
> #2  0xf7fd7e82 in malloc (size=<optimized out>) at
> ../include/rtld-malloc.h:56
> #3  allocate_dtv_entry (alignment=8, size=<optimized out>) at dl-tls.c:752
> #4  allocate_and_init (map=0x566dcf50) at dl-tls.c:781
> #5  tls_get_addr_tail (ti=0xf670f758, dtv=0xf7fb5c18, the_map=0x566dcf50) at
> dl-tls.c:1004
> #6  0xf618a623 in QBindingStorage::QBindingStorage (this=0x56856004)
>     at
> /usr/src/debug/qt6-qtbase-6.9.0-2.fc43.i386/src/corelib/kernel/qproperty.cpp:
> 2289
> #7  0xf6176b86 in QObjectData::QObjectData (this=<optimized out>) at
> /usr/include/c++/15/bits/atomic_base.h:358
> 
> At that point in malloc, guess what we see?
> 
>    0xf769ad40 <_int_malloc+2256>:	movd   %edx,%xmm0
> 
> Want to guess what malloc is doing at that point?  It's the huge chunk
> of code where it sorts the unsorted bin, and sure enough:
> 
> (gdb) p/x $edx
> $25 = 0x56890b78
> 
> That's the "bad" pointer that ends up in this->d and gets passed to free()
> later.
> 
> So the PUNPCKLDQ opcode is merging this bad pointer - not the NULL it
> put in there - because ___tls_get_addr clobbered XMM0 and qt didn't
> expect it to.

Please provide the prepossessed which generates

   0xf618a600 <_ZN15QBindingStorageC2Ev>:       endbr32
   0xf618a604 <_ZN15QBindingStorageC2Ev+4>:     push   %ebx
   0xf618a605 <_ZN15QBindingStorageC2Ev+5>:     pxor   %xmm0,%xmm0
   0xf618a609 <_ZN15QBindingStorageC2Ev+9>:     call   0xf6051420
<__x86.get_pc_thunk.bx>
   0xf618a60e <_ZN15QBindingStorageC2Ev+14>:    add    $0x581ca6,%ebx
   0xf618a614 <_ZN15QBindingStorageC2Ev+20>:    sub    $0x8,%esp
   0xf618a617 <_ZN15QBindingStorageC2Ev+23>:    lea    0x34a4(,%ebx,1),%eax
   0xf618a61e <_ZN15QBindingStorageC2Ev+30>:    call   0xf6006b30
<___tls_get_addr@plt>
   0xf618a623 <_ZN15QBindingStorageC2Ev+35>:    movd   %eax,%xmm1
   0xf618a627 <_ZN15QBindingStorageC2Ev+39>:    mov    0x10(%esp),%eax
   0xf618a62b <_ZN15QBindingStorageC2Ev+43>:    punpckldq %xmm1,%xmm0
   0xf618a62f <_ZN15QBindingStorageC2Ev+47>:    movq   %xmm0,(%eax)
   0xf618a633 <_ZN15QBindingStorageC2Ev+51>:    add    $0x8,%esp
   0xf618a636 <_ZN15QBindingStorageC2Ev+54>:    pop    %ebx
   0xf618a637 <_ZN15QBindingStorageC2Ev+55>:    ret

which may be a GCC bug.

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


More information about the Glibc-bugs mailing list