This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Don't segfault disassembling bad rex prefixes
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sourceware dot org
- Date: Mon, 7 Nov 2005 10:50:23 +1030
- Subject: Re: Don't segfault disassembling bad rex prefixes
- References: <20051101160509.GA29060@nevyn.them.org>
On Tue, Nov 01, 2005 at 11:05:09AM -0500, Daniel Jacobowitz wrote:
> A customer noticed that objdump -D on x86_64 tended to crash on bad data.
> I have a few more testcases to try, but this appears to be the main culprit:
> ckprefix ignores rex followed by any other prefix, including rex. But it
> also prints out the prefix. So if you have a long run of rex prefixes in a
> row, you'll run out the end of obuf.
>
> This isn't an elegant fix, but I didn't feel like bending over backwards to
> use dynamic allocation just to handle an obviously invalid instruction. The
> disassembly is still pretty clear about what's going on:
>
> ffffffff80800ec8: 40 rex
> ffffffff80800ec9: 40 rex
> ffffffff80800eca: 40 rex
> ffffffff80800ecb: 40 rex
> ffffffff80800ecc: 40 rex
> ffffffff80800ecd: 40 rex
> ffffffff80800ece: 40 rex
> ffffffff80800ecf: 40 rex
> ffffffff80800ed0: 40 rex
> ffffffff80800ed1: 40 rex
> ffffffff80800ed2: 40 rex
> ffffffff80800ed3: 40 rex
> ffffffff80800ed4: 41 rexZ
> ffffffff80800ed5: 41 rexZ
> ffffffff80800ed6: 42 rexY
> ffffffff80800ed7: 42 rexY
> ffffffff80800ed8: 42 rexY
> ffffffff80800ed9: 43 rexYZ
> ffffffff80800eda: 43 rexYZ
> ffffffff80800edb: 43 rexYZ
> ffffffff80800edc: 43 43 43 43 43 43 43 rexXY rexYZ cmp %r15d,%ds:(%rax)
> ffffffff80800ee3: 43 43 43 42 43 43 43
> ffffffff80800eea: 43 44 44 44 41 45 45
> ffffffff80800ef1: 3e 46 39 38
I prefer the following.
0: 40 rex
1: 40 rex
2: 40 rex
3: 40 rex
4: 40 rex
5: 40 rex
6: 40 rex
7: 40 rex
8: 40 rex
9: 40 rex
a: 40 rex
b: 40 rex
c: 41 rexZ
d: 41 rexZ
e: 42 rexY
f: 42 rexY
10: 42 rexY
11: 43 rexYZ
12: 43 rexYZ
13: 43 rexYZ
14: 43 rexYZ
15: 43 rexYZ
16: 43 rexYZ
17: 43 rexYZ
18: 43 rexYZ
19: 43 rexYZ
1a: 43 rexYZ
1b: 43 rexYZ
1c: 43 rexYZ
1d: 43 rexYZ
1e: 42 rexY
1f: 43 rexYZ
20: 43 rexYZ
21: 43 rexYZ
22: 43 rexYZ
23: 44 rexX
24: 44 rexX
25: 44 rexX
26: 41 rexZ
27: 45 rexXZ
28: 45 rexXZ
29: 3e 46 39 38 rexXY cmp %r15d,%ds:(%rax)
* i386-dis.c (ckprefix): Handle rex on fwait. Don't print
ignored rex prefixes here.
(print_insn): Instead, handle them similarly to fwait followed
by non-fp insns.
Index: opcodes/i386-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/i386-dis.c,v
retrieving revision 1.68
diff -u -p -r1.68 i386-dis.c
--- opcodes/i386-dis.c 28 Sep 2005 15:34:53 -0000 1.68
+++ opcodes/i386-dis.c 7 Nov 2005 00:03:32 -0000
@@ -1814,7 +1814,7 @@ ckprefix (void)
/* fwait is really an instruction. If there are prefixes
before the fwait, they belong to the fwait, *not* to the
following instruction. */
- if (prefixes)
+ if (prefixes || rex)
{
prefixes |= PREFIX_FWAIT;
codep++;
@@ -1828,8 +1828,8 @@ ckprefix (void)
/* Rex is ignored when followed by another prefix. */
if (rex)
{
- oappend (prefix_name (rex, 0));
- oappend (" ");
+ rex_used = rex;
+ return;
}
rex = newrex;
codep++;
@@ -2117,13 +2117,14 @@ print_insn (bfd_vma pc, disassemble_info
FETCH_DATA (info, codep + 1);
two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
- if ((prefixes & PREFIX_FWAIT)
- && ((*codep < 0xd8) || (*codep > 0xdf)))
+ if (((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ || (rex && rex_used))
{
const char *name;
- /* fwait not followed by floating point instruction. Print the
- first prefix, which is probably fwait itself. */
+ /* fwait not followed by floating point instruction, or rex followed
+ by other prefixes. Print the first prefix. */
name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
if (name == NULL)
name = INTERNAL_DISASSEMBLER_ERROR;
--
Alan Modra
IBM OzLabs - Linux Technology Centre