2011-05-23 Pedro Alves <pedro@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / i386-tdep.c
index 22854bdbf77d43b2150ec03d2004e6d5d41cf6e9..b2b74121a678598073191843126b7ed01f61da66 100644 (file)
@@ -2,7 +2,7 @@
 
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010 Free Software Foundation, Inc.
+   2010, 2011 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -45,7 +45,7 @@
 #include "dis-asm.h"
 #include "disasm.h"
 #include "remote.h"
-
+#include "exceptions.h"
 #include "gdb_assert.h"
 #include "gdb_string.h"
 
@@ -165,7 +165,7 @@ i386_dword_regnum_p (struct gdbarch *gdbarch, int regnum)
   return regnum >= 0 && regnum < tdep->num_dword_regs;
 }
 
-int
+static int
 i386_ymmh_regnum_p (struct gdbarch *gdbarch, int regnum)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -445,17 +445,17 @@ i386_skip_prefixes (gdb_byte *insn, size_t max_len)
 static int
 i386_absolute_jmp_p (const gdb_byte *insn)
 {
-  /* jmp far (absolute address in operand) */
+  /* jmp far (absolute address in operand) */
   if (insn[0] == 0xea)
     return 1;
 
   if (insn[0] == 0xff)
     {
-      /* jump near, absolute indirect (/4) */
+      /* jump near, absolute indirect (/4) */
       if ((insn[1] & 0x38) == 0x20)
         return 1;
 
-      /* jump far, absolute indirect (/5) */
+      /* jump far, absolute indirect (/5) */
       if ((insn[1] & 0x38) == 0x28)
         return 1;
     }
@@ -466,17 +466,17 @@ i386_absolute_jmp_p (const gdb_byte *insn)
 static int
 i386_absolute_call_p (const gdb_byte *insn)
 {
-  /* call far, absolute */
+  /* call far, absolute */
   if (insn[0] == 0x9a)
     return 1;
 
   if (insn[0] == 0xff)
     {
-      /* Call near, absolute indirect (/2) */
+      /* Call near, absolute indirect (/2) */
       if ((insn[1] & 0x38) == 0x10)
         return 1;
 
-      /* Call far, absolute indirect (/3) */
+      /* Call far, absolute indirect (/3) */
       if ((insn[1] & 0x38) == 0x18)
         return 1;
     }
@@ -489,9 +489,9 @@ i386_ret_p (const gdb_byte *insn)
 {
   switch (insn[0])
     {
-    case 0xc2: /* ret near, pop N bytes */
+    case 0xc2: /* ret near, pop N bytes */
     case 0xc3: /* ret near */
-    case 0xca: /* ret far, pop N bytes */
+    case 0xca: /* ret far, pop N bytes */
     case 0xcb: /* ret far */
     case 0xcf: /* iret */
       return 1;
@@ -507,7 +507,7 @@ i386_call_p (const gdb_byte *insn)
   if (i386_absolute_call_p (insn))
     return 1;
 
-  /* call near, relative */
+  /* call near, relative */
   if (insn[0] == 0xe8)
     return 1;
 
@@ -518,7 +518,7 @@ i386_call_p (const gdb_byte *insn)
    length in bytes.  Otherwise, return zero.  */
 
 static int
-i386_syscall_p (const gdb_byte *insn, ULONGEST *lengthp)
+i386_syscall_p (const gdb_byte *insn, int *lengthp)
 {
   if (insn[0] == 0xcd)
     {
@@ -529,6 +529,43 @@ i386_syscall_p (const gdb_byte *insn, ULONGEST *lengthp)
   return 0;
 }
 
+/* Some kernels may run one past a syscall insn, so we have to cope.
+   Otherwise this is just simple_displaced_step_copy_insn.  */
+
+struct displaced_step_closure *
+i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
+                              CORE_ADDR from, CORE_ADDR to,
+                              struct regcache *regs)
+{
+  size_t len = gdbarch_max_insn_length (gdbarch);
+  gdb_byte *buf = xmalloc (len);
+
+  read_memory (from, buf, len);
+
+  /* GDB may get control back after the insn after the syscall.
+     Presumably this is a kernel bug.
+     If this is a syscall, make sure there's a nop afterwards.  */
+  {
+    int syscall_length;
+    gdb_byte *insn;
+
+    insn = i386_skip_prefixes (buf, len);
+    if (insn != NULL && i386_syscall_p (insn, &syscall_length))
+      insn[syscall_length] = NOP_OPCODE;
+  }
+
+  write_memory (to, buf, len);
+
+  if (debug_displaced)
+    {
+      fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
+                          paddress (gdbarch, from), paddress (gdbarch, to));
+      displaced_step_dump_bytes (gdb_stdlog, buf, len);
+    }
+
+  return (struct displaced_step_closure *) buf;
+}
+
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 
@@ -587,7 +624,7 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
       && ! i386_ret_p (insn))
     {
       ULONGEST orig_eip;
-      ULONGEST insn_len;
+      int insn_len;
 
       regcache_cooked_read_unsigned (regs, I386_EIP_REGNUM, &orig_eip);
 
@@ -606,7 +643,12 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
          it unrelocated.  Goodness help us if there are PC-relative
          system calls.  */
       if (i386_syscall_p (insn, &insn_len)
-          && orig_eip != to + (insn - insn_start) + insn_len)
+          && orig_eip != to + (insn - insn_start) + insn_len
+         /* GDB can get control back after the insn after the syscall.
+            Presumably this is a kernel bug.
+            i386_displaced_step_copy_insn ensures its a nop,
+            we add one to the length for it.  */
+          && orig_eip != to + (insn - insn_start) + insn_len + 1)
         {
           if (debug_displaced)
             fprintf_unfiltered (gdb_stdlog,
@@ -658,6 +700,93 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
                             paddress (gdbarch, retaddr));
     }
 }
+
+static void
+append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf)
+{
+  target_write_memory (*to, buf, len);
+  *to += len;
+}
+
+static void
+i386_relocate_instruction (struct gdbarch *gdbarch,
+                          CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[I386_MAX_INSN_LEN];
+  int offset = 0, rel32, newrel;
+  int insn_length;
+  gdb_byte *insn = buf;
+
+  read_memory (oldloc, buf, I386_MAX_INSN_LEN);
+
+  insn_length = gdb_buffered_insn_length (gdbarch, insn,
+                                         I386_MAX_INSN_LEN, oldloc);
+
+  /* Get past the prefixes.  */
+  insn = i386_skip_prefixes (insn, I386_MAX_INSN_LEN);
+
+  /* Adjust calls with 32-bit relative addresses as push/jump, with
+     the address pushed being the location where the original call in
+     the user program would return to.  */
+  if (insn[0] == 0xe8)
+    {
+      gdb_byte push_buf[16];
+      unsigned int ret_addr;
+
+      /* Where "ret" in the original code will return to.  */
+      ret_addr = oldloc + insn_length;
+      push_buf[0] = 0x68; /* pushq $...  */
+      memcpy (&push_buf[1], &ret_addr, 4);
+      /* Push the push.  */
+      append_insns (to, 5, push_buf);
+
+      /* Convert the relative call to a relative jump.  */
+      insn[0] = 0xe9;
+
+      /* Adjust the destination offset.  */
+      rel32 = extract_signed_integer (insn + 1, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + 1, 4, byte_order, newrel);
+
+      if (debug_displaced)
+       fprintf_unfiltered (gdb_stdlog,
+                           "Adjusted insn rel32=%s at %s to"
+                           " rel32=%s at %s\n",
+                           hex_string (rel32), paddress (gdbarch, oldloc),
+                           hex_string (newrel), paddress (gdbarch, *to));
+
+      /* Write the adjusted jump into its displaced location.  */
+      append_insns (to, 5, insn);
+      return;
+    }
+
+  /* Adjust jumps with 32-bit relative addresses.  Calls are already
+     handled above.  */
+  if (insn[0] == 0xe9)
+    offset = 1;
+  /* Adjust conditional jumps.  */
+  else if (insn[0] == 0x0f && (insn[1] & 0xf0) == 0x80)
+    offset = 2;
+
+  if (offset)
+    {
+      rel32 = extract_signed_integer (insn + offset, 4, byte_order);
+      newrel = (oldloc - *to) + rel32;
+      store_signed_integer (insn + offset, 4, byte_order, newrel);
+      if (debug_displaced)
+       fprintf_unfiltered (gdb_stdlog,
+                           "Adjusted insn rel32=%s at %s to"
+                           " rel32=%s at %s\n",
+                           hex_string (rel32), paddress (gdbarch, oldloc),
+                           hex_string (newrel), paddress (gdbarch, *to));
+    }
+
+  /* Write the adjusted instructions into their displaced
+     location.  */
+  append_insns (to, insn_length, buf);
+}
+
 \f
 #ifdef I386_REGNO_TO_SYMMETRY
 #error "The Sequent Symmetry is no longer supported."
