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]>
