https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125803

--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Gerald Pfeifer <[email protected]>:

https://gcc.gnu.org/g:e8385ea3b57862ce6c6ace5e6973b96cf238f4b6

commit r17-2785-ge8385ea3b57862ce6c6ace5e6973b96cf238f4b6
Author: Piotr Kubaj <[email protected]>
Date:   Wed Jul 22 15:45:04 2026 +0200

    libgcc: rs6000: fix TOC restore when unwinding on FreeBSD powerpc64 ELFv2
[PR target/125803]

    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, and guard the ELFv1-only code-reading cases (the old
    PLT stub form and the function pointer call sequence) with
    _CALL_ELF != 2, 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.  Guard
            the ELFv1-only PLT stub and function pointer call sequences
            with _CALL_ELF != 2, mirroring linux-unwind.h.

    Signed-off-by: Piotr Kubaj <[email protected]>

Reply via email to