Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] Resubmit process record and replay, 8/10
@ 2008-11-17  7:04 teawater
  2008-11-20  5:56 ` Michael Snyder
  0 siblings, 1 reply; 3+ messages in thread
From: teawater @ 2008-11-17  7:04 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 17854 bytes --]

This patch add code to make I386 architecture support process record and replay.

2008-11-16  Hui Zhu  <teawater@gmail.com>

	I386 architecture process record and replay support.

	* i386-tdep.c (PREFIX_REPZ, PREFIX_REPNZ, PREFIX_LOCK,
	PREFIX_DATA, PREFIX_ADDR): New macros. Help decode the I386
	instruction.
	(aflag, dflag, override, modrm, mod, reg, rm, ot,
	i386_record_pc): New variables. Ditto.
	(i386_record_modrm, i386_record_lea_modrm_addr,
	i386_record_lea_modrm): New functions. Ditto.
	(i386_process_record): New function. Parse the instruction in
	address "addr" and record the values of registers and memory
	that will be change in this instruction.
	(i386_gdbarch_init): Set "i386_process_record" to GDBARCH
	"process_record" interface.
	* i386-tdep.h (gdbarch_tdep): New function pointers
	"i386_intx80_record" and "i386_sysenter_record" that point to
	the function can record "intx80" and "sysenter" execute log.

 i386-tdep.c | 2964 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 i386-tdep.h |    3
 2 files changed, 2967 insertions(+)

Following is the diff with the previous patch:
@@ -10,7 +10,7 @@
  /* Register names.  */

  static char *i386_register_names[] =
-@@ -2638,6 +2641,2707 @@ i386_skip_permanent_breakpoint (struct r
+@@ -2638,6 +2641,2965 @@ i386_skip_permanent_breakpoint (struct r
  }


@@ -56,8 +56,12 @@
 +{
 +  if (target_read_memory (i386_record_pc, &modrm, 1))
 +    {
-+      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+			 paddr_nz (i386_record_pc));
++      if (record_debug)
++	{
++	  printf_unfiltered (_
++			     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++			     paddr_nz (i386_record_pc));
++	}
 +      return (-1);
 +    }
 +  i386_record_pc++;
@@ -92,8 +96,12 @@
 +	  havesib = 1;
 +	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	    {
-+	      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				 paddr_nz (i386_record_pc));
++	      if (record_debug)
++		{
++		  printf_unfiltered (_
++				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				     paddr_nz (i386_record_pc));
++		}
 +	      return (-1);
 +	    }
 +	  i386_record_pc++;
@@ -110,8 +118,12 @@
 +	      base = 0xff;
 +	      if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
 +		{
-+		  printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				     paddr_nz (i386_record_pc));
++		  if (record_debug)
++		    {
++		      printf_unfiltered (_
++					 ("Process record: error reading memory at addr 0x%s len = 4.\n"),
++					 paddr_nz (i386_record_pc));
++		    }
 +		  return (-1);
 +		}
 +	      i386_record_pc += 4;
@@ -124,8 +136,12 @@
 +	case 1:
 +	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	    {
-+	      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				 paddr_nz (i386_record_pc));
++	      if (record_debug)
++		{
++		  printf_unfiltered (_
++				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				     paddr_nz (i386_record_pc));
++		}
 +	      return (-1);
 +	    }
 +	  i386_record_pc++;
@@ -134,8 +150,12 @@
 +	case 2:
 +	  if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
 +	    {
-+	      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				 paddr_nz (i386_record_pc));
++	      if (record_debug)
++		{
++		  printf_unfiltered (_
++				     ("Process record: error reading memory at addr 0x%s len = 4.\n"),
++				     paddr_nz (i386_record_pc));
++		}
 +	      return (-1);
 +	    }
 +	  i386_record_pc += 4;
@@ -166,8 +186,12 @@
 +	      if (target_read_memory
 +		  (i386_record_pc, (gdb_byte *) & tmpu16, 2))
 +		{
-+		  printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				     paddr_nz (i386_record_pc));
++		  if (record_debug)
++		    {
++		      printf_unfiltered (_
++					 ("Process record: error reading memory at addr 0x%s len = 2.\n"),
++					 paddr_nz (i386_record_pc));
++		    }
 +		  return (-1);
 +		}
 +	      i386_record_pc += 2;
@@ -183,8 +207,12 @@
 +	case 1:
 +	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	    {
-+	      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				 paddr_nz (i386_record_pc));
++	      if (record_debug)
++		{
++		  printf_unfiltered (_
++				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				     paddr_nz (i386_record_pc));
++		}
 +	      return (-1);
 +	    }
 +	  i386_record_pc++;
@@ -193,8 +221,12 @@
 +	case 2:
 +	  if (target_read_memory (i386_record_pc, (gdb_byte *) & tmpu16, 2))
 +	    {
-+	      printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+				 paddr_nz (i386_record_pc));
++	      if (record_debug)
++		{
++		  printf_unfiltered (_
++				     ("Process record: error reading memory at addr 0x%s len = 2.\n"),
++				     paddr_nz (i386_record_pc));
++		}
 +	      return (-1);
 +	    }
 +	  i386_record_pc += 2;
@@ -276,7 +308,7 @@
 +    {
 +      if (record_debug)
 +	printf_unfiltered (_
-+			   ("Process record ignores the memory change of instruction in
address 0x%s because it can't get the value of the segment
register.\n"),
++			   ("Process record ignores the memory change of instruction at
address 0x%s because it can't get the value of the segment
register.\n"),
 +			   paddr_nz (i386_record_pc));
 +      return (0);
 +    }
@@ -322,8 +354,12 @@
 +    {
 +      if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	{
-+	  printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+			     paddr_nz (i386_record_pc));
++	  if (record_debug)
++	    {
++	      printf_unfiltered (_
++				 ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				 paddr_nz (i386_record_pc));
++	    }
 +	  return (-1);
 +	}
 +      i386_record_pc++;
@@ -385,8 +421,12 @@
 +    case 0x0f:
 +      if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	{
-+	  printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+			     paddr_nz (i386_record_pc));
++	  if (record_debug)
++	    {
++	      printf_unfiltered (_
++				 ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				 paddr_nz (i386_record_pc));
++	    }
 +	  return (-1);
 +	}
 +      i386_record_pc++;
@@ -395,14 +435,54 @@
 +      break;
 +
 +      /* arith & logic */
-+    case 0x00 ... 0x05:
-+    case 0x08 ... 0x0d:
-+    case 0x10 ... 0x15:
-+    case 0x18 ... 0x1d:
-+    case 0x20 ... 0x25:
-+    case 0x28 ... 0x2d:
-+    case 0x30 ... 0x35:
-+    case 0x38 ... 0x3d:
++    case 0x00:
++    case 0x01:
++    case 0x02:
++    case 0x03:
++    case 0x04:
++    case 0x05:
++    case 0x08:
++    case 0x09:
++    case 0x0a:
++    case 0x0b:
++    case 0x0c:
++    case 0x0d:
++    case 0x10:
++    case 0x11:
++    case 0x12:
++    case 0x13:
++    case 0x14:
++    case 0x15:
++    case 0x18:
++    case 0x19:
++    case 0x1a:
++    case 0x1b:
++    case 0x1c:
++    case 0x1d:
++    case 0x20:
++    case 0x21:
++    case 0x22:
++    case 0x23:
++    case 0x24:
++    case 0x25:
++    case 0x28:
++    case 0x29:
++    case 0x2a:
++    case 0x2b:
++    case 0x2c:
++    case 0x2d:
++    case 0x30:
++    case 0x31:
++    case 0x32:
++    case 0x33:
++    case 0x34:
++    case 0x35:
++    case 0x38:
++    case 0x39:
++    case 0x3a:
++    case 0x3b:
++    case 0x3c:
++    case 0x3d:
 +      if (((opcode >> 3) & 7) != OP_CMPL)
 +	{
 +	  if ((opcode & 1) == 0)
@@ -472,7 +552,10 @@
 +      break;
 +
 +      /* GRP1 */
-+    case 0x80 ... 0x83:
++    case 0x80:
++    case 0x81:
++    case 0x82:
++    case 0x83:
 +      if (i386_record_modrm ())
 +	{
 +	  return (-1);
@@ -511,9 +594,23 @@
 +      break;
 +
 +      /* inv */
-+    case 0x40 ... 0x47:
++    case 0x40:
++    case 0x41:
++    case 0x42:
++    case 0x43:
++    case 0x44:
++    case 0x45:
++    case 0x46:
++    case 0x47:
 +      /* dec */
-+    case 0x48 ... 0x4f:
++    case 0x48:
++    case 0x49:
++    case 0x4a:
++    case 0x4b:
++    case 0x4c:
++    case 0x4d:
++    case 0x4e:
++    case 0x4f:
 +      if (record_arch_list_add_reg (opcode & 7))
 +	{
 +	  return (-1);
@@ -913,7 +1010,14 @@
 +      break;
 +
 +      /* push */
-+    case 0x50 ... 0x57:
++    case 0x50:
++    case 0x51:
++    case 0x52:
++    case 0x53:
++    case 0x54:
++    case 0x55:
++    case 0x56:
++    case 0x57:
 +    case 0x68:
 +    case 0x6a:
 +      /* push es */
@@ -942,7 +1046,14 @@
 +      break;
 +
 +      /* pop */
-+    case 0x58 ... 0x5f:
++    case 0x58:
++    case 0x59:
++    case 0x5a:
++    case 0x5b:
++    case 0x5c:
++    case 0x5d:
++    case 0x5e:
++    case 0x5f:
 +      ot = dflag + OT_WORD;
 +      if (record_arch_list_add_reg (I386_ESP_REGNUM))
 +	{
@@ -1315,7 +1426,7 @@
 +	  {
 +	    if (record_debug)
 +	      printf_unfiltered (_
-+				 ("Process record ignores the memory change of instruction in
address 0x%s because it can't get the value of the segment
register.\n"),
++				 ("Process record ignores the memory change of instruction at
address 0x%s because it can't get the value of the segment
register.\n"),
 +				 paddr_nz (i386_record_pc));
 +	  }
 +	else
@@ -1333,9 +1444,12 @@
 +		if (target_read_memory
 +		    (i386_record_pc, (gdb_byte *) & addr, 4))
 +		  {
-+		    printf_unfiltered (_
-+				       ("Process record: read memeory 0x%s error.\n"),
-+				       paddr_nz (i386_record_pc));
++		    if (record_debug)
++		      {
++			printf_unfiltered (_
++					   ("Process record: error reading memory at addr 0x%s len = 4.\n"),
++					   paddr_nz (i386_record_pc));
++		      }
 +		    return (-1);
 +		  }
 +		i386_record_pc += 4;
@@ -1345,9 +1459,12 @@
 +		if (target_read_memory
 +		    (i386_record_pc, (gdb_byte *) & tmpu16, 4))
 +		  {
-+		    printf_unfiltered (_
-+				       ("Process record: read memeory 0x%s error.\n"),
-+				       paddr_nz (i386_record_pc));
++		    if (record_debug)
++		      {
++			printf_unfiltered (_
++					   ("Process record: error reading memory at addr 0x%s len = 4.\n"),
++					   paddr_nz (i386_record_pc));
++		      }
 +		    return (-1);
 +		  }
 +		i386_record_pc += 2;
@@ -1362,7 +1479,14 @@
 +      break;
 +
 +      /* mov R, Ib */
-+    case 0xb0 ... 0xb7:
++    case 0xb0:
++    case 0xb1:
++    case 0xb2:
++    case 0xb3:
++    case 0xb4:
++    case 0xb5:
++    case 0xb6:
++    case 0xb7:
 +      if (record_arch_list_add_reg ((opcode & 0x7) & 0x3))
 +	{
 +	  return (-1);
@@ -1370,7 +1494,14 @@
 +      break;
 +
 +      /* mov R, Iv */
-+    case 0xb8 ... 0xbf:
++    case 0xb8:
++    case 0xb9:
++    case 0xba:
++    case 0xbb:
++    case 0xbc:
++    case 0xbd:
++    case 0xbe:
++    case 0xbf:
 +      if (record_arch_list_add_reg (opcode & 0x7))
 +	{
 +	  return (-1);
@@ -1378,7 +1509,13 @@
 +      break;
 +
 +      /* xchg R, EAX */
-+    case 0x91 ... 0x97:
++    case 0x91:
++    case 0x92:
++    case 0x93:
++    case 0x94:
++    case 0x95:
++    case 0x96:
++    case 0x97:
 +      if (record_arch_list_add_reg (I386_EAX_REGNUM))
 +	{
 +	  return (-1);
@@ -1569,7 +1706,14 @@
 +
 +      /* floats */
 +      /* It just record the memory change of instrcution. */
-+    case 0xd8 ... 0xdf:
++    case 0xd8:
++    case 0xd9:
++    case 0xda:
++    case 0xdb:
++    case 0xdc:
++    case 0xdd:
++    case 0xde:
++    case 0xdf:
 +      if (i386_record_modrm ())
 +	{
 +	  return (-1);
@@ -1586,17 +1730,54 @@
 +	    }
 +	  switch (reg)
 +	    {
-+	    case 0x00 ... 0x07:
-+	    case 0x10 ... 0x17:
-+	    case 0x20 ... 0x27:
-+	    case 0x30 ... 0x37:
++	    case 0x00:
++	    case 0x01:
++	    case 0x02:
++	    case 0x03:
++	    case 0x04:
++	    case 0x05:
++	    case 0x06:
++	    case 0x07:
++	    case 0x10:
++	    case 0x11:
++	    case 0x12:
++	    case 0x13:
++	    case 0x14:
++	    case 0x15:
++	    case 0x16:
++	    case 0x17:
++	    case 0x20:
++	    case 0x21:
++	    case 0x22:
++	    case 0x23:
++	    case 0x24:
++	    case 0x25:
++	    case 0x26:
++	    case 0x27:
++	    case 0x30:
++	    case 0x31:
++	    case 0x32:
++	    case 0x33:
++	    case 0x34:
++	    case 0x35:
++	    case 0x36:
++	    case 0x37:
 +	      break;
 +	    case 0x08:
 +	    case 0x0a:
 +	    case 0x0b:
-+	    case 0x18 ... 0x1b:
-+	    case 0x28 ... 0x2b:
-+	    case 0x38 ... 0x3b:
++	    case 0x18:
++	    case 0x19:
++	    case 0x1a:
++	    case 0x1b:
++	    case 0x28:
++	    case 0x29:
++	    case 0x2a:
++	    case 0x2b:
++	    case 0x38:
++	    case 0x39:
++	    case 0x3a:
++	    case 0x3b:
 +	      switch (reg & 7)
 +		{
 +		case 0:
@@ -1767,7 +1948,7 @@
 +	    /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */
 +            if (record_debug)
 +	      printf_unfiltered (_
-+			         ("Process record ignores the memory change of
instruction in address 0x%s because it can't get the value of the
segment register.\n"),
++			         ("Process record ignores the memory change of
instruction at address 0x%s because it can't get the value of the
segment register.\n"),
 +			   paddr_nz (i386_record_pc));
 +	  }
 +
@@ -1988,13 +2169,58 @@
 +      /* jmp Jb */
 +    case 0xeb:
 +      /* jcc Jb */
-+    case 0x70 ... 0x7f:
++    case 0x70:
++    case 0x71:
++    case 0x72:
++    case 0x73:
++    case 0x74:
++    case 0x75:
++    case 0x76:
++    case 0x77:
++    case 0x78:
++    case 0x79:
++    case 0x7a:
++    case 0x7b:
++    case 0x7c:
++    case 0x7d:
++    case 0x7e:
++    case 0x7f:
 +      /* jcc Jv */
-+    case 0x0f80 ... 0x0f8f:
++    case 0x0f80:
++    case 0x0f81:
++    case 0x0f82:
++    case 0x0f83:
++    case 0x0f84:
++    case 0x0f85:
++    case 0x0f86:
++    case 0x0f87:
++    case 0x0f88:
++    case 0x0f89:
++    case 0x0f8a:
++    case 0x0f8b:
++    case 0x0f8c:
++    case 0x0f8d:
++    case 0x0f8e:
++    case 0x0f8f:
 +      break;
 +
 +      /* setcc Gv */
-+    case 0x0f90 ... 0x0f9f:
++    case 0x0f90:
++    case 0x0f91:
++    case 0x0f92:
++    case 0x0f93:
++    case 0x0f94:
++    case 0x0f95:
++    case 0x0f96:
++    case 0x0f97:
++    case 0x0f98:
++    case 0x0f99:
++    case 0x0f9a:
++    case 0x0f9b:
++    case 0x0f9c:
++    case 0x0f9d:
++    case 0x0f9e:
++    case 0x0f9f:
 +      ot = OT_BYTE;
 +      if (i386_record_modrm ())
 +	{
@@ -2017,7 +2243,22 @@
 +      break;
 +
 +      /* cmov Gv, Ev */
-+    case 0x0f40 ... 0x0f4f:
++    case 0x0f40:
++    case 0x0f41:
++    case 0x0f42:
++    case 0x0f43:
++    case 0x0f44:
++    case 0x0f45:
++    case 0x0f46:
++    case 0x0f47:
++    case 0x0f48:
++    case 0x0f49:
++    case 0x0f4a:
++    case 0x0f4b:
++    case 0x0f4c:
++    case 0x0f4d:
++    case 0x0f4e:
++    case 0x0f4f:
 +      if (i386_record_modrm ())
 +	{
 +	  return (-1);
@@ -2189,7 +2430,7 @@
 +      /* XXX */
 +    case 0x9b:
 +      printf_unfiltered (_
-+			 ("Process record don't support instruction fwait.\n"));
++			 ("Process record doesn't support instruction fwait.\n"));
 +      i386_record_pc -= 1;
 +      goto no_support;
 +      break;
@@ -2210,8 +2451,12 @@
 +	int ret;
 +	if (target_read_memory (i386_record_pc, &tmpu8, 1))
 +	  {
-+	    printf_unfiltered (_("Process record: read memeory 0x%s error.\n"),
-+			       paddr_nz (i386_record_pc));
++	    if (record_debug)
++	      {
++		printf_unfiltered (_
++				   ("Process record: error reading memory at addr 0x%s len = 1.\n"),
++				   paddr_nz (i386_record_pc));
++	      }
 +	    return (-1);
 +	  }
 +	i386_record_pc++;
@@ -2256,7 +2501,14 @@
 +      break;
 +
 +      /* bswap reg */
-+    case 0x0fc8 ... 0x0fcf:
++    case 0x0fc8:
++    case 0x0fc9:
++    case 0x0fca:
++    case 0x0fcb:
++    case 0x0fcc:
++    case 0x0fcd:
++    case 0x0fce:
++    case 0x0fcf:
 +      if (record_arch_list_add_reg (opcode & 7))
 +	{
 +	  return (-1);
@@ -2440,7 +2692,7 @@
 +	      {
 +		if (record_debug)
 +		  printf_unfiltered (_
-+				     ("Process record ignores the memory change of instruction
in address 0x%s because it can't get the value of the segment
register.\n"),
++				     ("Process record ignores the memory change of instruction
at address 0x%s because it can't get the value of the segment
register.\n"),
 +				     paddr_nz (i386_record_pc));
 +error("3");
 +	      }
@@ -2491,7 +2743,7 @@
 +		{
 +		  if (record_debug)
 +		    printf_unfiltered (_
-+				       ("Process record ignores the memory change of instruction
in address 0x%s because it can't get the value of the segment
register.\n"),
++				       ("Process record ignores the memory change of instruction
at address 0x%s because it can't get the value of the segment
register.\n"),
 +				       paddr_nz (i386_record_pc));
 +		}
 +	      else
@@ -2607,7 +2859,13 @@
 +      break;
 +
 +      /* nop (multi byte) */
-+    case 0x0f19 ... 0x0f1f:
++    case 0x0f19:
++    case 0x0f1a:
++    case 0x0f1b:
++    case 0x0f1c:
++    case 0x0f1d:
++    case 0x0f1e:
++    case 0x0f1f:
 +      break;
 +
 +      /* mov reg, crN */
@@ -2718,7 +2976,7 @@
  \f
  static struct gdbarch *
  i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-@@ -2829,6 +5533,8 @@ i386_gdbarch_init (struct gdbarch_info i
+@@ -2829,6 +5791,8 @@ i386_gdbarch_init (struct gdbarch_info i
    set_gdbarch_skip_permanent_breakpoint (gdbarch,
  					 i386_skip_permanent_breakpoint);

[-- Attachment #2: 8-i386-tdep.txt --]
[-- Type: text/plain, Size: 53802 bytes --]

--- a/i386-tdep.c
+++ b/i386-tdep.c
@@ -49,6 +49,9 @@
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
+#include "record.h"
+#include <stdint.h>
+
 /* Register names.  */
 
 static char *i386_register_names[] =
@@ -2638,6 +2641,2965 @@ i386_skip_permanent_breakpoint (struct r
 }
 
 
+#define PREFIX_REPZ	0x01
+#define PREFIX_REPNZ	0x02
+#define PREFIX_LOCK	0x04
+#define PREFIX_DATA	0x08
+#define PREFIX_ADDR	0x10
+
+/* operand size */
+enum
+{
+  OT_BYTE = 0,
+  OT_WORD,
+  OT_LONG,
+};
+
+/* i386 arith/logic operations */
+enum
+{
+  OP_ADDL,
+  OP_ORL,
+  OP_ADCL,
+  OP_SBBL,
+  OP_ANDL,
+  OP_SUBL,
+  OP_XORL,
+  OP_CMPL,
+};
+
+static int aflag = 1;
+static int dflag = 1;
+static int override = 0;
+static uint8_t modrm;
+static uint8_t mod, reg, rm;
+static int ot;
+static CORE_ADDR i386_record_pc;
+
+/* Parse "modrm" part in current memory address that i386_record_pc point to.
+   Return -1 if something wrong. */
+static int
+i386_record_modrm (void)
+{
+  if (target_read_memory (i386_record_pc, &modrm, 1))
+    {
+      if (record_debug)
+	{
+	  printf_unfiltered (_
+			     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+			     paddr_nz (i386_record_pc));
+	}
+      return (-1);
+    }
+  i386_record_pc++;
+  mod = (modrm >> 6) & 3;
+  reg = (modrm >> 3) & 7;
+  rm = modrm & 7;
+
+  return (0);
+}
+
+/* Get the memory address that current instruction  write to and set it to
+   the argument "addr".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm_addr (uint32_t * addr)
+{
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+
+  *addr = 0;
+  if (aflag)
+    {
+      /* 32 bits */
+      int havesib = 0;
+      uint8_t scale = 0;
+      uint8_t index = 0;
+      uint8_t base = rm;
+
+      if (base == 4)
+	{
+	  havesib = 1;
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      if (record_debug)
+		{
+		  printf_unfiltered (_
+				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				     paddr_nz (i386_record_pc));
+		}
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  scale = (tmpu8 >> 6) & 3;
+	  index = ((tmpu8 >> 3) & 7);
+	  base = (tmpu8 & 7);
+	}
+
+      switch (mod)
+	{
+	case 0:
+	  if ((base & 7) == 5)
+	    {
+	      base = 0xff;
+	      if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+		{
+		  if (record_debug)
+		    {
+		      printf_unfiltered (_
+					 ("Process record: error reading memory at addr 0x%s len = 4.\n"),
+					 paddr_nz (i386_record_pc));
+		    }
+		  return (-1);
+		}
+	      i386_record_pc += 4;
+	    }
+	  else
+	    {
+	      *addr = 0;
+	    }
+	  break;
+	case 1:
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      if (record_debug)
+		{
+		  printf_unfiltered (_
+				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				     paddr_nz (i386_record_pc));
+		}
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  *addr = (int8_t) tmpu8;
+	  break;
+	case 2:
+	  if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+	    {
+	      if (record_debug)
+		{
+		  printf_unfiltered (_
+				     ("Process record: error reading memory at addr 0x%s len = 4.\n"),
+				     paddr_nz (i386_record_pc));
+		}
+	      return (-1);
+	    }
+	  i386_record_pc += 4;
+	  break;
+	}
+
+      if (base != 0xff)
+	{
+	  regcache_raw_read (record_regcache, base, (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	}
+
+      /* XXX: index == 4 is always invalid */
+      if (havesib && (index != 4 || scale != 0))
+	{
+	  regcache_raw_read (record_regcache, index, (gdb_byte *) & tmpu32);
+	  *addr += tmpu32 << scale;
+	}
+    }
+  else
+    {
+      /* 16 bits */
+      switch (mod)
+	{
+	case 0:
+	  if (rm == 6)
+	    {
+	      if (target_read_memory
+		  (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+		{
+		  if (record_debug)
+		    {
+		      printf_unfiltered (_
+					 ("Process record: error reading memory at addr 0x%s len = 2.\n"),
+					 paddr_nz (i386_record_pc));
+		    }
+		  return (-1);
+		}
+	      i386_record_pc += 2;
+	      *addr = (int16_t) tmpu16;
+	      rm = 0;
+	      goto no_rm;
+	    }
+	  else
+	    {
+	      *addr = 0;
+	    }
+	  break;
+	case 1:
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      if (record_debug)
+		{
+		  printf_unfiltered (_
+				     ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				     paddr_nz (i386_record_pc));
+		}
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  *addr = (int8_t) tmpu8;
+	  break;
+	case 2:
+	  if (target_read_memory (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+	    {
+	      if (record_debug)
+		{
+		  printf_unfiltered (_
+				     ("Process record: error reading memory at addr 0x%s len = 2.\n"),
+				     paddr_nz (i386_record_pc));
+		}
+	      return (-1);
+	    }
+	  i386_record_pc += 2;
+	  *addr = (int16_t) tmpu16;
+	  break;
+	}
+
+      switch (rm)
+	{
+	case 0:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 1:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 2:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 3:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 4:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 5:
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 6:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 7:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	}
+      *addr &= 0xffff;
+    }
+
+no_rm:
+  return (0);
+}
+
+/* Record the value of the memory that willbe changed in current instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm (void)
+{
+  uint32_t addr;
+
+  if (override)
+    {
+      if (record_debug)
+	printf_unfiltered (_
+			   ("Process record ignores the memory change of instruction at address 0x%s because it can't get the value of the segment register.\n"),
+			   paddr_nz (i386_record_pc));
+      return (0);
+    }
+
+  if (i386_record_lea_modrm_addr (&addr))
+    {
+      return (-1);
+    }
+
+  if (record_arch_list_add_mem (addr, 1 << ot))
+    {
+      return (-1);
+    }
+
+  return (0);
+}
+
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_process_record (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  int prefixes = 0;
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+  uint32_t opcode;
+
+  i386_record_pc = addr;
+  aflag = 1;
+  dflag = 1;
+  override = 0;
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Process record: i386_record pc = 0x%s\n",
+			  paddr_nz (i386_record_pc));
+    }
+
+  /* prefixes */
+  while (1)
+    {
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	{
+	  if (record_debug)
+	    {
+	      printf_unfiltered (_
+				 ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				 paddr_nz (i386_record_pc));
+	    }
+	  return (-1);
+	}
+      i386_record_pc++;
+      switch (tmpu8)
+	{
+	case 0xf3:
+	  prefixes |= PREFIX_REPZ;
+	  break;
+	case 0xf2:
+	  prefixes |= PREFIX_REPNZ;
+	  break;
+	case 0xf0:
+	  prefixes |= PREFIX_LOCK;
+	  break;
+	case 0x2e:
+	  override = I386_CS_REGNUM;
+	  break;
+	case 0x36:
+	  override = I386_SS_REGNUM;
+	  break;
+	case 0x3e:
+	  override = I386_DS_REGNUM;
+	  break;
+	case 0x26:
+	  override = I386_ES_REGNUM;
+	  break;
+	case 0x64:
+	  override = I386_FS_REGNUM;
+	  break;
+	case 0x65:
+	  override = I386_GS_REGNUM;
+	  break;
+	case 0x66:
+	  prefixes |= PREFIX_DATA;
+	  break;
+	case 0x67:
+	  prefixes |= PREFIX_ADDR;
+	  break;
+	default:
+	  goto out_prefixes;
+	  break;
+	}
+    }
+out_prefixes:
+  if (prefixes & PREFIX_DATA)
+    {
+      dflag ^= 1;
+    }
+  if (prefixes & PREFIX_ADDR)
+    {
+      aflag ^= 1;
+    }
+
+  /* now check op code */
+  opcode = (uint32_t) tmpu8;
+reswitch:
+  switch (opcode)
+    {
+    case 0x0f:
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	{
+	  if (record_debug)
+	    {
+	      printf_unfiltered (_
+				 ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				 paddr_nz (i386_record_pc));
+	    }
+	  return (-1);
+	}
+      i386_record_pc++;
+      opcode = (uint16_t) tmpu8 | 0x0f00;
+      goto reswitch;
+      break;
+
+      /* arith & logic */
+    case 0x00:
+    case 0x01:
+    case 0x02:
+    case 0x03:
+    case 0x04:
+    case 0x05:
+    case 0x08:
+    case 0x09:
+    case 0x0a:
+    case 0x0b:
+    case 0x0c:
+    case 0x0d:
+    case 0x10:
+    case 0x11:
+    case 0x12:
+    case 0x13:
+    case 0x14:
+    case 0x15:
+    case 0x18:
+    case 0x19:
+    case 0x1a:
+    case 0x1b:
+    case 0x1c:
+    case 0x1d:
+    case 0x20:
+    case 0x21:
+    case 0x22:
+    case 0x23:
+    case 0x24:
+    case 0x25:
+    case 0x28:
+    case 0x29:
+    case 0x2a:
+    case 0x2b:
+    case 0x2c:
+    case 0x2d:
+    case 0x30:
+    case 0x31:
+    case 0x32:
+    case 0x33:
+    case 0x34:
+    case 0x35:
+    case 0x38:
+    case 0x39:
+    case 0x3a:
+    case 0x3b:
+    case 0x3c:
+    case 0x3d:
+      if (((opcode >> 3) & 7) != OP_CMPL)
+	{
+	  if ((opcode & 1) == 0)
+	    {
+	      ot = OT_BYTE;
+	    }
+	  else
+	    {
+	      ot = dflag + OT_WORD;
+	    }
+
+	  switch ((opcode >> 1) & 3)
+	    {
+	      /* OP Ev, Gv */
+	    case 0:
+	      if (i386_record_modrm ())
+		{
+		  return (-1);
+		}
+	      if (mod != 3)
+		{
+		  if (i386_record_lea_modrm ())
+		    {
+		      return (-1);
+		    }
+		}
+	      else
+		{
+		  if (ot == OT_BYTE)
+		    {
+		      rm &= 0x3;
+		    }
+		  if (record_arch_list_add_reg (rm))
+		    {
+		      return (-1);
+		    }
+		}
+	      break;
+	      /* OP Gv, Ev */
+	    case 1:
+	      if (i386_record_modrm ())
+		{
+		  return (-1);
+		}
+	      if (ot == OT_BYTE)
+		{
+		  reg &= 0x3;
+		}
+	      if (record_arch_list_add_reg (reg))
+		{
+		  return (-1);
+		}
+	      break;
+	      /* OP A, Iv */
+	    case 2:
+	      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+		{
+		  return (-1);
+		}
+	      break;
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* GRP1 */
+    case 0x80:
+    case 0x81:
+    case 0x82:
+    case 0x83:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (reg != OP_CMPL)
+	{
+	  if ((opcode & 1) == 0)
+	    {
+	      ot = OT_BYTE;
+	    }
+	  else
+	    {
+	      ot = dflag + OT_WORD;
+	    }
+
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* inv */
+    case 0x40:
+    case 0x41:
+    case 0x42:
+    case 0x43:
+    case 0x44:
+    case 0x45:
+    case 0x46:
+    case 0x47:
+      /* dec */
+    case 0x48:
+    case 0x49:
+    case 0x4a:
+    case 0x4b:
+    case 0x4c:
+    case 0x4d:
+    case 0x4e:
+    case 0x4f:
+      if (record_arch_list_add_reg (opcode & 7))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* GRP3 */
+    case 0xf6:
+    case 0xf7:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      switch (reg)
+	{
+	  /* test */
+	case 0:
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* not */
+	case 2:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* neg */
+	case 3:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* mul */
+	case 4:
+	  /* imul */
+	case 5:
+	  /* div */
+	case 6:
+	  /* idiv */
+	case 7:
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (ot != OT_BYTE)
+	    {
+	      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* GRP4 */
+    case 0xfe:
+      /* GRP5 */
+    case 0xff:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg >= 2 && opcode == 0xfe)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      switch (reg)
+	{
+	  /* inc */
+	case 0:
+	  /* dec */
+	case 1:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* call */
+	case 2:
+	  /* push */
+	case 6:
+	  if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem
+	      ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* lcall */
+	case 3:
+	  if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (record_arch_list_add_reg (I386_CS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem
+	      ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* jmp */
+	case 4:
+	  /* ljmp */
+	case 5:
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* test */
+    case 0x84:
+    case 0x85:
+    case 0xa8:
+    case 0xa9:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* CWDE/CBW */
+    case 0x98:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* CDQ/CWD */
+    case 0x99:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* imul */
+    case 0x0faf:
+    case 0x69:
+    case 0x6b:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xadd */
+    case 0x0fc0:
+    case 0x0fc1:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpxchg */
+    case 0x0fb0:
+    case 0x0fb1:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpxchg8b */
+    case 0x0fc7:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (i386_record_lea_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* push */
+    case 0x50:
+    case 0x51:
+    case 0x52:
+    case 0x53:
+    case 0x54:
+    case 0x55:
+    case 0x56:
+    case 0x57:
+    case 0x68:
+    case 0x6a:
+      /* push es */
+    case 0x06:
+      /* push cs */
+    case 0x0e:
+      /* push ss */
+    case 0x16:
+      /* push ds */
+    case 0x1e:
+      /* push fs */
+    case 0x0fa0:
+      /* push gs */
+    case 0x0fa8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop */
+    case 0x58:
+    case 0x59:
+    case 0x5a:
+    case 0x5b:
+    case 0x5c:
+    case 0x5d:
+    case 0x5e:
+    case 0x5f:
+      ot = dflag + OT_WORD;
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (ot == OT_BYTE)
+	{
+	  opcode &= 0x3;
+	}
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pusha */
+    case 0x60:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 4)), (1 << (dflag + 4))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* popa */
+    case 0x61:
+      for (tmpu8 = I386_EAX_REGNUM; tmpu8 <= I386_EDI_REGNUM; tmpu8++)
+	{
+	  if (record_arch_list_add_reg (tmpu8))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* pop */
+    case 0x8f:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* enter */
+    case 0xc8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* leave */
+    case 0xc9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop es */
+    case 0x07:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ES_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop ss */
+    case 0x17:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_SS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop ds */
+    case 0x1f:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_DS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop fs */
+    case 0x0fa1:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_FS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop gs */
+    case 0x0fa9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_GS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov */
+    case 0x88:
+    case 0x89:
+    case 0xc6:
+    case 0xc7:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod != 3)
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+      /* mov */
+    case 0x8a:
+    case 0x8b:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov seg */
+    case 0x8e:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      switch (reg)
+	{
+	case 0:
+	  tmpu8 = I386_ES_REGNUM;
+	  break;
+	case 2:
+	  tmpu8 = I386_SS_REGNUM;
+	  break;
+	case 3:
+	  tmpu8 = I386_DS_REGNUM;
+	  break;
+	case 4:
+	  tmpu8 = I386_FS_REGNUM;
+	  break;
+	case 5:
+	  tmpu8 = I386_GS_REGNUM;
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      if (record_arch_list_add_reg (tmpu8))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov seg */
+    case 0x8c:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg > 5)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  ot = OT_WORD;
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* movzbS */
+    case 0x0fb6:
+      /* movzwS */
+    case 0x0fb7:
+      /* movsbS */
+    case 0x0fbe:
+      /* movswS */
+    case 0x0fbf:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lea */
+    case 0x8d:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      ot = dflag;
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov EAX */
+    case 0xa0:
+    case 0xa1:
+      /* xlat */
+    case 0xd7:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov EAX */
+    case 0xa2:
+    case 0xa3:
+      {
+	uint32_t addr;
+
+	if (override)
+	  {
+	    if (record_debug)
+	      printf_unfiltered (_
+				 ("Process record ignores the memory change of instruction at address 0x%s because it can't get the value of the segment register.\n"),
+				 paddr_nz (i386_record_pc));
+	  }
+	else
+	  {
+	    if ((opcode & 1) == 0)
+	      {
+		ot = OT_BYTE;
+	      }
+	    else
+	      {
+		ot = dflag + OT_WORD;
+	      }
+	    if (aflag)
+	      {
+		if (target_read_memory
+		    (i386_record_pc, (gdb_byte *) & addr, 4))
+		  {
+		    if (record_debug)
+		      {
+			printf_unfiltered (_
+					   ("Process record: error reading memory at addr 0x%s len = 4.\n"),
+					   paddr_nz (i386_record_pc));
+		      }
+		    return (-1);
+		  }
+		i386_record_pc += 4;
+	      }
+	    else
+	      {
+		if (target_read_memory
+		    (i386_record_pc, (gdb_byte *) & tmpu16, 4))
+		  {
+		    if (record_debug)
+		      {
+			printf_unfiltered (_
+					   ("Process record: error reading memory at addr 0x%s len = 4.\n"),
+					   paddr_nz (i386_record_pc));
+		      }
+		    return (-1);
+		  }
+		i386_record_pc += 2;
+		addr = tmpu16;
+	      }
+	    if (record_arch_list_add_mem (addr, 1 << ot))
+	      {
+		return (-1);
+	      }
+	  }
+      }
+      break;
+
+      /* mov R, Ib */
+    case 0xb0:
+    case 0xb1:
+    case 0xb2:
+    case 0xb3:
+    case 0xb4:
+    case 0xb5:
+    case 0xb6:
+    case 0xb7:
+      if (record_arch_list_add_reg ((opcode & 0x7) & 0x3))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov R, Iv */
+    case 0xb8:
+    case 0xb9:
+    case 0xba:
+    case 0xbb:
+    case 0xbc:
+    case 0xbd:
+    case 0xbe:
+    case 0xbf:
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xchg R, EAX */
+    case 0x91:
+    case 0x92:
+    case 0x93:
+    case 0x94:
+    case 0x95:
+    case 0x96:
+    case 0x97:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xchg Ev, Gv */
+    case 0x86:
+    case 0x87:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod == 3)
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* les Gv */
+    case 0xc4:
+      /* lds Gv */
+    case 0xc5:
+      /* lss Gv */
+    case 0x0fb2:
+      /* lfs Gv */
+    case 0x0fb4:
+      /* lgs Gv */
+    case 0x0fb5:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (opcode > 0xff)
+	    {
+	      i386_record_pc -= 3;
+	    }
+	  else
+	    {
+	      i386_record_pc -= 2;
+	    }
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      switch (opcode)
+	{
+	  /* les Gv */
+	case 0xc4:
+	  tmpu8 = I386_ES_REGNUM;
+	  break;
+	  /* lds Gv */
+	case 0xc5:
+	  tmpu8 = I386_DS_REGNUM;
+	  break;
+	  /* lss Gv */
+	case 0x0fb2:
+	  tmpu8 = I386_SS_REGNUM;
+	  break;
+	  /* lfs Gv */
+	case 0x0fb4:
+	  tmpu8 = I386_FS_REGNUM;
+	  break;
+	  /* lgs Gv */
+	case 0x0fb5:
+	  tmpu8 = I386_GS_REGNUM;
+	  break;
+	}
+      if (record_arch_list_add_reg (tmpu8))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* shifts */
+    case 0xc0:
+    case 0xc1:
+    case 0xd0:
+    case 0xd1:
+    case 0xd2:
+    case 0xd3:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod != 3 && (opcode == 0xd2 || opcode == 0xd3))
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0x0fa4:
+    case 0x0fa5:
+    case 0x0fac:
+    case 0x0fad:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* floats */
+      /* It just record the memory change of instrcution. */
+    case 0xd8:
+    case 0xd9:
+    case 0xda:
+    case 0xdb:
+    case 0xdc:
+    case 0xdd:
+    case 0xde:
+    case 0xdf:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      reg |= ((opcode & 7) << 3);
+      if (mod != 3)
+	{
+	  /* memory */
+	  uint32_t addr;
+
+	  if (i386_record_lea_modrm_addr (&addr))
+	    {
+	      return (-1);
+	    }
+	  switch (reg)
+	    {
+	    case 0x00:
+	    case 0x01:
+	    case 0x02:
+	    case 0x03:
+	    case 0x04:
+	    case 0x05:
+	    case 0x06:
+	    case 0x07:
+	    case 0x10:
+	    case 0x11:
+	    case 0x12:
+	    case 0x13:
+	    case 0x14:
+	    case 0x15:
+	    case 0x16:
+	    case 0x17:
+	    case 0x20:
+	    case 0x21:
+	    case 0x22:
+	    case 0x23:
+	    case 0x24:
+	    case 0x25:
+	    case 0x26:
+	    case 0x27:
+	    case 0x30:
+	    case 0x31:
+	    case 0x32:
+	    case 0x33:
+	    case 0x34:
+	    case 0x35:
+	    case 0x36:
+	    case 0x37:
+	      break;
+	    case 0x08:
+	    case 0x0a:
+	    case 0x0b:
+	    case 0x18:
+	    case 0x19:
+	    case 0x1a:
+	    case 0x1b:
+	    case 0x28:
+	    case 0x29:
+	    case 0x2a:
+	    case 0x2b:
+	    case 0x38:
+	    case 0x39:
+	    case 0x3a:
+	    case 0x3b:
+	      switch (reg & 7)
+		{
+		case 0:
+		  break;
+		case 1:
+		  switch (reg >> 4)
+		    {
+		    case 0:
+		      if (record_arch_list_add_mem (addr, 4))
+			{
+			  return (-1);
+			}
+		      break;
+		    case 2:
+		      if (record_arch_list_add_mem (addr, 8))
+			{
+			  return (-1);
+			}
+		      break;
+		    case 3:
+		    default:
+		      if (record_arch_list_add_mem (addr, 2))
+			{
+			  return (-1);
+			}
+		      break;
+		    }
+		  break;
+		default:
+		  switch (reg >> 4)
+		    {
+		    case 0:
+		    case 1:
+		      if (record_arch_list_add_mem (addr, 4))
+			{
+			  return (-1);
+			}
+		      break;
+		    case 2:
+		      if (record_arch_list_add_mem (addr, 8))
+			{
+			  return (-1);
+			}
+		      break;
+		    case 3:
+		    default:
+		      if (record_arch_list_add_mem (addr, 2))
+			{
+			  return (-1);
+			}
+		      break;
+		    }
+		  break;
+		}
+	      break;
+	    case 0x0c:
+	    case 0x0d:
+	    case 0x1d:
+	    case 0x2c:
+	    case 0x3c:
+	    case 0x3d:
+	      break;
+	    case 0x0e:
+	      if (dflag)
+		{
+		  if (record_arch_list_add_mem (addr, 28))
+		    {
+		      return (-1);
+		    }
+		}
+	      else
+		{
+		  if (record_arch_list_add_mem (addr, 14))
+		    {
+		      return (-1);
+		    }
+		}
+	      break;
+	    case 0x0f:
+	    case 0x2f:
+	      if (record_arch_list_add_mem (addr, 2))
+		{
+		  return (-1);
+		}
+	      break;
+	    case 0x1f:
+	    case 0x3e:
+	      if (record_arch_list_add_mem (addr, 10))
+		{
+		  return (-1);
+		}
+	      break;
+	    case 0x2e:
+	      if (dflag)
+		{
+		  if (record_arch_list_add_mem (addr, 28))
+		    {
+		      return (-1);
+		    }
+		  addr += 28;
+		}
+	      else
+		{
+		  if (record_arch_list_add_mem (addr, 14))
+		    {
+		      return (-1);
+		    }
+		  addr += 14;
+		}
+	      if (record_arch_list_add_mem (addr, 80))
+		{
+		  return (-1);
+		}
+	      break;
+	    case 0x3f:
+	      if (record_arch_list_add_mem (addr, 8))
+		{
+		  return (-1);
+		}
+	      break;
+	    default:
+	      i386_record_pc -= 2;
+	      opcode = opcode << 8 | modrm;
+	      goto no_support;
+	      break;
+	    }
+	}
+      break;
+
+      /* string ops */
+      /* movsS */
+    case 0xa4:
+    case 0xa5:
+      /* stosS */
+    case 0xaa:
+    case 0xab:
+      /* insS */
+    case 0x6c:
+    case 0x6d:
+      {
+	uint32_t addr;
+
+	if ((opcode & 1) == 0)
+	  {
+	    ot = OT_BYTE;
+	  }
+	else
+	  {
+	    ot = dflag + OT_WORD;
+	  }
+	if (opcode == 0xa4 || opcode == 0xa5)
+	  {
+	    if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	      {
+		return (-1);
+	      }
+	  }
+	if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	  {
+	    return (-1);
+	  }
+
+	regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			   (gdb_byte *) & addr);
+	if (!aflag)
+	  {
+	    addr &= 0xffff;
+	    /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */
+            if (record_debug)
+	      printf_unfiltered (_
+			         ("Process record ignores the memory change of instruction at address 0x%s because it can't get the value of the segment register.\n"),
+			   paddr_nz (i386_record_pc));
+	  }
+
+	if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	  {
+	    uint32_t count;
+
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & count);
+	    if (!aflag)
+	      {
+		count &= 0xffff;
+	      }
+
+	    regcache_raw_read (record_regcache, I386_EFLAGS_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if ((tmpu32 >> 10) & 0x1)
+	      {
+		addr -= (count - 1) * (1 << ot);
+	      }
+
+	    if (aflag)
+	      {
+	        if (record_arch_list_add_mem (addr, count * (1 << ot)))
+	          {
+		    return (-1);
+	          }
+	      }
+
+	    if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	      {
+		return (-1);
+	      }
+	  }
+	else
+	  {
+	    if (aflag)
+	      {
+	        if (record_arch_list_add_mem (addr, 1 << ot))
+	          {
+		    return (-1);
+	          }
+	      }
+	  }
+      }
+      break;
+
+      /* lodsS */
+    case 0xac:
+    case 0xad:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* outsS */
+    case 0x6e:
+    case 0x6f:
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* scasS */
+    case 0xae:
+    case 0xaf:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpsS */
+    case 0xa6:
+    case 0xa7:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* port I/O */
+    case 0xe4:
+    case 0xe5:
+    case 0xec:
+    case 0xed:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0xe6:
+    case 0xe7:
+    case 0xee:
+    case 0xef:
+      break;
+
+      /* control */
+      /* ret im */
+    case 0xc2:
+      /* ret */
+    case 0xc3:
+      /* lret im */
+    case 0xca:
+      /* lret */
+    case 0xcb:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* iret */
+    case 0xcf:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* call im */
+    case 0xe8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lcall im */
+    case 0x9a:
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* jmp im */
+    case 0xe9:
+      /* ljmp im */
+    case 0xea:
+      /* jmp Jb */
+    case 0xeb:
+      /* jcc Jb */
+    case 0x70:
+    case 0x71:
+    case 0x72:
+    case 0x73:
+    case 0x74:
+    case 0x75:
+    case 0x76:
+    case 0x77:
+    case 0x78:
+    case 0x79:
+    case 0x7a:
+    case 0x7b:
+    case 0x7c:
+    case 0x7d:
+    case 0x7e:
+    case 0x7f:
+      /* jcc Jv */
+    case 0x0f80:
+    case 0x0f81:
+    case 0x0f82:
+    case 0x0f83:
+    case 0x0f84:
+    case 0x0f85:
+    case 0x0f86:
+    case 0x0f87:
+    case 0x0f88:
+    case 0x0f89:
+    case 0x0f8a:
+    case 0x0f8b:
+    case 0x0f8c:
+    case 0x0f8d:
+    case 0x0f8e:
+    case 0x0f8f:
+      break;
+
+      /* setcc Gv */
+    case 0x0f90:
+    case 0x0f91:
+    case 0x0f92:
+    case 0x0f93:
+    case 0x0f94:
+    case 0x0f95:
+    case 0x0f96:
+    case 0x0f97:
+    case 0x0f98:
+    case 0x0f99:
+    case 0x0f9a:
+    case 0x0f9b:
+    case 0x0f9c:
+    case 0x0f9d:
+    case 0x0f9e:
+    case 0x0f9f:
+      ot = OT_BYTE;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm & 0x3))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* cmov Gv, Ev */
+    case 0x0f40:
+    case 0x0f41:
+    case 0x0f42:
+    case 0x0f43:
+    case 0x0f44:
+    case 0x0f45:
+    case 0x0f46:
+    case 0x0f47:
+    case 0x0f48:
+    case 0x0f49:
+    case 0x0f4a:
+    case 0x0f4b:
+    case 0x0f4c:
+    case 0x0f4d:
+    case 0x0f4e:
+    case 0x0f4f:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (dflag == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg & 0x3))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* flags */
+      /* pushf */
+    case 0x9c:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* popf */
+    case 0x9d:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sahf */
+    case 0x9e:
+      /* cmc */
+    case 0xf5:
+      /* clc */
+    case 0xf8:
+      /* stc */
+    case 0xf9:
+      /* cld */
+    case 0xfc:
+      /* std */
+    case 0xfd:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lahf */
+    case 0x9f:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bit operations */
+      /* bt/bts/btr/btc Gv, im */
+    case 0x0fba:
+      /* bts */
+    case 0x0fab:
+      /* btr */
+    case 0x0fb3:
+      /* btc */
+    case 0x0fbb:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg < 4)
+	{
+	  i386_record_pc -= 3;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      reg -= 4;
+      if (reg != 0)
+	{
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bt Gv, Ev */
+    case 0x0fa3:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bsf */
+    case 0x0fbc:
+      /* bsr */
+    case 0x0fbd:
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bcd */
+      /* daa */
+    case 0x27:
+      /* das */
+    case 0x2f:
+      /* aaa */
+    case 0x37:
+      /* aas */
+    case 0x3f:
+      /* aam */
+    case 0xd4:
+      /* aad */
+    case 0xd5:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* misc */
+      /* nop */
+    case 0x90:
+      if (prefixes & PREFIX_LOCK)
+	{
+	  i386_record_pc -= 1;
+	  goto no_support;
+	}
+      break;
+
+      /* fwait */
+      /* XXX */
+    case 0x9b:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction fwait.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int3 */
+      /* XXX */
+    case 0xcc:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction int3.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int */
+      /* XXX */
+    case 0xcd:
+      {
+	int ret;
+	if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	  {
+	    if (record_debug)
+	      {
+		printf_unfiltered (_
+				   ("Process record: error reading memory at addr 0x%s len = 1.\n"),
+				   paddr_nz (i386_record_pc));
+	      }
+	    return (-1);
+	  }
+	i386_record_pc++;
+	if (tmpu8 != 0x80
+	    || gdbarch_tdep (gdbarch)->i386_intx80_record == NULL)
+	  {
+	    printf_unfiltered (_
+			       ("Process record doesn't support instruction int 0x%02x.\n"),
+			       tmpu8);
+	    i386_record_pc -= 2;
+	    goto no_support;
+	  }
+	ret = gdbarch_tdep (gdbarch)->i386_intx80_record ();
+	if (ret)
+	  {
+	    return (ret);
+	  }
+      }
+      break;
+
+      /* into */
+      /* XXX */
+    case 0xce:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction into.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* cli */
+    case 0xfa:
+      /* sti */
+    case 0xfb:
+      break;
+
+      /* bound */
+    case 0x62:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction bound.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* bswap reg */
+    case 0x0fc8:
+    case 0x0fc9:
+    case 0x0fca:
+    case 0x0fcb:
+    case 0x0fcc:
+    case 0x0fcd:
+    case 0x0fce:
+    case 0x0fcf:
+      if (record_arch_list_add_reg (opcode & 7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* salc */
+    case 0xd6:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* loopnz */
+    case 0xe0:
+      /* loopz */
+    case 0xe1:
+      /* loop */
+    case 0xe2:
+      /* jecxz */
+    case 0xe3:
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* wrmsr */
+    case 0x0f30:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction wrmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdmsr */
+    case 0x0f32:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction rdmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdtsc */
+    case 0x0f31:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction rdtsc.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* sysenter */
+    case 0x0f34:
+      {
+	int ret;
+	if (gdbarch_tdep (gdbarch)->i386_sysenter_record == NULL)
+	  {
+	    printf_unfiltered (_
+			       ("Process record doesn't support instruction sysenter.\n"));
+	    i386_record_pc -= 2;
+	    goto no_support;
+	  }
+	ret = gdbarch_tdep (gdbarch)->i386_sysenter_record ();
+	if (ret)
+	  {
+	    return (ret);
+	  }
+      }
+      break;
+
+      /* sysexit */
+    case 0x0f35:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction sysexit.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* cpuid */
+    case 0x0fa2:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* hlt */
+    case 0xf4:
+      printf_unfiltered (_
+			 ("Process record doesn't support instruction hlt.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+    case 0x0f00:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      switch (reg)
+	{
+	  /* sldt */
+	case 0:
+	  /* str */
+	case 1:
+	  if (mod == 3)
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      ot = OT_WORD;
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* lldt */
+	case 2:
+	  /* ltr */
+	case 3:
+	  break;
+	  /* verr */
+	case 4:
+	  /* verw */
+	case 5:
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 3;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+    case 0x0f01:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      switch (reg)
+	{
+	  /* sgdt */
+	case 0:
+	  {
+	    uint32_t addr;
+
+	    if (mod == 3)
+	      {
+		i386_record_pc -= 3;
+		opcode = opcode << 8 | modrm;
+		goto no_support;
+	      }
+
+	    if (override)
+	      {
+		if (record_debug)
+		  printf_unfiltered (_
+				     ("Process record ignores the memory change of instruction at address 0x%s because it can't get the value of the segment register.\n"),
+				     paddr_nz (i386_record_pc));
+error("3");
+	      }
+	    else
+	      {
+		if (i386_record_lea_modrm_addr (&addr))
+		  {
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (addr, 2))
+		  {
+		    return (-1);
+		  }
+		addr += 2;
+		if (record_arch_list_add_mem (addr, 4))
+		  {
+		    return (-1);
+		  }
+	      }
+	  }
+	  break;
+	case 1:
+	  if (mod == 3)
+	    {
+	      switch (rm)
+		{
+		  /* monitor */
+		case 0:
+		  break;
+		  /* mwait */
+		case 1:
+		  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+		    {
+		      return (-1);
+		    }
+		  break;
+		default:
+		  i386_record_pc -= 3;
+		  opcode = opcode << 8 | modrm;
+		  goto no_support;
+		  break;
+		}
+	    }
+	  else
+	    {
+	      /* sidt */
+	      if (override)
+		{
+		  if (record_debug)
+		    printf_unfiltered (_
+				       ("Process record ignores the memory change of instruction at address 0x%s because it can't get the value of the segment register.\n"),
+				       paddr_nz (i386_record_pc));
+		}
+	      else
+		{
+		  uint32_t addr;
+
+		  if (i386_record_lea_modrm_addr (&addr))
+		    {
+		      return (-1);
+		    }
+		  if (record_arch_list_add_mem (addr, 2))
+		    {
+		      return (-1);
+		    }
+		  addr += 2;
+		  if (record_arch_list_add_mem (addr, 4))
+		    {
+		      return (-1);
+		    }
+		}
+	    }
+	  break;
+	  /* lgdt */
+	case 2:
+	  /* lidt */
+	case 3:
+	  /* invlpg */
+	case 7:
+	default:
+	  if (mod == 3)
+	    {
+	      i386_record_pc -= 3;
+	      opcode = opcode << 8 | modrm;
+	      goto no_support;
+	    }
+	  break;
+	  /* smsw */
+	case 4:
+	  if (mod == 3)
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      ot = OT_WORD;
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* lmsw */
+	case 6:
+	  break;
+	}
+      break;
+
+      /* invd */
+    case 0x0f08:
+      /* wbinvd */
+    case 0x0f09:
+      break;
+
+      /* arpl */
+    case 0x63:
+      ot = dflag ? OT_LONG : OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod != 3)
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lar */
+    case 0x0f02:
+      /* lsl */
+    case 0x0f03:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0x0f18:
+      break;
+
+      /* nop (multi byte) */
+    case 0x0f19:
+    case 0x0f1a:
+    case 0x0f1b:
+    case 0x0f1c:
+    case 0x0f1d:
+    case 0x0f1e:
+    case 0x0f1f:
+      break;
+
+      /* mov reg, crN */
+    case 0x0f20:
+      /* mov crN, reg */
+    case 0x0f22:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if ((modrm & 0xc0) != 0xc0)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      switch (reg)
+	{
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 8:
+	  if (opcode & 2)
+	    {
+	    }
+	  else
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* mov reg, drN */
+    case 0x0f21:
+      /* mov drN, reg */
+    case 0x0f23:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if ((modrm & 0xc0) != 0xc0 || reg == 4 || reg == 5 || reg >= 8)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      if (opcode & 2)
+	{
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* clts */
+    case 0x0f06:
+      break;
+
+      /* MMX/SSE/SSE2/PNI support */
+      /* XXX */
+
+    default:
+      if (opcode > 0xff)
+	{
+	  i386_record_pc -= 2;
+	}
+      else
+	{
+	  i386_record_pc -= 1;
+	}
+      goto no_support;
+      break;
+    }
+
+/* In the future, Maybe still need to deal with need_dasm */
+  if (record_arch_list_add_reg (I386_EIP_REGNUM))
+    {
+      return (-1);
+    }
+  if (record_arch_list_add_end (0))
+    {
+      return (-1);
+    }
+
+  return (0);
+
+no_support:
+  printf_unfiltered (_
+		     ("Process record doesn't support instruction 0x%02x at address 0x%s.\n"),
+		     (unsigned int) (opcode), paddr_nz (i386_record_pc));
+  return (-1);
+}
+
 \f
 static struct gdbarch *
 i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
@@ -2829,6 +5791,8 @@ i386_gdbarch_init (struct gdbarch_info i
   set_gdbarch_skip_permanent_breakpoint (gdbarch,
 					 i386_skip_permanent_breakpoint);
 
+  set_gdbarch_process_record (gdbarch, i386_process_record);
+
   return gdbarch;
 }
 
--- a/i386-tdep.h
+++ b/i386-tdep.h
@@ -106,6 +106,9 @@ struct gdbarch_tdep
   /* ISA-specific data types.  */
   struct type *i386_mmx_type;
   struct type *i386_sse_type;
+
+  int (*i386_intx80_record) (void);
+  int (*i386_sysenter_record) (void);
 };
 
 /* Floating-point registers.  */

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-11-20  4:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-17  7:04 [RFA] Resubmit process record and replay, 8/10 teawater
2008-11-20  5:56 ` Michael Snyder
2008-11-20 12:08   ` Thiago Jung Bauermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox