* ppc-linux-nat.c (PTRACE_GET_DEBUGREG, PTRACE_SET_DEBUGREG,

PTRACE_GETSIGINFO): Define.
	(last_stopped_data_address): New.
	(ppc_linux_check_watch_resources): New function.
	(ppc_linux_region_ok_for_hw_watchpoint): New function.
	(ppc_linux_insert_watchpoint): New function.
	(ppc_linux_remove_watchpoint): New function.
	(ppc_linux_stopped_data_address): New function.
	(ppc_linux_stopped_by_watchpoint): New function.
	(_initialize_ppc_linux_nat): Set the above hardware watchpoint
	related target vectors.
	* rs6000-tdep.c (rs6000_gdbarch_init): Set PPC architectures
	to have nonsteppable watchpoint.
	* target.c (default_region_ok_for_hw_watchpoint,
	debug_to_region_ok_for_hw_watchpoint): New prototypes.
	(update_current_target): Inherit to_region_ok_for_hw_watchpoint
	and set default to_region_ok_for_hw_watchpoint.
	(default_region_ok_for_hw_watchpoint): New function.
	(debug_to_region_ok_for_hw_watchpoint): New function.
	(setup_target_debug): Set to_region_ok_for_hw_watchpoint of
	debug_target.
	* target.h (struct target_ops): Add a new target vector
	to_region_ok_for_hw_watchpoint.
	(TARGET_REGION_OK_FOR_HW_WATCHPOINT): Define this if it is not
	defined anyplace else.
This commit is contained in:
Wu Zhou 2006-02-08 05:41:06 +00:00
parent 0d2a638963
commit e0d24f8d6e
5 changed files with 203 additions and 2 deletions

View file

@ -1,5 +1,33 @@
2005-02-07 Joel Brobecker <brobecker@adacore.com>
2006-02-08 Ben Elliston <bje@au1.ibm.com>
Wu Zhou <woodzltc@cn.ibm.com>
* ppc-linux-nat.c (PTRACE_GET_DEBUGREG, PTRACE_SET_DEBUGREG,
PTRACE_GETSIGINFO): Define.
(last_stopped_data_address): New.
(ppc_linux_check_watch_resources): New function.
(ppc_linux_region_ok_for_hw_watchpoint): New function.
(ppc_linux_insert_watchpoint): New function.
(ppc_linux_remove_watchpoint): New function.
(ppc_linux_stopped_data_address): New function.
(ppc_linux_stopped_by_watchpoint): New function.
(_initialize_ppc_linux_nat): Set the above hardware watchpoint
related target vectors.
* rs6000-tdep.c (rs6000_gdbarch_init): Set PPC architectures
to have nonsteppable watchpoint.
* target.c (default_region_ok_for_hw_watchpoint,
debug_to_region_ok_for_hw_watchpoint): New prototypes.
(update_current_target): Inherit to_region_ok_for_hw_watchpoint
and set default to_region_ok_for_hw_watchpoint.
(default_region_ok_for_hw_watchpoint): New function.
(debug_to_region_ok_for_hw_watchpoint): New function.
(setup_target_debug): Set to_region_ok_for_hw_watchpoint of
debug_target.
* target.h (struct target_ops): Add a new target vector
to_region_ok_for_hw_watchpoint.
(TARGET_REGION_OK_FOR_HW_WATCHPOINT): Define this if it is not
defined anyplace else.
2005-02-07 Joel Brobecker <brobecker@adacore.com>
* symfile.c (add_symbol_file_command): Abort if the user forgot
to provide the address when the file has been loaded.

View file