@@ -675,6 +804,7 @@ struct i386_frame_cache
 {
   /* Base address.  */
   CORE_ADDR base;
+  int base_p;
   LONGEST sp_offset;
   CORE_ADDR pc;
 
@@ -699,6 +829,7 @@ i386_alloc_frame_cache (void)
   cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache);
 
   /* Base address.  */
+  cache->base_p = 0;
   cache->base = 0;
   cache->sp_offset = -4;
   cache->pc = 0;
@@ -728,7 +859,9 @@ i386_follow_jump (struct gdbarch *gdbarch, CORE_ADDR pc)
   long delta = 0;
   int data16 = 0;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
+
   if (op == 0x66)
     {
       data16 = 1;
@@ -794,12 +927,15 @@ i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc <= pc)
     return pc;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
 
   if (op != 0x58)              /* popl %eax */
     return pc;
 
-  target_read_memory (pc + 1, buf, 4);
+  if (target_read_memory (pc + 1, buf, 4))
+    return pc;
+
   if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0)
     return pc;
 
@@ -838,7 +974,8 @@ i386_skip_probe (CORE_ADDR pc)
   gdb_byte buf[8];
   gdb_byte op;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
 
   if (op == 0x68 || op == 0x6a)
     {
@@ -989,42 +1126,91 @@ struct i386_insn
   gdb_byte mask[I386_MAX_MATCHED_INSN_LEN];
 };
 
-/* Search for the instruction at PC in the list SKIP_INSNS.  Return
+/* Return whether instruction at PC matches PATTERN.  */
+
+static int
+i386_match_pattern (CORE_ADDR pc, struct i386_insn pattern)
+{
+  gdb_byte op;
+
+  if (target_read_memory (pc, &op, 1))
+    return 0;
+
+  if ((op & pattern.mask[0]) == pattern.insn[0])
+    {
+      gdb_byte buf[I386_MAX_MATCHED_INSN_LEN - 1];
+      int insn_matched = 1;
+      size_t i;
+
+      gdb_assert (pattern.len > 1);
+      gdb_assert (pattern.len <= I386_MAX_MATCHED_INSN_LEN);
+
+      if (target_read_memory (pc + 1, buf, pattern.len - 1))
+       return 0;
+
+      for (i = 1; i < pattern.len; i++)
+       {
+         if ((buf[i - 1] & pattern.mask[i]) != pattern.insn[i])
+           insn_matched = 0;
+       }
+      return insn_matched;
+    }
+  return 0;
+}
+
+/* Search for the instruction at PC in the list INSN_PATTERNS.  Return
    the first instruction description that matches.  Otherwise, return
    NULL.  */
 
 static struct i386_insn *
