Ping. Is anything else needed?

On 26-06-17 12:27:35, Manjunath Matti wrote:
> This looks good to me, I cannot approve it though.
> 
> Adding the port maintainer to the list!
> 
> Thanks,
> 
> Manjunath S Matti.
> 
> 
> On 16/06/26 11:15 am, Piotr Kubaj wrote:
> > From: Piotr Kubaj <[email protected]>
> >
> > On powerpc64, when the unwind info for a frame does not explicitly
> > describe how r2 (the TOC pointer) was saved -- which is the normal case
> > for the linker-generated PLT call stubs -- frob_update_context inspects
> > the code stream to locate the saved TOC and arranges for r2 to be
> > restored from it.
> >
> > The FreeBSD version of this hook hard-coded the ELFv1 TOC save slot
> > offset of 40 bytes, matching "std r2,40(r1)" (0xF8410028) and
> > "ld r2,40(r1)" (0xE8410028).  FreeBSD/powerpc64 (both big-endian and
> > powerpc64le) uses ELFv2, where the TOC is saved at offset 24
> > ("std r2,24(r1)" / "ld r2,24(r1)").  As a result the checks never
> > matched, r2 was left unrestored, and code reached by unwinding -- e.g. a
> > C++ catch handler in a different module than libgcc_s -- ran with the
> > wrong TOC.  Any global or PLT access from such a handler then computed a
> > bogus address, typically crashing.  This made C++ exceptions unusable on
> > FreeBSD/powerpc64le whenever gcc's shared libgcc_s provided the unwinder
> > (for instance any clang-built C++ program that pulls in libgfortran).
> >
> > Define TOC_SAVE_SLOT based on _CALL_ELF (24 for ELFv2, 40 otherwise) and
> > use it throughout, mirroring linux-unwind.h.
> >
> > libgcc/ChangeLog:
> >
> >     PR target/125803
> >     * config/rs6000/freebsd-unwind.h (TOC_SAVE_SLOT): New macro,
> >     defined according to _CALL_ELF.
> >     (frob_update_context): Use TOC_SAVE_SLOT instead of the hard-coded
> >     ELFv1 offset 40 when checking for and locating the saved TOC, so
> >     that r2 is restored correctly under ELFv2.
> >
> > Signed-off-by: Piotr Kubaj <[email protected]>
> > ---
> > Moved the macro to file scope as suggested.
> >
> > Changes since v1:
> >   * Move the TOC_SAVE_SLOT definition out of frob_update_context to file
> >     scope, alongside the other #defines, as suggested by Manjunath Matti.
> >
> > Tested on powerpc64le-unknown-freebsd15.1: a minimal throw/catch
> > reproducer and a real "octave-cli pkg install" both succeed where they
> > previously SIGSEGV'd.  freebsd-unwind.h is not exercised by the usual
> > bootstrap/regtest on Linux, so no on-target regtest line is offered.
> > Inert on ELFv1.
> >
> >   libgcc/config/rs6000/freebsd-unwind.h | 20 ++++++++++++++------
> >   1 file changed, 14 insertions(+), 6 deletions(-)
> >
> > diff --git a/libgcc/config/rs6000/freebsd-unwind.h 
> > b/libgcc/config/rs6000/freebsd-unwind.h
> > index d97ed0c..6f9efd8 100644
> > --- a/libgcc/config/rs6000/freebsd-unwind.h
> > +++ b/libgcc/config/rs6000/freebsd-unwind.h
> > @@ -24,6 +24,14 @@
> >   
> >   #define R_LR              65
> >   
> > +#ifdef __powerpc64__
> > +#if _CALL_ELF == 2
> > +#define TOC_SAVE_SLOT 24
> > +#else
> > +#define TOC_SAVE_SLOT 40
> > +#endif
> > +#endif
> > +
> >   #define MD_FROB_UPDATE_CONTEXT frob_update_context
> >   
> >   static void
> > @@ -40,9 +48,9 @@ frob_update_context (struct _Unwind_Context *context,
> >      figure out if it was saved.  The big problem here is that the
> >      code that does the save/restore is generated by the linker, so
> >      we have no good way to determine at compile time what to do.  */
> > -      if (pc[0] == 0xF8410028
> > +      if (pc[0] == 0xF8410000 + TOC_SAVE_SLOT
> >       || ((pc[0] & 0xFFFF0000) == 0x3D820000
> > -         && pc[1] == 0xF8410028))
> > +         && pc[1] == 0xF8410000 + TOC_SAVE_SLOT))
> >     {
> >       /* We are in a plt call stub or r2 adjusting long branch stub,
> >          before r2 has been saved.  Keep REG_UNSAVED.  */
> > @@ -51,17 +59,17 @@ frob_update_context (struct _Unwind_Context *context,
> >     {
> >       unsigned int *insn
> >         = (unsigned int *) _Unwind_GetGR (context, R_LR);
> > -     if (insn && *insn == 0xE8410028)
> > -       _Unwind_SetGRPtr (context, 2, context->cfa + 40);
> > +     if (insn && *insn == 0xE8410000 + TOC_SAVE_SLOT)
> > +       _Unwind_SetGRPtr (context, 2, context->cfa + TOC_SAVE_SLOT);
> >       else if (pc[0] == 0x4E800421
> > -              && pc[1] == 0xE8410028)
> > +              && pc[1] == 0xE8410000 + TOC_SAVE_SLOT)
> >         {
> >           /* We are at the bctrl instruction in a call via function
> >              pointer.  gcc always emits the load of the new R2 just
> >              before the bctrl so this is the first and only place
> >              we need to use the stored R2.  */
> >           _Unwind_Word sp = _Unwind_GetGR (context, 1);
> > -         _Unwind_SetGRPtr (context, 2, (void *)(sp + 40));
> > +         _Unwind_SetGRPtr (context, 2, (void *)(sp + TOC_SAVE_SLOT));
> >         }
> >     }
> >       }

Attachment: signature.asc
Description: PGP signature



Reply via email to