* inf-ptrace.h: Update copyright year. Sync comment with
authorMark Kettenis <kettenis@gnu.org>
Mon, 10 Jan 2005 20:36:38 +0000 (20:36 +0000)
committerMark Kettenis <kettenis@gnu.org>
Mon, 10 Jan 2005 20:36:38 +0000 (20:36 +0000)
inf-ptrace.c.
(inf_ptrace_trad_target): New prototype.
* inf-ptrace.c: Update copyright year.  Include "regcache.h" and
"gdb_assert.h"
(inf_ptrace_target): Add comment.
(inf_ptrace+register_u_offset): New variable.
(inf_ptrace_fetch_register, inf_ptrace_fetch_registers)
(inf_ptrace_store_register, inf_ptrace_store_registers)
(inf_ptrace_trad_target): New functions.
* Makefile.in (inf-ptrace.o): Update dependencies.

gdb/ChangeLog
gdb/Makefile.in
gdb/inf-ptrace.c
gdb/inf-ptrace.h

index 4fc76e12b58e58ca7249d799e12b8f46dd3f7079..d3c3a7bbfbecc52623c5d642d933388d912f12c6 100644 (file)
@@ -1,3 +1,17 @@
+2005-01-10  Mark Kettenis  <kettenis@gnu.org>
+
+       * inf-ptrace.h: Update copyright year.  Sync comment with
+       inf-ptrace.c.
+       (inf_ptrace_trad_target): New prototype.
+       * inf-ptrace.c: Update copyright year.  Include "regcache.h" and
+       "gdb_assert.h"
+       (inf_ptrace_target): Add comment.
+       (inf_ptrace+register_u_offset): New variable.
+       (inf_ptrace_fetch_register, inf_ptrace_fetch_registers)
+       (inf_ptrace_store_register, inf_ptrace_store_registers)
+       (inf_ptrace_trad_target): New functions.
+       * Makefile.in (inf-ptrace.o): Update dependencies.
+
 2005-01-09  Mark Kettenis  <kettenis@gnu.org>
 
        * configure.ac: Provide prerequisite headers when checking
index 77f5e6296c3e90e97931e307614d487b6e7c66c1..68c2a600ab7f2c8ef76ef0f8f93ef3d647ba0443 100644 (file)
@@ -2079,8 +2079,8 @@ inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \
        $(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) \
        $(inflow_h)
 inf-ptrace.o: inf-ptrace.c $(defs_h) $(command_h) $(inferior_h) $(inflow_h) \
-       $(gdbcore_h) $(observer_h) $(gdb_string_h) $(gdb_ptrace_h) \
-       $(gdb_wait_h) $(inf_child_h)
+       $(gdbcore_h) $(observer_h) $(regcache_h) $(gdb_assert_h) \
+       $(gdb_string_h) $(gdb_ptrace_h) $(gdb_wait_h) $(inf_child_h)
 inf-ttrace.o: inf-ttrace.c $(defs_h) $(command_h) $(gdbcore_h) \
        $(gdbthread_h) $(inferior_h) $(observer_h) $(target_h) \
        $(gdb_assert_h) $(gdb_string_h) $(inf_child_h) $(inf_ttrace_h)