-i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns)
+i386_match_insn (CORE_ADDR pc, struct i386_insn *insn_patterns)
 {
-  struct i386_insn *insn;
+  struct i386_insn *pattern;
+
+  for (pattern = insn_patterns; pattern->len > 0; pattern++)
+    {
+      if (i386_match_pattern (pc, *pattern))
+       return pattern;
+    }
+
+  return NULL;
+}
+
+/* Return whether PC points inside a sequence of instructions that
+   matches INSN_PATTERNS.  */
+
+static int
+i386_match_insn_block (CORE_ADDR pc, struct i386_insn *insn_patterns)
+{
+  CORE_ADDR current_pc;
+  int ix, i;
   gdb_byte op;
+  struct i386_insn *insn;
 
-  target_read_memory (pc, &op, 1);
+  insn = i386_match_insn (pc, insn_patterns);
+  if (insn == NULL)
+    return 0;
 
-  for (insn = skip_insns; insn->len > 0; insn++)
+  current_pc = pc - insn->len;
+  ix = insn - insn_patterns;
+  for (i = ix - 1; i >= 0; i--)
     {
-      if ((op & insn->mask[0]) == insn->insn[0])
-       {
-         gdb_byte buf[I386_MAX_MATCHED_INSN_LEN - 1];
-         int insn_matched = 1;
-         size_t i;
+      if (!i386_match_pattern (current_pc, insn_patterns[i]))
+       return 0;
 
-         gdb_assert (insn->len > 1);
-         gdb_assert (insn->len <= I386_MAX_MATCHED_INSN_LEN);
+      current_pc -= insn_patterns[i].len;
+    }
 
-         target_read_memory (pc + 1, buf, insn->len - 1);
-         for (i = 1; i < insn->len; i++)
-           {
-             if ((buf[i - 1] & insn->mask[i]) != insn->insn[i])
-               insn_matched = 0;
-           }
+  current_pc = pc + insn->len;
+  for (insn = insn_patterns + ix + 1; insn->len > 0; insn++)
+    {
+      if (!i386_match_pattern (current_pc, *insn))
+       return 0;
 
-         if (insn_matched)
-           return insn;
-       }
+      current_pc += insn->len;
     }
 
-  return NULL;
+  return 1;
 }
 
 /* Some special instructions that might be migrated by GCC into the
@@ -1035,7 +1221,7 @@ i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns)
 
 struct i386_insn i386_frame_setup_skip_insns[] =
 {
-  /* Check for `movb imm8, r' and `movl imm32, r'. 
+  /* Check for `movb imm8, r' and `movl imm32, r'.
     
      ??? Should we handle 16-bit operand-sizes here?  */
 
