qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: qemu-ppc64-linux-user: signal handler endianness in elfv2


From: David Gibson
Subject: Re: qemu-ppc64-linux-user: signal handler endianness in elfv2
Date: Tue, 17 Mar 2020 10:20:46 +1100

On Mon, Mar 16, 2020 at 04:26:57PM -0500, Vincent Fazio wrote:
> David,
> 
> On 3/16/20 3:43 AM, David Gibson wrote:
> > On Sun, Mar 15, 2020 at 10:40:00PM -0500, Vincent Fazio wrote:
> > > David,
> > > 
> > > On Sun, Mar 15, 2020 at 10:12 PM David Gibson
> > > <address@hidden> wrote:
> > > I can dig into this a bit more when i'm back at work with hardware.
> > > but the gist is that the value copied into the struct is calculated
> > > from GPR2/GPR12 as they're set after the jump into the ELF binary.
> > Where is this copying into the structure happening in the code?  If
> > that's qemu code putting something in there, I suspect we should have
> > a swap at that point (which would cancel the other one).
> > 
> > I had looked through the code before, and I thought that structure was
> > just copied as a whole from the guest memory at sigaction() time.
> 
> The copy from guest memory should be the case. In the specific scenario i'm
> testing:
> 
> https://github.com/openssl/openssl/blob/master/crypto/ppccap.c#L372
> 
>     memset(&ill_act, 0, sizeof(ill_act));
>     ill_act.sa_handler = ill_handler;
>     ill_act.sa_mask = all_masked;
> 
>     sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
>     sigaction(SIGILL, &ill_act, &ill_oact);
> 
> MUSL's sigaction:
> 
> http://git.musl-libc.org/cgit/musl/tree/src/signal/sigaction.c#n26
> 
> When ill_act.sa_handler is set, ill_handler is in little endian

Uh.. what?  That openssl code is running on the guest/target side,
yes?  Which is big-endian?  In which case I'd expect ill_handler, and
therefore .sa_handler to also be big-endian...

> and is
> copied that way when running on an x86 machine emulating an E6500 BE CPU.
> 
> I've added a quick debug statement:
> 
> vfazio@vfazio1 ~/development/br-xfs $ grep printf
> output/build/libopenssl-1.1.1d/crypto/ppccap.c
>     printf("DEBUG: %llx\n", &ill_handler);
> 
> (gdb) run -E LD_LIBRARY_PATH="output/target/lib/:output/target/usr/lib/"
> -cpu e6500 output/target/lib/ld-musl-powerpc64.so.1
> output/target/usr/bin/openssl
> Starting program: /home/vfazio/development/qemu/ppc64-linux-user/qemu-ppc64
> -E LD_LIBRARY_PATH="output/target/lib/:output/target/usr/lib/" -cpu e6500
> output/target/lib/ld-musl-powerpc64.so.1 output/target/usr/bin/openssl
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
> [New Thread 0x7ffff7ff9700 (LWP 6135)]
> DEBUG: 4000af1014

.. as indeed it appears to be (it's a target-side printf() so it
should print BE values correctly).

To be really sure, you could change the printf to explicitly print
ill_handler byte by byte.

> Thread 1 "qemu-ppc64" received signal SIGSEGV, Segmentation fault.
> 0x00000000600a9257 in ldl_he_p (ptr=0x1410af0040000000) at
> /home/vfazio/development/qemu/include/qemu/bswap.h:351
> 351        __builtin_memcpy(&r, ptr, sizeof(r));
> 
> 
> I suppose there could be a double endian swap, once when handling the
> sigaction call and back when handling the signal, but is there much of a
> benefit of doing that?

Yes, if it means data in itermin structures is in the right
endiannness for its context.  Plus, the two swaps may be conditional
on different conditions - they end up cancelling out in your case, but
with other combinations we may only want one of them to act.

> > > In ELFv2, function pointers are _relative_ to the values stored in
> > > those registers, so they will maintain their endianness. It's probably
> > > not exactly clear in the example below, but i was trying show:
> > > 
> > > 1) the offsets within the ELF for the TOC, entry point, and the
> > > sigaction handler
> > > 2) GPR12 is the basis for GPR2. In ELFv2, GPR12 is set when hitting
> > > the PLT stub and is the entry point for the ELF binary
> > > 3) that the handler value is calculated relative to GPR2
> > > 4) that dereferencing the pointer shows the same byte pattern (when
> > > endianness is accounted for)
> > > 5) all of this assumes the registers are in host (not target)
> > > endianness. the registers should all be valid virtual addresses in the
> > > host that map to the ELF on disk.
> > > 
> > > I'm sure i'm missing some technical jargon with how QEMU does it's
> > > magic, and most of my assembly experience comes from x86 Windows PEs,
> > > not x86/PPC Linux ELFs, so forgive me if some of my terms are
> > > incorrect.
> > > Thanks,
> > > -Vincent
> > > 

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]