gdbserver/linux-low: turn watchpoint ops into methods

gdbserver/ChangeLog:
2020-04-02  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>

	Turn the 'stopped_by_watchpoint' and 'stopped_data_address' linux
	target ops into methods of linux_process_target.

	* linux-low.h (struct linux_target_ops): Remove the ops.
	(class linux_process_target) <check_stopped_by_watchpoint>
	<low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	* linux-low.cc (check_stopped_by_watchpoint): Turn into...
	(linux_process_target::check_stopped_by_watchpoint): ...this.
	(linux_process_target::low_stopped_by_watchpoint): Define.
	(linux_process_target::low_stopped_data_address): Define.
	* linux-x86-low.cc (class x86_target) <low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	(x86_stopped_by_watchpoint): Turn into...
	(x86_target::low_stopped_by_watchpoint): ...this.
	(x86_stopped_data_address): Turn into...
	(x86_target::low_stopped_data_address): ...this.
	(the_low_target): Remove the op fields.
	* linux-aarch64-low.cc (class aarch64_target)
	<low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	(aarch64_stopped_by_watchpoint): Turn into...
	(aarch64_target::low_stopped_by_watchpoint): ...this.
	(aarch64_stopped_data_address): Turn into...
	(aarch64_target::low_stopped_data_address): ...this.
	(the_low_target): Remove the op fields.
	* linux-arm-low.cc (class arm_target) <low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	(arm_stopped_by_watchpoint): Turn into...
	(arm_target::low_stopped_by_watchpoint): ...this.
	(arm_stopped_data_address): Turn into...
	(arm_target::low_stopped_data_address): ...this.
	(the_low_target): Remove the op fields.
	* linux-crisv32-low.cc (class crisv32_target)
	<low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	(cris_stopped_by_watchpoint): Turn into...
	(crisv32_target::low_stopped_by_watchpoint): ...this.
	(cris_stopped_data_address): Turn into...
	(crisv32_target::low_stopped_data_address): ...this.
	(the_low_target): Remove the op fields.
	* linux-mips-low.cc (class mips_target) <low_stopped_by_watchpoint>
	<low_stopped_data_address>: Declare.
	(mips_stopped_by_watchpoint): Turn into...
	(mips_target::low_stopped_by_watchpoint): ...this.
	(mips_stopped_data_address): Turn into...
	(mips_target::low_stopped_data_address): ...this.
	(the_low_target): Remove the op fields.
	* linux-bfin-low.cc (the_low_target): Remove the op fields.
	* linux-m32r-low.cc (the_low_target): Ditto.
	* linux-m68k-low.cc (the_low_target): Ditto.
	* linux-ppc-low.cc (the_low_target): Ditto.
	* linux-s390-low.cc (the_low_target): Ditto.
	* linux-sh-low.cc (the_low_target): Ditto.
	* linux-sparc-low.cc (the_low_target): Ditto.
	* linux-tic6x-low.cc (the_low_target): Ditto.
	* linux-tile-low.cc (the_low_target): Ditto.
	* linux-xtensa-low.cc (the_low_target): Ditto.
This commit is contained in:
Tankut Baris Aktemur 2020-04-02 15:11:27 +02:00
parent 9db9aa232a
commit ac1bbaca10
18 changed files with 158 additions and 107 deletions

View File

