[Bug target/125803] [powerpc64 FreeBSD ELFv2] frob_update_context in freebsd-unwind.h uses the ELFv1 TOC save-slot offset (40), so r2 is not restored when unwinding and C++ exceptions crash

"cvs-commit at gcc dot gnu.org via Gcc-bugs" <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
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]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.