merge from gcc
[deliverable/binutils-gdb.git] / gdb / i386nbsd-tdep.c
index 9fd98839db9b4c0bd4893d036e81f8fab4a46c73..75fc64c974dca3088e9565d0c63c7558d4d90f86 100644 (file)
@@ -1,14 +1,13 @@
 /* Target-dependent code for NetBSD/i386.
 
 /* Target-dependent code for NetBSD/i386.
 
-   Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002,
-   2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, 2003,
+   2004, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +16,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "arch-utils.h"
 
 #include "defs.h"
 #include "arch-utils.h"
@@ -29,6 +26,8 @@
 #include "regset.h"
 #include "osabi.h"
 #include "symtab.h"
 #include "regset.h"
 #include "osabi.h"
 #include "symtab.h"
+#include "trad-frame.h"
+#include "tramp-frame.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -59,166 +58,215 @@ static int i386nbsd_r_reg_offset[] =
   15 * 4                       /* %gs */
 };
 
   15 * 4                       /* %gs */
 };
 
-static void
-i386nbsd_aout_supply_regset (const struct regset *regset,
-                            struct regcache *regcache, int regnum,
-                            const void *regs, size_t len)
+/* From <machine/signal.h>.  */
+int i386nbsd_sc_reg_offset[] =
 {
 {
-  const struct gdbarch_tdep *tdep = regset->descr;
+  10 * 4,                      /* %eax */
+  9 * 4,                       /* %ecx */
+  8 * 4,                       /* %edx */
+  7 * 4,                       /* %ebx */
+  14 * 4,                      /* %esp */
+  6 * 4,                       /* %ebp */
+  5 * 4,                       /* %esi */
+  4 * 4,                       /* %edi */
+  11 * 4,                      /* %eip */
+  13 * 4,                      /* %eflags */
+  12 * 4,                      /* %cs */
+  15 * 4,                      /* %ss */
+  3 * 4,                       /* %ds */
+  2 * 4,                       /* %es */
+  1 * 4,                       /* %fs */
+  0 * 4                                /* %gs */
+};
 
 
-  gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
+/* From <machine/mcontext.h>.  */
+int i386nbsd_mc_reg_offset[] =
+{
+  11 * 4,                      /* %eax */
+  10 * 4,                      /* %ecx */
+  9 * 4,                       /* %edx */
+  8 * 4,                       /* %ebx */
+  7 * 4,                       /* %esp */
+  6 * 4,                       /* %ebp */
+  5 * 4,                       /* %esi */
+  4 * 4,                       /* %edi */
+  14 * 4,                      /* %eip */
+  16 * 4,                      /* %eflags */
+  15 * 4,                      /* %cs */
+  18 * 4,                      /* %ss */
+  3 * 4,                       /* %ds */
+  2 * 4,                       /* %es */
+  1 * 4,                       /* %fs */
+  0 * 4                                /* %gs */
+};
 
 
-  i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
-  i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
-}
+static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *,
+                                         struct frame_info *,
+                                         struct trad_frame_cache *,
+                                         CORE_ADDR);
 
 
-static const struct regset *
-i386nbsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
-                                       const char *sect_name,
-                                       size_t sect_size)
+static const struct tramp_frame i386nbsd_sigtramp_sc16 =
 {
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 },
+                       /* leal  0x10(%esp), %eax */
+    { 0x50, -1 },      /* pushl %eax */
+    { 0x50, -1 },      /* pushl %eax */
+    { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x127, %eax           # __sigreturn14 */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x1, %eax             # exit */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
 
 
-  /* NetBSD a.out core dumps don't use seperate register sets for the
-     general-purpose and floating-point registers.  */
+static const struct tramp_frame i386nbsd_sigtramp_sc2 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 },
+                       /* leal  0x0c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x127, %eax           # __sigreturn14 */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
 
 
-  if (strcmp (sect_name, ".reg") == 0
-      && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
-    {
-      if (tdep->gregset == NULL)
-       {
-         tdep->gregset = XMALLOC (struct regset);
-         tdep->gregset->descr = tdep;
-         tdep->gregset->supply_regset = i386nbsd_aout_supply_regset;
-       }
-      return tdep->gregset;
-    }
+static const struct tramp_frame i386nbsd_sigtramp_si2 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 },
+                       /* movl  8(%esp),%eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1 },
+                       /* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1 },
+                       /* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
 
 
-  return NULL;
-}
+static const struct tramp_frame i386nbsd_sigtramp_si31 =
+{
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
+        { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* leal  0x8c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
+};
 
 
-/* Under NetBSD/i386, signal handler invocations can be identified by the
-   designated code sequence that is used to return from a signal handler.
-   In particular, the return address of a signal handler points to the
-   following code sequence:
-
-       leal    0x10(%esp), %eax
-       pushl   %eax
-       pushl   %eax
-       movl    $0x127, %eax            # __sigreturn14
-       int     $0x80
-
-   Each instruction has a unique encoding, so we simply attempt to match
-   the instruction the PC is pointing to with any of the above instructions.
-   If there is a hit, we know the offset to the start of the designated
-   sequence and can then check whether we really are executing in the
-   signal trampoline.  If not, -1 is returned, otherwise the offset from the
-   start of the return sequence is returned.  */
-#define RETCODE_INSN1          0x8d
-#define RETCODE_INSN2          0x50
-#define RETCODE_INSN3          0x50
-#define RETCODE_INSN4          0xb8
-#define RETCODE_INSN5          0xcd
-
-#define RETCODE_INSN2_OFF      4
-#define RETCODE_INSN3_OFF      5
-#define RETCODE_INSN4_OFF      6
-#define RETCODE_INSN5_OFF      11
-
-static const unsigned char sigtramp_retcode[] =
+static const struct tramp_frame i386nbsd_sigtramp_si4 =
 {
 {
-  RETCODE_INSN1, 0x44, 0x24, 0x10,
-  RETCODE_INSN2,
-  RETCODE_INSN3,
-  RETCODE_INSN4, 0x27, 0x01, 0x00, 0x00,
-  RETCODE_INSN5, 0x80,
+  SIGTRAMP_FRAME,
+  1,
+  {
+    { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 },
+        { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* leal  0x8c(%esp), %eax */
+    { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+                       /* movl  %eax, 0x4(%esp) */
+    { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 },
+                       /* movl  $0x134, %eax            # setcontext */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 },
+        { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 },
+                       /* movl   $0xffffffff,0x4(%esp) */
+    { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 },
+                       /* movl  $0x1, %eax */
+    { 0xcd, -1 }, { 0x80, -1},
+                       /* int   $0x80 */
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  i386nbsd_sigtramp_cache_init
 };
 
 };
 
-static LONGEST
-i386nbsd_sigtramp_offset (CORE_ADDR pc)
+static void
+i386nbsd_sigtramp_cache_init (const struct tramp_frame *self,
+                             struct frame_info *this_frame,
+                             struct trad_frame_cache *this_cache,
+                             CORE_ADDR func)
 {
 {
-  unsigned char ret[sizeof(sigtramp_retcode)], insn;
-  LONGEST off;
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
+  CORE_ADDR base;
+  int *reg_offset;
+  int num_regs;
   int i;
 
   int i;
 
-  if (read_memory_nobpt (pc, &insn, 1) != 0)
-    return -1;
-
-  switch (insn)
+  if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2)
     {
     {
-    case RETCODE_INSN1:
-      off = 0;
-      break;
-
-    case RETCODE_INSN2:
-      /* INSN2 and INSN3 are the same.  Read at the location of PC+1
-        to determine if we're actually looking at INSN2 or INSN3.  */
-      if (read_memory_nobpt (pc + 1, &insn, 1) != 0)
-       return -1;
-
-      if (insn == RETCODE_INSN3)
-       off = RETCODE_INSN2_OFF;
-      else
-       off = RETCODE_INSN3_OFF;
-      break;
-
-    case RETCODE_INSN4:
-      off = RETCODE_INSN4_OFF;
-      break;
-
-    case RETCODE_INSN5:
-      off = RETCODE_INSN5_OFF;
-      break;
-
-    default:
-      return -1;
-    }
-
-  pc -= off;
+      reg_offset = i386nbsd_sc_reg_offset;
+      num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
 
 
-  if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0)
-    return -1;
-
-  if (memcmp (ret, sigtramp_retcode, sizeof (ret)) == 0)
-    return off;
-
-  return -1;
-}
+      /* Read in the sigcontext address */
+      base = read_memory_unsigned_integer (sp + 8, 4);
+    }
+  else
+    {
+      reg_offset = i386nbsd_mc_reg_offset;
+      num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset);
 
 
-/* Return whether the frame preceding NEXT_FRAME corresponds to a
-   NetBSD sigtramp routine.  */
+      /* Read in the ucontext address */
+      base = read_memory_unsigned_integer (sp + 8, 4);
+      /* offsetof(ucontext_t, uc_mcontext) == 36 */
+      base += 36;
+    }
 
 
-static int
-i386nbsd_sigtramp_p (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  char *name;
+  for (i = 0; i < num_regs; i++)
+    if (reg_offset[i] != -1)
+      trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
 
 
-  find_pc_partial_function (pc, &name, NULL, NULL);
-  return (nbsd_pc_in_sigtramp (pc, name)
-         || i386nbsd_sigtramp_offset (pc) >= 0);
+  /* Construct the frame ID using the function start.  */
+  trad_frame_set_id (this_cache, frame_id_build (sp, func));
 }
 }
