[PATCH] RISC-V: Fix weak function call reloc overflow on llvm build.
This fixes the llvm build failure that Andreas Schwab reported.
In _bfd_riscv_relax_section, if there is a PLT then we use it unconditionally.
However, in riscv_elf_relocate_section, a PLT is only used if bfd_link_pic,
i.e. the output is a shared library or PIE. So we are relaxing using a
different symbol address than what we are linking for which causes the trouble.
Since this is a linker relaxation problem, it must be _bfd_riscv_relax_section
that is wrong. Adding a check for bfd_link_pic solves the linker errors. But
there is still a potential problem that we aren't handling undef weak functions
in riscv_elf_relocate_section if there is a PLT, which could be a problem if a
program is linked to run at a high address out of range of 0. This is common
for embedded but probably not for linux, but I think we should still fix it.
So I need to add a !bfd_link_pic check there.
Tested with a native binutils/gcc/glibc build and check with no regressions.
And Andreas verified that it fixes his llvm build failure.
* elfnn-riscv.c (riscv_elf_relocate_section) <R_RISCV_CALL>: Add
check for !bfd_link_pic (info).
<R_RISCV_CALL_PLT>: Move next to R_RISCV_CALL.
<R_RISCV_JAL>: Add comment.
(_bfd_riscv_relax_section): For plt.offset check, add check for
bfd_link_pic (info). Add comment.
+ case R_RISCV_CALL_PLT:
/* Handle a call to an undefined weak function. This won't be
relaxed, so we have to handle it here. */
if (h != NULL && h->root.type == bfd_link_hash_undefweak
- && h->plt.offset == MINUS_ONE)
+ && (!bfd_link_pic (info) || h->plt.offset == MINUS_ONE))
/* We can use x0 as the base register. */
bfd_vma insn = bfd_get_32 (input_bfd,
@@ -2003,9 +2004,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
/* Fall through. */
- case R_RISCV_CALL_PLT:
+ /* This line has to match the check in _bfd_riscv_relax_section. */
if (bfd_link_pic (info) && h != NULL && h->plt.offset != MINUS_ONE)
/* Refer to the PLT entry. */
@@ -4128,7 +4129,9 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
undefined_weak = TRUE;
- if (h->plt.offset != MINUS_ONE)
+ /* This line has to match the check in riscv_elf_relocate_section
+ in the R_RISCV_CALL[_PLT] case. */
+ if (bfd_link_pic (info) && h->plt.offset != MINUS_ONE)
sym_sec = htab->elf.splt;
symval = h->plt.offset;