@@ -1090,7 +1276,8 @@ i386_skip_noop (CORE_ADDR pc)
   gdb_byte op;
   int check = 1;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
 
   while (check) 
     {
@@ -1099,7 +1286,8 @@ i386_skip_noop (CORE_ADDR pc)
       if (op == 0x90) 
        {
          pc += 1;
-         target_read_memory (pc, &op, 1);
+         if (target_read_memory (pc, &op, 1))
+           return pc;
          check = 1;
        }
       /* Ignore no-op instruction `mov %edi, %edi'.
@@ -1115,11 +1303,15 @@ i386_skip_noop (CORE_ADDR pc)
 
       else if (op == 0x8b)
        {
-         target_read_memory (pc + 1, &op, 1);
+         if (target_read_memory (pc + 1, &op, 1))
+           return pc;
+
          if (op == 0xff)
            {
              pc += 2;
-             target_read_memory (pc, &op, 1);
+             if (target_read_memory (pc, &op, 1))
+               return pc;
+
              check = 1;
            }
        }
@@ -1145,7 +1337,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
   if (limit <= pc)
     return limit;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
 
   if (op == 0x55)              /* pushl %ebp */
     {
@@ -1180,7 +1373,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
       if (limit <= pc + skip)
        return limit;
 
-      target_read_memory (pc + skip, &op, 1);
+      if (target_read_memory (pc + skip, &op, 1))
+       return pc + skip;
 
       /* Check for `movl %esp, %ebp' -- can be written in two ways.  */
       switch (op)
@@ -1216,7 +1410,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch,
 
         NOTE: You can't subtract a 16-bit immediate from a 32-bit
         reg, so we don't have to worry about a data16 prefix.  */
-      target_read_memory (pc, &op, 1);
+      if (target_read_memory (pc, &op, 1))
+       return pc;
       if (op == 0x83)
        {
          /* `subl' with 8-bit immediate.  */
@@ -1272,7 +1467,8 @@ i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
     offset -= cache->locals;
   for (i = 0; i < 8 && pc < current_pc; i++)
     {
-      target_read_memory (pc, &op, 1);
+      if (target_read_memory (pc, &op, 1))
+       return pc;
       if (op < 0x50 || op > 0x57)
        break;
 
@@ -1365,7 +1561,9 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 
   for (i = 0; i < 6; i++)
     {
-      target_read_memory (pc + i, &op, 1);
+      if (target_read_memory (pc + i, &op, 1))
+       return pc;
+
       if (pic_pat[i] != op)
        break;
     }
@@ -1373,7 +1571,8 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
     {
       int delta = 6;
 
-      target_read_memory (pc + delta, &op, 1);
+      if (target_read_memory (pc + delta, &op, 1))
+       return pc;
 
       if (op == 0x89)          /* movl %ebx, x(%ebp) */
        {
@@ -1386,7 +1585,8 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
          else                  /* Unexpected instruction.  */
            delta = 0;
 
-          target_read_memory (pc + delta, &op, 1);
+          if (target_read_memory (pc + delta, &op, 1))
+           return pc;
        }
 
       /* addl y,%ebx */
@@ -1416,7 +1616,8 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte op;
 
-  target_read_memory (pc, &op, 1);
+  if (target_read_memory (pc, &op, 1))
+    return pc;
   if (op == 0xe8)
     {
       gdb_byte buf[4];
@@ -1455,20 +1656,16 @@ i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 
 /* Normal frames.  */
 
-static struct i386_frame_cache *
-i386_frame_cache (struct frame_info *this_frame, void **this_cache)
+static void
+i386_frame_cache_1 (struct frame_info *this_frame,
+                   struct i386_frame_cache *cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  struct i386_frame_cache *cache;
   gdb_byte buf[4];
   int i;
 
-  if (*this_cache)
-    return *this_cache;
-
-  cache = i386_alloc_frame_cache ();
-  *this_cache = cache;
+  cache->pc = get_frame_func (this_frame);
 
   /* In principle, for normal frames, %ebp holds the frame pointer,
      which holds the base address for the current stack frame.
@@ -1482,23 +1679,15 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache)
   get_frame_register (this_frame, I386_EBP_REGNUM, buf);
   cache->base = extract_unsigned_integer (buf, 4, byte_order);
   if (cache->base == 0)
-    return cache;
+    return;
 
   /* For normal frames, %eip is stored at 4(%ebp).  */
   cache->saved_regs[I386_EIP_REGNUM] = 4;
 
-  cache->pc = get_frame_func (this_frame);
   if (cache->pc != 0)
     i386_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
                           cache);
 
-  if (cache->saved_sp_reg != -1)
-    {
-      /* Saved stack pointer has been saved.  */
-      get_frame_register (this_frame, cache->saved_sp_reg, buf);
-      cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
-    }
-
   if (cache->locals < 0)
     {
       /* We didn't find a valid frame, which means that CACHE->base
@@ -1511,6 +1700,10 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       if (cache->saved_sp_reg != -1)
        {
+         /* Saved stack pointer has been saved.  */
+         get_frame_register (this_frame, cache->saved_sp_reg, buf);
+         cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
+
          /* We're halfway aligning the stack.  */
          cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4;
          cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4;
@@ -1538,9 +1731,17 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache)
        cache->saved_regs[I386_EBP_REGNUM] = 0;
     }
 
+  if (cache->saved_sp_reg != -1)
+    {
+      /* Saved stack pointer has been saved (but the SAVED_SP_REG
+        register may be unavailable).  */
+      if (cache->saved_sp == 0
+         && frame_register_read (this_frame, cache->saved_sp_reg, buf))
+       cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order);
+    }
   /* Now that we have the base address for the stack frame we can
      calculate the value of %esp in the calling frame.  */
-  if (cache->saved_sp == 0)
+  else if (cache->saved_sp == 0)
     cache->saved_sp = cache->base + 8;
 
   /* Adjust all the saved registers such that they contain addresses
@@ -1549,6 +1750,28 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache)
     if (cache->saved_regs[i] != -1)
       cache->saved_regs[i] += cache->base;
 
+  cache->base_p = 1;
+}
+
+static struct i386_frame_cache *
+i386_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+  volatile struct gdb_exception ex;
+  struct i386_frame_cache *cache;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = i386_alloc_frame_cache ();
+  *this_cache = cache;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      i386_frame_cache_1 (this_frame, cache);
+    }
+  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+    throw_exception (ex);
+
   return cache;
 }
 
@@ -1566,6 +1789,22 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
   (*this_id) = frame_id_build (cache->base + 8, cache->pc);
 }
 
+static enum unwind_stop_reason
+i386_frame_unwind_stop_reason (struct frame_info *this_frame,
+                              void **this_cache)
+{
+  struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
+
+  if (!cache->base_p)
+    return UNWIND_UNAVAILABLE;
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return UNWIND_OUTERMOST;
+
+  return UNWIND_NO_REASON;
+}
+
 static struct value *
 i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
                          int regnum)
@@ -1605,8 +1844,19 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
   if (regnum == I386_EIP_REGNUM && cache->pc_in_eax)
     return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM);
 
-  if (regnum == I386_ESP_REGNUM && cache->saved_sp)
-    return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
+  if (regnum == I386_ESP_REGNUM
+      && (cache->saved_sp != 0 || cache->saved_sp_reg != -1))
+    {
+      /* If the SP has been saved, but we don't know where, then this
+        means that SAVED_SP_REG register was found unavailable back
+        when we built the cache.  */
+      if (cache->saved_sp == 0)
+       return frame_unwind_got_register (this_frame, regnum,
+                                         cache->saved_sp_reg);
+      else
+       return frame_unwind_got_constant (this_frame, regnum,
+                                         cache->saved_sp);
+    }
 
   if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
     return frame_unwind_got_memory (this_frame, regnum,
@@ -1618,6 +1868,7 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache,
 static const struct frame_unwind i386_frame_unwind =
 {
   NORMAL_FRAME,
+  i386_frame_unwind_stop_reason,
   i386_frame_this_id,
   i386_frame_prev_register,
   NULL,
@@ -1661,6 +1912,7 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  volatile struct gdb_exception ex;
   struct i386_frame_cache *cache;
   gdb_byte buf[4];
 
@@ -1670,23 +1922,43 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache = i386_alloc_frame_cache ();
   *this_cache = cache;
 
-  /* Cache base will be %esp plus cache->sp_offset (-4).  */
-  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
-  cache->base = extract_unsigned_integer (buf, 4, 
-                                         byte_order) + cache->sp_offset;
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      /* Cache base will be %esp plus cache->sp_offset (-4).  */
+      get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+      cache->base = extract_unsigned_integer (buf, 4,
+                                             byte_order) + cache->sp_offset;
+
+      /* Cache pc will be the frame func.  */
+      cache->pc = get_frame_pc (this_frame);
 
-  /* Cache pc will be the frame func.  */
-  cache->pc = get_frame_pc (this_frame);
+      /* The saved %esp will be at cache->base plus 8.  */
+      cache->saved_sp = cache->base + 8;
 
-  /* The saved %esp will be at cache->base plus 8.  */
-  cache->saved_sp = cache->base + 8;
+      /* The saved %eip will be at cache->base plus 4.  */
+      cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4;
 
-  /* The saved %eip will be at cache->base plus 4.  */
-  cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4;
+      cache->base_p = 1;
+    }
+  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+    throw_exception (ex);
 
   return cache;
 }
 
+static enum unwind_stop_reason
+i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
+                                       void **this_cache)
+{
+  struct i386_frame_cache *cache
+    = i386_epilogue_frame_cache (this_frame, this_cache);
+
+  if (!cache->base_p)
+    return UNWIND_UNAVAILABLE;
+
+  return UNWIND_NO_REASON;
+}
+
 static void
 i386_epilogue_frame_this_id (struct frame_info *this_frame,
                             void **this_cache,
@@ -1695,12 +1967,16 @@ i386_epilogue_frame_this_id (struct frame_info *this_frame,
   struct i386_frame_cache *cache = i386_epilogue_frame_cache (this_frame,
                                                              this_cache);
 
+  if (!cache->base_p)
+    return;
+
   (*this_id) = frame_id_build (cache->base + 8, cache->pc);
 }
 
 static const struct frame_unwind i386_epilogue_frame_unwind =
 {
   NORMAL_FRAME,
+  i386_epilogue_frame_unwind_stop_reason,
   i386_epilogue_frame_this_id,
   i386_frame_prev_register,
   NULL, 
@@ -1708,6 +1984,88 @@ static const struct frame_unwind i386_epilogue_frame_unwind =
 };
 \f
 
+/* Stack-based trampolines.  */
+
+/* These trampolines are used on cross x86 targets, when taking the
+   address of a nested function.  When executing these trampolines,
+   no stack frame is set up, so we are in a similar situation as in
+   epilogues and i386_epilogue_frame_this_id can be re-used.  */
+
+/* Static chain passed in register.  */
+
+struct i386_insn i386_tramp_chain_in_reg_insns[] =
+{
+  /* `movl imm32, %eax' and `movl imm32, %ecx' */
+  { 5, { 0xb8 }, { 0xfe } },
+
+  /* `jmp imm32' */
+  { 5, { 0xe9 }, { 0xff } },
+
+  {0}
+};
+
+/* Static chain passed on stack (when regparm=3).  */
+
+struct i386_insn i386_tramp_chain_on_stack_insns[] =
+{
+  /* `push imm32' */
+  { 5, { 0x68 }, { 0xff } },
+
+  /* `jmp imm32' */
+  { 5, { 0xe9 }, { 0xff } },
+
+  {0}
+};
+
+/* Return whether PC points inside a stack trampoline.   */
+
+static int
+i386_in_stack_tramp_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  gdb_byte insn;
+  char *name;
+
+  /* A stack trampoline is detected if no name is associated
+    to the current pc and if it points inside a trampoline
+    sequence.  */
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (name)
+    return 0;
+
+  if (target_read_memory (pc, &insn, 1))
+    return 0;
+
+  if (!i386_match_insn_block (pc, i386_tramp_chain_in_reg_insns)
+      && !i386_match_insn_block (pc, i386_tramp_chain_on_stack_insns))
+    return 0;
+
+  return 1;
+}
+
+static int
+i386_stack_tramp_frame_sniffer (const struct frame_unwind *self,
+                            struct frame_info *this_frame,
+                            void **this_prologue_cache)
+{
+  if (frame_relative_level (this_frame) == 0)
+    return i386_in_stack_tramp_p (get_frame_arch (this_frame),
+                                 get_frame_pc (this_frame));
+  else
+    return 0;
+}
+
+static const struct frame_unwind i386_stack_tramp_frame_unwind =
+{
+  NORMAL_FRAME,
+  i386_epilogue_frame_unwind_stop_reason,
+  i386_epilogue_frame_this_id,
+  i386_frame_prev_register,
+  NULL, 
+  i386_stack_tramp_frame_sniffer
+};
+\f
+
 /* Signal trampolines.  */
 
 static struct i386_frame_cache *
@@ -1716,6 +2074,7 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  volatile struct gdb_exception ex;
   struct i386_frame_cache *cache;
   CORE_ADDR addr;
   gdb_byte buf[4];
@@ -1725,30 +2084,50 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
 
   cache = i386_alloc_frame_cache ();
 
-  get_frame_register (this_frame, I386_ESP_REGNUM, buf);
-  cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4;
-
-  addr = tdep->sigcontext_addr (this_frame);
-  if (tdep->sc_reg_offset)
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
     {
-      int i;
+      get_frame_register (this_frame, I386_ESP_REGNUM, buf);
+      cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4;
 
-      gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
+      addr = tdep->sigcontext_addr (this_frame);
+      if (tdep->sc_reg_offset)
+       {
+         int i;
 
-      for (i = 0; i < tdep->sc_num_regs; i++)
-       if (tdep->sc_reg_offset[i] != -1)
-         cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
-    }
-  else
-    {
-      cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
-      cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+         gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS);
+
+         for (i = 0; i < tdep->sc_num_regs; i++)
+           if (tdep->sc_reg_offset[i] != -1)
+             cache->saved_regs[i] = addr + tdep->sc_reg_offset[i];
+       }
+      else
+       {
+         cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset;
+         cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset;
+       }
+
+      cache->base_p = 1;
     }
+  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+    throw_exception (ex);
 
   *this_cache = cache;
   return cache;
 }
 
