This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
objdump -M for x86
- To: binutils at sources dot redhat dot com
- Subject: objdump -M for x86
- From: Alan Modra <amodra at bigpond dot net dot au>
- Date: Wed, 14 Nov 2001 13:44:29 +1030
Applying to mainline. Note to gdb people: Some backwards compatibility
stuff can be removed when i386-tdep.c and x86-64-tdep are updated to use
the new (old!) print_insn_i386.
binutils/ChangeLog
* doc/binutils.texi (objdump): Document x86 -M options.
include/ChangeLog
* dis-asm.h (print_insn_i386): Declare.
opcodes/ChangeLog
* disassemble.c (disassembler): Call print_insn_i386.
* i386-dis.c (SUFFIX_ALWAYS): Define.
(struct dis_private): Add orig_sizeflag.
(print_insn_i386): Make it a wrapper, calling..
(print_insn): ..The old body of print_insn_i386. Avoid longjmp
warning without using volatile by moving orig_sizeflag to priv,
and removing inbuf. Parse disassembler_options.
(print_insn_i386_att, print_insn_i386_intel): Move initialisation
code to print_insn.
(putop): Remove #ifdef SUFFIX_ALWAYS.
--
Alan Modra
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.8
diff -u -p -r1.8 binutils.texi
--- binutils.texi 2001/09/25 16:44:18 1.8
+++ binutils.texi 2001/11/14 02:29:01
@@ -1569,6 +1569,19 @@ using the switch @option{--disassembler-
useful when attempting to disassemble thumb code produced by other
compilers.
+For the x86, some of the options duplicate functions of the @option{-m}
+switch, but allow finer grained control. Multiple selections from the
+following may be specified as a comma separated string.
+@option{x86_64}, @option{i386} and @option{i8086} select disassembly for
+the given architecture. @option{intel} and @option{att} select between
+intel syntax mode and AT&T syntax mode. @option{addr32},
+@option{addr16}, @option{data32} and @option{data16} specify the default
+address size and operand size. These four options will be overridden if
+@option{x86_64}, @option{i386} or @option{i8086} appear later in the
+option string. Lastly, @option{suffix}, when in AT&T mode,
+instructs the dissassembler to print a mnemonic suffix even when the
+suffix could be inferred by the operands.
+
@item -p
@itemx --private-headers
Print information that is specific to the object file format. The exact
Index: include/dis-asm.h
===================================================================
RCS file: /cvs/src/src/include/dis-asm.h,v
retrieving revision 1.26
diff -u -p -r1.26 dis-asm.h
--- dis-asm.h 2001/11/11 15:45:34 1.26
+++ dis-asm.h 2001/11/14 02:29:34
@@ -177,6 +177,7 @@ typedef int (*disassembler_ftype)
extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info *));
extern int print_insn_i386_att PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_i386_intel PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_ia64 PARAMS ((bfd_vma, disassemble_info*));
Index: opcodes/disassemble.c
===================================================================
RCS file: /cvs/src/src/opcodes/disassemble.c,v
retrieving revision 1.28
diff -u -p -r1.28 disassemble.c
--- disassemble.c 2001/10/30 15:20:14 1.28
+++ disassemble.c 2001/11/14 02:29:52
@@ -150,11 +150,7 @@ disassembler (abfd)
#endif
#ifdef ARCH_i386
case bfd_arch_i386:
- if (bfd_get_mach (abfd) == bfd_mach_i386_i386_intel_syntax
- || bfd_get_mach (abfd) == bfd_mach_x86_64_intel_syntax)
- disassemble = print_insn_i386_intel;
- else
- disassemble = print_insn_i386_att;
+ disassemble = print_insn_i386;
break;
#endif
#ifdef ARCH_i860
Index: opcodes/i386-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/i386-dis.c,v
retrieving revision 1.32
diff -u -p -r1.32 i386-dis.c
--- i386-dis.c 2001/11/13 01:03:55 1.32
+++ i386-dis.c 2001/11/14 02:29:54
@@ -52,7 +52,7 @@ Foundation, Inc., 59 Temple Place - Suit
static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
static void ckprefix PARAMS ((void));
static const char *prefix_name PARAMS ((int, int));
-static int print_insn_i386 PARAMS ((bfd_vma, disassemble_info *));
+static int print_insn PARAMS ((bfd_vma, disassemble_info *));
static void dofloat PARAMS ((int));
static void OP_ST PARAMS ((int, int));
static void OP_STi PARAMS ((int, int));
@@ -101,6 +101,7 @@ struct dis_private {
bfd_byte *max_fetched;
bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start;
+ int orig_sizeflag;
jmp_buf bailout;
};
@@ -298,9 +299,7 @@ fetch_data (info, addr)
#define loop_jcxz_flag NULL, loop_jcxz_mode
/* bits in sizeflag */
-#if 0 /* Leave undefined until someone adds the extra flag to objdump. */
#define SUFFIX_ALWAYS 4
-#endif
#define AFLAG 2
#define DFLAG 1
@@ -442,9 +441,9 @@ struct dis386 {
'N' => print 'n' if instruction has no wait "prefix"
'O' => print 'd', or 'o'
'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
- or suffix_always is true
- print 'q' if rex prefix is present.
- 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always is true
+ . or suffix_always is true. print 'q' if rex prefix is present.
+ 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
+ . is true
'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
'S' => print 'w', 'l' or 'q' if suffix_always is true
'T' => print 'q' in 64bit mode and behave as 'P' otherwise
@@ -1837,25 +1836,17 @@ static char close_char;
static char separator_char;
static char scale_char;
+/* Here for backwards compatibility. When gdb stops using
+ print_insn_i386_att and print_insn_i386_intel these functions can
+ disappear, and print_insn_i386 be merged into print_insn. */
int
print_insn_i386_att (pc, info)
bfd_vma pc;
disassemble_info *info;
{
intel_syntax = 0;
- names64 = att_names64;
- names32 = att_names32;
- names16 = att_names16;
- names8 = att_names8;
- names8rex = att_names8rex;
- names_seg = att_names_seg;
- index16 = att_index16;
- open_char = '(';
- close_char = ')';
- separator_char = ',';
- scale_char = ',';
- return print_insn_i386 (pc, info);
+ return print_insn (pc, info);
}
int
@@ -1864,52 +1855,128 @@ print_insn_i386_intel (pc, info)
disassemble_info *info;
{
intel_syntax = 1;
- names64 = intel_names64;
- names32 = intel_names32;
- names16 = intel_names16;
- names8 = intel_names8;
- names8rex = intel_names8rex;
- names_seg = intel_names_seg;
- index16 = intel_index16;
- open_char = '[';
- close_char = ']';
- separator_char = '+';
- scale_char = '*';
- return print_insn_i386 (pc, info);
+ return print_insn (pc, info);
}
-static int
+int
print_insn_i386 (pc, info)
bfd_vma pc;
disassemble_info *info;
{
+ intel_syntax = -1;
+
+ return print_insn (pc, info);
+}
+
+static int
+print_insn (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
const struct dis386 *dp;
int i;
int two_source_ops;
char *first, *second, *third;
int needcomma;
unsigned char uses_SSE_prefix;
- VOLATILE int sizeflag;
- VOLATILE int orig_sizeflag;
-
+ int sizeflag;
+ const char *p;
struct dis_private priv;
- bfd_byte *inbuf = priv.the_buffer;
mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
|| info->mach == bfd_mach_x86_64);
+ if (intel_syntax == -1)
+ intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
+ || info->mach == bfd_mach_x86_64_intel_syntax);
+
if (info->mach == bfd_mach_i386_i386
|| info->mach == bfd_mach_x86_64
|| info->mach == bfd_mach_i386_i386_intel_syntax
|| info->mach == bfd_mach_x86_64_intel_syntax)
- sizeflag = AFLAG | DFLAG;
+ priv.orig_sizeflag = AFLAG | DFLAG;
else if (info->mach == bfd_mach_i386_i8086)
- sizeflag = 0;
+ priv.orig_sizeflag = 0;
else
abort ();
- orig_sizeflag = sizeflag;
+ for (p = info->disassembler_options; p != NULL; )
+ {
+ if (strncmp (p, "x86_64", 6) == 0)
+ {
+ mode_64bit = 1;
+ priv.orig_sizeflag = AFLAG | DFLAG;
+ }
+ else if (strncmp (p, "i386", 4) == 0)
+ {
+ mode_64bit = 0;
+ priv.orig_sizeflag = AFLAG | DFLAG;
+ }
+ else if (strncmp (p, "i8086", 5) == 0)
+ {
+ mode_64bit = 0;
+ priv.orig_sizeflag = 0;
+ }
+ else if (strncmp (p, "intel", 5) == 0)
+ {
+ intel_syntax = 1;
+ }
+ else if (strncmp (p, "att", 3) == 0)
+ {
+ intel_syntax = 0;
+ }
+ else if (strncmp (p, "addr", 4) == 0)
+ {
+ if (p[4] == '1' && p[5] == '6')
+ priv.orig_sizeflag &= ~AFLAG;
+ else if (p[4] == '3' && p[5] == '2')
+ priv.orig_sizeflag |= AFLAG;
+ }
+ else if (strncmp (p, "data", 4) == 0)
+ {
+ if (p[4] == '1' && p[5] == '6')
+ priv.orig_sizeflag &= ~DFLAG;
+ else if (p[4] == '3' && p[5] == '2')
+ priv.orig_sizeflag |= DFLAG;
+ }
+ else if (strncmp (p, "suffix", 6) == 0)
+ priv.orig_sizeflag |= SUFFIX_ALWAYS;
+
+ p = strchr (p, ',');
+ if (p != NULL)
+ p++;
+ }
+
+ if (intel_syntax)
+ {
+ names64 = intel_names64;
+ names32 = intel_names32;
+ names16 = intel_names16;
+ names8 = intel_names8;
+ names8rex = intel_names8rex;
+ names_seg = intel_names_seg;
+ index16 = intel_index16;
+ open_char = '[';
+ close_char = ']';
+ separator_char = '+';
+ scale_char = '*';
+ }
+ else
+ {
+ names64 = att_names64;
+ names32 = att_names32;
+ names16 = att_names16;
+ names8 = att_names8;
+ names8rex = att_names8rex;
+ names_seg = att_names_seg;
+ index16 = att_index16;
+ open_char = '(';
+ close_char = ')';
+ separator_char = ',';
+ scale_char = ',';
+ }
+
/* The output looks better if we put 7 bytes on a line, since that
puts most long word instructions on a single line. */
info->bytes_per_line = 7;
@@ -1927,26 +1994,26 @@ print_insn_i386 (pc, info)
the_info = info;
start_pc = pc;
- start_codep = inbuf;
- codep = inbuf;
+ start_codep = priv.the_buffer;
+ codep = priv.the_buffer;
if (setjmp (priv.bailout) != 0)
{
const char *name;
/* Getting here means we tried for data but didn't get it. That
- means we have an incomplete instruction of some sort. Just
- print the first byte as a prefix or a .byte pseudo-op. */
- if (codep > inbuf)
+ means we have an incomplete instruction of some sort. Just
+ print the first byte as a prefix or a .byte pseudo-op. */
+ if (codep > priv.the_buffer)
{
- name = prefix_name (inbuf[0], orig_sizeflag);
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name != NULL)
(*info->fprintf_func) (info->stream, "%s", name);
else
{
/* Just print the first byte as a .byte instruction. */
(*info->fprintf_func) (info->stream, ".byte 0x%x",
- (unsigned int) inbuf[0]);
+ (unsigned int) priv.the_buffer[0]);
}
return 1;
@@ -1959,6 +2026,7 @@ print_insn_i386 (pc, info)
ckprefix ();
insn_codep = codep;
+ sizeflag = priv.orig_sizeflag;
FETCH_DATA (info, codep + 1);
two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
@@ -1970,7 +2038,7 @@ print_insn_i386 (pc, info)
/* fwait not followed by floating point instruction. Print the
first prefix, which is probably fwait itself. */
- name = prefix_name (inbuf[0], orig_sizeflag);
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name);
@@ -2116,7 +2184,7 @@ print_insn_i386 (pc, info)
{
const char *name;
- name = prefix_name (inbuf[0], orig_sizeflag);
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s", name);
@@ -2125,7 +2193,7 @@ print_insn_i386 (pc, info)
if (rex & ~rex_used)
{
const char *name;
- name = prefix_name (rex | 0x40, orig_sizeflag);
+ name = prefix_name (rex | 0x40, priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
(*info->fprintf_func) (info->stream, "%s ", name);
@@ -2189,7 +2257,7 @@ print_insn_i386 (pc, info)
(*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+ op_address[op_index[i]]), info);
}
- return codep - inbuf;
+ return codep - priv.the_buffer;
}
static const char *float_mem[] = {
@@ -2548,20 +2616,14 @@ putop (template, sizeflag)
case 'A':
if (intel_syntax)
break;
- if (mod != 3
-#ifdef SUFFIX_ALWAYS
- || (sizeflag & SUFFIX_ALWAYS)
-#endif
- )
+ if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
*obufp++ = 'b';
break;
case 'B':
if (intel_syntax)
break;
-#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'b';
-#endif
break;
case 'E': /* For jcxz/jecxz */
if (sizeflag & AFLAG)
@@ -2571,11 +2633,7 @@ putop (template, sizeflag)
case 'F':
if (intel_syntax)
break;
- if ((prefixes & PREFIX_ADDR)
-#ifdef SUFFIX_ALWAYS
- || (sizeflag & SUFFIX_ALWAYS)
-#endif
- )
+ if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
{
if (sizeflag & AFLAG)
*obufp++ = 'l';
@@ -2602,10 +2660,8 @@ putop (template, sizeflag)
case 'L':
if (intel_syntax)
break;
-#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'l';
-#endif
break;
case 'N':
if ((prefixes & PREFIX_FWAIT) == 0)
@@ -2634,10 +2690,7 @@ putop (template, sizeflag)
break;
if ((prefixes & PREFIX_DATA)
|| (rex & REX_MODE64)
-#ifdef SUFFIX_ALWAYS
- || (sizeflag & SUFFIX_ALWAYS)
-#endif
- )
+ || (sizeflag & SUFFIX_ALWAYS))
{
USED_REX (REX_MODE64);
if (rex & REX_MODE64)
@@ -2665,11 +2718,7 @@ putop (template, sizeflag)
if (intel_syntax)
break;
USED_REX (REX_MODE64);
- if (mod != 3
-#ifdef SUFFIX_ALWAYS
- || (sizeflag & SUFFIX_ALWAYS)
-#endif
- )
+ if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
{
if (rex & REX_MODE64)
*obufp++ = 'q';
@@ -2718,7 +2767,6 @@ putop (template, sizeflag)
case 'S':
if (intel_syntax)
break;
-#ifdef SUFFIX_ALWAYS
if (sizeflag & SUFFIX_ALWAYS)
{
if (rex & REX_MODE64)
@@ -2732,7 +2780,6 @@ putop (template, sizeflag)
used_prefixes |= (prefixes & PREFIX_DATA);
}
}
-#endif
break;
case 'X':
if (prefixes & PREFIX_DATA)