diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 81 |
1 files changed, 60 insertions, 21 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 7cda14e..b534698 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -47,7 +47,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define UNIXWARE_COMPAT 1 #endif - static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *)); struct dis_private @@ -59,6 +58,27 @@ struct dis_private jmp_buf bailout; }; +/* The opcode for the fwait instruction, which we treat as a prefix + when we can. */ +#define FWAIT_OPCODE (0x9b) + +/* Flags for the prefixes for the current instruction. See below. */ +static int prefixes; + +/* Flags stored in PREFIXES. */ +#define PREFIX_REPZ 1 +#define PREFIX_REPNZ 2 +#define PREFIX_LOCK 4 +#define PREFIX_CS 8 +#define PREFIX_SS 0x10 +#define PREFIX_DS 0x20 +#define PREFIX_ES 0x40 +#define PREFIX_FS 0x80 +#define PREFIX_GS 0x100 +#define PREFIX_DATA 0x200 +#define PREFIX_ADDR 0x400 +#define PREFIX_FWAIT 0x800 + /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) to ADDR (exclusive) are valid. Returns 1 for success, longjmps on error. */ @@ -81,7 +101,16 @@ fetch_data (info, addr) info); if (status != 0) { - (*info->memory_error_func) (status, start, info); + /* If we have found an fwait prefix and an fwait opcode, then + print_insn_i386 will arrange to print an instruction after we + longjmp, and we don't want to print an error message here. + This hack is required because we treat fwait as a prefix, but + since fwait is really an instruction we want to print a + standalone fwait correctly. */ + if ((prefixes & PREFIX_FWAIT) == 0 + || memchr (priv->the_buffer, FWAIT_OPCODE, + priv->max_fetched - priv->the_buffer) == NULL) + (*info->memory_error_func) (status, start, info); longjmp (priv->bailout, 1); } else @@ -1848,21 +1877,6 @@ static const struct dis386 prefix_user_table[][2] = { #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>") -#define PREFIX_REPZ 1 -#define PREFIX_REPNZ 2 -#define PREFIX_LOCK 4 -#define PREFIX_CS 8 -#define PREFIX_SS 0x10 -#define PREFIX_DS 0x20 -#define PREFIX_ES 0x40 -#define PREFIX_FS 0x80 -#define PREFIX_GS 0x100 -#define PREFIX_DATA 0x200 -#define PREFIX_ADDR 0x400 -#define PREFIX_FWAIT 0x800 - -static int prefixes; - static void ckprefix () { @@ -1905,7 +1919,7 @@ ckprefix () case 0x67: prefixes |= PREFIX_ADDR; break; - case 0x9b: + case FWAIT_OPCODE: /* fwait is really an instruction. If there are prefixes before the fwait, they belong to the fwait, *not* to the following instruction. */ @@ -2008,9 +2022,6 @@ print_insn_i386 (pc, info) info->private_data = (PTR) &priv; priv.max_fetched = priv.the_buffer; priv.insn_start = pc; - if (setjmp (priv.bailout) != 0) - /* Error return. */ - return -1; obuf[0] = 0; op1out[0] = 0; @@ -2024,6 +2035,34 @@ print_insn_i386 (pc, info) start_codep = inbuf; codep = inbuf; + if (setjmp (priv.bailout) != 0) + { + /* Getting here means we tried for data but didn't get it. That + means we have an incomplete instruction of some sort. + However, we need to check at least one case here: fwait is a + complete instruction, although we treat it as a prefix. */ + if (prefixes & PREFIX_FWAIT) + { + unsigned char *p; + + p = memchr (inbuf, FWAIT_OPCODE, codep - inbuf); + if (p != NULL) + { + (*info->fprintf_func) (info->stream, "fwait"); + return (p + 1) - inbuf; + } + } + + if (codep > inbuf) + { + /* This will at least let objdump print the bytes followed + by the error message generated by fetch_data. */ + return codep - inbuf; + } + + return -1; + } + ckprefix (); insn_codep = codep; |