* arm-dis.c (print_insn_coprocessor): Check that a user specified
        ARM architecture supports the matched instruction.
        (print_insn_arm): Likewise.
        (select_arm_features): New function.  Fills in the fields of an
        arm_feature_set structure based on a given arm machine number.
        (print_insn): Initialise an arm_feature_set structure.

        * objdump.c (disassemble_bytes): Set the
        USER_SPECIFIED_MACHINE_TYPE flag in the disassemble_info structure
        if the user has invoked the -m switch.
        * doc/binutils.texi: Document the additional behaviour of
        objdump's -m switch for ARM targets.

        * dis-asm.h (USER_SPECIFIED_MACHINE_TYPE): New value for the flags
        field of struct disassemble_info.

        * gas/arm/align.s: Add labels so that COFF based targets can
        correctly locate THUMB code.
        * gas/arm/copro.d: Do not pass --architecture switch to objdump.
This commit is contained in:
Nick Clifton 2009-06-18 10:31:21 +00:00
parent 470c710ef0
commit 0313a2b8d2
10 changed files with 556 additions and 422 deletions

View file

@ -1,8 +1,18 @@
2009-06-18 Nick Clifton <nickc@redhat.com>
PR 10288
* objdump.c (disassemble_bytes): Set the
USER_SPECIFIED_MACHINE_TYPE flag in the disassemble_info structure
if the user has invoked the -m switch.
* doc/binutils.texi: Document the additional behaviour of
objdump's -m switch for ARM targets.
2009-06-18 Dave Korn <dave.korn.cygwin@gmail.com> 2009-06-18 Dave Korn <dave.korn.cygwin@gmail.com>
Merge cegcc and mingw32ce target name changes from CeGCC project. * configure.in: Merge cegcc and mingw32ce target name changes from
CeGCC project.
2007-12-25 Pedro Alves <pedro_alves@portugalmail.pt> 2007-12-25 Pedro Alves <pedro_alves@portugalmail.pt>
* configure.in: Add arm*-*-cegcc* and arm*-*-mingw32ce* targets. * configure.in: Add arm*-*-cegcc* and arm*-*-mingw32ce* targets.
* configure: Regenerate. * configure: Regenerate.

View file

@ -1801,6 +1801,10 @@ expected to contain instructions.
Like @option{-d}, but disassemble the contents of all sections, not just Like @option{-d}, but disassemble the contents of all sections, not just
those expected to contain instructions. those expected to contain instructions.
If the target is an ARM architecture this switch also has the effect
of forcing the disassembler to decode pieces of data found in code
sections as if they were instructions.
@item --prefix-addresses @item --prefix-addresses
When disassembling, print the complete address on each line. This is When disassembling, print the complete address on each line. This is
the older disassembly format. the older disassembly format.
@ -1884,6 +1888,13 @@ can be useful when disassembling object files which do not describe
architecture information, such as S-records. You can list the available architecture information, such as S-records. You can list the available
architectures with the @option{-i} option. architectures with the @option{-i} option.
If the target is an ARM architecture then this switch has an
additional effect. It restricts the disassembly to only those
instructions supported by the architecture specified by @var{machine}.
If it is necessary to use this switch because the input file does not
contain any architecture information, but it is also desired to
disassemble all the instructions use @option{-marm}.
@item -M @var{options} @item -M @var{options}
@itemx --disassembler-options=@var{options} @itemx --disassembler-options=@var{options}
Pass target specific information to the disassembler. Only supported on Pass target specific information to the disassembler. Only supported on

View file

