[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