--- libgcc/config/rs6000/freebsd-unwind.h.orig 2026-04-30 08:33:28 UTC +++ 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,13 @@ 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 +#if _CALL_ELF != 2 + /* The ELFv2 linker never generates the old PLT stub form. */ || ((pc[0] & 0xFFFF0000) == 0x3D820000 - && pc[1] == 0xF8410028)) + && pc[1] == 0xF8410000 + TOC_SAVE_SLOT) +#endif + ) { /* We are in a plt call stub or r2 adjusting long branch stub, before r2 has been saved. Keep REG_UNSAVED. */ @@ -51,18 +63,21 @@ 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); +#if _CALL_ELF != 2 + /* ELFv2 does not use this function pointer call sequence. */ 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)); } +#endif } } #endif