Move construction of IA-32 vector types to i386-tdep.c.
[deliverable/binutils-gdb.git] / gdb / amd64obsd-tdep.c
index 6ccf39ff172a7730f447f14cde6a5d335029fb1e..f97b9a6c57e2e9007ccaf79135658b3a219d5071 100644 (file)
 #include "defs.h"
 #include "frame.h"
 #include "gdbcore.h"
+#include "symtab.h"
+#include "objfiles.h"
 #include "osabi.h"
+#include "regset.h"
 #include "target.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
 
-#include "x86-64-tdep.h"
+#include "amd64-tdep.h"
+#include "i387-tdep.h"
+#include "solib-svr4.h"
+
+/* Support for core dumps.  */
+
+static void
+amd64obsd_supply_regset (const struct regset *regset,
+                        struct regcache *regcache, int regnum,
+                        const void *regs, size_t len)
+{
+  const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
+
+  gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE);
+
+  i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
+  amd64_supply_fxsave (regcache, regnum, (char *)regs + tdep->sizeof_gregset);
+}
+
+static const struct regset *
+amd64obsd_regset_from_core_section (struct gdbarch *gdbarch,
+                                   const char *sect_name, size_t sect_size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* OpenBSD core dumps don't use seperate register sets for the
+     general-purpose and floating-point registers.  */
+
+  if (strcmp (sect_name, ".reg") == 0
+      && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE)
+    {
+      if (tdep->gregset == NULL)
+        tdep->gregset = regset_alloc (gdbarch, amd64obsd_supply_regset, NULL);
+      return tdep->gregset;
+    }
+
+  return NULL;
+}
+\f
 
 /* Support for signal handlers.  */
 
+/* Default page size.  */
 static const int amd64obsd_page_size = 4096;
 
+/* Return whether the frame preceding NEXT_FRAME corresponds to an
+   OpenBSD sigtramp routine.  */
+
 static int
-amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+amd64obsd_sigtramp_p (struct frame_info *next_frame)
 {
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
   CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
   const char sigreturn[] =
   {
     0x48, 0xc7, 0xc0,
     0x67, 0x00, 0x00, 0x00,    /* movq $SYS_sigreturn, %rax */
-    0x0f, 0x05                 /* syscall */
+    0xcd, 0x80                 /* int $0x80 */
   };
-  char *buf;
+  size_t buflen = (sizeof sigreturn) + 1;
+  char *name, *buf;
 
-  if (name)
+  /* 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;
 
   /* If we can't read the instructions at START_PC, return zero.  */
-  buf = alloca (sizeof sigreturn);
-  if (target_read_memory (start_pc + 0x7, buf, sizeof sigreturn))
+  buf = alloca ((sizeof sigreturn) + 1);
+  if (!safe_frame_unwind_memory (next_frame, start_pc + 6, buf, buflen))
     return 0;
 
-  /* Check for sigreturn(2).  */
-  if (memcmp (buf, sigreturn, sizeof sigreturn))
+  /* Check for sigreturn(2).  Depending on how the assembler encoded
+     the `movq %rsp, %rdi' instruction, the code starts at offset 6 or
+     7.  */
+  if (memcmp (buf, sigreturn, sizeof sigreturn)
+      && memcpy (buf + 1, sigreturn, sizeof sigreturn))
     return 0;
 
   return 1;
@@ -67,9 +125,25 @@ amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
 static CORE_ADDR
 amd64obsd_sigcontext_addr (struct frame_info *next_frame)
 {
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  ULONGEST offset = (pc & (amd64obsd_page_size - 1));
+
   /* The %rsp register points at `struct sigcontext' upon entry of a
-     signal trampoline.  */
-  return frame_unwind_register_unsigned (next_frame, X86_64_RSP_REGNUM);
+     signal trampoline.  The relevant part of the trampoline is
+
+        call    *%rax
+        movq    %rsp, %rdi
+        pushq   %rdi
+        movq    $SYS_sigreturn,%rax
+        int     $0x80
+
+     (see /usr/src/sys/arch/amd64/amd64/locore.S).  The `pushq'
+     instruction clobbers %rsp, but its value is saved in `%rdi'.  */
+
+  if (offset > 5)
+    return frame_unwind_register_unsigned (next_frame, AMD64_RDI_REGNUM);
+  else
+    return frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
 }
 \f
 /* OpenBSD 3.5 or later.  */
@@ -77,7 +151,7 @@ amd64obsd_sigcontext_addr (struct frame_info *next_frame)
 /* Mapping between the general-purpose registers in `struct reg'
    format and GDB's register cache layout.  */
 
-/* From <machine/reg.h>.  Used for ptrace(2), but not for core dumps.  */
+/* From <machine/reg.h>.  */
 int amd64obsd_r_reg_offset[] =
 {
   14 * 8,                      /* %rax */
@@ -106,7 +180,7 @@ int amd64obsd_r_reg_offset[] =
   23 * 8                       /* %gs */
 };
 
-/* From <machine/signal.h>.  Also used for core dumps.  */
+/* From <machine/signal.h>.  */
 static int amd64obsd_sc_reg_offset[] =
 {
   14 * 8,                      /* %rax */
@@ -140,19 +214,26 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* Initialize general-purpose register set details first.  */
-  tdep->gregset_reg_offset = amd64obsd_sc_reg_offset;
-  tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
-  tdep->sizeof_gregset = 26 * 8;
+  amd64_init_abi (info, gdbarch);
+
+  /* Initialize general-purpose register set details.  */
+  tdep->gregset_reg_offset = amd64obsd_r_reg_offset;
+  tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset);
+  tdep->sizeof_gregset = 24 * 8;
 
-  x86_64_init_abi (info, gdbarch);
+  set_gdbarch_regset_from_core_section (gdbarch,
+                                       amd64obsd_regset_from_core_section);
 
   tdep->jb_pc_offset = 7 * 8;
 
-  set_gdbarch_pc_in_sigtramp (gdbarch, amd64obsd_pc_in_sigtramp);
+  tdep->sigtramp_p = amd64obsd_sigtramp_p;
   tdep->sigcontext_addr = amd64obsd_sigcontext_addr;
   tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
+
+  /* OpenBSD uses SVR4-style shared libraries.  */
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_lp64_fetch_link_map_offsets);
 }
 \f
 
@@ -160,11 +241,15 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 void _initialize_amd64obsd_tdep (void);
 
 void
-_initialize_amd64obsd_ndep (void)
+_initialize_amd64obsd_tdep (void)
 {
   /* The OpenBSD/amd64 native dependent code makes this assumption.  */
-  gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == X86_64_NUM_GREGS);
+  gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS);
 
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
                          GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi);
+
+  /* OpenBSD uses traditional (a.out) NetBSD-style core dumps.  */
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
+                         GDB_OSABI_NETBSD_AOUT, amd64obsd_init_abi);
 }
This page took 0.029786 seconds and 4 git commands to generate.