[binutils-gdb] RISC-V: PR32499, Fix PR18841 segfault caused by ifunc relocation ordering

Nelson Chu nelsonc1225@sourceware.org
Fri Jan 17 08:55:55 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a223bdd674f1001d6cf315bacfd962cb62fb3555

commit a223bdd674f1001d6cf315bacfd962cb62fb3555
Author: Nelson Chu <nelson@rivosinc.com>
Date:   Tue Jan 14 14:16:48 2025 +0800

    RISC-V: PR32499, Fix PR18841 segfault caused by ifunc relocation ordering
    
    Even though the relocation isn't IRELATIVE, it still should be come last if
    refering to ifunc symbol.  In order to get the ifunc relocs properly sorted
    the correct class needs to be returned.  The code mimics what has been done
    for x86, sparc, aarch64 and arm32.
    
    bfd/
            PR 18841
            PR 32499
            * elfnn-riscv.c (riscv_reloc_type_class): Handle ifunc relocation
            ordering, even though it's not IRELATIVE, it still should be come
            last if refering ifunc symbol.

Diff:
---
 bfd/elfnn-riscv.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 2122aa36c7c..c3881bb9edd 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3658,13 +3658,47 @@ riscv_elf_plt_sym_val (bfd_vma i, const asection *plt,
   return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
 }
 
+/* Used to decide how to sort relocs in an optimal manner for the
+   dynamic linker, before writing them out.  */
+
 static enum elf_reloc_type_class
-riscv_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+riscv_reloc_type_class (const struct bfd_link_info *info,
 			const asection *rel_sec ATTRIBUTE_UNUSED,
 			const Elf_Internal_Rela *rela)
 {
+  struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+
+  if (htab->elf.dynsym != NULL
+      && htab->elf.dynsym->contents != NULL)
+    {
+      /* Check relocation against STT_GNU_IFUNC symbol if there are
+	 dynamic symbols.  */
+      bfd *abfd = info->output_bfd;
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+      unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
+      if (r_symndx != STN_UNDEF)
+	{
+	  Elf_Internal_Sym sym;
+	  if (!bed->s->swap_symbol_in (abfd,
+				       (htab->elf.dynsym->contents
+					+ r_symndx * bed->s->sizeof_sym),
+				       0, &sym))
+	    {
+	      /* xgettext:c-format */
+	      _bfd_error_handler (_("%pB symbol number %lu references"
+				    " nonexistent SHT_SYMTAB_SHNDX section"),
+				  abfd, r_symndx);
+	      /* Ideally an error class should be returned here.  */
+	    }
+	  else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+	    return reloc_class_ifunc;
+	}
+    }
+
   switch (ELFNN_R_TYPE (rela->r_info))
     {
+    case R_RISCV_IRELATIVE:
+      return reloc_class_ifunc;
     case R_RISCV_RELATIVE:
       return reloc_class_relative;
     case R_RISCV_JUMP_SLOT:


More information about the Binutils-cvs mailing list