Vectorize gdbserver x86 debug register accessors

Message ID 1403184103-10895-1-git-send-email-gbenson@redhat.com
State Committed
Headers

Commit Message

Gary Benson June 19, 2014, 1:21 p.m. UTC
  Hi all,

This commit makes gdbserver access the x86 debug register accessor
functions via the same function vector as GDB proper.  This removes
a chunk of conditional code that was previously in i386-{nat,low}.h
and leaves a single macro as the only GDB/gdbserver difference in
nat/i386-dregs.c.

Built and regtested on RHEL6.5 x86_64.  The win32 part of this patch
is untested.

Ok to commit?

Cheers,
Gary


gdb/
2014-06-19  Gary Benson  <gbenson@redhat.com>

	* i386-nat.h (debug_hw_points): Moved to nat/i386-dregs.c.
	(i386_dr_low_type): Moved to nat/i386-dregs.h.
	(i386_dr_low): Likewise.
	(i386_dr_low_can_set_addr): Moved to nat/i386-dregs.c.
	(i386_dr_low_set_addr): Likewise.
	(i386_dr_low_get_addr): Likewise.
	(i386_dr_low_can_set_control): Likewise.
	(i386_dr_low_set_control): Likewise.
	(i386_dr_low_get_control): Likewise.
	(i386_dr_low_get_status): Likewise.
	(i386_get_debug_register_length): Likewise.
	* nat/i386-dregs.h (i386_dr_low_type): Moved from i386-nat.h.
	(i386_dr_low): Likewise.
	* nat/i386-dregs.c (i386-low.h): Remove include.
	(i386-nat.h): Likewise.
	(nat/i386-dregs.h): New include.
	(i386_dr_low_can_set_addr): Moved from i386-nat.h.
	(i386_dr_low_set_addr): Likewise.
	(i386_dr_low_get_addr): Likewise.
	(i386_dr_low_can_set_control): Likewise.
	(i386_dr_low_set_control): Likewise.
	(i386_dr_low_get_control): Likewise.
	(i386_dr_low_get_status): Likewise.
	(i386_get_debug_register_length): Likewise.
	(debug_hw_points): Likewise.

gdb/gdbserver/
2014-06-19  Gary Benson  <gbenson@redhat.com>

	* i386-low.h (i386_dr_low_can_set_addr): Removed.
	(i386_dr_low_set_addr): Likewise.
	(i386_dr_low_get_addr): Likewise.
	(i386_dr_low_can_set_control): Likewise.
	(i386_dr_low_set_control): Likewise.
	(i386_dr_low_get_control): Likewise.
	(i386_dr_low_get_status): Likewise.
	(i386_get_debug_register_length): Likewise.
	* linux-x86-low.c (i386_dr_low_set_addr):
	Changed signature.  Made static.
	(i386_dr_low_get_addr): Likewise.
	(i386_dr_low_set_control): Likewise.
	(i386_dr_low_get_control): Likewise.
	(i386_dr_low_get_status): Likewise.
	(i386_dr_low): New global variable.
	* win32-i386-low.c (i386_dr_low_set_addr):
	Changed signature.  Made static.
	(i386_dr_low_get_addr): Likewise.
	(i386_dr_low_set_control): Likewise.
	(i386_dr_low_get_control): Likewise.
	(i386_dr_low_get_status): Likewise.
	(i386_dr_low): New global variable.
---
 gdb/ChangeLog                  |   28 ++++++++++++++++
 gdb/gdbserver/ChangeLog        |   25 ++++++++++++++
 gdb/gdbserver/i386-low.h       |   41 -----------------------
 gdb/gdbserver/linux-x86-low.c  |   25 ++++++++++----
 gdb/gdbserver/win32-i386-low.c |   25 ++++++++++----
 gdb/i386-nat.h                 |   70 ----------------------------------------
 gdb/nat/i386-dregs.c           |   37 +++++++++++++++++++--
 gdb/nat/i386-dregs.h           |   31 +++++++++++++++++
 8 files changed, 154 insertions(+), 128 deletions(-)
  

