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: Sun, 15 Mar 2020 22:40:00 -0500

David,

On Sun, Mar 15, 2020 at 10:12 PM David Gibson
<address@hidden> wrote:
>
> On Thu, Feb 27, 2020 at 01:40:53PM -0600, Vincent Fazio wrote:
>
> Sorry, I should have replied to this earlier.
>
> > In the ELFv2 ABI, function pointers are relative to the TOC stored in GPR2.
> > There's no hop into .opd to pull an address that needs to be endian swapped
> > relative to the host as in ELFv1.
>
> Right.
>
> > As best as I can tell, GPR2 is in QEMU's host endianness as it's calculated
>
> Sort of.  In hardware the register has no endianness, since it's not
> byte-addressable.  In qemu's modelling, env->gpr[2], like all the
> registers, is stored in host endianness.  That's because the fact
> those registers have an in memory representation is a qemu/host side
> detail.
>
> > from GPR12 or the ELF load address + entry point so there should be no need
> > to swap the value of the signal handler function pointer in ELFv2.
>
> Erm... if the address was coming from a register, yes.  But AFAICT
> it's not coming from a register, it's coming from the guest's struct
> sigaction, which I'd expect to be in target/guest endianness.
>

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.

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.

>
> >
> > >>>
> > vfazio@vfazio1 ~/development/buildroot $
> > output/host/powerpc64-buildroot-linux-musl/bin/objdump -x
> > output/build/libopenssl-1.1.1d/libcrypto.so | egrep -e
> > ".TOC|\<_init|ill_handler"
> > 0000000000186014 l     F .text    0000000000000034 0x60 ill_handler
> > 00000000002b7f00 l     O .got    0000000000000000 .TOC.
> > 000000000007de00 l     F .init    0000000000000010 0x60 _init
> >
> > 000000000007de00 <_init>:
> >    7de00:       3c 4c 00 24     addis   r2,r12,36
> >    7de04:       38 42 a1 00     addi    r2,r2,-24320
> >
> > (gdb) p/x 0x7de00 + (36 << 16) - 24320
> > $69 = 0x2b7f00
> >
> >    7f180:       3f a2 ff ed     addis   r29,r2,-19
> >    7f184:       3b bd e1 14     addi    r29,r29,-7916
> >
> > (gdb) p/x 0x2b7f00 - (19 << 16) - 7916
> > $75 = 0x186014
> >
> > (gdb) where
> > #0  setup_rt_frame (sig=4, ka=0x628c5f80 <sigact_table+96>, info=0x629314d8,
> > set=0x7fffffffd368, env=0x629240c0) at
> > /home/vfazio/development/qemu/linux-user/ppc/signal.c:579
> > #1  0x000000006008d6b3 in handle_pending_signal (cpu_env=0x629240c0, sig=4,
> > k=0x629314d0) at /home/vfazio/development/qemu/linux-user/signal.c:922
> > #2  0x000000006008d84b in process_pending_signals (cpu_env=0x629240c0) at
> > /home/vfazio/development/qemu/linux-user/signal.c:960
> > #3  0x0000000060097ec7 in cpu_loop (env=0x629240c0) at
> > /home/vfazio/development/qemu/linux-user/ppc/cpu_loop.c:469
> > #4  0x000000006006444e in main (argc=9, argv=0x7fffffffde48,
> > envp=0x7fffffffde98) at /home/vfazio/development/qemu/linux-user/main.c:865
> >
> > (gdb) p/x env->gpr[2]
> > $83 = 0x4000c21f00
> > (gdb) p/x env->gpr[2] - (19 << 16) - 7916
> > $84 = 0x4000af0014
> > (gdb) p/x ka->_sa_handler
> > $85 = 0x4000af0014
> > (gdb) p/x *ka->_sa_handler
> > $86 = 0x13004c3c
> >
> > 0000000000186014 <ill_handler>:
> >   186014:       3c 4c 00 13     addis   r2,r12,19
> >   186018:       38 42 1e ec     addi    r2,r2,7916
> >   18601c:       7c 08 02 a6     mflr    r0
> >
> > <<<
> >
> > If this seems reasonable, I can submit a patch.
> >
>
> --
> 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

Thanks,
-Vincent



reply via email to

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