[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: |
Mon, 16 Mar 2020 19:43:26 +1100 |
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:
> >
> > 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.
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.
> 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.
> > >
> >
>
> 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
signature.asc
Description: PGP signature