@ -81,6 +81,16 @@
#define PTRACE_SETEVRREGS 21
#endif
/* Similarly for the hardware watchpoint support. */
#ifndef PTRACE_GET_DEBUGREG
#define PTRACE_GET_DEBUGREG 25
#endif
#ifndef PTRACE_SET_DEBUGREG
#define PTRACE_SET_DEBUGREG 26
#endif
#ifndef PTRACE_GETSIGINFO
#define PTRACE_GETSIGINFO 0x4202
#endif
/* This oddity is because the Linux kernel defines elf_vrregset_t as
an array of 33 16 bytes long elements. I.e. it leaves out vrsave.
@ -146,6 +156,7 @@ struct gdb_evrregset_t
error. */
int have_ptrace_getvrregs = 1;
static CORE_ADDR last_stopped_data_address = 0;
/* Non-zero if our kernel may support the PTRACE_GETEVRREGS and
PTRACE_SETEVRREGS requests, for reading and writing the SPE
@ -153,7 +164,6 @@ int have_ptrace_getvrregs = 1;
error. */
int have_ptrace_getsetevrregs = 1;
int
kernel_u_size (void)
{
@ -777,6 +787,124 @@ store_ppc_registers (int tid)
store_spe_register (tid, -1);
}
static int
ppc_linux_check_watch_resources (int type, int cnt, int ot)
{
int tid;
ptid_t ptid = inferior_ptid;
/* DABR (data address breakpoint register) is optional for PPC variants.
Some variants have one DABR, others have none. So CNT can't be larger
than 1. */
if (cnt > 1)
return 0;
/* We need to know whether ptrace supports PTRACE_SET_DEBUGREG and whether
the target has DABR. If either answer is no, the ptrace call will
return -1. Fail in that case. */
tid = TIDGET (ptid);
if (tid == 0)
tid = PIDGET (ptid);
if (ptrace (PTRACE_SET_DEBUGREG, tid, 0, 0) == -1)
return 0;
return 1;
}
static int
ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
/* Handle sub-8-byte quantities. */
if (len <= 0)
return 0;
/* addr+len must fall in the 8 byte watchable region. */
if ((addr + len) > (addr & ~7) + 8)
return 0;
return 1;
}
/* Set a watchpoint of type TYPE at address ADDR. */
static long
ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
{
int tid;
long dabr_value;
ptid_t ptid = inferior_ptid;
dabr_value = addr & ~7;
switch (rw)
{
case hw_read:
/* Set read and translate bits. */
dabr_value |= 5;
break;
case hw_write:
/* Set write and translate bits. */
dabr_value |= 6;
break;
case hw_access:
/* Set read, write and translate bits. */
dabr_value |= 7;
break;
}
tid = TIDGET (ptid);
if (tid == 0)
tid = PIDGET (ptid);
return ptrace (PTRACE_SET_DEBUGREG, tid, 0, dabr_value);
}
static long
ppc_linux_remove_watchpoint (CORE_ADDR addr, int len)
{
int tid;
ptid_t ptid = inferior_ptid;
tid = TIDGET (ptid);
if (tid == 0)
tid = PIDGET (ptid);
return ptrace (PTRACE_SET_DEBUGREG, tid, 0, 0);
}
static int
ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
{
if (last_stopped_data_address)
{
*addr_p = last_stopped_data_address;
last_stopped_data_address = 0;
return 1;
}
return 0;
}
static int
ppc_linux_stopped_by_watchpoint (void)
{
int tid;
struct siginfo siginfo;
ptid_t ptid = inferior_ptid;
CORE_ADDR *addr_p;
tid = TIDGET(ptid);
if (tid == 0)
tid = PIDGET (ptid);
errno = 0;
ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
if (errno != 0 || siginfo.si_signo != SIGTRAP ||
(siginfo.si_code & 0xffff) != 0x0004)
return 0;
last_stopped_data_address = (CORE_ADDR) siginfo.si_addr;
return 1;
}
static void
ppc_linux_store_inferior_registers (int regno)
{
@ -900,6 +1028,14 @@ _initialize_ppc_linux_nat (void)
t->to_fetch_registers = ppc_linux_fetch_inferior_registers;
t->to_store_registers = ppc_linux_store_inferior_registers;
/* Add our watchpoint methods. */
t->to_can_use_hw_breakpoint = ppc_linux_check_watch_resources;
t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
t->to_stopped_data_address = ppc_linux_stopped_data_address;
/* Register the target. */
add_target (t);
}

