summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/i386-low.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@codesourcery.com>2010-08-25 14:40:21 +0000
committerPedro Alves <pedro@codesourcery.com>2010-08-25 14:40:21 +0000
commit57c1cfefed9d946b9bf5849587cca013c644ddff (patch)
tree255b7dbba3ca606dc48615a33df77d21a65e6a46 /gdb/gdbserver/i386-low.c
parente87d6c313d172c51a3e9fb11120924ca55d4b0d7 (diff)
downloadgdb-57c1cfefed9d946b9bf5849587cca013c644ddff.tar.gz
PR threads/10729
* linux-x86-low.c (update_debug_registers_callback): New. (i386_dr_low_set_addr): Use it. (i386_dr_low_get_addr): New. (i386_dr_low_set_control): Use update_debug_registers_callback. (i386_dr_low_get_control): New. (i386_dr_low_get_status): Adjust. * linux-low.c (linux_stop_lwp): New. * linux-low.h (linux_stop_lwp): Declare. * i386-low.c (I386_DR_GET_RW_LEN): Take the dr7 contents as argument instead of a i386_debug_reg_state. (I386_DR_WATCH_HIT): Take the dr6 contents as argument instead of a i386_debug_reg_state. (i386_insert_aligned_watchpoint): Adjust. (i386_remove_aligned_watchpoint): Adjust. (i386_low_stopped_data_address): Read the debug registers from the inferior instead of from the mirrors. * i386-low.h (struct i386_debug_reg_state): Extend comment. (i386_dr_low_get_addr): Declare. (i386_dr_low_get_control): Declare. (i386_dr_low_get_status): Change prototype. * win32-i386-low.c (dr_status_mirror, dr_control_mirror): New globals. (i386_dr_low_get_addr): New. (i386_dr_low_get_control): New. (i386_dr_low_get_status): Adjust prototype. Return dr_status_mirror. (i386_initial_stuff): Clear dr_status_mirror and dr_control_mirror. (i386_get_thread_context): Adjust. (i386_set_thread_context): Adjust. (i386_thread_added): Adjust.
Diffstat (limited to 'gdb/gdbserver/i386-low.c')
-rw-r--r--gdb/gdbserver/i386-low.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/gdb/gdbserver/i386-low.c b/gdb/gdbserver/i386-low.c
index 494b8087f2a..f13ae269cf4 100644
--- a/gdb/gdbserver/i386-low.c
+++ b/gdb/gdbserver/i386-low.c
@@ -132,12 +132,12 @@ enum target_hw_bp_type
} while (0)
/* Get from DR7 the RW and LEN fields for the I'th debug register. */
-#define I386_DR_GET_RW_LEN(state, i) \
- (((state)->dr_control_mirror \
+#define I386_DR_GET_RW_LEN(dr7, i) \
+ (((dr7) \
>> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
/* Did the watchpoint whose address is in the I'th register break? */
-#define I386_DR_WATCH_HIT(state,i) ((state)->dr_status_mirror & (1 << (i)))
+#define I386_DR_WATCH_HIT(dr6, i) ((dr6) & (1 << (i)))
/* A macro to loop over all debug registers. */
#define ALL_DEBUG_REGISTERS(i) for (i = 0; i < DR_NADDR; i++)
@@ -271,7 +271,7 @@ i386_insert_aligned_watchpoint (struct i386_debug_reg_state *state,
{
if (!I386_DR_VACANT (state, i)
&& state->dr_mirror[i] == addr
- && I386_DR_GET_RW_LEN (state, i) == len_rw_bits)
+ && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
{
state->dr_ref_count[i]++;
return 0;
@@ -329,7 +329,7 @@ i386_remove_aligned_watchpoint (struct i386_debug_reg_state *state,
{
if (!I386_DR_VACANT (state, i)
&& state->dr_mirror[i] == addr
- && I386_DR_GET_RW_LEN (state, i) == len_rw_bits)
+ && I386_DR_GET_RW_LEN (state->dr_control_mirror, i) == len_rw_bits)
{
if (--state->dr_ref_count[i] == 0) /* No longer in use? */
{
@@ -539,21 +539,26 @@ i386_low_stopped_data_address (struct i386_debug_reg_state *state,
CORE_ADDR addr = 0;
int i;
int rc = 0;
+ unsigned status;
+ unsigned control;
- /* Get dr_status_mirror for use by I386_DR_WATCH_HIT. */
- i386_dr_low_get_status (state);
+ /* Get the current values the inferior has. If the thread was
+ running when we last changed watchpoints, the mirror no longer
+ represents what was set in this LWP's debug registers. */
+ status = i386_dr_low_get_status ();
+ control = i386_dr_low_get_control ();
ALL_DEBUG_REGISTERS (i)
{
- if (I386_DR_WATCH_HIT (state, i)
+ if (I386_DR_WATCH_HIT (status, i)
/* This second condition makes sure DRi is set up for a data
watchpoint, not a hardware breakpoint. The reason is
that GDB doesn't call the target_stopped_data_address
method except for data watchpoints. In other words, I'm
being paranoiac. */
- && I386_DR_GET_RW_LEN (state, i) != 0)
+ && I386_DR_GET_RW_LEN (control, i) != 0)
{
- addr = state->dr_mirror[i];
+ addr = i386_dr_low_get_addr (i);
rc = 1;
if (debug_hw_points)
i386_show_dr (state, "watchpoint_hit", addr, -1, hw_write);