+static enum unwind_stop_reason
+i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
+                                       void **this_cache)
+{
+  struct i386_frame_cache *cache =
+    i386_sigtramp_frame_cache (this_frame, this_cache);
+
+  if (!cache->base_p)
+    return UNWIND_UNAVAILABLE;
+
+  return UNWIND_NO_REASON;
+}
+
 static void
 i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
                             struct frame_id *this_id)
@@ -1756,6 +2135,9 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
   struct i386_frame_cache *cache =
     i386_sigtramp_frame_cache (this_frame, this_cache);
 
+  if (!cache->base_p)
+    return;
+
   /* See the end of i386_push_dummy_call.  */
   (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
 }
@@ -1803,6 +2185,7 @@ i386_sigtramp_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind i386_sigtramp_frame_unwind =
 {
   SIGTRAMP_FRAME,
+  i386_sigtramp_frame_unwind_stop_reason,
   i386_sigtramp_frame_this_id,
   i386_sigtramp_frame_prev_register,
   NULL,
@@ -2049,7 +2432,8 @@ i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       else
        internal_error (__FILE__, __LINE__,
-                       _("Cannot extract return value of %d bytes long."), len);
+                       _("Cannot extract return value of %d bytes long."),
+                       len);
     }
 }
 
@@ -2295,7 +2679,7 @@ i386_ymm_type (struct gdbarch *gdbarch)
                                   init_vector_type (bt->builtin_int128, 2));
 
       TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "builtin_type_vec128i";
+      TYPE_NAME (t) = "builtin_type_vec256i";
       tdep->i386_ymm_type = t;
     }
 
@@ -2345,7 +2729,7 @@ i386_mmx_type (struct gdbarch *gdbarch)
 }
 
 /* Return the GDB type object for the "standard" data type of data in
-   register REGNUM. */
+   register REGNUM.  */
 
 static struct type *
 i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
@@ -2387,18 +2771,21 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
   return (I387_ST0_REGNUM (tdep) + fpreg);
 }
 
-void
+enum register_status
 i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
   gdb_byte raw_buf[MAX_REGISTER_SIZE];
+  enum register_status status;
 
   if (i386_mmx_regnum_p (gdbarch, regnum))
     {
       int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
 
       /* Extract (always little endian).  */
-      regcache_raw_read (regcache, fpnum, raw_buf);
+      status = regcache_raw_read (regcache, fpnum, raw_buf);
+      if (status != REG_VALID)
+       return status;
       memcpy (buf, raw_buf, register_size (gdbarch, regnum));
     }
   else
@@ -2409,15 +2796,19 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
        {
          regnum -= tdep->ymm0_regnum;
 
-         /* Extract (always little endian).  Read lower 128bits. */
-         regcache_raw_read (regcache,
-                            I387_XMM0_REGNUM (tdep) + regnum,
-                            raw_buf);
+         /* Extract (always little endian).  Read lower 128bits.  */
+         status = regcache_raw_read (regcache,
+                                     I387_XMM0_REGNUM (tdep) + regnum,
+                                     raw_buf);
+         if (status != REG_VALID)
+           return status;
          memcpy (buf, raw_buf, 16);
          /* Read upper 128bits.  */
-         regcache_raw_read (regcache,
-                            tdep->ymm0h_regnum + regnum,
-                            raw_buf);
+         status = regcache_raw_read (regcache,
+                                     tdep->ymm0h_regnum + regnum,
+                                     raw_buf);
+         if (status != REG_VALID)
+           return status;
          memcpy (buf + 16, raw_buf, 16);
        }
       else if (i386_word_regnum_p (gdbarch, regnum))
@@ -2425,7 +2816,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
          int gpnum = regnum - tdep->ax_regnum;
 
          /* Extract (always little endian).  */
-         regcache_raw_read (regcache, gpnum, raw_buf);
+         status = regcache_raw_read (regcache, gpnum, raw_buf);
+         if (status != REG_VALID)
+           return status;
          memcpy (buf, raw_buf, 2);
        }
       else if (i386_byte_regnum_p (gdbarch, regnum))
@@ -2437,7 +2830,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
          /* Extract (always little endian).  We read both lower and
             upper registers.  */
-         regcache_raw_read (regcache, gpnum % 4, raw_buf);
+         status = regcache_raw_read (regcache, gpnum % 4, raw_buf);
+         if (status != REG_VALID)
+           return status;
          if (gpnum >= 4)
            memcpy (buf, raw_buf + 1, 1);
          else
@@ -2446,6 +2841,8 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       else
        internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
+
+  return REG_VALID;
 }
 
 void
@@ -2549,7 +2946,8 @@ i386_next_regnum (int regnum)
    needs any special handling.  */
 
 static int
-i386_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+i386_convert_register_p (struct gdbarch *gdbarch,
+                        int regnum, struct type *type)
 {
   int len = TYPE_LENGTH (type);
 
@@ -2578,21 +2976,17 @@ i386_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
    return its contents in TO.  */
 
-static void
+static int
 i386_register_to_value (struct frame_info *frame, int regnum,
-                       struct type *type, gdb_byte *to)
+                       struct type *type, gdb_byte *to,
+                       int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   int len = TYPE_LENGTH (type);
 
-  /* FIXME: kettenis/20030609: What should we do if REGNUM isn't
-     available in FRAME (i.e. if it wasn't saved)?  */
-
   if (i386_fp_regnum_p (gdbarch, regnum))
-    {
-      i387_register_to_value (frame, regnum, type, to);
-      return;
-    }
+    return i387_register_to_value (frame, regnum, type, to,
+                                  optimizedp, unavailablep);
 
   /* Read a value spread across multiple registers.  */
 
@@ -2603,11 +2997,18 @@ i386_register_to_value (struct frame_info *frame, int regnum,
       gdb_assert (regnum != -1);
       gdb_assert (register_size (gdbarch, regnum) == 4);
 
-      get_frame_register (frame, regnum, to);
+      if (!get_frame_register_bytes (frame, regnum, 0,
+                                    register_size (gdbarch, regnum),
+                                    to, optimizedp, unavailablep))
+       return 0;
+
       regnum = i386_next_regnum (regnum);
       len -= 4;
       to += 4;
     }
+
+  *optimizedp = *unavailablep = 0;
+  return 1;
 }
 
 /* Write the contents FROM of a value of type TYPE into register
@@ -2736,7 +3137,6 @@ i386_supply_xstateregset (const struct regset *regset,
                          struct regcache *regcache, int regnum,
                          const void *xstateregs, size_t len)
 {
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
   i387_supply_xsave (regcache, regnum, xstateregs);
 }
 
@@ -2747,7 +3147,6 @@ i386_collect_xstateregset (const struct regset *regset,
                           const struct regcache *regcache,
                           int regnum, void *xstateregs, size_t len)
 {
-  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
   i387_collect_xsave (regcache, regnum, xstateregs, 1);
 }
 
@@ -2947,6 +3346,8 @@ i386_go32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
      set_gdbarch_sdb_reg_to_regnum.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
   set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+
+  set_gdbarch_has_dos_based_file_system (gdbarch, 1);
 }
 \f
 
@@ -3113,7 +3514,7 @@ struct i386_record_s
 };
 
 /* Parse "modrm" part in current memory address that irp->addr point to
-   Return -1 if something wrong. */
+   Return -1 if something wrong.  */
 
 static int
 i386_record_modrm (struct i386_record_s *irp)
@@ -3138,7 +3539,7 @@ i386_record_modrm (struct i386_record_s *irp)
 
 /* Get the memory address that current instruction  write to and set it to
    the argument "addr".
-   Return -1 if something wrong. */
+   Return -1 if something wrong.  */
 
 static int
 i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr)
@@ -3371,7 +3772,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr)
 
 /* Record the value of the memory that willbe changed in current instruction
    to "record_arch_list".
-   Return -1 if something wrong. */
+   Return -1 if something wrong.  */
 
 static int
 i386_record_lea_modrm (struct i386_record_s *irp)
@@ -3381,10 +3782,21 @@ i386_record_lea_modrm (struct i386_record_s *irp)
 
   if (irp->override >= 0)
     {
-      warning (_("Process record ignores the memory change "
-                 "of instruction at address %s because it "
-                 "can't get the value of the segment register."),
-               paddress (gdbarch, irp->orig_addr));
+      if (record_memory_query)
+        {
+         int q;
+
+          target_terminal_ours ();
+          q = yquery (_("\
+Process record ignores the memory change of instruction at address %s\n\
+because it can't get the value of the segment register.\n\
+Do you want to stop the program?"),
+                      paddress (gdbarch, irp->orig_addr));
+            target_terminal_inferior ();
+            if (q)
+              return -1;
+        }
+
       return 0;
     }
 
@@ -3398,7 +3810,7 @@ i386_record_lea_modrm (struct i386_record_s *irp)
 }
 
 /* Record the push operation to "record_arch_list".
-   Return -1 if something wrong. */
+   Return -1 if something wrong.  */
 
 static int
 i386_record_push (struct i386_record_s *irp, int size)