View file

@ -3387,6 +3387,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
_("rs6000_gdbarch_init: "
"received unexpected BFD 'arch' value"));
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
/* Sanity check on registers. */
gdb_assert (strcmp (tdep->regs[tdep->ppc_gp0_regnum].name, "r0") == 0);

View file

@ -48,6 +48,8 @@ static void kill_or_be_killed (int);
static void default_terminal_info (char *, int);
static int default_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static int default_region_size_ok_for_hw_watchpoint (int);
static int nosymbol (char *, CORE_ADDR *);
@ -129,6 +131,8 @@ static int debug_to_stopped_by_watchpoint (void);
static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int);
static int debug_to_region_size_ok_for_hw_watchpoint (int);
static void debug_to_terminal_init (void);
@ -406,6 +410,7 @@ update_current_target (void)
INHERIT (to_stopped_data_address, t);
INHERIT (to_stopped_by_watchpoint, t);
INHERIT (to_have_continuable_watchpoint, t);
INHERIT (to_region_ok_for_hw_watchpoint, t);
INHERIT (to_region_size_ok_for_hw_watchpoint, t);
INHERIT (to_terminal_init, t);
INHERIT (to_terminal_inferior, t);
@ -532,6 +537,8 @@ update_current_target (void)
de_fault (to_stopped_data_address,
(int (*) (struct target_ops *, CORE_ADDR *))
return_zero);
de_fault (to_region_ok_for_hw_watchpoint,
default_region_ok_for_hw_watchpoint);
de_fault (to_region_size_ok_for_hw_watchpoint,
default_region_size_ok_for_hw_watchpoint);
de_fault (to_terminal_init,
@ -1578,6 +1585,12 @@ find_default_create_inferior (char *exec_file, char *allargs, char **env,
return;
}
static int
default_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
return TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT (len);
}
static int
default_region_size_ok_for_hw_watchpoint (int byte_count)
{
@ -2118,6 +2131,21 @@ debug_to_can_use_hw_breakpoint (int type, int cnt, int from_tty)
return retval;
}
static int
debug_to_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
CORE_ADDR retval;
retval = debug_target.to_region_ok_for_hw_watchpoint (addr, len);
fprintf_unfiltered (gdb_stdlog,
"TARGET_REGION_OK_FOR_HW_WATCHPOINT (%ld, %ld) = 0x%lx\n",
(unsigned long) addr,
(unsigned long) len,
(unsigned long) retval);
return retval;
}
static int
debug_to_region_size_ok_for_hw_watchpoint (int byte_count)
{
@ -2537,6 +2565,7 @@ setup_target_debug (void)
current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
current_target.to_stopped_data_address = debug_to_stopped_data_address;
current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint;
current_target.to_region_size_ok_for_hw_watchpoint = debug_to_region_size_ok_for_hw_watchpoint;
current_target.to_terminal_init = debug_to_terminal_init;
current_target.to_terminal_inferior = debug_to_terminal_inferior;

View file

@ -346,6 +346,7 @@ struct target_ops
int (*to_stopped_by_watchpoint) (void);
int to_have_continuable_watchpoint;
int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int);
int (*to_region_size_ok_for_hw_watchpoint) (int);
void (*to_terminal_init) (void);
void (*to_terminal_inferior) (void);
@ -1031,6 +1032,11 @@ extern void (*deprecated_target_new_objfile_hook) (struct objfile *);
(*current_target.to_can_use_hw_breakpoint) (TYPE, CNT, OTHERTYPE);
#endif
#ifndef TARGET_REGION_OK_FOR_HW_WATCHPOINT
#define TARGET_REGION_OK_FOR_HW_WATCHPOINT(addr, len) \
(*current_target.to_region_ok_for_hw_watchpoint) (addr, len)
#endif
#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT)
#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_count) \
(*current_target.to_region_size_ok_for_hw_watchpoint) (byte_count)