Hi Ulrich,
Thanks for the suggestion. I tried -mlongcall and it doesn't work on PowerPC,
though not for the reason I expected.
gcc does generate the right calling sequence with it - saves r2,
loads the target into r12, uses mtctr/bctrl, restores r2:
  24:    std     r2,24(r1)
  30:    addis   r12,r2,0
            30: R_PPC64_PLT16_HA    _setjmp
  34:    ld      r12,0(r12)
            34: R_PPC64_PLT16_LO_DS    _setjmp
  80:    mtctr   r12
            80: R_PPC64_PLTSEQ    longjmp
  84:    bctrl
            84: R_PPC64_PLTCALL    longjmp
  88:    ld      r2,24(r1)
But it obtains the target address from a PLT slot addressed off r2,
so the calls need R_PPC64_PLT16_HA / R_PPC64_PLT16_LO_DS, which BFD's generic linker rejects:
warning: Compiled module "/tmp/gdbobj-6tZVEd/out1.o" section ".text": dangerous relocation: generic linker can't handle R_PPC64_PLT16_HA
warning: Compiled module "/tmp/gdbobj-6tZVEd/out1.o" section ".text": dangerous relocation: generic linker can't handle R_PPC64_PLT16_LO_DS
-mlongcall also converts the intra-module call to a PLT call,
so it fails earlier than before - in _gdb_expr rather than in the callee.
Same result with -mcmodel=large -mlongcall and with -fno-plt -mlongcall (-mno-plt is not recognised on PowerPC).
So on PowerPC -mlongcall gives the correct convention but still requires a PLT,
which is the one thing GDB can't supply. Resolving PLT16 would mean building a table
within +-32KB of the module's TOC and computing slot offsets - more machinery than the stub, not less.

With the patch, GDB builds the target address as immediates instead, needing no table:
call site:
  bl      <stub>
  ld      r2,24(r1)          ; the nop, rewritten
stub:
  std     r2,24(r1)
  lis     r12,target@highest
  ori     r12,r12,target@higher
  rldicr  r12,r12,32,31
  oris    r12,r12,target@h
  ori     r12,r12,target@l
  mtctr   r12
  bctr
At entry to _setjmp, r12 holds the callee's entry address and r2 the correct TOC;
before the patch r2 pointed past the end of libc, which is the SIGSEGV.
The patch applies cleanly to master and gives 526 passes, 0 failures in gdb.compile on powerpc64le.

Thanks
Abhay


On 18/08/26 17:49, Ulrich Weigand wrote:
Abhay Kandpal <abhay@linux.ibm.com> wrote:

The compile command loads a module into inferior memory and relocates
it itself, without a linker.  For R_PPC64_REL24 it patches the branch
to point directly at the target.  On ELFv2 that is not a valid call to
another module: the callee derives its TOC pointer from r12, which
only
a PLT-style call stub sets up, and the caller's TOC pointer is never
restored because the nop following the bl is left alone.
On other platforms, the way this is supposed to work is to use a
set of compiler command-line options that result in code that does
not require PLTs for external calls.  Typically, this means to use
-mcmodel=large.

However, it seems that on PowerPC, while that option exists, it
generates code that still needs PLTs.  There is another option
-mlongcall that should avoid this, however.

I'm wondering if we were to just add -mlongcall to the platform-
specific compiler options for PowerPC, we could fix this issue
without having to reimplement a full PLT solution in GDB ...

Bye,
Ulrich