bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH,Hurd] Add hardware watch support


From: Samuel Thibault
Subject: [PATCH,Hurd] Add hardware watch support
Date: Sun, 31 Aug 2014 03:57:27 +0200
User-agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30)

2014-08-31  Samuel Thibault  <samuel.thibault@ens-lyon.org>

        Add hardware watch support to gnu-i386 platform.

        * gdb/gdb/gnu-nat.c (inf_threads): New function.
        * gdb/gdb/gnu-nat.h (inf_threads): New declaration.
        * gdb/gdb/i386gnu-nat.c: Include "i386-nat.h" and "inf-child.h"
        [i386_DEBUG_STATE] (DR_FIRSTADDR, DR_LASTADDR, DR_STATUS, DR_CONTROL):
        New macros
        [i386_DEBUG_STATE] (i386_gnu_dr_get, i386_gnu_dr_set,
        i386_gnu_dr_set_control, i386_gnu_dr_set_addr, i386_gnu_dr_get_reg,
        i386_gnu_dr_get_addr, 386_gnu_dr_get_status, i386_gnu_dr_get_control):
        New functions
        [i386_DEBUG_STATE] (_initialize_i386gnu_nat): Initialize hardware i386
        debugging register hooks.

Index: gdb/gdb/gnu-nat.c
===================================================================
--- gdb.orig/gdb/gnu-nat.c
+++ gdb/gdb/gnu-nat.c
@@ -987,6 +987,16 @@ inf_port_to_thread (struct inf *inf, mac
   return 0;
 }
 
+/* Interate F over threads.  */
+void
+inf_threads (struct inf *inf, void (*f)(struct proc *thread))
+{
+  struct proc *thread;
+
+  for (thread = inf->threads; thread; thread = thread->next)
+    f(thread);
+}
+
 
 /* Make INF's list of threads be consistent with reality of TASK.  */
 void
Index: gdb/gdb/gnu-nat.h
===================================================================
--- gdb.orig/gdb/gnu-nat.h
+++ gdb/gdb/gnu-nat.h
@@ -29,6 +29,9 @@ extern struct inf *gnu_current_inf;
 /* Converts a GDB pid to a struct proc.  */
 struct proc *inf_tid_to_thread (struct inf *inf, int tid);
 
+/* Iterate F over threads */
+void inf_threads (struct inf *inf, void (*f)(struct proc *thread));
+
 /* Makes sure that INF's thread list is synced with the actual process.  */
 int inf_update_procs (struct inf *inf);
 
Index: gdb/gdb/i386gnu-nat.c
===================================================================
--- gdb.orig/gdb/i386gnu-nat.c
+++ gdb/gdb/i386gnu-nat.c
@@ -18,6 +18,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "i386-nat.h"
 #include "inferior.h"
 #include "floatformat.h"
 #include "regcache.h"
@@ -35,6 +36,7 @@
 #include "i386-tdep.h"
 
 #include "gnu-nat.h"
+#include "inf-child.h"
 #include "i387-tdep.h"
 
 #ifdef HAVE_SYS_PROCFS_H
@@ -309,6 +311,142 @@ gnu_store_registers (struct target_ops *
     }
 }
 