Comments

Pedro Alves June 20, 2014, 11:42 a.m. UTC | #1
On 06/19/2014 02:21 PM, Gary Benson wrote:
> Hi all,
> 
> This commit makes gdbserver access the x86 debug register accessor
> functions via the same function vector as GDB proper.  This removes
> a chunk of conditional code that was previously in i386-{nat,low}.h
> and leaves a single macro as the only GDB/gdbserver difference in
> nat/i386-dregs.c.
> 
> Built and regtested on RHEL6.5 x86_64.  The win32 part of this patch
> is untested.
> 
> Ok to commit?

OK if this cross builds for mingw/win32.
  
Gary Benson June 20, 2014, 12:10 p.m. UTC | #2
Pedro Alves wrote:
> On 06/19/2014 02:21 PM, Gary Benson wrote:
> > This commit makes gdbserver access the x86 debug register accessor
> > functions via the same function vector as GDB proper.  This removes
> > a chunk of conditional code that was previously in i386-{nat,low}.h
> > and leaves a single macro as the only GDB/gdbserver difference in
> > nat/i386-dregs.c.
> > 
> > Built and regtested on RHEL6.5 x86_64.  The win32 part of this
> > patch is untested.
> > 
> > Ok to commit?
> 
> OK if this cross builds for mingw/win32.

It builds for me*.  Pushed.

Thanks,
Gary

--
* with this patch:
https://sourceware.org/ml/gdb-patches/2014-06/msg00742.html
  

Patch

diff --git a/gdb/gdbserver/i386-low.h b/gdb/gdbserver/i386-low.h
index bad03b9..e726038 100644
--- a/gdb/gdbserver/i386-low.h
+++ b/gdb/gdbserver/i386-low.h
@@ -22,44 +22,3 @@ 
 
 /* Initialize STATE.  */
 extern void i386_low_init_dregs (struct i386_debug_reg_state *state);
