@@ -87,6 +87,10 @@ protected:
int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp) override;
+
+ bool low_stopped_by_watchpoint () override;
+
+ CORE_ADDR low_stopped_data_address () override;
};
/* The singleton target ops object. */
@@ -410,10 +414,10 @@ aarch64_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
return ret;
}
-/* Implementation of linux_target_ops method "stopped_data_address". */
+/* Implementation of linux target ops method "low_stopped_data_address". */
-static CORE_ADDR
-aarch64_stopped_data_address (void)
+CORE_ADDR
+aarch64_target::low_stopped_data_address ()
{
siginfo_t siginfo;
int pid, i;
@@ -472,15 +476,12 @@ aarch64_stopped_data_address (void)
return (CORE_ADDR) 0;
}
-/* Implementation of linux_target_ops method "stopped_by_watchpoint". */
+/* Implementation of linux target ops method "low_stopped_by_watchpoint". */
-static int
-aarch64_stopped_by_watchpoint (void)
+bool
+aarch64_target::low_stopped_by_watchpoint ()
{
- if (aarch64_stopped_data_address () != 0)
- return 1;
- else
- return 0;
+ return (low_stopped_data_address () != 0);
}
/* Fetch the thread-local storage pointer for libthread_db. */
@@ -3113,8 +3114,6 @@ aarch64_supports_hardware_single_step (void)
struct linux_target_ops the_low_target =
{
- aarch64_stopped_by_watchpoint,
- aarch64_stopped_data_address,
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
aarch64_linux_siginfo_fixup,
@@ -97,6 +97,10 @@ protected:
int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp) override;
+
+ bool low_stopped_by_watchpoint () override;
+
+ CORE_ADDR low_stopped_data_address () override;
};
/* The singleton target ops object. */
@@ -674,43 +678,43 @@ arm_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
}
/* Return whether current thread is stopped due to a watchpoint. */
-static int
-arm_stopped_by_watchpoint (void)
+bool
+arm_target::low_stopped_by_watchpoint ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
siginfo_t siginfo;
/* We must be able to set hardware watchpoints. */
if (arm_linux_get_hw_watchpoint_count () == 0)
- return 0;
+ return false;
/* Retrieve siginfo. */
errno = 0;
ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread), 0, &siginfo);
if (errno != 0)
- return 0;
+ return false;
/* This must be a hardware breakpoint. */
if (siginfo.si_signo != SIGTRAP
|| (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
- return 0;
+ return false;
/* If we are in a positive slot then we're looking at a breakpoint and not
a watchpoint. */
if (siginfo.si_errno >= 0)
- return 0;
+ return false;
/* Cache stopped data address for use by arm_stopped_data_address. */
lwp->arch_private->stopped_data_address
= (CORE_ADDR) (uintptr_t) siginfo.si_addr;
- return 1;
+ return true;
}
/* Return data address that triggered watchpoint. Called only if
- arm_stopped_by_watchpoint returned true. */
-static CORE_ADDR
-arm_stopped_data_address (void)
+ low_stopped_by_watchpoint returned true. */
+CORE_ADDR
+arm_target::low_stopped_data_address ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
return lwp->arch_private->stopped_data_address;
@@ -1103,8 +1107,6 @@ arm_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- arm_stopped_by_watchpoint,
- arm_stopped_data_address,
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -165,8 +165,6 @@ bfin_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -55,6 +55,10 @@ protected:
int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp) override;
+
+ bool low_stopped_by_watchpoint () override;
+
+ CORE_ADDR low_stopped_data_address () override;
};
/* The singleton target ops object. */
@@ -357,8 +361,8 @@ crisv32_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
return 0;
}
-static int
-cris_stopped_by_watchpoint (void)
+bool
+crisv32_target::low_stopped_by_watchpoint ()
{
unsigned long exs;
struct regcache *regcache = get_thread_regcache (current_thread, 1);
@@ -368,8 +372,8 @@ cris_stopped_by_watchpoint (void)
return (((exs & 0xff00) >> 8) == 0xc);
}
-static CORE_ADDR
-cris_stopped_data_address (void)
+CORE_ADDR
+crisv32_target::low_stopped_data_address ()
{
unsigned long eda;
struct regcache *regcache = get_thread_regcache (current_thread, 1);
@@ -466,8 +470,6 @@ crisv32_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- cris_stopped_by_watchpoint,
- cris_stopped_data_address,
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -786,8 +786,6 @@ get_syscall_trapinfo (struct lwp_info *lwp, int *sysno)
current_thread = saved_thread;
}
-static int check_stopped_by_watchpoint (struct lwp_info *child);
-
bool
linux_process_target::save_stop_reason (lwp_info *lwp)
{
@@ -2245,46 +2243,33 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat)
return 0;
}
-/* Fetch the possibly triggered data watchpoint info and store it in
- CHILD.
-
- On some archs, like x86, that use debug registers to set
- watchpoints, it's possible that the way to know which watched
- address trapped, is to check the register that is used to select
- which address to watch. Problem is, between setting the watchpoint
- and reading back which data address trapped, the user may change
- the set of watchpoints, and, as a consequence, GDB changes the
- debug registers in the inferior. To avoid reading back a stale
- stopped-data-address when that happens, we cache in LP the fact
- that a watchpoint trapped, and the corresponding data address, as
- soon as we see CHILD stop with a SIGTRAP. If GDB changes the debug
- registers meanwhile, we have the cached data we can rely on. */
-
-static int
-check_stopped_by_watchpoint (struct lwp_info *child)
+bool
+linux_process_target::check_stopped_by_watchpoint (lwp_info *child)
{
- if (the_low_target.stopped_by_watchpoint != NULL)
- {
- struct thread_info *saved_thread;
+ struct thread_info *saved_thread = current_thread;
+ current_thread = get_lwp_thread (child);
- saved_thread = current_thread;
- current_thread = get_lwp_thread (child);
+ if (low_stopped_by_watchpoint ())
+ {
+ child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
+ child->stopped_data_address = low_stopped_data_address ();
+ }
- if (the_low_target.stopped_by_watchpoint ())
- {
- child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
+ current_thread = saved_thread;
- if (the_low_target.stopped_data_address != NULL)
- child->stopped_data_address
- = the_low_target.stopped_data_address ();
- else
- child->stopped_data_address = 0;
- }
+ return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
+}
- current_thread = saved_thread;
- }
+bool
+linux_process_target::low_stopped_by_watchpoint ()
+{
+ return false;
+}
- return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
+CORE_ADDR
+linux_process_target::low_stopped_data_address ()
+{
+ return 0;
}
/* Return the ptrace options that we want to try to enable. */
@@ -131,9 +131,6 @@ struct lwp_info;
struct linux_target_ops
{
- int (*stopped_by_watchpoint) (void);
- CORE_ADDR (*stopped_data_address) (void);
-
/* Hooks to reformat register data for PEEKUSR/POKEUSR (in particular
for registers smaller than an xfer unit). */
void (*collect_ptrace_register) (struct regcache *regcache,
@@ -624,6 +621,22 @@ class linux_process_target : public process_stratum_target
/* Install breakpoints for software single stepping. */
void install_software_single_step_breakpoints (lwp_info *lwp);
+ /* Fetch the possibly triggered data watchpoint info and store it in
+ CHILD.
+
+ On some archs, like x86, that use debug registers to set
+ watchpoints, it's possible that the way to know which watched
+ address trapped, is to check the register that is used to select
+ which address to watch. Problem is, between setting the watchpoint
+ and reading back which data address trapped, the user may change
+ the set of watchpoints, and, as a consequence, GDB changes the
+ debug registers in the inferior. To avoid reading back a stale
+ stopped-data-address when that happens, we cache in LP the fact
+ that a watchpoint trapped, and the corresponding data address, as
+ soon as we see CHILD stop with a SIGTRAP. If GDB changes the debug
+ registers meanwhile, we have the cached data we can rely on. */
+ bool check_stopped_by_watchpoint (lwp_info *child);
+
protected:
/* The architecture-specific "low" methods are listed below. */
@@ -667,6 +680,10 @@ class linux_process_target : public process_stratum_target
virtual int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp);
+ virtual bool low_stopped_by_watchpoint ();
+
+ virtual CORE_ADDR low_stopped_data_address ();
+
/* How many bytes the PC should be decremented after a break. */
int m_decr_pc_after_break;
};
@@ -163,8 +163,6 @@ m32r_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -259,8 +259,6 @@ m68k_supports_hardware_single_step (void)
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -62,6 +62,10 @@ protected:
int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp) override;
+
+ bool low_stopped_by_watchpoint () override;
+
+ CORE_ADDR low_stopped_data_address () override;
};
/* The singleton target ops object. */
@@ -610,12 +614,12 @@ mips_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
return 0;
}
-/* This is the implementation of linux_target_ops method
- stopped_by_watchpoint. The watchhi R and W bits indicate
+/* This is the implementation of linux target ops method
+ low_stopped_by_watchpoint. The watchhi R and W bits indicate
the watch register triggered. */
-static int
-mips_stopped_by_watchpoint (void)
+bool
+mips_target::low_stopped_by_watchpoint ()
{
struct process_info *proc = current_process ();
struct arch_process_info *priv = proc->priv->arch_private;
@@ -634,16 +638,16 @@ mips_stopped_by_watchpoint (void)
for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++)
if (mips_linux_watch_get_watchhi (&priv->watch_readback, n)
& (R_MASK | W_MASK))
- return 1;
+ return true;
- return 0;
+ return false;
}
-/* This is the implementation of linux_target_ops method
- stopped_data_address. */
+/* This is the implementation of linux target ops method
+ low_stopped_data_address. */
-static CORE_ADDR
-mips_stopped_data_address (void)
+CORE_ADDR
+mips_target::low_stopped_data_address ()
{
struct process_info *proc = current_process ();
struct arch_process_info *priv = proc->priv->arch_private;
@@ -978,8 +982,6 @@ mips_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- mips_stopped_by_watchpoint,
- mips_stopped_data_address,
mips_collect_ptrace_register,
mips_supply_ptrace_register,
NULL, /* siginfo_fixup */
@@ -3418,8 +3418,6 @@ ppc_get_ipa_tdesc_idx (void)
}
struct linux_target_ops the_low_target = {
- NULL,
- NULL,
ppc_collect_ptrace_register,
ppc_supply_ptrace_register,
NULL, /* siginfo_fixup */
@@ -2832,8 +2832,6 @@ s390_emit_ops (void)
}
struct linux_target_ops the_low_target = {
- NULL,
- NULL,
s390_collect_ptrace_register,
s390_supply_ptrace_register,
NULL, /* siginfo_fixup */
@@ -194,8 +194,6 @@ sh_target::low_arch_setup ()
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -343,7 +343,6 @@ sparc_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- NULL, NULL,
NULL, NULL
};
@@ -425,8 +425,6 @@ tic6x_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -226,8 +226,6 @@ tile_supports_hardware_single_step (void)
struct linux_target_ops the_low_target =
{
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */
@@ -133,6 +133,10 @@ protected:
int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
int size, raw_breakpoint *bp) override;
+
+ bool low_stopped_by_watchpoint () override;
+
+ CORE_ADDR low_stopped_data_address () override;
};
/* The singleton target ops object. */
@@ -654,15 +658,15 @@ x86_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
}
}
-static int
-x86_stopped_by_watchpoint (void)
+bool
+x86_target::low_stopped_by_watchpoint ()
{
struct process_info *proc = current_process ();
return x86_dr_stopped_by_watchpoint (&proc->priv->arch_private->debug_reg_state);
}
-static CORE_ADDR
-x86_stopped_data_address (void)
+CORE_ADDR
+x86_target::low_stopped_data_address ()
{
struct process_info *proc = current_process ();
CORE_ADDR addr;
@@ -2911,8 +2915,6 @@ x86_get_ipa_tdesc_idx (void)
struct linux_target_ops the_low_target =
{
- x86_stopped_by_watchpoint,
- x86_stopped_data_address,
/* collect_ptrace_register/supply_ptrace_register are not needed in the
native i386 case (no registers smaller than an xfer unit), and are not
used in the biarch case (HAVE_LINUX_USRREGS is not defined). */
@@ -331,8 +331,6 @@ xtensa_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
- NULL, /* stopped_by_watchpoint */
- NULL, /* stopped_data_address */
NULL, /* collect_ptrace_register */
NULL, /* supply_ptrace_register */
NULL, /* siginfo_fixup */