@@ -3423,9 +3835,9 @@ i386_record_push (struct i386_record_s *irp, int size)
 #define I386_SAVE_FPU_ENV               0xfffe
 #define I386_SAVE_FPU_ENV_REG_STACK     0xffff
 
-/* Record the value of floating point registers which will be changed by the
-   current instruction to "record_arch_list".  Return -1 if something is wrong.
-*/
+/* Record the value of floating point registers which will be changed
+   by the current instruction to "record_arch_list".  Return -1 if
+   something is wrong.  */
 
 static int i386_record_floats (struct gdbarch *gdbarch,
                                struct i386_record_s *ir,
@@ -3487,7 +3899,7 @@ static int i386_record_floats (struct gdbarch *gdbarch,
 
 /* 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. */
+   Return -1 if something wrong.  */
 
 #define I386_RECORD_ARCH_LIST_ADD_REG(regnum) \
     record_arch_list_add_reg (ir.regcache, ir.regmap[(regnum)])
@@ -3620,7 +4032,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   else if (ir.regmap[X86_RECORD_R8_REGNUM])
     ir.aflag = 2;
 
-  /* now check op code */
+  /* Now check op code.  */
   opcode = (uint32_t) opcode8;
  reswitch:
   switch (opcode)
@@ -4275,11 +4687,20 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
     case 0xa3:
       if (ir.override >= 0)
         {
-         warning (_("Process record ignores the memory change "
-                     "of instruction at address %s because "
-                     "it can't get the value of the segment "
-                     "register."),
-                   paddress (gdbarch, ir.orig_addr));
+          if (record_memory_query)
+            {
+             int q;
+
+              target_terminal_ours ();
+              q = yquery (_("\
+Process record ignores the memory change of instruction at address %s\n\
+because it can't get the value of the segment register.\n\
+Do you want to stop the program?"),
+                          paddress (gdbarch, ir.orig_addr));
+              target_terminal_inferior ();
+              if (q)
+                return -1;
+            }
        }
       else
        {
@@ -4399,6 +4820,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
          ir.addr -= 1;
          goto no_support;
        }
+      /* FALLTHROUGH */
     case 0x0fb2:    /* lss Gv */
     case 0x0fb4:    /* lfs Gv */
     case 0x0fb5:    /* lgs Gv */
@@ -4494,7 +4916,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
       ir.reg |= ((opcode & 7) << 3);
       if (ir.mod != 3)
        {
-         /* Memory. */
+         /* Memory.  */
          uint64_t addr64;
 
          if (i386_record_lea_modrm_addr (&ir, &addr64))
@@ -4956,11 +5378,20 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
           if (ir.aflag && (es != ds))
             {
               /* addr += ((uint32_t) read_register (I386_ES_REGNUM)) << 4; */
-              warning (_("Process record ignores the memory "
-                         "change of instruction at address %s "
-                         "because it can't get the value of the "
-                         "ES segment register."),
-                       paddress (gdbarch, ir.orig_addr));
+              if (record_memory_query)
+                {
+                 int q;
+
+                  target_terminal_ours ();
+                  q = yquery (_("\
+Process record ignores the memory change of instruction at address %s\n\
+because it can't get the value of the segment register.\n\
+Do you want to stop the program?"),
+                              paddress (gdbarch, ir.orig_addr));
+                  target_terminal_inferior ();
+                  if (q)
+                    return -1;
+                }
             }
           else
             {
@@ -5169,6 +5600,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
           ir.addr -= 1;
           goto no_support;
         }
+      /* FALLTHROUGH */
     case 0xf5:    /* cmc */
     case 0xf8:    /* clc */
     case 0xf9:    /* stc */
@@ -5513,12 +5945,20 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
              }
            if (ir.override >= 0)
              {
-               warning (_("Process record ignores the memory "
-                           "change of instruction at "
-                           "address %s because it can't get "
-                           "the value of the segment "
-                           "register."),
-                         paddress (gdbarch, ir.orig_addr));
+                if (record_memory_query)
+                  {
+                   int q;
+
+                    target_terminal_ours ();
+                    q = yquery (_("\
+Process record ignores the memory change of instruction at address %s\n\
+because it can't get the value of the segment register.\n\
+Do you want to stop the program?"),
+                                paddress (gdbarch, ir.orig_addr));
+                    target_terminal_inferior ();
+                    if (q)
+                      return -1;
+                  }
              }
            else
              {
@@ -5562,12 +6002,20 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
              /* sidt */
              if (ir.override >= 0)
                {
-                 warning (_("Process record ignores the memory "
-                             "change of instruction at "
-                             "address %s because it can't get "
-                             "the value of the segment "
-                             "register."),
-                           paddress (gdbarch, ir.orig_addr));
+                  if (record_memory_query)
+                    {
+                     int q;
+
+                      target_terminal_ours ();
+                      q = yquery (_("\
+Process record ignores the memory change of instruction at address %s\n\
+because it can't get the value of the segment register.\n\
+Do you want to stop the program?"),
+                                  paddress (gdbarch, ir.orig_addr));
+                      target_terminal_inferior ();
+                      if (q)
+                        return -1;
+                    }
                }
              else
                {
@@ -6087,7 +6535,7 @@ reswitch_prefix_add:
         case 0x660f3804:    /* pmaddubsw */
         case 0x660f3805:    /* phsubw */
         case 0x660f3806:    /* phsubd */
-        case 0x660f3807:    /* phaddsw */
+        case 0x660f3807:    /* phsubsw */
         case 0x660f3808:    /* psignb */
         case 0x660f3809:    /* psignw */
         case 0x660f380a:    /* psignd */
@@ -6178,7 +6626,7 @@ reswitch_prefix_add:
         case 0x660f63:      /* packsswb */
         case 0x660f64:      /* pcmpgtb */
         case 0x660f65:      /* pcmpgtw */
-        case 0x660f66:      /* pcmpgtl */
+        case 0x660f66:      /* pcmpgtd */
         case 0x660f67:      /* packuswb */
         case 0x660f68:      /* punpckhbw */
         case 0x660f69:      /* punpckhwd */
@@ -6194,7 +6642,7 @@ reswitch_prefix_add:
         case 0xf30f70:      /* pshufhw */
         case 0x660f74:      /* pcmpeqb */
         case 0x660f75:      /* pcmpeqw */
-        case 0x660f76:      /* pcmpeql */
+        case 0x660f76:      /* pcmpeqd */
         case 0x660f7c:      /* haddpd */
         case 0xf20f7c:      /* haddps */
         case 0x660f7d:      /* hsubpd */
@@ -6240,7 +6688,7 @@ reswitch_prefix_add:
         case 0x660fed:      /* paddsw */
         case 0x660fee:      /* pmaxsw */
         case 0x660fef:      /* pxor */
-        case 0x660ff0:      /* lddqu */
+        case 0xf20ff0:      /* lddqu */
         case 0x660ff1:      /* psllw */
         case 0x660ff2:      /* pslld */
         case 0x660ff3:      /* psllq */
@@ -6249,11 +6697,11 @@ reswitch_prefix_add:
         case 0x660ff6:      /* psadbw */
         case 0x660ff8:      /* psubb */
         case 0x660ff9:      /* psubw */
-        case 0x660ffa:      /* psubl */
+        case 0x660ffa:      /* psubd */
         case 0x660ffb:      /* psubq */
         case 0x660ffc:      /* paddb */
         case 0x660ffd:      /* paddw */
-        case 0x660ffe:      /* paddl */
+        case 0x660ffe:      /* paddd */
           if (i386_record_modrm (&ir))
            return -1;
           ir.reg |= rex_r;
@@ -6289,7 +6737,8 @@ reswitch_prefix_add:
                   || opcode == 0x0f17 || opcode == 0x660f17)
                 goto no_support;
               ir.rm |= ir.rex_b;
-              if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm))
+              if (!i386_xmm_regnum_p (gdbarch,
+                                     I387_XMM0_REGNUM (tdep) + ir.rm))
                 goto no_support;
               record_arch_list_add_reg (ir.regcache,
                                         I387_XMM0_REGNUM (tdep) + ir.rm);
@@ -6355,7 +6804,7 @@ reswitch_prefix_add:
         case 0x0f3804:    /* pmaddubsw */
         case 0x0f3805:    /* phsubw */
         case 0x0f3806:    /* phsubd */
-        case 0x0f3807:    /* phaddsw */
+        case 0x0f3807:    /* phsubsw */
         case 0x0f3808:    /* psignb */
         case 0x0f3809:    /* psignw */
         case 0x0f380a:    /* psignd */
@@ -6388,7 +6837,7 @@ reswitch_prefix_add:
         case 0x0f63:      /* packsswb */
         case 0x0f64:      /* pcmpgtb */
         case 0x0f65:      /* pcmpgtw */
-        case 0x0f66:      /* pcmpgtl */
+        case 0x0f66:      /* pcmpgtd */
         case 0x0f67:      /* packuswb */
         case 0x0f68:      /* punpckhbw */
         case 0x0f69:      /* punpckhwd */
@@ -6399,7 +6848,7 @@ reswitch_prefix_add:
         case 0x0f70:      /* pshufw */
         case 0x0f74:      /* pcmpeqb */
         case 0x0f75:      /* pcmpeqw */
-        case 0x0f76:      /* pcmpeql */
+        case 0x0f76:      /* pcmpeqd */
         case 0x0fc4:      /* pinsrw */
         case 0x0fd1:      /* psrlw */
         case 0x0fd2:      /* psrld */
@@ -6437,11 +6886,11 @@ reswitch_prefix_add:
         case 0x0ff6:      /* psadbw */
         case 0x0ff8:      /* psubb */
         case 0x0ff9:      /* psubw */
-        case 0x0ffa:      /* psubl */
+        case 0x0ffa:      /* psubd */
         case 0x0ffb:      /* psubq */
         case 0x0ffc:      /* paddb */
         case 0x0ffd:      /* paddw */
-        case 0x0ffe:      /* paddl */
+        case 0x0ffe:      /* paddd */
           if (i386_record_modrm (&ir))
            return -1;
           if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg))
