From 4eeb0013059856b8660b4a0351589b096167b4d1 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 30 Sep 2022 10:26:30 +0930 Subject: [PATCH] PR29626, Segfault when disassembling ARM code PR 29626 * arm-dis.c (mapping_symbol_for_insn): Return false on zero symtab_size. Delete later symtab_size test. --- opcodes/arm-dis.c | 124 +++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 684c74f7f20..caf3531ae3d 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -11865,77 +11865,75 @@ mapping_symbol_for_insn (bfd_vma pc, struct disassemble_info *info, struct arm_private_data *private_data; if (info->private_data == NULL + || info->symtab_size == 0 || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour) return false; private_data = info->private_data; /* First, look for mapping symbols. */ - if (info->symtab_size != 0) - { - if (pc <= private_data->last_mapping_addr) - private_data->last_mapping_sym = -1; - - /* Start scanning at the start of the function, or wherever - we finished last time. */ - n = info->symtab_pos + 1; - - /* If the last stop offset is different from the current one it means we - are disassembling a different glob of bytes. As such the optimization - would not be safe and we should start over. */ - can_use_search_opt_p - = private_data->last_mapping_sym >= 0 - && info->stop_offset == private_data->last_stop_offset; - - if (n >= private_data->last_mapping_sym && can_use_search_opt_p) - n = private_data->last_mapping_sym; - - /* Look down while we haven't passed the location being disassembled. - The reason for this is that there's no defined order between a symbol - and an mapping symbol that may be at the same address. We may have to - look at least one position ahead. */ - for (; n < info->symtab_size; n++) - { - addr = bfd_asymbol_value (info->symtab[n]); - if (addr > pc) - break; - if (get_map_sym_type (info, n, &type)) - { - last_sym = n; - found = true; - } - } + if (pc <= private_data->last_mapping_addr) + private_data->last_mapping_sym = -1; + + /* Start scanning at the start of the function, or wherever + we finished last time. */ + n = info->symtab_pos + 1; + + /* If the last stop offset is different from the current one it means we + are disassembling a different glob of bytes. As such the optimization + would not be safe and we should start over. */ + can_use_search_opt_p + = (private_data->last_mapping_sym >= 0 + && info->stop_offset == private_data->last_stop_offset); + + if (n >= private_data->last_mapping_sym && can_use_search_opt_p) + n = private_data->last_mapping_sym; + + /* Look down while we haven't passed the location being disassembled. + The reason for this is that there's no defined order between a symbol + and an mapping symbol that may be at the same address. We may have to + look at least one position ahead. */ + for (; n < info->symtab_size; n++) + { + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + break; + if (get_map_sym_type (info, n, &type)) + { + last_sym = n; + found = true; + } + } - if (!found) - { - n = info->symtab_pos; - if (n >= private_data->last_mapping_sym && can_use_search_opt_p) - n = private_data->last_mapping_sym; - - /* No mapping symbol found at this address. Look backwards - for a preceeding one, but don't go pass the section start - otherwise a data section with no mapping symbol can pick up - a text mapping symbol of a preceeding section. The documentation - says section can be NULL, in which case we will seek up all the - way to the top. */ - if (info->section) - section_vma = info->section->vma; - - for (; n >= 0; n--) - { - addr = bfd_asymbol_value (info->symtab[n]); - if (addr < section_vma) - break; + if (!found) + { + n = info->symtab_pos; + if (n >= private_data->last_mapping_sym && can_use_search_opt_p) + n = private_data->last_mapping_sym; + + /* No mapping symbol found at this address. Look backwards + for a preceeding one, but don't go pass the section start + otherwise a data section with no mapping symbol can pick up + a text mapping symbol of a preceeding section. The documentation + says section can be NULL, in which case we will seek up all the + way to the top. */ + if (info->section) + section_vma = info->section->vma; + + for (; n >= 0; n--) + { + addr = bfd_asymbol_value (info->symtab[n]); + if (addr < section_vma) + break; - if (get_map_sym_type (info, n, &type)) - { - last_sym = n; - found = true; - break; - } - } - } - } + if (get_map_sym_type (info, n, &type)) + { + last_sym = n; + found = true; + break; + } + } + } /* If no mapping symbol was found, try looking up without a mapping symbol. This is done by walking up from the current PC to the nearest -- 2.30.2