mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-28 10:00:51 +00:00
2011-01-11 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
Thiago Jung Bauermann <bauerman@br.ibm.com> Implement support for PowerPC BookE ranged watchpoints. gdb/ * breakpoint.h (struct breakpoint_ops) <resources_needed>: New method. Initialize to NULL in all existing breakpoint_ops instances. (struct breakpoint) <exact>: New field. (target_exact_watchpoints): Declare external global. * breakpoint.c (target_exact_watchpoints): New global flag. (update_watchpoint): Set b->type to bp_hardware_watchpoint and b->enable_state to bp_enabled before calling hw_watchpoint_used_count. (hw_watchpoint_used_count): Iterate over all bp_locations in a watchpoint. Call breakpoint's breakpoint_ops.resources_needed if available. (insert_watchpoint, remove_watchpoint): Use fixed length of 1 byte if the watchpoint is exact. (resources_needed_watchpoint): New function. (watchpoint_breakpoint_ops): Add resources_needed_watchpoint. (watch_command_1): Set b->exact if the user asked for an exact watchpoint and one can be set. (can_use_hardware_watchpoint): Add exact_watchpoints argument. Pass fixed length of 1 to target_region_ok_for_hw_watchpoint if the user asks for an exact watchpoint and one can be set. Return number of needed debug registers to watch the expression. * gdbtypes.c (is_scalar_type): New function, based on valprint.c:scalar_type_p. (is_scalar_type_recursive): New function. * gdbtypes.h (is_scalar_type_recursive): Declare. * ppc-linux-nat.c (ppc_linux_region_ok_for_hw_watchpoint): Always handle regions when ranged watchpoints are available. (create_watchpoint_request): New function. (ppc_linux_insert_watchpoint, ppc_linux_remove_watchpoint): Use create_watchpoint_request. * rs6000-tdep.c (show_powerpc_exact_watchpoints): New function. (_initialize_rs6000_tdep): Add `exact-watchpoints' boolean to the `set powerpc' and `show powerpc' commands. * target.h (struct target_ops) <to_region_ok_for_hw_watchpoint>: Mention documentation comment in the target macro. (target_region_ok_for_hw_watchpoint): Document return value. gdb/doc/ * gdb.texinfo (PowerPC Embedded): Document ranged watchpoints and the "set powerpc exact-watchpoints" flag.
This commit is contained in:
@@ -1497,9 +1497,16 @@ ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
|
||||
to determine the hardcoded watchable region for watchpoints. */
|
||||
if (have_ptrace_booke_interface ())
|
||||
{
|
||||
if (booke_debug_info.data_bp_alignment
|
||||
&& (addr + len > (addr & ~(booke_debug_info.data_bp_alignment - 1))
|
||||
+ booke_debug_info.data_bp_alignment))
|
||||
/* DAC-based processors (i.e., embedded processors), like the PowerPC 440
|
||||
have ranged watchpoints and can watch any access within an arbitrary
|
||||
memory region. This is useful to watch arrays and structs, for
|
||||
instance. It takes two hardware watchpoints though. */
|
||||
if (len > 1
|
||||
&& booke_debug_info.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE)
|
||||
return 2;
|
||||
else if (booke_debug_info.data_bp_alignment
|
||||
&& (addr + len > (addr & ~(booke_debug_info.data_bp_alignment - 1))
|
||||
+ booke_debug_info.data_bp_alignment))
|
||||
return 0;
|
||||
}
|
||||
/* addr+len must fall in the 8 byte watchable region for DABR-based
|
||||
@@ -1889,6 +1896,55 @@ ppc_linux_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int rw,
|
||||
&& check_condition (addr, cond, &data_value));
|
||||
}
|
||||
|
||||
/* Set up P with the parameters necessary to request a watchpoint covering
|
||||
LEN bytes starting at ADDR and if possible with condition expression COND
|
||||
evaluated by hardware. INSERT tells if we are creating a request for
|
||||
inserting or removing the watchpoint. */
|
||||
|
||||
static void
|
||||
create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr,
|
||||
int len, int rw, struct expression *cond,
|
||||
int insert)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
int use_condition;
|
||||
CORE_ADDR data_value;
|
||||
|
||||
use_condition = (insert? can_use_watchpoint_cond_accel ()
|
||||
: booke_debug_info.num_condition_regs > 0);
|
||||
if (cond && use_condition && check_condition (addr, cond, &data_value))
|
||||
calculate_dvc (addr, len, data_value, &p->condition_mode,
|
||||
&p->condition_value);
|
||||
else
|
||||
{
|
||||
p->condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p->condition_value = 0;
|
||||
}
|
||||
|
||||
p->addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p->addr2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
|
||||
p->condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p->condition_value = 0;
|
||||
|
||||
/* The watchpoint will trigger if the address of the memory access is
|
||||
within the defined range, as follows: p->addr <= address < p->addr2.
|
||||
|
||||
Note that the above sentence just documents how ptrace interprets
|
||||
its arguments; the watchpoint is set to watch the range defined by
|
||||
the user _inclusively_, as specified by the user interface. */
|
||||
p->addr2 = (uint64_t) addr + len;
|
||||
}
|
||||
|
||||
p->version = PPC_DEBUG_CURRENT_VERSION;
|
||||
p->trigger_type = get_trigger_type (rw);
|
||||
p->addr = (uint64_t) addr;
|
||||
}
|
||||
|
||||
static int
|
||||
ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
|
||||
struct expression *cond)
|
||||
@@ -1900,23 +1956,8 @@ ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
|
||||
if (have_ptrace_booke_interface ())
|
||||
{
|
||||
struct ppc_hw_breakpoint p;
|
||||
CORE_ADDR data_value;
|
||||
|
||||
if (cond && can_use_watchpoint_cond_accel ()
|
||||
&& check_condition (addr, cond, &data_value))
|
||||
calculate_dvc (addr, len, data_value, &p.condition_mode,
|
||||
&p.condition_value);
|
||||
else
|
||||
{
|
||||
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p.condition_value = 0;
|
||||
}
|
||||
|
||||
p.version = PPC_DEBUG_CURRENT_VERSION;
|
||||
p.trigger_type = get_trigger_type (rw);
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.addr = (uint64_t) addr;
|
||||
p.addr2 = 0;
|
||||
create_watchpoint_request (&p, addr, len, rw, cond, 1);
|
||||
|
||||
ALL_LWPS (lp, ptid)
|
||||
booke_insert_point (&p, TIDGET (ptid));
|
||||
@@ -1984,23 +2025,8 @@ ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
|
||||
if (have_ptrace_booke_interface ())
|
||||
{
|
||||
struct ppc_hw_breakpoint p;
|
||||
CORE_ADDR data_value;
|
||||
|
||||
if (cond && booke_debug_info.num_condition_regs > 0
|
||||
&& check_condition (addr, cond, &data_value))
|
||||
calculate_dvc (addr, len, data_value, &p.condition_mode,
|
||||
&p.condition_value);
|
||||
else
|
||||
{
|
||||
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p.condition_value = 0;
|
||||
}
|
||||
|
||||
p.version = PPC_DEBUG_CURRENT_VERSION;
|
||||
p.trigger_type = get_trigger_type (rw);
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.addr = (uint64_t) addr;
|
||||
p.addr2 = 0;
|
||||
create_watchpoint_request (&p, addr, len, rw, cond, 0);
|
||||
|
||||
ALL_LWPS (lp, ptid)
|
||||
booke_remove_point (&p, TIDGET (ptid));
|
||||
|
||||
Reference in New Issue
Block a user