[PATCH] D63076: [ELF][RISCV] Support PLT, GOT, copy and relative relocations

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 19:08:24 PDT 2019


MaskRay marked 2 inline comments as done.
MaskRay added inline comments.


================
Comment at: test/ELF/riscv-plt.s:72
+  call foo
+  call bar
+  call bar at plt
----------------
jrtc27 wrote:
> MaskRay wrote:
> > jrtc27 wrote:
> > > jrtc27 wrote:
> > > > MaskRay wrote:
> > > > > jrtc27 wrote:
> > > > > > This should never use a PLT stub.
> > > > > > This should never use a PLT stub.
> > > > > 
> > > > > Which function should not use a PLT stub? I think the behavior is consistent with ld.bfd, foo doesn't get a PLT but weak and bar get PLT stubs.
> > > > Yes, and I'm 99% sure that's an unintended bug. If you delete the `call foo at plt`, then the `call bar` *doesn't* use a PLT stub.
> > > I mean delete `call bar at plt`, of course...
> > > Yes, and I'm 99% sure that's an unintended bug. If you delete the call bar at plt, then the call bar *doesn't* use a PLT stub.
> > 
> > I think you misread it..
> > 
> > bar at plt will be created, even if I delete `call bar at plt`. The behavior is consistent with ld.bfd.
> > 
> > Because bar is not local, a PLT has to be created.
> No, the whole point is that by *not* adding `@plt` you forcefully bypass the PLT and don't allow bar to be preempted in this instance:
> 
> ```
> burn:snippets jrtc4% cat call-plt.s
> .global test, foo, bar, baz
> 
> test:
>     call foo
>     call bar
>     call bar at plt
>     call baz at plt
> burn:snippets jrtc4% riscv64-linux-gnu-gcc -o call-plt-pic.so -shared -fPIC call-plt.s -nostdlib
> burn:snippets jrtc4% riscv64-linux-gnu-objdump -d call-plt-pic.so                               
> 
> call-plt-pic.so:     file format elf64-littleriscv
> 
> 
> Disassembly of section .plt:
> 
> 00000000000002f0 <.plt>:
>  2f0:   00002397            auipc   t2,0x2
>  2f4:   41c30333            sub t1,t1,t3
>  2f8:   d103be03            ld  t3,-752(t2) # 2000 <.got>
>  2fc:   fd430313            addi    t1,t1,-44
>  300:   d1038293            addi    t0,t2,-752
>  304:   00135313            srli    t1,t1,0x1
>  308:   0082b283            ld  t0,8(t0)
>  30c:   000e0067            jr  t3
> 
> 0000000000000310 <baz at plt>:
>  310:   00002e17            auipc   t3,0x2
>  314:   d00e3e03            ld  t3,-768(t3) # 2010 <baz>
>  318:   000e0367            jalr    t1,t3
>  31c:   00000013            nop
> 
> 0000000000000320 <bar at plt>:
>  320:   00002e17            auipc   t3,0x2
>  324:   cf8e3e03            ld  t3,-776(t3) # 2018 <bar>
>  328:   000e0367            jalr    t1,t3
>  32c:   00000013            nop
> 
> Disassembly of section .text:
> 
> 0000000000000330 <test>:
>  330:   00000097            auipc   ra,0x0
>  334:   cd0080e7            jalr    -816(ra) # 0 <_PROCEDURE_LINKAGE_TABLE_-0x2f0>
>  338:   fe9ff0ef            jal ra,320 <bar at plt>
>  33c:   fe5ff0ef            jal ra,320 <bar at plt>
>  340:   fd1ff0ef            jal ra,310 <baz at plt>
> ```
> 
> `foo` and `baz` behave as expected, with the former not using a PLT stub but the latter using a PLT stub (based on whether or not they were suffixed with `@plt`). However, *both* calls to `bar` end up using a PLT stub, despite only one of them having a `@plt` suffix. This is the BFD bug I was talking about.
`call bar` (`R_RISCV_CALL`) and `call bar at plt` (`R_RISCV_CALL_PLT`) can both appear in an object file as a result of ld -r.

Making `call bar` and `call bar at plt` resolve to different targets (`R_RISCV_CALL`->`__ehdr_start`; `R_RISCV_CALL_PLT`->plt stub) is nonsensical. The preemptability is the property of the symbol, not the property of the relocation type. The preemptability decides whether a PLT stub should be the target. This is both simple and consistent.

Preemptability, as a property of the symbol, is mergeable. If you have an undefined reference to foo in a.o and a defined foo in b.o, after ld -r, you get a defined foo, which is non-preemptable if you eventually use it in a -no-pie/-pie link. In contrast, preemptability on relocation types is not mergeable. If you place the preemptability information on the relocation types, you can get things that aren't consistent after ld -r.

I don't think `R_RISCV_CALL` is meaningful so I filed https://github.com/riscv/riscv-elf-psabi-doc/issues/98 The examples I raised (`R_X86_64_PLT32` `R_PPC_LOCAL24PC` `R_PPC_PLTREL24`) were to demonstrate how the PLT relocation types evolved on other architectures.

@jrtc27 Have said all that I've no objections to make them distinct in the future if RISC-V folks can convince me the distinction between `R_RISCV_CALL` and `R_RISCV_CALL_PLT` is useful :) Does this patch look good from your perspective minus this difference from ld.bfd?



Repository:
  rLLD LLVM Linker

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63076/new/

https://reviews.llvm.org/D63076





More information about the llvm-commits mailing list