forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
@@ -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++)
|
||||
{
|
||||
last_sym = 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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user