@ -1526,6 +1526,8 @@ disassemble_bytes (struct disassemble_info * info,
info->bytes_per_line = 0; info->bytes_per_line = 0;
info->bytes_per_chunk = 0; info->bytes_per_chunk = 0;
info->flags = disassemble_all ? DISASSEMBLE_DATA : 0; info->flags = disassemble_all ? DISASSEMBLE_DATA : 0;
if (machine)
info->flags |= USER_SPECIFIED_MACHINE_TYPE;
if (info->disassembler_needs_relocs if (info->disassembler_needs_relocs
&& (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0 && (bfd_get_file_flags (aux->abfd) & EXEC_P) == 0

View file

@ -1,3 +1,10 @@
2009-06-18 Nick Clifton <nickc@redhat.com>
PR 10288
* gas/arm/align.s: Add labels so that COFF based targets can
correctly locate THUMB code.
* gas/arm/copro.d: Do not pass --architecture switch to objdump.
2009-06-15 Nick Clifton <nickc@redhat.com> 2009-06-15 Nick Clifton <nickc@redhat.com>
PR gas/10186 PR gas/10186

View file

@ -1,5 +1,7 @@
.syntax unified .syntax unified
.thumb .thumb
.global foo
foo:
nop nop
mov r1,r2 mov r1,r2
.p2align 4 .p2align 4
@ -7,6 +9,8 @@
.p2align 3 .p2align 3
.arm .arm
.global bar
bar:
nop nop
mov r1,r2 mov r1,r2
.p2align 4 .p2align 4

View file

@ -1,4 +1,4 @@
#objdump: -dr --prefix-addresses --show-raw-insn --architecture=armv5te #objdump: -dr --prefix-addresses --show-raw-insn
#name: ARM CoProcessor Instructions #name: ARM CoProcessor Instructions
#as: -march=armv5te -EL #as: -march=armv5te -EL

View file

@ -1,11 +1,16 @@
2009-06-18 Nick Clifton <nickc@redhat.com>
* dis-asm.h (USER_SPECIFIED_MACHINE_TYPE): New value for the flags
field of struct disassemble_info.
2009-06-09 Ian Lance Taylor <ian@airs.com> 2009-06-09 Ian Lance Taylor <ian@airs.com>
* ansidecl.h (ATTRIBUTE_UNUSED_LABEL): Define for C++. * ansidecl.h (ATTRIBUTE_UNUSED_LABEL): Define for C++.
2009-06-15 Nick Clifton <nickc@redhat.com> 2009-06-15 Nick Clifton <nickc@redhat.com>
* dis-asm.h (struct disassemble_info): New value for the flags * dis-asm.h (DISASSEMBLE_DATA): New value for the flags field of
field. struct disassemble_info.
2009-06-02 Ian Lance Taylor <iant@google.com> 2009-06-02 Ian Lance Taylor <iant@google.com>

View file

@ -113,6 +113,9 @@ typedef struct disassemble_info
#define INSN_HAS_RELOC (1 << 31) #define INSN_HAS_RELOC (1 << 31)
/* Set if the user has requested the disassembly of data as well as code. */ /* Set if the user has requested the disassembly of data as well as code. */
#define DISASSEMBLE_DATA (1 << 30) #define DISASSEMBLE_DATA (1 << 30)
/* Set if the user has specifically set the machine type encoded in the
mach field of this structure. */
#define USER_SPECIFIED_MACHINE_TYPE (1 << 29)
/* Use internally by the target specific disassembly code. */ /* Use internally by the target specific disassembly code. */
void *private_data; void *private_data;

View file

@ -1,3 +1,13 @@
2009-06-18 Nick Clifton <nickc@redhat.com>
PR 10288
* arm-dis.c (print_insn_coprocessor): Check that a user specified
ARM architecture supports the matched instruction.
(print_insn_arm): Likewise.
(select_arm_features): New function. Fills in the fields of an
arm_feature_set structure based on a given arm machine number.
(print_insn): Initialise an arm_feature_set structure.
2009-06-16 Maciej W. Rozycki <macro@linux-mips.org> 2009-06-16 Maciej W. Rozycki <macro@linux-mips.org>
* vax-dis.c (is_function_entry): Return success for synthetic * vax-dis.c (is_function_entry): Return success for synthetic

View file

@ -1635,6 +1635,8 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
for (insn = coprocessor_opcodes; insn->assembler; insn++) for (insn = coprocessor_opcodes; insn->assembler; insn++)
{ {
const char *c;
if (insn->value == FIRST_IWMMXT_INSN if (insn->value == FIRST_IWMMXT_INSN
&& info->mach != bfd_mach_arm_XScale && info->mach != bfd_mach_arm_XScale
&& info->mach != bfd_mach_arm_iWMMXt && info->mach != bfd_mach_arm_iWMMXt
@ -1671,9 +1673,12 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
cond = 16; cond = 16;
} }
} }
if ((given & mask) == value)
{ if ((given & mask) != value)
const char *c; continue;
if ((insn->arch & ((arm_feature_set *) info->private_data)->coproc) == 0)
continue;
for (c = insn->assembler; *c; c++) for (c = insn->assembler; *c; c++)
{ {
@ -1815,6 +1820,7 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
break; break;
} }
break; break;
case 'Q': case 'Q':
switch (given & 0x00408000) switch (given & 0x00408000)
{ {
@ -1832,6 +1838,7 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
break; break;
} }
break; break;
case 'R': case 'R':
switch (given & 0x60) switch (given & 0x60)
{ {
@ -2066,7 +2073,6 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
switch (puw_bits) switch (puw_bits)
{ {
case 1: case 1:
/* fall through */
case 3: case 3:
func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm); func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm);
if (imm4) if (imm4)
@ -2074,11 +2080,8 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
break; break;
case 4: case 4:
/* fall through */
case 5: case 5:
/* fall through */
case 6: case 6:
/* fall through */
case 7: case 7:
func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm); func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm);
if (imm4 > 0) if (imm4 > 0)
@ -2112,7 +2115,6 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
} }
return TRUE; return TRUE;
} }
}
return FALSE; return FALSE;
} }
@ -2221,7 +2223,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
{ {
if ((given & 0xef000000) == 0xef000000) if ((given & 0xef000000) == 0xef000000)
{ {
/* move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */ /* Move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */
unsigned long bit28 = given & (1 << 28); unsigned long bit28 = given & (1 << 28);
given &= 0x00ffffff; given &= 0x00ffffff;
@ -2687,13 +2689,18 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
&& info->mach != bfd_mach_arm_iWMMXt) && info->mach != bfd_mach_arm_iWMMXt)
insn = insn + IWMMXT_INSN_COUNT; insn = insn + IWMMXT_INSN_COUNT;
if ((given & insn->mask) == insn->value if ((given & insn->mask) != insn->value)
continue;
if ((insn->arch & ((arm_feature_set *) info->private_data)->core) == 0)
continue;
/* Special case: an instruction with all bits set in the condition field /* Special case: an instruction with all bits set in the condition field
(0xFnnn_nnnn) is only matched if all those bits are set in insn->mask, (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
or by the catchall at the end of the table. */ or by the catchall at the end of the table. */
&& ((given & 0xF0000000) != 0xF0000000 if ((given & 0xF0000000) != 0xF0000000
|| (insn->mask & 0xF0000000) == 0xF0000000 || (insn->mask & 0xF0000000) == 0xF0000000
|| (insn->mask == 0 && insn->value == 0))) || (insn->mask == 0 && insn->value == 0))
{ {
const char *c; const char *c;
@ -3967,6 +3974,47 @@ get_sym_code_type (struct disassemble_info *info, int n,
return FALSE; return FALSE;
} }
/* 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.
FIXME: This could more efficiently implemented as a constant array,
although it would also be less robust. */
static void
select_arm_features (unsigned long mach,
arm_feature_set * features)
{
#undef ARM_FEATURE
#define ARM_FEATURE(ARCH,CEXT) \
features->core = (ARCH); \
features->coproc = (CEXT) | FPU_FPA; \
return
switch (mach)
{
case bfd_mach_arm_2: ARM_ARCH_V2;
case bfd_mach_arm_2a: ARM_ARCH_V2S;
case bfd_mach_arm_3: ARM_ARCH_V3;
case bfd_mach_arm_3M: ARM_ARCH_V3M;
case bfd_mach_arm_4: ARM_ARCH_V4;
case bfd_mach_arm_4T: ARM_ARCH_V4T;
case bfd_mach_arm_5: ARM_ARCH_V5;
case bfd_mach_arm_5T: ARM_ARCH_V5T;
case bfd_mach_arm_5TE: ARM_ARCH_V5TE;
case bfd_mach_arm_XScale: ARM_ARCH_XSCALE;
case bfd_mach_arm_ep9312: ARM_FEATURE (ARM_AEXT_V4T, ARM_CEXT_MAVERICK | FPU_MAVERICK);
case bfd_mach_arm_iWMMXt: ARM_ARCH_IWMMXT;
case bfd_mach_arm_iWMMXt2: ARM_ARCH_IWMMXT2;
/* If the machine type is unknown allow all
architecture types and all extensions. */
case bfd_mach_arm_unknown: ARM_FEATURE (-1UL, -1UL);
default:
abort ();
}
}
/* NOTE: There are no checks in these routines that /* NOTE: There are no checks in these routines that
the relevant number of data bytes exist. */ the relevant number of data bytes exist. */
@ -3991,6 +4039,40 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
info->disassembler_options = NULL; info->disassembler_options = NULL;
} }
/* PR 10288: Control which instructions will be disassembled. */
if (info->private_data == NULL)
{
static arm_feature_set features;
if ((info->flags & USER_SPECIFIED_MACHINE_TYPE) == 0)
/* If the user did not use the -m command line switch then default to
disassembling all types of ARM instruction.
The info->mach value has to be ignored as this will be based on
the default archictecture for the target and/or hints in the notes
section, but it will never be greater than the current largest arm
machine value (iWMMXt2), which is only equivalent to the V5TE
architecture. ARM architectures have advanced beyond the machine
value encoding, and these newer architectures would be ignored if
the machine value was used.
Ie the -m switch is used to restrict which instructions will be
disassembled. If it is necessary to use the -m switch to tell
objdump that an ARM binary is being disassembled, eg because the
input is a raw binary file, but it is also desired to disassemble
all ARM instructions then use "-marm". This will select the
"unknown" arm architecture which is compatible with any ARM
instruction. */
info->mach = bfd_mach_arm_unknown;
/* 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);
info->private_data = & features;
}
/* Decide if our code is going to be little-endian, despite what the /* Decide if our code is going to be little-endian, despite what the
function argument might say. */ function argument might say. */
little_code = ((info->endian_code == BFD_ENDIAN_LITTLE) || little); little_code = ((info->endian_code == BFD_ENDIAN_LITTLE) || little);
@ -4146,7 +4228,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
info->bytes_per_chunk = 4; info->bytes_per_chunk = 4;
size = 4; size = 4;
status = info->read_memory_func (pc, (bfd_byte *)b, 4, info); status = info->read_memory_func (pc, (bfd_byte *) b, 4, info);
if (little_code) if (little_code)
given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
else else
@ -4176,7 +4258,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
|| (given & 0xF800) == 0xF000 || (given & 0xF800) == 0xF000
|| (given & 0xF800) == 0xE800) || (given & 0xF800) == 0xE800)
{ {
status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info); status = info->read_memory_func (pc + 2, (bfd_byte *) b, 2, info);
if (little_code) if (little_code)
given = (b[0]) | (b[1] << 8) | (given << 16); given = (b[0]) | (b[1] << 8) | (given << 16);
else else
@ -4188,7 +4270,7 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
} }
if (ifthen_address != pc) if (ifthen_address != pc)
find_ifthen_state(pc, info, little_code); find_ifthen_state (pc, info, little_code);
if (ifthen_state) if (ifthen_state)
{ {