-
-
-/* Each target needs to provide several low-level functions
-   that will be called to insert watchpoints and hardware breakpoints
-   into the inferior, remove them, and check their status.  These
-   functions are:
-
-      i386_dr_low_set_control  -- set the debug control (DR7)
-				  register to a given value
-
-      i386_dr_low_set_addr     -- put an address into one debug register
-
-      i386_dr_low_get_status   -- return the value of the debug
-				  status (DR6) register.
-*/
-
-/* Can we update the inferior's debug registers?  */
-#define i386_dr_low_can_set_addr() 1
-
-/* Update the inferior's debug register REGNUM from STATE.  */
-extern void i386_dr_low_set_addr (const struct i386_debug_reg_state *state,
-				  int regnum);
-
-/* Return the inferior's debug register REGNUM.  */
-extern CORE_ADDR i386_dr_low_get_addr (int regnum);
-
-/* Can we update the inferior's DR7 control register?  */
-#define i386_dr_low_can_set_control() 1
-
-/* Update the inferior's DR7 debug control register from STATE.  */
-extern void i386_dr_low_set_control (const struct i386_debug_reg_state *state);
-
-/* Return the value of the inferior's DR7 debug control register.  */
-extern unsigned i386_dr_low_get_control (void);
-
-/* Return the value of the inferior's DR6 debug status register.  */
-extern unsigned i386_dr_low_get_status (void);
-
-/* Return the debug register size, in bytes.  */
-/* Note that sizeof (long) == 4 on win64.  */
-#define i386_get_debug_register_length() (sizeof (void *))
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index b8a0006..94451da 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -587,8 +587,8 @@  update_debug_registers_callback (struct inferior_list_entry *entry,
 
 /* Update the inferior's debug register REGNUM from STATE.  */
 
-void
-i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
+static void
+i386_dr_low_set_addr (int regnum, CORE_ADDR addr)
 {
   /* Only update the threads of this process.  */
   int pid = pid_of (current_inferior);
@@ -601,7 +601,7 @@  i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
 
 /* Return the inferior's debug register REGNUM.  */
 
-CORE_ADDR
+static CORE_ADDR
 i386_dr_low_get_addr (int regnum)
 {
   ptid_t ptid = ptid_of (current_inferior);
@@ -614,8 +614,8 @@  i386_dr_low_get_addr (int regnum)
 
 /* Update the inferior's DR7 debug control register from STATE.  */
 
-void
-i386_dr_low_set_control (const struct i386_debug_reg_state *state)
+static void
+i386_dr_low_set_control (unsigned long control)
 {
   /* Only update the threads of this process.  */
   int pid = pid_of (current_inferior);
@@ -625,7 +625,7 @@  i386_dr_low_set_control (const struct i386_debug_reg_state *state)
 
 /* Return the inferior's DR7 debug control register.  */
 
-unsigned
+static unsigned long
 i386_dr_low_get_control (void)
 {
   ptid_t ptid = ptid_of (current_inferior);
@@ -636,13 +636,24 @@  i386_dr_low_get_control (void)
 /* Get the value of the DR6 debug status register from the inferior
    and record it in STATE.  */
 
-unsigned
+static unsigned long
 i386_dr_low_get_status (void)
 {
   ptid_t ptid = ptid_of (current_inferior);
 
   return x86_linux_dr_get (ptid, DR_STATUS);
 }
+
+/* Low-level function vector.  */
+struct i386_dr_low_type i386_dr_low =
+  {
+    i386_dr_low_set_control,
+    i386_dr_low_set_addr,
+    i386_dr_low_get_addr,
+    i386_dr_low_get_status,
+    i386_dr_low_get_control,
+    sizeof (void *),
+  };
 
 /* Breakpoint/Watchpoint support.  */
 
diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c
index 09160dd..e894677 100644
--- a/gdb/gdbserver/win32-i386-low.c
+++ b/gdb/gdbserver/win32-i386-low.c
@@ -45,8 +45,8 @@  static int debug_registers_used = 0;
 
 /* Update the inferior's debug register REGNUM from STATE.  */
 
-void
-i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
+static void
+i386_dr_low_set_addr (int regnum, CORE_ADDR addr)
 {
   if (! (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR))
     fatal ("Invalid debug register %d", regnum);
@@ -58,7 +58,7 @@  i386_dr_low_set_addr (const struct i386_debug_reg_state *state, int regnum)
   debug_registers_used = 1;
 }
 
-CORE_ADDR
+static CORE_ADDR
 i386_dr_low_get_addr (int regnum)
 {
   gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
@@ -68,8 +68,8 @@  i386_dr_low_get_addr (int regnum)
 
 /* Update the inferior's DR7 debug control register from STATE.  */
 
-void
-i386_dr_low_set_control (const struct i386_debug_reg_state *state)
+static void
+i386_dr_low_set_control (unsigned long control)
 {
   /* debug_reg_state.dr_control_mirror is already set.
      Just notify i386_set_thread_context, i386_thread_added
@@ -78,7 +78,7 @@  i386_dr_low_set_control (const struct i386_debug_reg_state *state)
   debug_registers_used = 1;
 }
 
-unsigned
+static unsigned long
 i386_dr_low_get_control (void)
 {
   return debug_reg_state.dr_control_mirror;
@@ -87,7 +87,7 @@  i386_dr_low_get_control (void)
 /* Get the value of the DR6 debug status register from the inferior
    and record it in STATE.  */
 
-unsigned
+static unsigned long
 i386_dr_low_get_status (void)
 {
   /* We don't need to do anything here, the last call to thread_rec for
@@ -95,6 +95,17 @@  i386_dr_low_get_status (void)
   return debug_reg_state.dr_status_mirror;
 }
 
+/* Low-level function vector.  */
+struct i386_dr_low_type i386_dr_low =
+  {
+    i386_dr_low_set_control,
+    i386_dr_low_set_addr,
+    i386_dr_low_get_addr,
+    i386_dr_low_get_status,
+    i386_dr_low_get_control,
+    sizeof (void *),
+  };
+
 /* Breakpoint/watchpoint support.  */
 
 static int
diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h
index 4a213b3..acac71a 100644
--- a/gdb/i386-nat.h
+++ b/gdb/i386-nat.h
@@ -27,82 +27,12 @@ 
 
 /* Hardware-assisted breakpoints and watchpoints.  */
 
-/* Whether or not to print the mirrored debug registers.  */
-extern int debug_hw_points;
-
 /* Add watchpoint methods to the provided target_ops.  
    Targets using i386 family debug registers for watchpoints should call
    this.  */
 struct target_ops;
 extern void i386_use_watchpoints (struct target_ops *);
 
-/* Support for hardware watchpoints and breakpoints using the i386
-   debug registers.
-
-   Each target should provide several low-level functions
-   regrouped into i386_dr_low_type struct below.  These functions
-   that will be called to insert watchpoints and hardware breakpoints
-   into the inferior, remove them, and check their status.  These
-   functions are:
-
-      set_control              -- set the debug control (DR7)
-				  register to a given value for all LWPs
-
-      set_addr                 -- put an address into one debug
-				  register for all LWPs
-
-      get_addr                 -- return the address in a given debug
-				  register of the current LWP
-
-      get_status               -- return the value of the debug
-				  status (DR6) register for current LWP
-
-      get_control               -- return the value of the debug
-				  control (DR7) register for current LWP
-
-   Additionally, the native file should set the debug_register_length
-   field to 4 or 8 depending on the number of bytes used for
-   deubg registers.  */
-
-struct i386_dr_low_type
-  {
-    void (*set_control) (unsigned long);
-    void (*set_addr) (int, CORE_ADDR);
-    CORE_ADDR (*get_addr) (int);
-    unsigned long (*get_status) (void);
-    unsigned long (*get_control) (void);
-    int debug_register_length;
-  };
-
-extern struct i386_dr_low_type i386_dr_low;
-
-/* Can we update the inferior's debug registers?  */
-#define i386_dr_low_can_set_addr() (i386_dr_low.set_addr != NULL)
-
-/* Update the inferior's debug register REGNUM from STATE.  */
-#define i386_dr_low_set_addr(new_state, i) \
-  (i386_dr_low.set_addr ((i), (new_state)->dr_mirror[(i)]))
-
-/* Return the inferior's debug register REGNUM.  */
-#define i386_dr_low_get_addr(i) (i386_dr_low.get_addr ((i)))
-
-/* Can we update the inferior's DR7 control register?  */
-#define i386_dr_low_can_set_control() (i386_dr_low.set_control != NULL)
-
-/* Update the inferior's DR7 debug control register from STATE.  */
-#define i386_dr_low_set_control(new_state) \
-  (i386_dr_low.set_control ((new_state)->dr_control_mirror))
-
-/* Return the value of the inferior's DR7 debug control register.  */
-#define i386_dr_low_get_control() (i386_dr_low.get_control ())
-
-/* Return the value of the inferior's DR6 debug status register.  */
-#define i386_dr_low_get_status() (i386_dr_low.get_status ())
-
-/* Return the debug register size, in bytes.  */
-#define i386_get_debug_register_length() \
-  (i386_dr_low.debug_register_length)
-
 /* Use this function to set i386_dr_low debug_register_length field
    rather than setting it directly to check that the length is only
    set once.  It also enables the 'maint set/show show-debug-regs' 
diff --git a/gdb/nat/i386-dregs.c b/gdb/nat/i386-dregs.c
index 0067a90..e7d1620 100644
--- a/gdb/nat/i386-dregs.c
+++ b/gdb/nat/i386-dregs.c
@@ -19,12 +19,11 @@ 
 
 #ifdef GDBSERVER
 #include "server.h"
-#include "i386-low.h"
 #else
 #include "defs.h"
-#include "i386-nat.h"
 #include "inferior.h"
 #endif
+#include "nat/i386-dregs.h"
 
 /* Support for hardware watchpoints and breakpoints using the i386
    debug registers.
@@ -37,6 +36,35 @@ 
    The functions below implement debug registers sharing by reference
    counts, and allow to watch regions up to 16 bytes long.  */
 
+/* Accessor macros for low-level function vector.  */
+
+/* Can we update the inferior's debug registers?  */
+#define i386_dr_low_can_set_addr() (i386_dr_low.set_addr != NULL)
+
+/* Update the inferior's debug register REGNUM from STATE.  */
+#define i386_dr_low_set_addr(new_state, i) \
+  (i386_dr_low.set_addr ((i), (new_state)->dr_mirror[(i)]))
+
+/* Return the inferior's debug register REGNUM.  */
+#define i386_dr_low_get_addr(i) (i386_dr_low.get_addr ((i)))
+
+/* Can we update the inferior's DR7 control register?  */
+#define i386_dr_low_can_set_control() (i386_dr_low.set_control != NULL)
+
+/* Update the inferior's DR7 debug control register from STATE.  */
+#define i386_dr_low_set_control(new_state) \
+  (i386_dr_low.set_control ((new_state)->dr_control_mirror))
+
+/* Return the value of the inferior's DR7 debug control register.  */
+#define i386_dr_low_get_control() (i386_dr_low.get_control ())
+
+/* Return the value of the inferior's DR6 debug status register.  */
+#define i386_dr_low_get_status() (i386_dr_low.get_status ())
+
+/* Return the debug register size, in bytes.  */
+#define i386_get_debug_register_length() \
+  (i386_dr_low.debug_register_length)
+
 /* Support for 8-byte wide hw watchpoints.  */
 #define TARGET_HAS_DR_LEN_8 (i386_get_debug_register_length () == 8)
 
@@ -147,8 +175,11 @@ 
 /* Types of operations supported by i386_handle_nonaligned_watchpoint.  */
 typedef enum { WP_INSERT, WP_REMOVE, WP_COUNT } i386_wp_op_t;
 
-/* Print debugging messages.  */
 #ifndef GDBSERVER
+/* Whether or not to print the mirrored debug registers.  */
+extern int debug_hw_points;
+
+/* Print debugging messages.  */
 #define debug_printf(fmt, args...) \
   fprintf_unfiltered (gdb_stdlog, fmt, ##args);
 #endif
diff --git a/gdb/nat/i386-dregs.h b/gdb/nat/i386-dregs.h
index 58029ef..16edf63 100644
--- a/gdb/nat/i386-dregs.h
+++ b/gdb/nat/i386-dregs.h
@@ -35,6 +35,37 @@ 
 /* Forward declaration.  */
 enum target_hw_bp_type;
 
+/* Low-level function vector.  */
+
+struct i386_dr_low_type
+  {
+    /* Set the debug control (DR7) register to a given value for
+       all LWPs.  May be NULL if the debug control register cannot
+       be set.  */
+    void (*set_control) (unsigned long);
+
+    /* Put an address into one debug register for all LWPs.  May
+       be NULL if debug registers cannot be set*/
+    void (*set_addr) (int, CORE_ADDR);
+
+    /* Return the address in a given debug register of the current
+       LWP.  */
+    CORE_ADDR (*get_addr) (int);
+
+    /* Return the value of the debug status (DR6) register for
+       current LWP.  */
+    unsigned long (*get_status) (void);
+
+    /* Return the value of the debug control (DR7) register for
+       current LWP.  */
+    unsigned long (*get_control) (void);
+
+    /* Number of bytes used for debug registers (4 or 8).  */
+    int debug_register_length;
+  };
+
+extern struct i386_dr_low_type i386_dr_low;
+
 /* Debug registers' indices.  */
 #define DR_FIRSTADDR 0
 #define DR_LASTADDR  3