index c2f5ead9874b463ef8ce093a6088a5db3a470cbd..821e4240ffbab27d53b64f5cf30132dbc7c2db09 100644 (file)
@@ -1,7 +1,8 @@
 /* Low-level child interface to ptrace.
 
    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2004, 2005
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,7 +27,9 @@
 #include "inflow.h"
 #include "gdbcore.h"
 #include "observer.h"
+#include "regcache.h"
 
+#include "gdb_assert.h"
 #include "gdb_string.h"
 #include "gdb_ptrace.h"
 #include "gdb_wait.h"
@@ -592,10 +595,14 @@ inf_ptrace_pid_to_str (ptid_t ptid)
   return normal_pid_to_str (ptid);
 }
 
+/* Create a prototype ptrace target.  The client can override it with
+   local methods.  */
+
 struct target_ops *
 inf_ptrace_target (void)
 {
   struct target_ops *t = inf_child_target ();
+
   t->to_open = inf_ptrace_open;
   t->to_attach = inf_ptrace_attach;
   t->to_post_attach = inf_ptrace_post_attach;
@@ -633,5 +640,128 @@ inf_ptrace_target (void)
   t->to_has_execution = 1;
   t->to_magic = OPS_MAGIC;
   ptrace_ops_hack = t;
+
+  return t;
+}
+\f
+
+/* Pointer to a function that returns the oggset within the user area
+   where a particular register is stored.  */
+static CORE_ADDR (*inf_ptrace_register_u_offset)(int);
+
+/* Fetch register REGNUM from the inferior.  */
+
+static void
+inf_ptrace_fetch_register (int regnum)
+{
+  CORE_ADDR addr;
+  size_t size;
+  PTRACE_TYPE_RET *buf;
+  int pid, i;
+
+  /* Cater for systems like GNU/Linux, that implement threads as
+     seperate processes.  */
+  pid = ptid_get_lwp (inferior_ptid);
+  if (pid == 0)
+    pid = ptid_get_pid (inferior_ptid);
+
+  /* This isn't really an address, but ptrace thinks of it as one.  */
+  addr = inf_ptrace_register_u_offset (regnum);
+  size = register_size (current_gdbarch, regnum);
+
+  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+  buf = alloca (size);
+
+  /* Read the register contents from the inferior a chuck at the time.  */
+  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+    {
+      errno = 0;
+      buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3) addr, 0);
+      if (errno != 0)
+       error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regnum),
+              regnum, safe_strerror (errno));
+
+      addr += sizeof (PTRACE_TYPE_RET);
+    }
+  regcache_raw_supply (current_regcache, regnum, buf);
+}
+
+/* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
+   for all registers.  */
+
+static void
+inf_ptrace_fetch_registers (int regnum)
+{
+  if (regnum == -1)
+    for (regnum = 0; regnum < NUM_REGS; regnum++)
+      inf_ptrace_fetch_register (regnum);
+  else
+    inf_ptrace_fetch_register (regnum);
+}
+
+/* Store register REGNUM into the inferior.  */
+
+static void
+inf_ptrace_store_register (int regnum)
+{
+  CORE_ADDR addr;
+  size_t size;
+  PTRACE_TYPE_RET *buf;
+  int pid, i;
+
+  /* Cater for systems like GNU/Linux, that implement threads as
+     seperate processes.  */
+  pid = ptid_get_lwp (inferior_ptid);
+  if (pid == 0)
+    pid = ptid_get_pid (inferior_ptid);
+
+  /* This isn't really an address, but ptrace thinks of it as one.  */
+  addr = inf_ptrace_register_u_offset (regnum);
+  size = register_size (current_gdbarch, regnum);
+
+  gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
+  buf = alloca (size);
+
+  /* Write the register contents into the inferior a chunk at the time.  */
+  regcache_raw_collect (current_regcache, regnum, buf);
+  for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
+    {
+      errno = 0;
+      ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3) addr, buf[i]);
+      if (errno != 0)
+       error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regnum),
+              regnum, safe_strerror (errno));
+
+      addr += sizeof (PTRACE_TYPE_RET);
+    }
+}
+
+/* Store register REGNUM back into the inferior.  If REGNUM is -1, do
+   this for all registers.  */
+
+void
+inf_ptrace_store_registers (int regnum)
+{
+  if (regnum == -1)
+    for (regnum = 0; regnum < NUM_REGS; regnum++)
+      inf_ptrace_store_register (regnum);
+  else
+    inf_ptrace_store_register (regnum);
+}
+
+/* Create a "traditional" ptrace target.  REGISTER_U_OFFSET should be
+   a function returning the offset within the user area where a
+   particular register is stored.  */
+
+struct target_ops *
+inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)(int))
+{
+  struct target_ops *t = inf_ptrace_target();
+
+  gdb_assert (register_u_offset);
+  inf_ptrace_register_u_offset = register_u_offset;
+  t->to_fetch_registers = inf_ptrace_fetch_registers;
+  t->to_store_registers = inf_ptrace_store_registers;
+
   return t;
 }
index e9ceae3c9636502554f595982715430c8feedab7..ef86b518e27939f2a00b2089e9040d5cb28570bd 100644 (file)
@@ -1,7 +1,6 @@
-/* Low level Unix child interface to ptrace, for GDB when running
-   under Unix.
+/* Low level child interface to ptrace.
 
-   Copyright 2004 Free Software Foundation, Inc.
+   Copyright 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 extern struct target_ops *inf_ptrace_target (void);
 
+/* Create a "traditional" ptrace target.  REGISTER_U_OFFSET should be
+   a function returning the offset within the user area where a
+   particular register is stored.  */
+
+extern struct target_ops *
+  inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)(int));
+
 #endif