summaryrefslogtreecommitdiff
path: root/opcodes/arm-dis.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-09-30 10:26:30 +0930
committerAlan Modra <amodra@gmail.com>2022-09-30 10:33:27 +0930
commit4eeb0013059856b8660b4a0351589b096167b4d1 (patch)
treed554fb699194ae69fb93b9665bf6ec111055fcd8 /opcodes/arm-dis.c
parent478fced3a8904bed9a99ecf9c0374a49c3ac2115 (diff)
downloadbinutils-gdb-4eeb0013059856b8660b4a0351589b096167b4d1.tar.gz
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.
Diffstat (limited to 'opcodes/arm-dis.c')
-rw-r--r--opcodes/arm-dis.c124
1 files 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