[PATCH v2 0/8] RISC-V: Support GNU indirect functions
Nelson Chu
nelson.chu@sifive.com
Mon Aug 10 07:35:33 GMT 2020
Hi binutils,
On Fri, Aug 7, 2020 at 4:23 PM Nelson Chu <nelson.chu@sifive.com> wrote:
> $ cat ifunc-plt-02.s
> .text
> .type foo_resolver, @function
> foo_resolver:
> ret
> .size foo_resolver, .-foo_resolver
>
> .globl foo
> .type foo, %gnu_indirect_function
> .set foo, foo_resolver
>
> .globl bar
> .type bar, @function
> bar:
> # ifunc-reloc-got
> .L1:
> auipc x1, %got_pcrel_hi (foo)
> ld x1, %pcrel_lo (.L1) (x1)
> # ifunc-reloc-data
> .L2:
> auipc x2, %pcrel_hi (foo_addr)
> ld x2, %pcrel_lo (.L2) (x2)
> # ifunc-reloc-pcrel
> .L3:
> auipc x3, %pcrel_hi (foo)
> addi x3, x3, %pcrel_lo (.L3)
> # ifunc-reloc-call
> call foo
> call foo@plt
> ret
> .size bar, .-bar
>
> .data
> foo_addr:
> .quad foo
>
> $ riscv64-unknown-linux-gnu-as ifunc-plt-02.s -o ifunc-plt-02.o
> $ ld.lld -pie ifunc-plt-02.o -o lld.pie
> $ riscv64-unknown-linux-gnu-readelf -Ws lld.pie
> Symbol table '.symtab' contains 9 entries:
> ...
> 1: 0000000000001278 4 FUNC LOCAL DEFAULT 6 foo_resolver
> ...
> 7: 00000000000012b0 0 FUNC GLOBAL DEFAULT UND foo
> ...
>
> $ riscv64-unknown-linux-gnu-readelf -Wr lld.pie
> Relocation section '.rela.dyn' at offset 0x248 contains 2 entries:
> Offset Info Type Symbol's
> Value Symbol's Name + Addend
> 00000000000023d0 0000000000000003 R_RISCV_RELATIVE
> 12b0
> 00000000000033e0 000000000000003a R_RISCV_IRELATIVE
> 1278
>
> $ riscv64-unknown-linux-gnu-objdump -D lld.pie | less
> Disassembly of section .text:
>
> 0000000000001278 <foo_resolver>:
> 1278: 00008067 ret
>
> 000000000000127c <bar>:
> 127c: 00001097 auipc ra,0x1
> 1280: 1540a083 lw ra,340(ra) # 23d0
> <_DYNAMIC+0x110>
>
> 0000000000001284 <.L2>:
> 1284: 00002117 auipc sp,0x2
> 1288: 15412103 lw sp,340(sp) # 33d8 <foo_addr>
>
> 000000000000128c <.L3>:
> 128c: 00000197 auipc gp,0x0
> 1290: 02418193 addi gp,gp,36 # 12b0 <.L3+0x24>
> 1294: 00000097 auipc ra,0x0
> 1298: 01c080e7 jalr 28(ra) # 12b0 <.L3+0x24>
> 129c: 00000097 auipc ra,0x0
> 12a0: 014080e7 jalr 20(ra) # 12b0 <.L3+0x24>
> 12a4: 00008067 ret
>
> Disassembly of section .iplt:
>
> 00000000000012b0 <.iplt>:
> 12b0: 00002e17 auipc t3,0x2
> 12b4: 130e3e03 ld t3,304(t3) # 33e0 <foo_addr+0x8>
> 12b8: 000e0367 jalr t1,t3
> 12bc: 00000013 nop
> ...
> Disassembly of section .data:
>
> 00000000000033d8 <foo_addr>:
> 33d8: 12b0 addi a2,sp,360
> ...
>
> 0x23d0 is GOT entry, 0x33d8 is data section, and 0x33e0 is .got.plt enrty.
> My understanding is that the GOT refers to `foo` and will get the
> address of .plt
> entry after ld.so resolved the R_RISCV_RELATIVE reloc. Also, lld stroe the
> .plt entry address into the data section `foo_addr`. Therefore, the function
> pointer equality looks good since we should always get the .plt entry as the
> function address. As for the .got.plt, we should get the resolved IFUNC
> address after ld.so resolved the R_RISCV_IRELATIVE reloc.
Sorry, correct the lld readelf results, they are a little bit different,
$ riscv64-unknown-linux-gnu-readelf -Ws lld.pie
Symbol table '.symtab' contains 9 entries:
1: 0000000000001290 4 FUNC LOCAL DEFAULT 6 foo_resolver
7: 00000000000012c0 0 FUNC GLOBAL DEFAULT 7 foo
$ riscv64-unknown-linux-gnu-readelf -Wr lld.pie
Relocation section '.rela.dyn' at offset 0x248 contains 3 entries:
Offset Info Type Symbol's
Value Symbol's Name + Addend
00000000000023e0 0000000000000003 R_RISCV_RELATIVE
12c0
00000000000033e8 0000000000000003 R_RISCV_RELATIVE
12c0
00000000000033f0 000000000000003a R_RISCV_IRELATIVE
1290
0x23e0 is GOT entry, 0x33e8 is the data address `foo_addr`, 0x12c0 is
.plt entry, and 0x33f0 is .got.plt entry. 0x1290 is the address of
`foo_resolver`. Otherwise, the results are the same as the previous
mails.
I got the undef FUNC `foo` and missing R_RISCV_RELATIVE for 0x23e0
(data section) before, these unexpected behavior might caused since I
forgot to give "-defsym __64_bit__=1" to assembler when assembling
ifunc-plt-02.s... Sorry about these...
* Conclusion
1. For LLD
- PCREL relocation should be resolved locally, so it doesn’t allowed
to build shared library (different modules).
- Once the non-GOT and non-PLT reloc is used, lld will redirect them
to the corresponding .plt entry, and change the STT_IFUNC to STT_FUNC
to make sure the pointer equality.
2. For LD
- I treat PCREL and CALL as the same - through PLT, and allowed to
build shared library.
- GNU ld don't change the STT_IFUNC to STT_FUNC, we add more IRELATIVE
relocs to make sure the pointer equality.
- GNU ld will redirect the GOT and DATA relocs to the .plt entry only
when generating PDE (position dependent executable), and then fill the
.plt address into GOT and data region directly without dynamic relocs.
Thanks
Nelson
More information about the Binutils
mailing list