2011-05-06 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>

Thiago Jung Bauermann  <bauerman@br.ibm.com>

	Implement support for PowerPC BookE masked watchpoints.

gdb/
	* NEWS: Mention masked watchpoint support.  Create "Changed commands"
	section.
	* breakpoint.h (struct breakpoint_ops) <works_in_software_mode>: New
	method.  Initialize to NULL in all existing breakpoint_ops instances.
	(struct breakpoint) <hw_wp_mask>: New field.
	* breakpoint.c (is_masked_watchpoint): Add prototype.
	(update_watchpoint): Don't set b->val for masked watchpoints.  Call
	breakpoint's breakpoint_ops.works_in_software_mode if available.
	(watchpoints_triggered): Handle the case of a hardware masked
	watchpoint trigger.
	(watchpoint_check): Likewise.
	(works_in_software_mode_watchpoint): New function.
	(insert_masked_watchpoint, remove_masked_watchpoint)
	(resources_needed_masked_watchpoint)
	(works_in_software_mode_masked_watchpoint, print_it_masked_watchpoint)
	(print_one_detail_masked_watchpoint, print_mention_masked_watchpoint)
	(print_recreate_masked_watchpoint, is_masked_watchpoint): New
	functions.
	(masked_watchpoint_breakpoint_ops): New structure.
	(watch_command_1): Check for the existence of the `mask' parameter.
	Set b->ops according to the type of hardware watchpoint being created.
	* ppc-linux-nat.c (ppc_linux_insert_mask_watchpoint)
	(ppc_linux_remove_mask_watchpoint)
	(ppc_linux_masked_watch_num_registers): New functions.
	(_initialize_ppc_linux_nat): Initialize to_insert_mask_watchpoint,
	to_remove_mask_watchpoint and to_masked_watch_num_registers.
	* target.c (update_current_target): Mention to_insert_mask_watchpoint,
	to_remove_mask_watchpoint, and to_masked_watch_num_registers.
	(target_insert_mask_watchpoint, target_remove_mask_watchpoint)
	(target_masked_watch_num_registers): New functions.
	* target.h (struct target_ops) <to_insert_mask_watchpoint>,
	<to_remove_mask_watchpoint>, <to_masked_watch_num_registers>: New
	methods.
	(target_insert_mask_watchpoint, target_remove_mask_watchpoint)
	(target_masked_watch_num_registers): Add prototypes.

gdb/doc/
	* gdb.texinfo (Set Watchpoints): Document mask parameter.
	(PowerPC Embedded): Mention support of masked watchpoints.
This commit is contained in:
Thiago Jung Bauermann
2011-05-06 18:46:33 +00:00
parent d472a4264b
commit 9c06b0b428
10 changed files with 617 additions and 72 deletions

View File

@@ -1739,6 +1739,64 @@ get_trigger_type (int rw)
return t;
}
/* Insert a new masked watchpoint at ADDR using the mask MASK.
RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
or hw_access for an access watchpoint. Returns 0 on success and throws
an error on failure. */
static int
ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
CORE_ADDR mask, int rw)
{
ptid_t ptid;
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
gdb_assert (have_ptrace_booke_interface ());
p.version = PPC_DEBUG_CURRENT_VERSION;
p.trigger_type = get_trigger_type (rw);
p.addr_mode = PPC_BREAKPOINT_MODE_MASK;
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
p.addr = addr;
p.addr2 = mask;
p.condition_value = 0;
ALL_LWPS (lp, ptid)
booke_insert_point (&p, TIDGET (ptid));
return 0;
}
/* Remove a masked watchpoint at ADDR with the mask MASK.
RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
or hw_access for an access watchpoint. Returns 0 on success and throws
an error on failure. */
static int
ppc_linux_remove_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
CORE_ADDR mask, int rw)
{
ptid_t ptid;
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
gdb_assert (have_ptrace_booke_interface ());
p.version = PPC_DEBUG_CURRENT_VERSION;
p.trigger_type = get_trigger_type (rw);
p.addr_mode = PPC_BREAKPOINT_MODE_MASK;
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
p.addr = addr;
p.addr2 = mask;
p.condition_value = 0;
ALL_LWPS (lp, ptid)
booke_remove_point (&p, TIDGET (ptid));
return 0;
}
/* Check whether we have at least one free DVC register. */
static int
can_use_watchpoint_cond_accel (void)
@@ -2224,6 +2282,26 @@ ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
return start <= addr + mask && start + length - 1 >= addr;
}
/* Return the number of registers needed for a masked hardware watchpoint. */
static int
ppc_linux_masked_watch_num_registers (struct target_ops *target,
CORE_ADDR addr, CORE_ADDR mask)
{
if (!have_ptrace_booke_interface ()
|| (booke_debug_info.features & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0)
return -1;
else if ((mask & 0xC0000000) != 0xC0000000)
{
warning (_("The given mask covers kernel address space "
"and cannot be used.\n"));
return -2;
}
else
return 2;
}
static void
ppc_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
@@ -2438,11 +2516,14 @@ _initialize_ppc_linux_nat (void)
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_insert_mask_watchpoint = ppc_linux_insert_mask_watchpoint;
t->to_remove_mask_watchpoint = ppc_linux_remove_mask_watchpoint;
t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
t->to_stopped_data_address = ppc_linux_stopped_data_address;
t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
t->to_can_accel_watchpoint_condition
= ppc_linux_can_accel_watchpoint_condition;
t->to_masked_watch_num_registers = ppc_linux_masked_watch_num_registers;
t->to_ranged_break_num_registers = ppc_linux_ranged_break_num_registers;
t->to_read_description = ppc_linux_read_description;