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

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 17 05:49:54 PDT 2019


MaskRay added a comment.

> Still disagree about the behaviour of R_RISCV_CALL. You can't just choose the ABI that you want. Please at least put it back to R_PC. @ruiu do you have an opinion on this?

@jrtc27 `R_PC` and `R_PLT_PC` do not behave in the way you thought. In fact, when used as a PLT relocation, `R_PC` and `R_PLT_PC` work almost the same way. The difference is: `R_PLT_PC` is considered a PLT-generating relocation but `R_PC`.

- If the target symbol is non-preemptable, an `R_PLT_PC` gets optimized to an `R_PC`, and the `R_PC` is considered a link-time constant.
- Otherwise, `R_PLT_PC` is still a link-time constant. **However, `R_PC` will trigger the creation of a canonical PLT** and behave as if an `R_PLT_PC` was used:

  // Relocations.cpp:1026
    if (Sym.isFunc()) {
      if (Config->Pie && Config->EMachine == EM_386)
        errorOrWarn("symbol '" + toString(Sym) +
                    "' cannot be preempted; recompile with -fPIE" +
                    getLocation(Sec, Sym, Offset));
      if (!Sym.isInPlt())
        addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym);
      if (!Sym.isDefined())
        replaceWithDefined(
            Sym, In.Plt,
            Target->PltHeaderSize + Target->PltEntrySize * Sym.PltIndex, 0);
      Sym.NeedsPltAddr = true;  /// marks the creation of a canonical PLT
      Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
      return;
    }

@ruiu There is visible difference, but the difference is related to **whether a canonical PLT is created**, not as @jrtc27 thought that it changed the bindings. I reported the ld.bfd bug at https://sourceware.org/bugzilla/show_bug.cgi?id=24685

  % riscv-ld -m elf64lriscv a.o b.so -o bfd; riscv-objdump -d bfd
  
  0000000000010250 <_start>:
     10250:       00000097                auipc   ra,0x0
     10254:       020080e7                jalr    32(ra) # 10270 <foo>
     10258:       00000097                auipc   ra,0x0
     1025c:       fe8080e7                jalr    -24(ra) # 10240 <bar at plt>
     10260:       00000097                auipc   ra,0x0
     10264:       fe0080e7                jalr    -32(ra) # 10240 <bar at plt>
     10268:       00000097                auipc   ra,0x0
     1026c:       fc8080e7                jalr    -56(ra) # 10230 <weak at plt>
  % readelf --dyn-s bfd
  ...
       1: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND weak
       2: 0000000000010240     0 FUNC    GLOBAL DEFAULT  UND bar  # this is a canonical PLT, it is however not needed. See 
  ...

With this patch, the 4 calls bind the symbols the same as ld.bfd:

  % myld.lld a.o b.so -o a; riscv-objdump -d a
  0000000000011000 <_start>:                                                                                     
     11000:       00000097                auipc   ra,0x0                  
     11004:       020080e7                jalr    32(ra) # 11020 <foo>                
     11008:       00000097                auipc   ra,0x0                   
     1100c:       048080e7                jalr    72(ra) # 11050 <bar at plt>
     11010:       00000097                auipc   ra,0x0   
     11014:       040080e7                jalr    64(ra) # 11050 <bar at plt>                                       
     11018:       00000097                auipc   ra,0x0
     1101c:       048080e7                jalr    72(ra) # 11060 <weak at plt>

The call sites are: `<foo>, <bar at plt>, <bar at plt>, <weak at plt>`, the same as ld.bfd. **This is the behavior that matters.**.

The difference is that we don't create the unnecessary canonical PLT:

  % readelf --dyn-s a
       1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND bar
       2: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND weak

@jrtc27 You might consider ld.bfd's behavior as a bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24683 However, I think that is exactly what it should behave (and that is why I think the distinction of `R_RISCV_PLT` doesn't make sense).


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