This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC PATCH] Fix decoding of superfluous data32 prefix before superfluous rex.W prefix before push.


x86-64 hardware ignores a superfluous data32 (0x66) prefix that precedes a
superfluous rex.W (0x48) prefix that precedes a push-immediate (0x68)
instruction.  But the disassembler gets confused by this:

   0:	48 68 01 02 03 04    	rex.W pushq $0x4030201
   6:	66 48 68 01 02       	data32 pushq $0x201
   b:	03                   	.byte 0x3
   c:	04                   	.byte 0x4

With this change it's at least not confused in the decoding:

   0:	48 68 01 02 03 04    	rex.W pushq $0x4030201
   6:	66 48 68 01 02 03 04 	data32 pushq $0x4030201

That's the most important thing, since it prevents it losing track of the
instruction boundaries.  But I'm not at all sure this is really the best
way to fix that.  The i386-dis.c code is extremely hairy and barely
commented.

As of 2.20, it was not so confused and printed:

   0:	66 48 68 01 02 03 04 	pushq  $0x4030201

So this is a regression of sorts.

What would really be ideal is:

   0:	48 68 01 02 03 04    	rex.W pushq $0x4030201
   6:	66 48 68 01 02 03 04 	data32 rex.W pushq $0x4030201

i.e., print both superfluous prefixes rather than ignoring either.
But it's not at all clear to me how to make that happen.  I also really
have no idea what other cases might be affected by the same sort of problem.

HJ, do you have any insight into all this?


Thanks,
Roland


binutils/testsuite/
2012-08-03  Roland McGrath  <mcgrathr@google.com>

	* binutils-all/x86-64/data32-pushq-imm.s: New file.
	* binutils-all/x86-64/data32-pushq-imm.d: New file.

opcodes/
2012-08-03  Roland McGrath  <mcgrathr@google.com>
	    Victor Khimenko  <khim@google.com>

	* i386-dis.c (OP_sI): In v_mode, REX_W trumps DFLAG.


diff --git a/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.d b/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.d
new file mode 100644
index 0000000..211b2ca
--- /dev/null
+++ b/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.d
@@ -0,0 +1,13 @@
+# This is really a test of the disassembler in objdump, but run_dump_test
+# wants us to specify some other program to run first after assembling.
+#PROG: objcopy
+#as: --64
+#objdump: -d
+
+.*: +file format .*
+
+
+Disassembly of section \.text:
+
+0+ <foo>:
+\s*0:	66 48 68 01 02 03 04 	data32 pushq \$0x4030201
diff --git a/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.s b/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.s
new file mode 100644
index 0000000..6d9d39a
--- /dev/null
+++ b/binutils/testsuite/binutils-all/x86-64/data32-pushq-imm.s
@@ -0,0 +1,4 @@
+.text
+foo:
+	.byte 0x66
+	rex.W pushq $0x04030201
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 685e968..5f2eb78 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -1,6 +1,6 @@
 /* Print i386 instructions for GDB, the GNU debugger.
    Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
    This file is part of the GNU opcodes library.
@@ -13730,7 +13730,8 @@ OP_sI (int bytemode, int sizeflag)
 	}
       break;
     case v_mode:
-      if (sizeflag & DFLAG)
+      /* The operand-size prefix is overridden by a REX prefix.  */
+      if ((sizeflag & DFLAG) || (rex & REX_W))
 	op = get32s ();
       else
 	op = get16 ();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]