[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
gcc-bugzilla@gcc.gnu.org
Wed Jul 29 10:49:15 GMT 2026
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 <gerald@gcc.gnu.org>:
https://gcc.gnu.org/g:e8385ea3b57862ce6c6ace5e6973b96cf238f4b6
commit r17-2785-ge8385ea3b57862ce6c6ace5e6973b96cf238f4b6
Author: Piotr Kubaj <pkubaj@FreeBSD.org>
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 <pkubaj@FreeBSD.org>
More information about the Gcc-bugs
mailing list