From 5bc5ae8810c03b55f46b9e575389c3fa85a62b5c Mon Sep 17 00:00:00 2001 From: Renlin Li Date: Mon, 25 Jan 2016 15:06:54 +0000 Subject: [PATCH[ARM]Check mapping symbol while backward searching for IT block. opcodes/ * arm-dis.c (mapping_symbol_for_insn): New function. (find_ifthen_state): Call mapping_symbol_for_insn(). gas/ * testsuite/gas/arm/thumb2_it_search.d: New. * testsuite/gas/arm/thumb2_it_search.s: New. --- opcodes/arm-dis.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 3 deletions(-) (limited to 'opcodes/arm-dis.c') diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 56da264..481270e 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -5947,6 +5947,10 @@ parse_disassembler_options (char *options) } } +static bfd_boolean +mapping_symbol_for_insn (bfd_vma pc, struct disassemble_info *info, + enum map_type *map_symbol); + /* Search back through the insn stream to determine if this instruction is conditionally executed. */ @@ -6009,9 +6013,15 @@ find_ifthen_state (bfd_vma pc, } if ((insn & 0xff00) == 0xbf00 && (insn & 0xf) != 0) { - /* This could be an IT instruction. */ - seen_it = insn; - it_count = count >> 1; + enum map_type type = MAP_ARM; + bfd_boolean found = mapping_symbol_for_insn (addr, info, &type); + + if (!found || (found && type == MAP_THUMB)) + { + /* This could be an IT instruction. */ + seen_it = insn; + it_count = count >> 1; + } } if ((insn & 0xf800) >= 0xe800) count++; @@ -6095,6 +6105,71 @@ get_sym_code_type (struct disassemble_info *info, return FALSE; } +/* Search the mapping symbol state for instruction at pc. This is only + applicable for elf target. + + There is an assumption Here, info->private_data contains the correct AND + up-to-date information about current scan process. The information will be + used to speed this search process. + + Return TRUE if the mapping state can be determined, and map_symbol + will be updated accordingly. Otherwise, return FALSE. */ + +static bfd_boolean +mapping_symbol_for_insn (bfd_vma pc, struct disassemble_info *info, + enum map_type *map_symbol) +{ + bfd_vma addr; + int n, start = 0; + bfd_boolean found = FALSE; + enum map_type type = MAP_ARM; + 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; + if (pc == 0) + start = 0; + else + start = private_data->last_mapping_sym; + + start = (start == -1)? 0 : start; + addr = bfd_asymbol_value (info->symtab[start]); + + if (pc >= addr) + { + if (get_map_sym_type (info, start, &type)) + found = TRUE; + } + else + { + for (n = start - 1; n >= 0; n--) + { + if (get_map_sym_type (info, n, &type)) + { + found = TRUE; + break; + } + } + } + + /* No mapping symbols were found. A leading $d may be + omitted for sections which start with data; but for + compatibility with legacy and stripped binaries, only + assume the leading $d if there is at least one mapping + symbol in the file. */ + if (!found && private_data->has_mapping_symbols == 1) + { + type = MAP_DATA; + found = TRUE; + } + + *map_symbol = type; + return found; +} + /* Given a bfd_mach_arm_XXX value, this function fills in the fields of the supplied arm_feature_set structure with bitmasks indicating the support base architectures and coprocessor extensions. -- cgit v1.1