* 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:
parent
0d2a638963
commit
e0d24f8d6e
5 changed files with 203 additions and 2 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
29
gdb/target.c
29
gdb/target.c
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue