[PATCH] microblaze: neutralise relocations against discarded sections

Sam Price <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
From: Samuel Price <[email protected]>

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]>
Assisted-by: Claude (Anthropic)
---
 bfd/elf32-microblaze.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 9afb1ccfdeb..d58c6cdd4e2 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
-- 
2.39.5 (Apple Git-154)
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.