Re: [PATCHi v1] PowerPC: Create call stubs for compiled modules

Abhay Kandpal <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
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<[email protected]> 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
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.