@ -1,3 +1,64 @@
2020-04-02 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Turn the 'stopped_by_watchpoint' and 'stopped_data_address' linux
target ops into methods of linux_process_target.
* linux-low.h (struct linux_target_ops): Remove the ops.
(class linux_process_target) <check_stopped_by_watchpoint>
<low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
* linux-low.cc (check_stopped_by_watchpoint): Turn into...
(linux_process_target::check_stopped_by_watchpoint): ...this.
(linux_process_target::low_stopped_by_watchpoint): Define.
(linux_process_target::low_stopped_data_address): Define.
* linux-x86-low.cc (class x86_target) <low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
(x86_stopped_by_watchpoint): Turn into...
(x86_target::low_stopped_by_watchpoint): ...this.
(x86_stopped_data_address): Turn into...
(x86_target::low_stopped_data_address): ...this.
(the_low_target): Remove the op fields.
* linux-aarch64-low.cc (class aarch64_target)
<low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
(aarch64_stopped_by_watchpoint): Turn into...
(aarch64_target::low_stopped_by_watchpoint): ...this.
(aarch64_stopped_data_address): Turn into...
(aarch64_target::low_stopped_data_address): ...this.
(the_low_target): Remove the op fields.
* linux-arm-low.cc (class arm_target) <low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
(arm_stopped_by_watchpoint): Turn into...
(arm_target::low_stopped_by_watchpoint): ...this.
(arm_stopped_data_address): Turn into...
(arm_target::low_stopped_data_address): ...this.
(the_low_target): Remove the op fields.
* linux-crisv32-low.cc (class crisv32_target)
<low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
(cris_stopped_by_watchpoint): Turn into...
(crisv32_target::low_stopped_by_watchpoint): ...this.
(cris_stopped_data_address): Turn into...
(crisv32_target::low_stopped_data_address): ...this.
(the_low_target): Remove the op fields.
* linux-mips-low.cc (class mips_target) <low_stopped_by_watchpoint>
<low_stopped_data_address>: Declare.
(mips_stopped_by_watchpoint): Turn into...
(mips_target::low_stopped_by_watchpoint): ...this.
(mips_stopped_data_address): Turn into...
(mips_target::low_stopped_data_address): ...this.
(the_low_target): Remove the op fields.
* linux-bfin-low.cc (the_low_target): Remove the op fields.
* linux-m32r-low.cc (the_low_target): Ditto.
* linux-m68k-low.cc (the_low_target): Ditto.
* linux-ppc-low.cc (the_low_target): Ditto.
* linux-s390-low.cc (the_low_target): Ditto.
* linux-sh-low.cc (the_low_target): Ditto.
* linux-sparc-low.cc (the_low_target): Ditto.
* linux-tic6x-low.cc (the_low_target): Ditto.
* linux-tile-low.cc (the_low_target): Ditto.
* linux-xtensa-low.cc (the_low_target): Ditto.
2020-04-02 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
Turn the 'insert_point' and 'remove_point' linux target ops into

View File

@ -86,6 +86,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. */
@ -409,10 +413,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;
@ -471,15 +475,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. */
@ -3112,8 +3113,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,

View File

@ -95,6 +95,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. */
@ -672,43 +676,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;
@ -1101,8 +1105,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 */

View File

@ -171,8 +171,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 */

View File

@ -53,6 +53,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. */
@ -355,8 +359,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);
@ -366,8 +370,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);
@ -464,8 +468,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 */

View File

@ -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,48 +2243,35 @@ 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 = current_thread;
current_thread = get_lwp_thread (child);
if (low_stopped_by_watchpoint ())
{
struct thread_info *saved_thread;
saved_thread = current_thread;
current_thread = get_lwp_thread (child);
if (the_low_target.stopped_by_watchpoint ())
{
child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
if (the_low_target.stopped_data_address != NULL)
child->stopped_data_address
= the_low_target.stopped_data_address ();
else
child->stopped_data_address = 0;
}
current_thread = saved_thread;
child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
child->stopped_data_address = low_stopped_data_address ();
}
current_thread = saved_thread;
return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
}
bool
linux_process_target::low_stopped_by_watchpoint ()
{
return false;
}
CORE_ADDR
linux_process_target::low_stopped_data_address ()
{
return 0;
}
/* Return the ptrace options that we want to try to enable. */
static int

View File

@ -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,
@ -622,6 +619,22 @@ private:
/* 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. */
@ -665,6 +678,10 @@ protected:
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. */
virtual int low_decr_pc_after_break ();
};

View File

@ -161,8 +161,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 */

View File

@ -265,8 +265,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 */

View File

@ -60,6 +60,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. */
@ -608,12 +612,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;
@ -632,16 +636,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;
@ -976,8 +980,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 */

View File

@ -3416,8 +3416,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 */

View File

@ -2838,8 +2838,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 */

View File

@ -192,8 +192,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 */

View File

@ -341,7 +341,6 @@ sparc_target::get_regs_info ()
}
struct linux_target_ops the_low_target = {
NULL, NULL,
NULL, NULL
};

View File

@ -423,8 +423,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 */

View File

@ -224,8 +224,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 */

View File

@ -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. */
@ -661,15 +665,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;
@ -2918,8 +2922,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). */

View File

@ -329,8 +329,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 */