From patchwork Thu Jun 19 13:21:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 1567 Received: (qmail 25176 invoked by alias); 19 Jun 2014 13:21:52 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 24942 invoked by uid 89); 19 Jun 2014 13:21:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 19 Jun 2014 13:21:47 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5JDLj6g001424 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 19 Jun 2014 09:21:45 -0400 Received: from blade.nx (ovpn-116-59.ams2.redhat.com [10.36.116.59]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5JDLiL2028164 for ; Thu, 19 Jun 2014 09:21:44 -0400 Received: from blade.nx (localhost [127.0.0.1]) by blade.nx (Postfix) with ESMTP id 6872D26243A for ; Thu, 19 Jun 2014 14:21:43 +0100 (BST) From: Gary Benson To: gdb-patches@sourceware.org Subject: [PATCH] Vectorize gdbserver x86 debug register accessors Date: Thu, 19 Jun 2014 14:21:43 +0100 Message-Id: <1403184103-10895-1-git-send-email-gbenson@redhat.com> X-IsSubscribed: yes 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 * 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 * 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(-) 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