+
+/* Support for debug registers.  */
+
+#ifdef i386_DEBUG_STATE
+
+#ifndef DR_FIRSTADDR
+#define DR_FIRSTADDR 0
+#endif
+
+#ifndef DR_LASTADDR
+#define DR_LASTADDR 3
+#endif
+
+#ifndef DR_STATUS
+#define DR_STATUS 6
+#endif
+
+#ifndef DR_CONTROL
+#define DR_CONTROL 7
+#endif
+
+/* Get debug registers for thread THREAD.  */
+
+static void
+i386_gnu_dr_get(struct i386_debug_state *regs, struct proc *thread)
+{
+  mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT;
+  error_t err;
+
+  err = thread_get_state (thread->port, i386_DEBUG_STATE,
+                         (thread_state_t) regs, &count);
+  if (err || count != i386_DEBUG_STATE_COUNT)
+    {
+      warning (_("Couldn't fetch debug state from %s"),
+              proc_string (thread));
+      return;
+    }
+}
+
+/* Set debug registers for thread THREAD.  */
+
+static void
+i386_gnu_dr_set(const struct i386_debug_state *regs, struct proc *thread)
+{
+  error_t err;
+
+  err = thread_set_state (thread->port, i386_DEBUG_STATE,
+                         (thread_state_t) regs, i386_DEBUG_STATE_COUNT);
+  if (err)
+    {
+      warning (_("Couldn't store debug state into %s"),
+              proc_string (thread));
+      return;
+    }
+}
+
+/* Set DR_CONTROL to ADDR in all threads.  */
+
+static void
+i386_gnu_dr_set_control (unsigned long control)
+{
+  void f(struct proc *thread)
+  {
+    struct i386_debug_state regs;
+    i386_gnu_dr_get(&regs, thread);
+    regs.dr[DR_CONTROL] = control;
+    i386_gnu_dr_set(&regs, thread);
+  }
+
+  inf_update_procs (gnu_current_inf);
+  inf_threads(gnu_current_inf, f);
+}
+
+/* Set address REGNUM (zero based) to ADDR in all threads.  */
+
+static void
+i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
+{
+  void f(struct proc *thread)
+  {
+    struct i386_debug_state regs;
+    i386_gnu_dr_get(&regs, thread);
+    regs.dr[DR_FIRSTADDR + regnum] = addr;
+    i386_gnu_dr_set(&regs, thread);
+  }
+
+  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+
+  inf_update_procs (gnu_current_inf);
+  inf_threads(gnu_current_inf, f);
+}
+
+/* Get debug register REGNUM value from only the one LWP of PTID.  */
+
+static unsigned long
+i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
+{
+  struct i386_debug_state regs;
+  struct proc *thread;
+
+  /* Make sure we know about new threads.  */
+  inf_update_procs (gnu_current_inf);
+
+  thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid));
+  i386_gnu_dr_get(&regs, thread);
+
+  return regs.dr[regnum];
+}
+
+/* Return the inferior's debug register REGNUM.  */
+
+static CORE_ADDR
+i386_gnu_dr_get_addr (int regnum)
+{
+  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+
+  return i386_gnu_dr_get_reg (inferior_ptid, DR_FIRSTADDR + regnum);
+}
+
+/* Get DR_STATUS from only the one thread of INFERIOR_PTID.  */
+
+static unsigned long
+i386_gnu_dr_get_status (void)
+{
+  return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
+}
+
+/* Return the inferior's DR7 debug control register.  */
+
+static unsigned long
+i386_gnu_dr_get_control (void)
+{
+  return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
+}
+#endif /* i386_DEBUG_STATE */
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_i386gnu_nat;
 
@@ -320,6 +458,17 @@ _initialize_i386gnu_nat (void)
   /* Fill in the generic GNU/Hurd methods.  */
   t = gnu_target ();
 
+#ifdef i386_DEBUG_STATE
+  i386_use_watchpoints (t);
+
+  i386_dr_low.set_control = i386_gnu_dr_set_control;
+  i386_dr_low.set_addr = i386_gnu_dr_set_addr;
+  i386_dr_low.get_addr = i386_gnu_dr_get_addr;
+  i386_dr_low.get_status = i386_gnu_dr_get_status;
+  i386_dr_low.get_control = i386_gnu_dr_get_control;
+  i386_set_debug_register_length (4);
+#endif /* i386_DEBUG_STATE */
+
   t->to_fetch_registers = gnu_fetch_registers;
   t->to_store_registers = gnu_store_registers;
 
Index: gdb/gdb/config/i386/i386gnu.mh
===================================================================
--- gdb.orig/gdb/config/i386/i386gnu.mh
+++ gdb/gdb/config/i386/i386gnu.mh
@@ -1,5 +1,5 @@
 # Host: Intel 386 running the GNU Hurd
-NATDEPFILES= i386gnu-nat.o gnu-nat.o core-regset.o fork-child.o \
+NATDEPFILES= i386gnu-nat.o gnu-nat.o i386-nat.o core-regset.o fork-child.o \
             notify_S.o process_reply_S.o msg_reply_S.o \
             msg_U.o exc_request_U.o exc_request_S.o
 HAVE_NATIVE_GCORE_HOST = 1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]