diff options
Diffstat (limited to 'gdb/gdbserver/i386-low.c')
-rw-r--r-- | gdb/gdbserver/i386-low.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/gdb/gdbserver/i386-low.c b/gdb/gdbserver/i386-low.c index 494b808..f13ae26 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); |