[PATCH] microblaze: neutralise relocations against discarded sections
Sam Price
thesamprice@gmail.com
Thu Aug 13 04:45:29 GMT 2026
From: Samuel Price <thesamprice@gmail.com>
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 <thesamprice@gmail.com>
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)
More information about the Binutils
mailing list