[binutils-gdb] microblaze: neutralise relocations against discarded sections

Alan Modra via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f55053f1dc94121bcd8a5faedc9e2f8d41d692e1

commit f55053f1dc94121bcd8a5faedc9e2f8d41d692e1
Author: Samuel Price <[email protected]>
Date:   Thu Aug 13 00:45:29 2026 -0400

    microblaze: neutralise relocations against discarded sections
    
    microblaze_elf_relocate_section does not handle relocations against
    symbols defined in sections discarded by linkonce or comdat handling.
    bfd/elf32-microblaze.c contains no RELOC_AGAINST_DISCARDED_SECTION at
    all, where 60 other bfd/elf*.c files use it.  The relocation survives and
    resolves against a dead symbol, so debug sections end up holding garbage
    where zero is expected:
    
      ld-elf/linkonce2
        regexp "^.*(NONE|unused|UNUSED).*\*ABS\*$"
        line   "00000000 R_MICROBLAZE_32   foo"
    
      ld-discard/zero-range
        regexp "^ 0000 (01)?000000(01)? (01)?000000(01)? 00000000 00000000 .*$"
        line   " 0000 00000000 00000002 00000000 00000000  ................"
    
    sym_hashes is checked for NULL as RELOC_FOR_GLOBAL_SYMBOL does, since this
    lookup runs before that macro is reached.  elf_sym_hashes is left NULL for
    an object with no global symbols, the allocation in
    elf_link_add_object_symbols being gated on extsymcount, so the check is
    not only for the malformed input its comment there mentions.
    
    Most backends put the check after symbol resolution and before the
    bfd_link_relocatable early exit.  This one resolves the symbol separately
    in each of two branches, and the relocatable branch returns early for
    global symbols, which is exactly the case ld-elf/linkonce2 exercises.
    The defining section is therefore looked up once before either branch,
    which covers both the final and the relocatable link without
    restructuring the function.
    
    microblaze_elf_howto_table is an array of pointers, and
    R_MICROBLAZE_TEXTREL_32_LO has no entry in microblaze_elf_howto_raw, so
    howto can be NULL for a type that is in range.  Relaxation creates that
    type and _bfd_clear_contents reads howto->size, so the call is guarded, as
    elf32-ppc.c guards its own array of howto pointers.  Such a relocation is
    left alone rather than neutralised, as before.
    
    Fixes four existing tests on microblaze-elf:
    
      ld-discard/zero-range
      ld-discard/zero-rel
      ld-elf/linkonce1
      ld-elf/linkonce2
    
    ld/testsuite goes from 476 passes and 4 unexpected failures to 480 and 0.
    gas and binutils result lists are byte-identical.  No test changes state
    in the other direction.
    
    bfd/
            * elf32-microblaze.c (microblaze_elf_relocate_section): Look up
            the section defining the symbol and neutralise relocations
            against discarded sections, skipping relocation types with no
            howto table entry and objects with no symbol hash table.
    
    Signed-off-by: Sam Price <[email protected]>
    Reviewed-by: Neal Frager <[email protected]>
    Assisted-by: Claude (Anthropic)

Diff:
---
 bfd/elf32-microblaze.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index bf02aca2652..027b1886e9a 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -1063,6 +1063,7 @@ microblaze_elf_relocate_section (struct bfd_link_info *info,
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
+      asection *sym_sec;
       const char *sym_name;
       bfd_reloc_status_type r = bfd_reloc_ok;
       const char *errmsg = NULL;
@@ -1085,6 +1086,41 @@ microblaze_elf_relocate_section (struct bfd_link_info *info,
       howto = microblaze_elf_howto_table[r_type];
       r_symndx = ELF32_R_SYM (rel->r_info);
 
+      /* Find the section defining the symbol, so that a relocation
+	 against a section discarded by linkonce or comdat handling can
+	 be neutralised.  The symbol is resolved separately in each of
+	 the two branches below, so this has to be done here to cover
+	 both the final and the relocatable link.  sym_hashes is NULL for
+	 an object with no global symbols, so it is checked as
+	 RELOC_FOR_GLOBAL_SYMBOL does, this running before that macro is
+	 reached.  */
+      sym_sec = NULL;
+      if (r_symndx < symtab_hdr->sh_info)
+	sym_sec = local_sections[r_symndx];
+      else if (sym_hashes != NULL)
+	{
+	  struct elf_link_hash_entry *hd;
+
+	  hd = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	  while (hd != NULL
+		 && (hd->root.type == bfd_link_hash_indirect
+		     || hd->root.type == bfd_link_hash_warning))
+	    hd = (struct elf_link_hash_entry *) hd->root.u.i.link;
+
+	  if (hd != NULL
+	      && (hd->root.type == bfd_link_hash_defined
+		  || hd->root.type == bfd_link_hash_defweak))
+	    sym_sec = hd->root.u.def.section;
+	}
+
+      /* howto is NULL for R_MICROBLAZE_TEXTREL_32_LO, which has no entry
+	 in microblaze_elf_howto_raw, and _bfd_clear_contents reads
+	 howto->size.  elf32-ppc.c guards its howto pointers the same way.  */
+      if (sym_sec != NULL && discarded_section (sym_sec) && howto != NULL)
+	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+					 rel, 1, relend, R_MICROBLAZE_NONE,
+					 howto, 0, contents);
+
       if (bfd_link_relocatable (info))
 	{
 	  /* This is a relocatable link.  We don't have to change
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.