* amd64obsd-tdep.c: Include "regcache.h" and "bsd-uthread.h".
authorMark Kettenis <kettenis@gnu.org>
Sun, 4 Dec 2005 20:19:25 +0000 (20:19 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sun, 4 Dec 2005 20:19:25 +0000 (20:19 +0000)
(amd64obsd_uthread_reg_offset): New variable.
(AMD64OBSD_UTHREAD_RSP_OFFSET): New define.
(amd64obsd_supply_uthread, amd64obsd_collect_uthread): New
functions.
(amd64obsd_init_abi): Set supply_uthread and collect_uthread.
* Makefile.in (amd64obsd-tdep.o): Update dependencies.

gdb/ChangeLog
gdb/Makefile.in
gdb/amd64obsd-tdep.c

index d499633..c3ce8f8 100644 (file)
@@ -1,3 +1,13 @@
+2005-12-04  Mark Kettenis  <kettenis@gnu.org>
+
+       * amd64obsd-tdep.c: Include "regcache.h" and "bsd-uthread.h".
+       (amd64obsd_uthread_reg_offset): New variable.
+       (AMD64OBSD_UTHREAD_RSP_OFFSET): New define.
+       (amd64obsd_supply_uthread, amd64obsd_collect_uthread): New
+       functions.
+       (amd64obsd_init_abi): Set supply_uthread and collect_uthread.
+       * Makefile.in (amd64obsd-tdep.o): Update dependencies.
+
 2005-12-02  Andrew Stubbs  <andrew.stubbs@st.com>
 
        * breakpoint.c (BREAK_ARGS_HELP): New mecro.
index 8d8a79e..b3d71ca 100644 (file)
@@ -1716,9 +1716,9 @@ amd64obsd-nat.o: amd64obsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
        $(target_h) $(gdb_assert_h) $(amd64_tdep_h) $(amd64_nat_h) \
        $(bsd_kvm_h)
 amd64obsd-tdep.o: amd64obsd-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \
-       $(symtab_h) $(objfiles_h) $(osabi_h) $(regset_h) $(target_h) \
-       $(gdb_assert_h) $(gdb_string_h) $(amd64_tdep_h) $(i387_tdep_h) \
-       $(solib_svr4_h)
+       $(symtab_h) $(objfiles_h) $(osabi_h) $(regcache_h) $(regset_h) \
+       $(target_h) $(gdb_assert_h) $(gdb_string_h) $(amd64_tdep_h) \
+       $(i387_tdep_h) $(solib_svr4_h) $(bsd_uthread_h)
 amd64-sol2-tdep.o: amd64-sol2-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \
        $(regcache_h) $(osabi_h) $(symtab_h) $(gdb_string_h) $(amd64_tdep_h) \
        $(solib_svr4_h)
index acef49e..66d0ab2 100644 (file)
@@ -25,6 +25,7 @@
 #include "symtab.h"
 #include "objfiles.h"
 #include "osabi.h"
+#include "regcache.h"
 #include "regset.h"
 #include "target.h"
 
@@ -34,6 +35,7 @@
 #include "amd64-tdep.h"
 #include "i387-tdep.h"
 #include "solib-svr4.h"
+#include "bsd-uthread.h"
 
 /* Support for core dumps.  */
 
@@ -211,6 +213,127 @@ static int amd64obsd_sc_reg_offset[] =
   15 * 8                       /* %gs */
 };
 
+/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c.  */
+static int amd64obsd_uthread_reg_offset[] =
+{
+  19 * 8,                      /* %rax */
+  16 * 8,                      /* %rbx */
+  18 * 8,                      /* %rcx */
+  17 * 8,                      /* %rdx */
+  14 * 8,                      /* %rsi */
+  13 * 8,                      /* %rdi */
+  15 * 8,                      /* %rbp */
+  -1,                          /* %rsp */
+  12 * 8,                      /* %r8 ... */
+  11 * 8,
+  10 * 8,
+  9 * 8,
+  8 * 8,
+  7 * 8,
+  6 * 8,
+  5 * 8,                       /* ... %r15 */
+  20 * 8,                      /* %rip */
+  4 * 8,                       /* %eflags */
+  21 * 8,                      /* %cs */
+  -1,                          /* %ss */
+  3 * 8,                       /* %ds */
+  2 * 8,                       /* %es */
+  1 * 8,                       /* %fs */
+  0 * 8                                /* %gs */
+};
+
+/* Offset within the thread structure where we can find the saved
+   stack pointer (%esp).  */
+#define AMD64OBSD_UTHREAD_RSP_OFFSET   400
+
+static void
+amd64obsd_supply_uthread (struct regcache *regcache,
+                         int regnum, CORE_ADDR addr)
+{
+  CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
+  CORE_ADDR sp = 0;
+  gdb_byte buf[8];
+  int i;
+
+  gdb_assert (regnum >= -1);
+
+  if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
+    {
+      int offset;
+
+      /* Fetch stack pointer from thread structure.  */
+      sp = read_memory_unsigned_integer (sp_addr, 8);
+
+      /* Adjust the stack pointer such that it looks as if we just
+         returned from _thread_machdep_switch.  */
+      offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
+      store_unsigned_integer (buf, 8, sp + offset);
+      regcache_raw_supply (regcache, AMD64_RSP_REGNUM, buf);
+    }
+
+  for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
+    {
+      if (amd64obsd_uthread_reg_offset[i] != -1
+         && (regnum == -1 || regnum == i))
+       {
+         /* Fetch stack pointer from thread structure (if we didn't
+             do so already).  */
+         if (sp == 0)
+           sp = read_memory_unsigned_integer (sp_addr, 8);
+
+         /* Read the saved register from the stack frame.  */
+         read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
+         regcache_raw_supply (regcache, i, buf);
+       }
+    }
+}
+
+static void
+amd64obsd_collect_uthread (const struct regcache *regcache,
+                          int regnum, CORE_ADDR addr)
+{
+  CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET;
+  CORE_ADDR sp = 0;
+  gdb_byte buf[8];
+  int i;
+
+  gdb_assert (regnum >= -1);
+
+  if (regnum == -1 || regnum == AMD64_RSP_REGNUM)
+    {
+      int offset;
+
+      /* Calculate the stack pointer (frame pointer) that will be
+         stored into the thread structure.  */
+      offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8;
+      regcache_raw_collect (regcache, AMD64_RSP_REGNUM, buf);
+      sp = extract_unsigned_integer (buf, 8) - offset;
+
+      /* Store the stack pointer.  */
+      write_memory_unsigned_integer (sp_addr, 8, sp);
+
+      /* The stack pointer was (potentially) modified.  Make sure we
+         build a proper stack frame.  */
+      regnum = -1;
+    }
+
+  for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++)
+    {
+      if (amd64obsd_uthread_reg_offset[i] != -1
+         && (regnum == -1 || regnum == i))
+       {
+         /* Fetch stack pointer from thread structure (if we didn't
+             calculate it already).  */
+         if (sp == 0)
+           sp = read_memory_unsigned_integer (sp_addr, 8);
+
+         /* Write the register into the stack frame.  */
+         regcache_raw_collect (regcache, i, buf);
+         write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8);
+       }
+    }
+}
+
 static void
 amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -233,6 +356,10 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
 
+  /* OpenBSD provides a user-level threads implementation.  */
+  bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread);
+  bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread);
+
   /* OpenBSD uses SVR4-style shared libraries.  */
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_lp64_fetch_link_map_offsets);