-
-/* From <machine/signal.h>.  */
-int i386nbsd_sc_reg_offset[] =
-{
-  10 * 4,                      /* %eax */
-  9 * 4,                       /* %ecx */
-  8 * 4,                       /* %edx */
-  7 * 4,                       /* %ebx */
-  14 * 4,                      /* %esp */
-  6 * 4,                       /* %ebp */
-  5 * 4,                       /* %esi */
-  4 * 4,                       /* %edi */
-  11 * 4,                      /* %eip */
-  13 * 4,                      /* %eflags */
-  12 * 4,                      /* %cs */
-  15 * 4,                      /* %ss */
-  3 * 4,                       /* %ds */
-  2 * 4,                       /* %es */
-  1 * 4,                       /* %fs */
-  0 * 4                                /* %gs */
-};
+\f
 
 static void 
 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
 static void 
 i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -233,30 +281,22 @@ i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
   tdep->sizeof_gregset = 16 * 4;
 
   tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset);
   tdep->sizeof_gregset = 16 * 4;
 
-  /* NetBSD has different signal trampoline conventions.  */
-  tdep->sigtramp_start = 0;
-  tdep->sigtramp_end = 0;
-  tdep->sigtramp_p = i386nbsd_sigtramp_p;
-
   /* NetBSD uses -freg-struct-return by default.  */
   tdep->struct_return = reg_struct_return;
 
   /* NetBSD uses -freg-struct-return by default.  */
   tdep->struct_return = reg_struct_return;
 
