[PATCH] D13729: [TSAN, PowerPC] Setjmp/longjmp handling for PowerPC

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 11 08:39:20 PST 2015


uweigand added a comment.

I've now had a look at the current patch, and it seems the problem is simply that the assembly does not actually provide any .opd section in the ELFv1 case.

So instead of:

          .globl _setjmp
          .type _setjmp, @function
          .align 4
  _setjmp:

you need something along the lines of:

          .globl _setjmp
          .type   _setjmp, @function
         ​ .align 4
          .section        ".opd","aw"
          .align 3
  _setjmp:
          .quad   .L._setjmp,.TOC. at tocbase,0
          .previous
  .L._setjmp:

so that the _setjmp symbol actually points to the OPD!  (Otherwise, calling the function will load the first 8 bytes of function text and treat it as code address ....)

For a "normal" function, you could support both ELFv1 and ELFv2 by a prolog like this:

          .globl _setjmp
          .type _setjmp, @function
          .align 2
  #if _CALL_ELF == 2
  _setjmp:
           addis 2,12,(.TOC.-_setjmp)@ha;
           addi 2,2,(.TOC.-_setjmp)@l;
           .localentry _setjmp,.-_setjmp
  #else
           .section        ".opd","aw"
           .align 3
  _setjmp:
           .quad   .L._setjmp,.TOC. at tocbase,0
           .previous
  .L._setjmp:
  #endif

But if you interpose a function from a different shared library, this will not work correctly since caller and callee may get confused as to who is setting up the TOC.   To handle those cases, you'll have to explicitly set up the TOC just like your patch did:

          .globl _setjmp
          .type _setjmp, @function
          .align 2
  #if _CALL_ELF == 2
  _setjmp:
  #else
           .section        ".opd","aw"
           .align 3
  _setjmp:
           .quad   .L._setjmp,.TOC. at tocbase,0
           .previous
  .L._setjmp:
  #endif
  
  [...]
          // Materialize a TOC in case we were called from libc.
          // For ELFv1, we load the TOC from the OPD.  For
          // ELFv2 we use the .TOC. symbol to find it.
          nop
          bcl     20,31,0f
  0:
          mflr    r2
  #if _CALL_ELF == 2
          addis   r2,r2,.TOC.-0b at ha
          addi    r2,r2,.TOC.-0b at l
  #else
          addis   r2,r2,_setjmp-0b at ha 
          addi    r2,r2,_setjmp-0b at l
          ld      r2,8(r2)
  #endif

(Note that the _setjmp symbol now refers to the OPD entry in the ELFv1 case, not the code address!)


Repository:
  rL LLVM

http://reviews.llvm.org/D13729





More information about the llvm-commits mailing list