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: Vincent Fazio
Subject: Re: qemu-ppc64-linux-user: signal handler endianness in elfv2
Date: Mon, 16 Mar 2020 16:26:57 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.4.1

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

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?

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

--
Vincent Fazio
Embedded Software Engineer - Linux
Extreme Engineering Solutions, Inc
http://www.xes-inc.com




reply via email to

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