* hpux-core.c (thread_section_p): New function.
[deliverable/binutils-gdb.git] / gdb / i386obsd-tdep.c
index be9e735cb3c0d0a9982bf5cb28b3797e0772cffd..9ef868d6ec45a9ce48fa195800a1792ecdced2af 100644 (file)
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "frame.h"
 #include "gdbcore.h"
 #include "regcache.h"
 #include "regset.h"
+#include "symtab.h"
+#include "objfiles.h"
 #include "osabi.h"
+#include "target.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
 #include "i387-tdep.h"
 #include "solib-svr4.h"
 
+/* Support for signal handlers.  */
+
+/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
+   in virtual memory.  The randomness makes it somewhat tricky to
+   detect it, but fortunately we can rely on the fact that the start
+   of the sigtramp routine is page-aligned.  By the way, the mapping
+   is read-only, so you cannot place a breakpoint in the signal
+   trampoline.  */
+
+/* Default page size.  */
+static const int i386obsd_page_size = 4096;
+
+/* Return whether the frame preceding NEXT_FRAME corresponds to an
+   OpenBSD sigtramp routine.  */
+
+static int
+i386obsd_sigtramp_p (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
+  const char sigreturn[] =
+  {
+    0xb8,
+    0x67, 0x00, 0x00, 0x00,    /* movl $SYS_sigreturn, %eax */
+    0xcd, 0x80                 /* int $0x80 */
+  };
+  size_t buflen = sizeof sigreturn;
+  char *name, *buf;
+
+  /* If the function has a valid symbol name, it isn't a
+     trampoline.  */
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (name != NULL)
+    return 0;
+
+  /* If the function lives in a valid section (even without a starting
+     point) it isn't a trampoline.  */
+  if (find_pc_section (pc) != NULL)
+    return 0;
+
+  /* Allocate buffer.  */
+  buf = alloca (buflen);
+
+  /* If we can't read the instructions at START_PC, return zero.  */
+  if (!safe_frame_unwind_memory (next_frame, start_pc + 0x0a, buf, buflen))
+    return 0;
+
+  /* Check for sigreturn(2).  */
+  if (memcmp (buf, sigreturn, buflen) == 0)
+    return 1;
+
+  /* If we can't read the instructions at START_PC, return zero.  */
+  if (!safe_frame_unwind_memory (next_frame, start_pc + 0x14, buf, buflen))
+    return 0;
+
+  /* Check for sigreturn(2) (again).  */
+  if (memcmp (buf, sigreturn, buflen) == 0)
+    return 1;
+
+  return 0;
+}
+\f
+/* Mapping between the general-purpose registers in `struct reg'
+   format and GDB's register cache layout.  */
+
 /* From <machine/reg.h>.  */
 static int i386obsd_r_reg_offset[] =
 {
@@ -61,7 +130,7 @@ i386obsd_aout_supply_regset (const struct regset *regset,
                             struct regcache *regcache, int regnum,
                             const void *regs, size_t len)
 {
-  const struct gdbarch_tdep *tdep = regset->descr;
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
 
   gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
 
@@ -83,11 +152,8 @@ i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
       && 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 = i386obsd_aout_supply_regset;
-       }
+        tdep->gregset =
+         regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
       return tdep->gregset;
     }
 
@@ -95,8 +161,9 @@ i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
 }
 \f
 
-CORE_ADDR i386obsd_sigtramp_start = 0xbfbfdf20;
-CORE_ADDR i386obsd_sigtramp_end = 0xbfbfdff0;
+/* Sigtramp routine location for OpenBSD 3.1 and earlier releases.  */
+CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
+CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
 
 /* From <machine/signal.h>.  */
 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
@@ -136,11 +203,12 @@ i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->struct_return = reg_struct_return;
 
   /* OpenBSD uses a different memory layout.  */
-  tdep->sigtramp_start = i386obsd_sigtramp_start;
-  tdep->sigtramp_end = i386obsd_sigtramp_end;
+  tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
+  tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
+  tdep->sigtramp_p = i386obsd_sigtramp_p;
 
   /* OpenBSD has a `struct sigcontext' that's different from the
-     origional 4.3 BSD.  */
+     original 4.3 BSD.  */
   tdep->sc_reg_offset = i386obsd_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
 }
This page took 0.024865 seconds and 4 git commands to generate.