diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-05-20 09:16:41 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2021-05-20 13:35:54 +0100 |
commit | 427e4066afd13d1bf52c849849475f536e285d66 (patch) | |
tree | 9436dcc8227e05bc1f1be839dcc3d3518c4a0758 /bfd | |
parent | 8baee38bfee176505e6bb541f1df8ec4156b3d46 (diff) | |
download | binutils-427e4066afd13d1bf52c849849475f536e285d66.zip binutils-427e4066afd13d1bf52c849849475f536e285d66.tar.gz binutils-427e4066afd13d1bf52c849849475f536e285d66.tar.bz2 |
gdb/bfd: avoid crash when architecture is forced to csky or riscv
I built GDB with `--enable-targets=all`, then started GDB passing it
an x86-64 executable, finally I ran 'maint selftest', and observed GDB
crash like this:
BFD: BFD (GNU Binutils) 2.36.50.20210519 assertion fail ../../src/bfd/hash.c:438
Aborted (core dumped)
The problem originates from two locations, for example in csky-dis.c
(csky_get_disassembler) where we do this:
const char *sec_name = NULL;
...
sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
if (bfd_get_section_by_name (abfd, sec_name) != NULL)
...
We end up in here because during the selftests GDB forces the
architecture to be csky, but the BFD being accessed is still of type
x86-64. As a result obj_attrs_section returns NULL, which means we
end up passing NULL to bfd_get_section_by_name. If we follow the
function calls from bfd_get_section_by_name we eventually end up in
bfd_hash_hash, which asserts that the string (i.e. the name) is not
NULL.
The same crash can be reproduced in GDB without using the selftests,
for example:
(gdb) file x86_64.elf
(gdb) start
(gdb) set architecture csky
(gdb) disassemble main
Dump of assembler code for function main:
BFD: BFD (GNU Binutils) 2.36.50.20210519 assertion fail ../../src/bfd/hash.c:438
Aborted (core dumped)
The fix I propose here is to have bfd_get_section_by_name return NULL
if name is ever NULL. For consistency I updated
bfd_get_section_by_name_if in the same way, even though I'm not
hitting any problems along that code path right now.
I looked through the source tree and removed two NULL checks in
bfd/dwarf2.c which are no longer needed, its possible that there are
additional NULL checks that could be removed, I just didn't find them.
bfd/ChangeLog:
* section.c (bfd_get_section_by_name): Return NULL if name is
NULL.
(bfd_get_section_by_name_if): Likewise.
* dwarf2.c (read_section): Remove unneeded NULL check.
(find_debug_info): Likewise.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/dwarf2.c | 12 | ||||
-rw-r--r-- | bfd/section.c | 6 |
3 files changed, 18 insertions, 8 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a389fdf..2ad7803 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2021-05-20 Andrew Burgess <andrew.burgess@embecosm.com> + + * section.c (bfd_get_section_by_name): Return NULL if name is + NULL. + (bfd_get_section_by_name_if): Likewise. + * dwarf2.c (read_section): Remove unneeded NULL check. + (find_debug_info): Likewise. + 2021-05-19 Nick Clifton <nickc@redhat.com> * plugin.c (bfd_plugin_open_input): Inform the user if the limit diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 0a8a557..cf1f1d1 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -545,8 +545,7 @@ read_section (bfd * abfd, if (msec == NULL) { section_name = sec->compressed_name; - if (section_name != NULL) - msec = bfd_get_section_by_name (abfd, section_name); + msec = bfd_get_section_by_name (abfd, section_name); } if (msec == NULL) { @@ -4226,12 +4225,9 @@ find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections, return msec; look = debug_sections[debug_info].compressed_name; - if (look != NULL) - { - msec = bfd_get_section_by_name (abfd, look); - if (msec != NULL) - return msec; - } + msec = bfd_get_section_by_name (abfd, look); + if (msec != NULL) + return msec; for (msec = abfd->sections; msec != NULL; msec = msec->next) if (startswith (msec->name, GNU_LINKONCE_INFO)) diff --git a/bfd/section.c b/bfd/section.c index a353488..6b6aa92 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -898,6 +898,9 @@ bfd_get_section_by_name (bfd *abfd, const char *name) { struct section_hash_entry *sh; + if (name == NULL) + return NULL; + sh = section_hash_lookup (&abfd->section_htab, name, false, false); if (sh != NULL) return &sh->section; @@ -1006,6 +1009,9 @@ bfd_get_section_by_name_if (bfd *abfd, const char *name, struct section_hash_entry *sh; unsigned long hash; + if (name == NULL) + return NULL; + sh = section_hash_lookup (&abfd->section_htab, name, false, false); if (sh == NULL) return NULL; |