@@ -6521,7 +6970,8 @@ reswitch_prefix_add:
           if (ir.mod == 3)
             {
               ir.rm |= ir.rex_b;
-              if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm))
+              if (!i386_xmm_regnum_p (gdbarch,
+                                     I387_XMM0_REGNUM (tdep) + ir.rm))
                 goto no_support;
               record_arch_list_add_reg (ir.regcache,
                                         I387_XMM0_REGNUM (tdep) + ir.rm);
@@ -6624,7 +7074,8 @@ i386_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
       /* Return a bit of target-specific detail to add to the caller's
         generic failure message.  */
       if (msg)
-       *msg = xstrprintf (_("; instruction is only %d bytes long, need at least %d bytes for the jump"),
+       *msg = xstrprintf (_("; instruction is only %d bytes long, "
+                            "need at least %d bytes for the jump"),
                           len, jumplen);
       return 0;
     }
@@ -6909,6 +7360,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdesc_data = tdesc_data_alloc ();
 
+  set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   info.tdep_info = (void *) tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
@@ -6944,7 +7397,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   ymm0_regnum = tdep->ax_regnum + tdep->num_word_regs;
   if (tdep->num_dword_regs)
     {
-      /* Support dword pseudo-registesr if it hasn't been disabled,  */
+      /* Support dword pseudo-register if it hasn't been disabled.  */
       tdep->eax_regnum = ymm0_regnum;
       ymm0_regnum += tdep->num_dword_regs;
     }
@@ -6954,7 +7407,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   mm0_regnum = ymm0_regnum;
   if (tdep->num_ymm_regs)
     {
-      /* Support YMM pseudo-registesr if it is available,  */
+      /* Support YMM pseudo-register if it is available.  */
       tdep->ymm0_regnum = ymm0_regnum;
       mm0_regnum += tdep->num_ymm_regs;
     }
@@ -6963,13 +7416,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   if (tdep->num_mmx_regs != 0)
     {
-      /* Support MMX pseudo-registesr if MMX hasn't been disabled,  */
+      /* Support MMX pseudo-register if MMX hasn't been disabled.  */
       tdep->mm0_regnum = mm0_regnum;
     }
   else
     tdep->mm0_regnum = -1;
 
   /* Hook in the legacy prologue-based unwinders last (fallback).  */
+  frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind);
   frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind);
   frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);
 
This page took 0.045668 seconds and 4 git commands to generate.