[PATCH v2 0/8] RISC-V: Support GNU indirect functions

Nelson Chu nelson.chu@sifive.com
Tue Aug 11 09:42:54 GMT 2020


Hi MaskRay,

On Tue, Aug 11, 2020 at 1:16 PM Fangrui Song <i@maskray.me> wrote:
>
> On 2020-08-07, Nelson Chu wrote:
> >Consider the ld's behavior,
> >$ riscv64-unknown-linux-gnu-as ifunc-plt-02.s -o ifunc-plt-02.o
> >$ riscv64-unknown-linux-gnu-ld -pie ifunc-plt-02.o -o ld.pie
> >$ riscv64-unknown-linux-gnu-readelf -Ws ld.pie
> >Symbol table '.symtab' contains 30 entries:
> >...
> >14: 0000000000000270     4 FUNC    LOCAL  DEFAULT    9 foo_resolver
> >...
> >25: 0000000000000270     4 IFUNC   GLOBAL DEFAULT    9 foo
> >...
> >
> >$ riscv64-unknown-linux-gnu-readelf -Wr ld.pie
> >Relocation section '.rela.dyn' at offset 0x210 contains 1 entry:
> >    Offset             Info             Type               Symbol's
> >Value  Symbol's Name + Addend
> >0000000000002000  000000000000003a R_RISCV_IRELATIVE                         270
> >
> >Relocation section '.rela.plt' at offset 0x228 contains 1 entry:
> >    Offset             Info             Type               Symbol's
> >Value  Symbol's Name + Addend
> >0000000000002018  000000000000003a R_RISCV_IRELATIVE                         270
> >
> >$ riscv64-unknown-linux-gnu-objdump -D ld.pie | less
> >Disassembly of section .plt:
> >
> >0000000000000240 <.plt>:
> > 240:   00002397                auipc   t2,0x2
> > 244:   41c30333                sub     t1,t1,t3
> > 248:   dc83be03                ld      t3,-568(t2) # 2008 <.got>
> > 24c:   fd430313                addi    t1,t1,-44
> > 250:   dc838293                addi    t0,t2,-568
> > 254:   00135313                srli    t1,t1,0x1
> > 258:   0082b283                ld      t0,8(t0)
> > 25c:   000e0067                jr      t3
> >
> >0000000000000260 <*ABS*+0x270@plt>:
> > 260:   00002e17                auipc   t3,0x2
> > 264:   db8e3e03                ld      t3,-584(t3) # 2018 <.got+0x10>
> > 268:   000e0367                jalr    t1,t3
> > 26c:   00000013                nop
> >
> >Disassembly of section .text:
> >
> >0000000000000270 <foo_resolver>:
> > 270:   00008067                ret
> >
> >0000000000000274 <bar>:
> > 274:   00002097                auipc   ra,0x2
> > 278:   da40a083                lw      ra,-604(ra) # 2018 <.got+0x10>
> > 27c:   00002117                auipc   sp,0x2
> > 280:   d8412103                lw      sp,-636(sp) # 2000 <__DATA_BEGIN__>
> > 284:   00000197                auipc   gp,0x0
> > 288:   fdc18193                addi    gp,gp,-36 # 260 <*ABS*+0x270@plt>
> > 28c:   00000097                auipc   ra,0x0
> > 290:   fd4080e7                jalr    -44(ra) # 260 <*ABS*+0x270@plt>
> > 294:   00000097                auipc   ra,0x0
> > 298:   fcc080e7                jalr    -52(ra) # 260 <*ABS*+0x270@plt>
> > 29c:   00008067                ret
> >...
> >Disassembly of section .data:
> >
> >0000000000002000 <__DATA_BEGIN__>:
> >    2000:       0000                    unimp
> >        ...
> >
> >0x2018 is a got.plt entry, the GOT and PLT share the same .got.plt in this case.
> >And 0x2000 is the data section.  The GOT refers to `foo` will get the address
> >of the resolved IFUNC address after ld.so resolved the R_RISCV_IRELATIVE
> >reloc.  Also, ld.so will fill the resolved IFUNC address to the data section.
> >However, the function pointer equality looks fine, too.  Since we should always
> >get the resolved IFUNC address as the function address.
>
> Do ra (after .L1), sp (after .l2) and gp (after .L3) in <bar> have the same
> value?  IIUC gp is 0x260. If the got entry (relocated by R_RISCV_IRELATIVE) does
> not always return 0x260, there will be an inequality.

Thanks for explaining this again.  I think I got your points.  I
modify your example in the previous mail, and then get the break
function equality for current GNU ld,

$ cat test.c
#include <stdio.h>

static void
foo1 (void)
{
  printf ("foo1\n");
}

void thefunc (void) __attribute__((ifunc("resolver")));
static void
*resolver (void)
{
  return &foo1;
}

void
main (void)
{
  asm(".option nopic");
  void (*theptr_nopic)(void) = &thefunc;
  asm(".option pic");
  void (*theptr_pic)(void) = &thefunc;

  printf ("foo1 address: %x\n", &foo1);
  printf ("IFunc address pic: %x, nopic: %x\n", theptr_pic, theptr_nopic);
  if (theptr_pic != theptr_nopic)
    printf ("Function equality break since .option pic/nopic\n");

  printf ("Call ifunc ");
  thefunc ();
  printf ("Call ifunc pic ");
  theptr_pic ();
  printf ("Call ifunc nopic ");
  theptr_nopic ();
}

$ ./a.out
foo1 address: e96f369a
IFunc address pic: e96f369a, nopic: e96f35c0
Function equality break since .option pic/nopic
Call ifunc foo1
Call ifunc pic foo1
Call ifunc nopic foo1

The IFunc address pic should be the resolved IFUNC address (foo1), and
the IFunc address nopic is the .plt entry.  In addition to the .option
pic/nopic example, I'm not sure if there is any compiler (gcc/clang)
that will generate the cases, which would break the function pointer
equality?  Ideally, I assume we can only select the file to be PIC or
No-PIC.  If PIC is chosen, then we should only use the GOT to get the
ifunc address.  And No-PIC will only use the PCREL to get the address.

Thanks
Nelson


More information about the Binutils mailing list