aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2024-06-29 17:08:02 +0930
committerAlan Modra <amodra@gmail.com>2024-06-30 14:41:37 +0930
commit6e46bdf64e3eb3be2bcb02f229a48b050b8431eb (patch)
treea68bed3ae09cd6be840573e058fb3936daceb7ba
parent8891a9751f91dd00b9d5656a5e6cb1fc77697868 (diff)
downloadgdb-6e46bdf64e3eb3be2bcb02f229a48b050b8431eb.zip
gdb-6e46bdf64e3eb3be2bcb02f229a48b050b8431eb.tar.gz
gdb-6e46bdf64e3eb3be2bcb02f229a48b050b8431eb.tar.bz2
Re: Rewrite SHT_GROUP handling
Some more error tweaks. Report a zero entry as "invalid entry.." rather than "unknown type..", and allow a section to be mentioned twice in a group. * elf.c (process_sht_group_entries): Tweak error messages, and allow a duplicate index in a group without reporting an error.
-rw-r--r--bfd/elf.c102
1 files changed, 52 insertions, 50 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 8bb296f..f85f79e 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -622,6 +622,7 @@ process_sht_group_entries (bfd *abfd,
{
unsigned int idx;
Elf_Internal_Shdr *shdr;
+ asection *elt;
p -= 4;
idx = H_GET_32 (abfd, p);
@@ -632,67 +633,68 @@ process_sht_group_entries (bfd *abfd,
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
break;
}
- if (idx < elf_numsections (abfd))
- shdr = elf_elfsections (abfd)[idx];
- if (idx >= elf_numsections (abfd)
- || shdr->sh_type == SHT_GROUP
- || (shdr->bfd_section != NULL
- && elf_next_in_group (shdr->bfd_section) != NULL))
+ if (idx == 0
+ || idx >= elf_numsections (abfd)
+ || (shdr = elf_elfsections (abfd)[idx])->sh_type == SHT_GROUP
+ || ((elt = shdr->bfd_section) != NULL
+ && elf_sec_group (elt) != NULL
+ && elf_sec_group (elt) != ghdr->bfd_section))
{
_bfd_error_handler
- (_("%pB: invalid entry in SHT_GROUP section [%u]"), abfd, gidx);
+ (_("%pB: invalid entry (%#x) in group [%u]"),
+ abfd, idx, gidx);
+ continue;
}
- else
- {
- /* PR binutils/23199: All sections in a section group should
- be marked with SHF_GROUP. But some tools generate broken
- objects without SHF_GROUP. Fix them up here. */
- shdr->sh_flags |= SHF_GROUP;
- asection *elt = shdr->bfd_section;
- if (elt != NULL)
- {
- if (last_elt == NULL)
- {
- /* Start a circular list with one element.
- It will be in reverse order to match what gas does. */
- elf_next_in_group (elt) = elt;
- /* Point the group section to it. */
- elf_next_in_group (ghdr->bfd_section) = elt;
- gname = group_signature (abfd, ghdr);
- if (gname == NULL)
- {
- free (contents);
- return false;
- }
- }
- else
- {
- elf_next_in_group (elt) = elf_next_in_group (last_elt);
- elf_next_in_group (last_elt) = elt;
- }
- last_elt = elt;
- elf_group_name (elt) = gname;
- elf_sec_group (elt) = ghdr->bfd_section;
- }
- else if (shdr->sh_type != SHT_RELA
- && shdr->sh_type != SHT_REL)
+ /* PR binutils/23199: According to the ELF gABI all sections in
+ a group must be marked with SHF_GROUP, but some tools
+ generate broken objects. Fix them up here. */
+ shdr->sh_flags |= SHF_GROUP;
+
+ if (elt == NULL)
+ {
+ if (shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
{
- /* There are some unknown sections in the group. */
+ const char *name = bfd_elf_string_from_elf_section
+ (abfd, elf_elfheader (abfd)->e_shstrndx, shdr->sh_name);
+
_bfd_error_handler
/* xgettext:c-format */
- (_("%pB: unknown type [%#x] section `%s' in group [%u]"),
- abfd,
- shdr->sh_type,
- bfd_elf_string_from_elf_section (abfd,
- (elf_elfheader (abfd)
- ->e_shstrndx),
- shdr->sh_name),
- gidx);
+ (_("%pB: unexpected type (%#x) section `%s' in group [%u]"),
+ abfd, shdr->sh_type, name, gidx);
+ }
+ continue;
+ }
+
+ /* Don't try to add a section to elf_next_in_group list twice. */
+ if (elf_sec_group (elt) != NULL)
+ continue;
+
+ if (last_elt == NULL)
+ {
+ /* Start a circular list with one element.
+ It will be in reverse order to match what gas does. */
+ elf_next_in_group (elt) = elt;
+ /* Point the group section to it. */
+ elf_next_in_group (ghdr->bfd_section) = elt;
+ gname = group_signature (abfd, ghdr);
+ if (gname == NULL)
+ {
+ free (contents);
+ return false;
}
}
+ else
+ {
+ elf_next_in_group (elt) = elf_next_in_group (last_elt);
+ elf_next_in_group (last_elt) = elt;
+ }
+ last_elt = elt;
+ elf_group_name (elt) = gname;
+ elf_sec_group (elt) = ghdr->bfd_section;
}
+
free (contents);
return true;
}