From b0e28b39b7de5e36bb162657c3b62ba6349ba4b2 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Fri, 29 Jan 2010 16:47:55 +0000 Subject: [PATCH] gas/testsuite/ * gas/arm/dis-data.d: Update test name. Do not expect .word output. * gas/arm/dis-data2.d, gas/arm/dis-data2.s, gas/arm/dis-data3.d, gas/arm/dis-data3.s: New tests. opcodes/ * opcodes/arm-dis.c (struct arm_private_data): New. (print_insn_coprocessor, print_insn_arm): Update to use struct arm_private_data. (is_mapping_symbol, get_map_sym_type): New functions. (get_sym_code_type): Check the symbol's section. Do not check mapping symbols. (print_insn): Default to disassembling ARM mode code. Check for mapping symbols separately from other symbols. Use struct arm_private_data. --- gas/testsuite/ChangeLog | 7 + gas/testsuite/gas/arm/dis-data.d | 8 +- gas/testsuite/gas/arm/dis-data2.d | 10 ++ gas/testsuite/gas/arm/dis-data2.s | 8 ++ gas/testsuite/gas/arm/dis-data3.d | 11 ++ gas/testsuite/gas/arm/dis-data3.s | 8 ++ opcodes/ChangeLog | 12 ++ opcodes/arm-dis.c | 206 ++++++++++++++++++++++-------- 8 files changed, 212 insertions(+), 58 deletions(-) create mode 100644 gas/testsuite/gas/arm/dis-data2.d create mode 100644 gas/testsuite/gas/arm/dis-data2.s create mode 100644 gas/testsuite/gas/arm/dis-data3.d create mode 100644 gas/testsuite/gas/arm/dis-data3.s diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index ffd0c49e692..b5258108a57 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-01-29 Daniel Jacobowitz + + * gas/arm/dis-data.d: Update test name. Do not expect + .word output. + * gas/arm/dis-data2.d, gas/arm/dis-data2.s, + gas/arm/dis-data3.d, gas/arm/dis-data3.s: New tests. + 2010-01-29 Nick Clifton PR 11136 diff --git a/gas/testsuite/gas/arm/dis-data.d b/gas/testsuite/gas/arm/dis-data.d index 97154537877..40ca7709b66 100644 --- a/gas/testsuite/gas/arm/dis-data.d +++ b/gas/testsuite/gas/arm/dis-data.d @@ -1,10 +1,10 @@ -# name: Data disassembler test +# name: Data disassembler test (no symbols) # skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix* # objdump: -dr --prefix-addresses --show-raw-insn .*: +file format .*arm.* Disassembly of section \.text: -0x00000000 20010000 .word 0x20010000 -0x00000004 000000f9 .word 0x000000f9 -0x00000008 00004cd5 .word 0x00004cd5 +0x00000000 20010000 andcs r0, r1, r0 +0x00000004 000000f9 strdeq r0, \[r0\], -r9 +0x00000008 00004cd5 ldrdeq r4, \[r0\], -r5 diff --git a/gas/testsuite/gas/arm/dis-data2.d b/gas/testsuite/gas/arm/dis-data2.d new file mode 100644 index 00000000000..ef7bb81d428 --- /dev/null +++ b/gas/testsuite/gas/arm/dis-data2.d @@ -0,0 +1,10 @@ +# name: Data disassembler test (function symbol) +# skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix* +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section \.text: +00000000
20010000 andcs r0, r1, r0 +00000004 000000f9 strdeq r0, \[r0\], -r9 +00000008 00004cd5 ldrdeq r4, \[r0\], -r5 diff --git a/gas/testsuite/gas/arm/dis-data2.s b/gas/testsuite/gas/arm/dis-data2.s new file mode 100644 index 00000000000..30eaa678a06 --- /dev/null +++ b/gas/testsuite/gas/arm/dis-data2.s @@ -0,0 +1,8 @@ +.syntax unified +.type main, %function +.globl main +main: +.word 0x20010000 +.word 0x000000f9 +.word 0x00004cd5 + diff --git a/gas/testsuite/gas/arm/dis-data3.d b/gas/testsuite/gas/arm/dis-data3.d new file mode 100644 index 00000000000..e33159b8404 --- /dev/null +++ b/gas/testsuite/gas/arm/dis-data3.d @@ -0,0 +1,11 @@ +# name: Data disassembler test (with mapping symbol) +# skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix* +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section \.text: +00000000
20010000 .word 0x20010000 +00000004 000000f9 .word 0x000000f9 +00000008 00004cd5 .word 0x00004cd5 +0000000c e1a00000 nop ; \(mov r0, r0\) diff --git a/gas/testsuite/gas/arm/dis-data3.s b/gas/testsuite/gas/arm/dis-data3.s new file mode 100644 index 00000000000..73da9b411c0 --- /dev/null +++ b/gas/testsuite/gas/arm/dis-data3.s @@ -0,0 +1,8 @@ +.syntax unified +.type main, %function +.globl main +main: +.word 0x20010000 +.word 0x000000f9 +.word 0x00004cd5 +nop diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 875ee2ce9a3..7ab07efa60b 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,15 @@ +2010-01-29 Daniel Jacobowitz + + * opcodes/arm-dis.c (struct arm_private_data): New. + (print_insn_coprocessor, print_insn_arm): Update to use struct + arm_private_data. + (is_mapping_symbol, get_map_sym_type): New functions. + (get_sym_code_type): Check the symbol's section. Do not check + mapping symbols. + (print_insn): Default to disassembling ARM mode code. Check + for mapping symbols separately from other symbols. Use + struct arm_private_data. + 2010-01-28 H.J. Lu * i386-dis.c (EXVexWdqScalar): New. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 0318d4a6aab..fba3e3bd12c 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -45,6 +45,16 @@ #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) #endif +struct arm_private_data +{ + /* The features to use when disassembling optional instructions. */ + arm_feature_set features; + + /* Whether any mapping symbols are present in the provided symbol + table. -1 if we do not know yet, otherwise 0 or 1. */ + int has_mapping_symbols; +}; + struct opcode32 { unsigned long arch; /* Architecture defining this insn. */ @@ -1750,7 +1760,8 @@ print_insn_coprocessor (bfd_vma pc, fprintf_ftype func = info->fprintf_func; unsigned long mask; unsigned long value = 0; - unsigned long allowed_arches = ((arm_feature_set *) info->private_data)->coproc; + struct arm_private_data *private_data = info->private_data; + unsigned long allowed_arches = private_data->features.coproc; int cond; for (insn = coprocessor_opcodes; insn->assembler; insn++) @@ -1776,7 +1787,7 @@ print_insn_coprocessor (bfd_vma pc, continue; case SENTINEL_GENERIC_START: - allowed_arches = ((arm_feature_set *) info->private_data)->core; + allowed_arches = private_data->features.core; continue; default: @@ -2843,6 +2854,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) const struct opcode32 *insn; void *stream = info->stream; fprintf_ftype func = info->fprintf_func; + struct arm_private_data *private_data = info->private_data; if (print_insn_coprocessor (pc, info, given, FALSE)) return; @@ -2855,7 +2867,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) if ((given & insn->mask) != insn->value) continue; - if ((insn->arch & ((arm_feature_set *) info->private_data)->core) == 0) + if ((insn->arch & private_data->features.core) == 0) continue; /* Special case: an instruction with all bits set in the condition field @@ -3057,7 +3069,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) /* The p-variants of tst/cmp/cmn/teq are the pre-V6 mechanism for setting PSR flag bits. They are obsolete in V6 onwards. */ - if (((((arm_feature_set *) info->private_data)->core) & ARM_EXT_V6) == 0) + if ((private_data->features.core & ARM_EXT_V6) == 0) func (stream, "p"); } break; @@ -4268,7 +4280,44 @@ find_ifthen_state (bfd_vma pc, ifthen_state = 0; } -/* Try to infer the code type (Arm or Thumb) from a symbol. +/* Returns nonzero and sets *MAP_TYPE if the N'th symbol is a + mapping symbol. */ + +static int +is_mapping_symbol (struct disassemble_info *info, int n, + enum map_type *map_type) +{ + const char *name; + + name = bfd_asymbol_name (info->symtab[n]); + if (name[0] == '$' && (name[1] == 'a' || name[1] == 't' || name[1] == 'd') + && (name[2] == 0 || name[2] == '.')) + { + *map_type = ((name[1] == 'a') ? MAP_ARM + : (name[1] == 't') ? MAP_THUMB + : MAP_DATA); + return TRUE; + } + + return FALSE; +} + +/* Try to infer the code type (ARM or Thumb) from a mapping symbol. + Returns nonzero if *MAP_TYPE was set. */ + +static int +get_map_sym_type (struct disassemble_info *info, + int n, + enum map_type *map_type) +{ + /* If the symbol is in a different section, ignore it. */ + if (info->section != NULL && info->section != info->symtab[n]->section) + return FALSE; + + return is_mapping_symbol (info, n, map_type); +} + +/* Try to infer the code type (ARM or Thumb) from a non-mapping symbol. Returns nonzero if *MAP_TYPE was set. */ static int @@ -4278,7 +4327,10 @@ get_sym_code_type (struct disassemble_info *info, { elf_symbol_type *es; unsigned int type; - const char *name; + + /* If the symbol is in a different section, ignore it. */ + if (info->section != NULL && info->section != info->symtab[n]->section) + return FALSE; es = *(elf_symbol_type **)(info->symtab + n); type = ELF_ST_TYPE (es->internal_elf_sym.st_info); @@ -4290,17 +4342,6 @@ get_sym_code_type (struct disassemble_info *info, return TRUE; } - /* Check for mapping symbols. */ - name = bfd_asymbol_name (info->symtab[n]); - if (name[0] == '$' && (name[1] == 'a' || name[1] == 't' || name[1] == 'd') - && (name[2] == 0 || name[2] == '.')) - { - *map_type = ((name[1] == 'a') ? MAP_ARM - : (name[1] == 't') ? MAP_THUMB - : MAP_DATA); - return TRUE; - } - return FALSE; } @@ -4355,12 +4396,12 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) long given; int status; int is_thumb = FALSE; - int is_data = (bfd_asymbol_flavour (*info->symtab) - == bfd_target_elf_flavour) ? TRUE : FALSE; + int is_data = FALSE; int little_code; unsigned int size = 4; void (*printer) (bfd_vma, struct disassemble_info *, long); bfd_boolean found = FALSE; + struct arm_private_data *private_data; if (info->disassembler_options) { @@ -4373,7 +4414,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) /* PR 10288: Control which instructions will be disassembled. */ if (info->private_data == NULL) { - static arm_feature_set features; + static struct arm_private_data private; if ((info->flags & USER_SPECIFIED_MACHINE_TYPE) == 0) /* If the user did not use the -m command line switch then default to @@ -4399,67 +4440,124 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) /* Compute the architecture bitmask from the machine number. Note: This assumes that the machine number will not change during disassembly.... */ - select_arm_features (info->mach, & features); + select_arm_features (info->mach, & private.features); - info->private_data = & features; + private.has_mapping_symbols = -1; + + info->private_data = & private; } - + + private_data = info->private_data; + /* Decide if our code is going to be little-endian, despite what the function argument might say. */ little_code = ((info->endian_code == BFD_ENDIAN_LITTLE) || little); - /* First check the full symtab for a mapping symbol, even if there - are no usable non-mapping symbols for this address. */ + /* For ELF, consult the symbol table to determine what kind of code + or data we have. */ if (info->symtab_size != 0 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) { bfd_vma addr; - int n; + int n, start; int last_sym = -1; - enum map_type type = MAP_DATA; + enum map_type type = MAP_ARM; - if (pc <= last_mapping_addr) - last_mapping_sym = -1; - is_thumb = (last_type == MAP_THUMB); - found = FALSE; /* Start scanning at the start of the function, or wherever we finished last time. */ - n = info->symtab_pos + 1; - if (n < last_mapping_sym) - n = last_mapping_sym; + start = info->symtab_pos + 1; + if (start < last_mapping_sym) + start = last_mapping_sym; + found = FALSE; - /* Scan up to the location being disassembled. */ - for (; n < info->symtab_size; n++) + /* First, look for mapping symbols. */ + if (private_data->has_mapping_symbols != 0) { - addr = bfd_asymbol_value (info->symtab[n]); - if (addr > pc) - break; - if ((info->section == NULL - || info->section == info->symtab[n]->section) - && get_sym_code_type (info, n, &type)) + /* Scan up to the location being disassembled. */ + for (n = start; 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) + { + /* No mapping symbol found at this address. Look backwards + for a preceeding one. */ + for (n = start - 1; n >= 0; n--) + { + if (get_map_sym_type (info, n, &type)) + { + last_sym = n; + found = TRUE; + break; + } + } + } + + if (found) + private_data->has_mapping_symbols = 1; + + /* 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) { - last_sym = n; + /* Look for mapping symbols, in any section. */ + for (n = 0; n < info->symtab_size; n++) + if (is_mapping_symbol (info, n, &type)) + { + private_data->has_mapping_symbols = 1; + break; + } + if (private_data->has_mapping_symbols == -1) + private_data->has_mapping_symbols = 0; + } + + if (!found && private_data->has_mapping_symbols == 1) + { + type = MAP_DATA; found = TRUE; } } + /* Next search for function symbols to separate ARM from Thumb + in binaries without mapping symbols. */ if (!found) { - n = info->symtab_pos; - if (n < last_mapping_sym - 1) - n = last_mapping_sym - 1; - - /* No mapping symbol found at this address. Look backwards - for a preceeding one. */ - for (; n >= 0; n--) + /* Scan up to the location being disassembled. */ + for (n = start; n < info->symtab_size; n++) { - if ((info->section == NULL - || info->section == info->symtab[n]->section) - && get_sym_code_type (info, n, &type)) + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + break; + if (get_sym_code_type (info, n, &type)) { last_sym = n; found = TRUE; - break; + } + } + + if (!found) + { + /* No mapping symbol found at this address. Look backwards + for a preceeding one. */ + for (n = start - 1; n >= 0; n--) + { + if (get_sym_code_type (info, n, &type)) + { + last_sym = n; + found = TRUE; + break; + } } } } -- 2.30.2