-  /* NetBSD has a `struct sigcontext' that's different from the
-     original 4.3 BSD.  */
-  tdep->sc_reg_offset = i386nbsd_sc_reg_offset;
-  tdep->sc_num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
-}
-
-/* NetBSD a.out.  */
-
-static void
-i386nbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-{
-  i386nbsd_init_abi (info, gdbarch);
-
-  /* NetBSD a.out has a single register set.  */
-  set_gdbarch_regset_from_core_section
-    (gdbarch, i386nbsd_aout_regset_from_core_section);
+  /* NetBSD uses tramp_frame sniffers for signal trampolines. */
+  tdep->sigcontext_addr= 0;
+  tdep->sigtramp_start = 0;
+  tdep->sigtramp_end = 0;
+  tdep->sigtramp_p = 0;
+  tdep->sc_reg_offset = 0;
+  tdep->sc_num_regs = 0;
+
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31);
+  tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4);
 }
 
 /* NetBSD ELF.  */
 }
 
 /* NetBSD ELF.  */
@@ -273,8 +313,6 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   i386_elf_init_abi (info, gdbarch);
 
   /* NetBSD ELF uses SVR4-style shared libraries.  */
   i386_elf_init_abi (info, gdbarch);
 
   /* NetBSD ELF uses SVR4-style shared libraries.  */
-  set_gdbarch_in_solib_call_trampoline
-    (gdbarch, generic_in_solib_call_trampoline);
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
@@ -285,8 +323,6 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 void
 _initialize_i386nbsd_tdep (void)
 {
 void
 _initialize_i386nbsd_tdep (void)
 {
-  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_AOUT,
-                         i386nbsdaout_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF,
                          i386nbsdelf_init_abi);
 }
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF,
                          i386nbsdelf_init_abi);
 }
This page took 0.027798 seconds and 4 git commands to generate.