/* Debug register code for x86 (i386 and x86-64).
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#ifdef GDBSERVER
-#include "server.h"
-#else
-#include "defs.h"
-#include "inferior.h"
-#endif
+#include "gdbsupport/common-defs.h"
#include "x86-dregs.h"
+#include "gdbsupport/break-common.h"
/* Support for hardware watchpoints and breakpoints using the x86
debug registers.
/* Types of operations supported by x86_handle_nonaligned_watchpoint. */
typedef enum { WP_INSERT, WP_REMOVE, WP_COUNT } x86_wp_op_t;
-#ifndef GDBSERVER
-/* Whether or not to print the mirrored debug registers. */
-extern int debug_hw_points;
-#endif
-
/* Print the values of the mirrored debug registers. */
static void
here. */
: "??unknown??"))));
debug_printf (":\n");
- debug_printf ("\tCONTROL (DR7): %s STATUS (DR6): %s\n",
- phex (state->dr_control_mirror, 8),
- phex (state->dr_status_mirror, 8));
+
+ debug_printf ("\tCONTROL (DR7): 0x%s\n", phex (state->dr_control_mirror, 8));
+ debug_printf ("\tSTATUS (DR6): 0x%s\n", phex (state->dr_status_mirror, 8));
+
ALL_DEBUG_ADDRESS_REGISTERS (i)
{
- debug_printf ("\
-\tDR%d: addr=0x%s, ref.count=%d DR%d: addr=0x%s, ref.count=%d\n",
+ debug_printf ("\tDR%d: addr=0x%s, ref.count=%d\n",
i, phex (state->dr_mirror[i],
x86_get_debug_register_length ()),
- state->dr_ref_count[i],
- i + 1, phex (state->dr_mirror[i + 1],
- x86_get_debug_register_length ()),
- state->dr_ref_count[i + 1]);
- i++;
+ state->dr_ref_count[i]);
}
}
case 8:
if (TARGET_HAS_DR_LEN_8)
return (DR_LEN_8 | rw);
- /* ELSE FALL THROUGH */
+ /* FALL THROUGH */
default:
internal_error (__FILE__, __LINE__, _("\
Invalid hardware breakpoint length %d in x86_length_and_rw_bits.\n"), len);
int align = addr % max_wp_len;
/* Four (eight on AMD64) is the maximum length a debug register
can watch. */
- int try = (len > max_wp_len ? (max_wp_len - 1) : len - 1);
- int size = size_try_array[try][align];
+ int attempt = (len > max_wp_len ? (max_wp_len - 1) : len - 1);
+ int size = size_try_array[attempt][align];
if (what == WP_COUNT)
{
if (retval == 0)
x86_update_inferior_debug_regs (state, &local_state);
- if (debug_hw_points)
+ if (show_debug_regs)
x86_show_dr (state, "insert_watchpoint", addr, len, type);
return retval;
if (retval == 0)
x86_update_inferior_debug_regs (state, &local_state);
- if (debug_hw_points)
+ if (show_debug_regs)
x86_show_dr (state, "remove_watchpoint", addr, len, type);
return retval;
{
addr = x86_dr_low_get_addr (i);
rc = 1;
- if (debug_hw_points)
+ if (show_debug_regs)
x86_show_dr (state, "watchpoint_hit", addr, -1, hw_write);
}
}
- if (debug_hw_points && addr == 0)
+ if (show_debug_regs && addr == 0)
x86_show_dr (state, "stopped_data_addr", 0, 0, hw_write);
if (rc)
CORE_ADDR addr = 0;
return x86_dr_stopped_data_address (state, &addr);
}
+
+/* Return non-zero if the inferior has some hardware breakpoint that
+ triggered. Otherwise return zero. */
+
+int
+x86_dr_stopped_by_hw_breakpoint (struct x86_debug_reg_state *state)
+{
+ CORE_ADDR addr = 0;
+ int i;
+ int rc = 0;
+ /* The current thread's DR_STATUS. We always need to read this to
+ check whether some watchpoint caused the trap. */
+ unsigned status;
+ /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a
+ breakpoint trap. Only fetch it when necessary, to avoid an
+ unnecessary extra syscall when no watchpoint triggered. */
+ int control_p = 0;
+ unsigned control = 0;
+
+ /* As above, always read the current thread's debug registers rather
+ than trusting dr_mirror. */
+ status = x86_dr_low_get_status ();
+
+ ALL_DEBUG_ADDRESS_REGISTERS (i)
+ {
+ if (!X86_DR_WATCH_HIT (status, i))
+ continue;
+
+ if (!control_p)
+ {
+ control = x86_dr_low_get_control ();
+ control_p = 1;
+ }
+
+ if (X86_DR_GET_RW_LEN (control, i) == 0)
+ {
+ addr = x86_dr_low_get_addr (i);
+ rc = 1;
+ if (show_debug_regs)
+ x86_show_dr (state, "watchpoint_hit", addr, -1, hw_execute);
+ }
+ }
+
+ return rc;
+}