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]

Re: Don't segfault disassembling bad rex prefixes


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


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