Hi Jakub,

> On Tue, Jul 14, 2020 at 02:32:57PM +0200, Rainer Orth wrote:
>> The latest Solaris 11.4/x86 update uncovered a libsanitizer bug that
>> caused one test to FAIL for 32-bit:
>> 
>> +FAIL: c-c++-common/asan/null-deref-1.c   -O0  output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c   -O1  output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c   -O2  output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c   -O2 -flto  output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c -O2 -flto -flto-partition=none
>> output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c   -O3 -g  output pattern test
>> +FAIL: c-c++-common/asan/null-deref-1.c   -Os  output pattern test
>> 
>> I've identified the problem and the fix has just landed in upstream
>> llvm-project:
>> 
>>      https://reviews.llvm.org/D83664
>> 
>> Tested on i386-pc-solaris2.11 on master, gcc-10 and gcc-9 branches.
>> 
>> Ok for all three?
>
> Won't this break i386-linux?

I must admit I missed that in that terrible nested maze of #ifdef's
compiler-rt uses.

> I mean, while the ifndef/define change is guarded by #if SANITIZER_SOLARIS,
> the last changed line is not.  I'm afraid I don't know if
> ucontext->uc_mcontext.gregs[REG_UESP] or ucontext->uc_mcontext.gregs[REG_ESP];
> is what we want to use on i686-linux...

So far, I've regtested both GCC and LLVM master on x86_64-pc-linux-gnu
(both m64 and m32 multilibs) and there were no regressions.

I've then tried to make sense of the situation in the Linux kernel
sources and found some hints suggesting that REG_UESP is right here,
too:

* arch/x86/um/os-Linux/mcontext.c has

void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
{
#ifdef __i386__
#define COPY2(X,Y) regs->gp[X] = mc->gregs[REG_##Y]
#define COPY(X) regs->gp[X] = mc->gregs[REG_##X]
[...]
        COPY(EDI); COPY(ESI); COPY(EBP);
        COPY2(UESP, ESP); /* sic */

* Similarly in arch/x86/um/user-offsets.c:

void foo(void)
{
#ifdef __i386__
[...]
        DEFINE(HOST_IP, EIP);
        DEFINE(HOST_SP, UESP);
[...]
        DEFINE(HOST_BP, EBP);

* And arch/x86/include/uapi/asm/sigcontext.h:

struct sigcontext_32 {
[...]
        __u32                           bp;
        __u32                           sp;
[...]
        __u32                           sp_at_signal;
        __u16                           ss, __ssh;

I may still be mistaken, but all this suggests that Linux might be
playing games with ESP and UESP, while Solaris and NetBSD (see below)
keep them separate, but in the end UESP is the register to use.

> Similarly netbsd.

Here's what I found in the NetBSD sources (I haven't tried doing builds
in a VM so far):

<sys/ucontext.h> includes <machine/mcontext.h>.  The i386 version
(sys/arch/i386/include/mcontext.h) has

#ifndef _UC_MACHINE_SP
#define _UC_MACHINE_SP(uc)      ((uc)->uc_mcontext.__gregs[_REG_UESP])
#endif
#define _UC_MACHINE_FP(uc)      ((uc)->uc_mcontext.__gregs[_REG_EBP])
#define _UC_MACHINE_PC(uc)      ((uc)->uc_mcontext.__gregs[_REG_EIP])

which suggests REG_UESP is right here.

        Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

Reply via email to