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:
Thiago Jung Bauermann 2011-01-11 19:23:03 +00:00
parent 9fa40276f0
commit e09342b536
11 changed files with 346 additions and 78 deletions

View File

@ -1,3 +1,45 @@
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.
* 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.
2011-01-11 Thiago Jung Bauermann <bauerman@br.ibm.com>
* breakpoint.c (update_watchpoint): Decide on using a software or

View File

@ -10901,6 +10901,7 @@ static struct breakpoint_ops catch_exception_breakpoint_ops =
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
NULL, /* resources_needed */
print_it_catch_exception,
print_one_catch_exception,
print_mention_catch_exception,
@ -10939,6 +10940,7 @@ static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = {
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
NULL, /* resources_needed */
print_it_catch_exception_unhandled,
print_one_catch_exception_unhandled,
print_mention_catch_exception_unhandled,
@ -10975,6 +10977,7 @@ static struct breakpoint_ops catch_assert_breakpoint_ops = {
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
NULL, /* resources_needed */
print_it_catch_assert,
print_one_catch_assert,
print_mention_catch_assert,

View File

@ -98,7 +98,7 @@ static void clear_command (char *, int);
static void catch_command (char *, int);
static int can_use_hardware_watchpoint (struct value *);
static int can_use_hardware_watchpoint (struct value *, int);
static void break_command_1 (char *, int, int);
@ -351,6 +351,9 @@ static int executing_breakpoint_commands;
/* Are overlay event breakpoints enabled? */
static int overlay_events_enabled;
/* See description in breakpoint.h. */
int target_exact_watchpoints = 0;
/* Walk the following statement or block through all breakpoints.
ALL_BREAKPOINTS_SAFE does so even if the statment deletes the
current breakpoint. */
@ -1481,29 +1484,41 @@ update_watchpoint (struct breakpoint *b, int reparse)
if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
&& reparse)
{
int mem_cnt;
int reg_cnt;
enum bp_loc_type loc_type;
struct bp_location *bl;
mem_cnt = can_use_hardware_watchpoint (val_chain);
if (mem_cnt)
reg_cnt = can_use_hardware_watchpoint (val_chain, b->exact);
if (reg_cnt)
{
int i, target_resources_ok, other_type_used;
enum enable_state orig_enable_state;
/* We need to determine how many resources are already
used for all other hardware watchpoints to see if we
still have enough resources to also fit this watchpoint
in as well. To avoid the hw_watchpoint_used_count call
below from counting this watchpoint, make sure that it
is marked as a software watchpoint. */
b->type = bp_watchpoint;
used for all other hardware watchpoints plus this one
to see if we still have enough resources to also fit
this watchpoint in as well. To guarantee the
hw_watchpoint_used_count call below counts this
watchpoint, make sure that it is marked as a hardware
watchpoint. */
b->type = bp_hardware_watchpoint;
/* hw_watchpoint_used_count ignores disabled watchpoints,
and b might be disabled if we're being called from
do_enable_breakpoint. */
orig_enable_state = b->enable_state;
b->enable_state = bp_enabled;
i = hw_watchpoint_used_count (bp_hardware_watchpoint,
&other_type_used);
target_resources_ok = target_can_use_hardware_watchpoint
(bp_hardware_watchpoint, i + mem_cnt, other_type_used);
if (target_resources_ok > 0)
b->type = bp_hardware_watchpoint;
b->enable_state = orig_enable_state;
target_resources_ok = target_can_use_hardware_watchpoint
(bp_hardware_watchpoint, i, other_type_used);
if (target_resources_ok <= 0)
b->type = bp_watchpoint;
}
else
b->type = bp_watchpoint;
@ -6094,6 +6109,7 @@ static struct breakpoint_ops catch_fork_breakpoint_ops =
insert_catch_fork,
remove_catch_fork,
breakpoint_hit_catch_fork,
NULL, /* resources_needed */
print_it_catch_fork,
print_one_catch_fork,
print_mention_catch_fork,
@ -6189,6 +6205,7 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops =
insert_catch_vfork,
remove_catch_vfork,
breakpoint_hit_catch_vfork,
NULL, /* resources_needed */
print_it_catch_vfork,
print_one_catch_vfork,
print_mention_catch_vfork,
@ -6472,6 +6489,7 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops =
insert_catch_syscall,
remove_catch_syscall,
breakpoint_hit_catch_syscall,
NULL, /* resources_needed */
print_it_catch_syscall,
print_one_catch_syscall,
print_mention_catch_syscall,
@ -6625,6 +6643,7 @@ static struct breakpoint_ops catch_exec_breakpoint_ops =
insert_catch_exec,
remove_catch_exec,
breakpoint_hit_catch_exec,
NULL, /* resources_needed */
print_it_catch_exec,
print_one_catch_exec,
print_mention_catch_exec,
@ -6665,20 +6684,30 @@ hw_breakpoint_used_count (void)
static int
hw_watchpoint_used_count (enum bptype type, int *other_type_used)
{
struct breakpoint *b;
int i = 0;
struct breakpoint *b;
struct bp_location *bl;
*other_type_used = 0;
ALL_BREAKPOINTS (b)
{
if (breakpoint_enabled (b))
{
{
if (!breakpoint_enabled (b))
continue;
if (b->type == type)
i++;
for (bl = b->loc; bl; bl = bl->next)
{
/* Special types of hardware watchpoints may use more than
one register. */
if (b->ops && b->ops->resources_needed)
i += b->ops->resources_needed (bl);
else
i++;
}
else if (is_hardware_watchpoint (b))
*other_type_used = 1;
}
}
}
return i;
}
@ -8226,8 +8255,10 @@ watchpoint_exp_is_const (const struct expression *exp)
static int
insert_watchpoint (struct bp_location *bl)
{
return target_insert_watchpoint (bl->address, bl->length,
bl->watchpoint_type, bl->owner->cond_exp);
int length = bl->owner->exact? 1 : bl->length;
return target_insert_watchpoint (bl->address, length, bl->watchpoint_type,
bl->owner->cond_exp);
}
/* Implement the "remove" breakpoint_ops method for hardware watchpoints. */
@ -8235,8 +8266,21 @@ insert_watchpoint (struct bp_location *bl)
static int
remove_watchpoint (struct bp_location *bl)
{
return target_remove_watchpoint (bl->address, bl->length,
bl->watchpoint_type, bl->owner->cond_exp);
int length = bl->owner->exact? 1 : bl->length;
return target_remove_watchpoint (bl->address, length, bl->watchpoint_type,
bl->owner->cond_exp);
}
/* Implement the "resources_needed" breakpoint_ops method for
hardware watchpoints. */
static int
resources_needed_watchpoint (const struct bp_location *bl)
{
int length = bl->owner->exact? 1 : bl->length;
return target_region_ok_for_hw_watchpoint (bl->address, length);
}
/* The breakpoint_ops structure to be used in hardware watchpoints. */
@ -8246,6 +8290,7 @@ static struct breakpoint_ops watchpoint_breakpoint_ops =
insert_watchpoint,
remove_watchpoint,
NULL, /* breakpoint_hit */
resources_needed_watchpoint,
NULL, /* print_it */
NULL, /* print_one */
NULL, /* print_mention */
@ -8272,7 +8317,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
char *cond_end = NULL;
int i, other_type_used, target_resources_ok = 0;
enum bptype bp_type;
int mem_cnt = 0;
int reg_cnt = 0;
int thread = -1;
int pc = 0;
@ -8407,14 +8452,14 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
else
bp_type = bp_hardware_watchpoint;
mem_cnt = can_use_hardware_watchpoint (val);
if (mem_cnt == 0 && bp_type != bp_hardware_watchpoint)
reg_cnt = can_use_hardware_watchpoint (val, target_exact_watchpoints);
if (reg_cnt == 0 && bp_type != bp_hardware_watchpoint)
error (_("Expression cannot be implemented with read/access watchpoint."));
if (mem_cnt != 0)
if (reg_cnt != 0)
{
i = hw_watchpoint_used_count (bp_type, &other_type_used);
target_resources_ok =
target_can_use_hardware_watchpoint (bp_type, i + mem_cnt,
target_can_use_hardware_watchpoint (bp_type, i + reg_cnt,
other_type_used);
if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
error (_("Target does not support this type of hardware watchpoint."));
@ -8426,7 +8471,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
/* Change the type of breakpoint to an ordinary watchpoint if a
hardware watchpoint could not be set. */
if (!mem_cnt || target_resources_ok <= 0)
if (!reg_cnt || target_resources_ok <= 0)
bp_type = bp_watchpoint;
frame = block_innermost_frame (exp_valid_block);
@ -8497,6 +8542,10 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
b->val_valid = 1;
b->ops = &watchpoint_breakpoint_ops;
/* Use an exact watchpoint when there's only one memory region to be
watched, and only one debug register is needed to watch it. */
b->exact = target_exact_watchpoints && reg_cnt == 1;
if (cond_start)
b->cond_string = savestring (cond_start, cond_end - cond_start);
else
@ -8536,12 +8585,15 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
update_global_location_list (1);
}
/* Return count of locations need to be watched and can be handled in
hardware. If the watchpoint can not be handled in hardware return
zero. */
/* Return count of debug registers needed to watch the given expression.
If EXACT_WATCHPOINTS is 1, then consider that only the address of
the start of the watched region will be monitored (i.e., all accesses
will be aligned). This uses less debug registers on some targets.
If the watchpoint cannot be handled in hardware return zero. */
static int
can_use_hardware_watchpoint (struct value *v)
can_use_hardware_watchpoint (struct value *v, int exact_watchpoints)
{
int found_memory_cnt = 0;
struct value *head = v;
@ -8594,12 +8646,18 @@ can_use_hardware_watchpoint (struct value *v)
&& TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
{
CORE_ADDR vaddr = value_address (v);
int len = TYPE_LENGTH (value_type (v));
int len;
int num_regs;
if (!target_region_ok_for_hw_watchpoint (vaddr, len))
len = (exact_watchpoints
&& is_scalar_type_recursive (vtype))?
1 : TYPE_LENGTH (value_type (v));
num_regs = target_region_ok_for_hw_watchpoint (vaddr, len);
if (!num_regs)
return 0;
else
found_memory_cnt++;
found_memory_cnt += num_regs;
}
}
}
@ -9025,6 +9083,7 @@ static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
NULL, /* insert */
NULL, /* remove */
NULL, /* breakpoint_hit */
NULL, /* resources_needed */
print_exception_catchpoint,
print_one_exception_catchpoint,
print_mention_exception_catchpoint,

View File

@ -385,6 +385,11 @@ struct breakpoint_ops
breakpoint was hit. */
int (*breakpoint_hit) (struct breakpoint *);
/* Tell how many hardware resources (debug registers) are needed
for this breakpoint. If this function is not provided, then
the breakpoint or watchpoint needs one debug register. */
int (*resources_needed) (const struct bp_location *);
/* The normal print routine for this breakpoint, called when we
hit it. */
enum print_stop_action (*print_it) (struct breakpoint *);
@ -425,6 +430,13 @@ DEF_VEC_P(bp_location_p);
detail to the breakpoints module. */
struct counted_command_line;
/* Some targets (e.g., embedded PowerPC) need two debug registers to set
a watchpoint over a memory region. If this flag is true, GDB will use
only one register per watchpoint, thus assuming that all acesses that
modify a memory location happen at its starting address. */
extern int target_exact_watchpoints;
/* Note that the ->silent field is not currently used by any commands
(though the code is in there if it was to be, and set_raw_breakpoint
does set it to 0). I implemented it because I thought it would be
@ -595,7 +607,10 @@ struct breakpoint
can sometimes be NULL for enabled GDBs as not all breakpoint
types are tracked by the Python scripting API. */
struct breakpoint_object *py_bp_object;
};
/* Whether this watchpoint is exact (see target_exact_watchpoints). */
int exact;
};
typedef struct breakpoint *breakpoint_p;
DEF_VEC_P(breakpoint_p);

View File

@ -1,3 +1,10 @@
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.texinfo (PowerPC Embedded): Document ranged watchpoints and
the "set powerpc exact-watchpoints" flag.
2011-01-07 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python API): Add descriptions to @menu items.
@ -8,7 +15,7 @@
2010-01-06 Paul Pluzhnikov <ppluzhnikov@google.com>
* gdb.texinfo (Debugging Output): Document "set debug jit".
* gdb.texinfo (Debugging Output): Document "set debug jit".
2011-01-06 Tom Tromey <tromey@redhat.com>

View File

@ -18721,9 +18721,25 @@ implement in hardware simple hardware watchpoint conditions of the form:
if @var{ADDRESS|VARIABLE} == @var{CONSTANT EXPRESSION}
@end smallexample
The DVC register will be automatically used whenever @value{GDBN} detects
such pattern in a condition expression. This feature is available in native
@value{GDBN} running on a Linux kernel version 2.6.34 or newer.
The DVC register will be automatically used when @value{GDBN} detects
such pattern in a condition expression, and the created watchpoint uses one
debug register (either the @code{exact-watchpoints} option is on and the
variable is scalar, or the variable has a length of one byte). This feature
is available in native @value{GDBN} running on a Linux kernel version 2.6.34
or newer.
When running on PowerPC embedded processors, @value{GDBN} automatically uses
ranged hardware watchpoints, unless the @code{exact-watchpoints} option is on,
in which case watchpoints using only one debug register are created when
watching variables of scalar types.
You can create an artificial array to watch an arbitrary memory
region using one of the following commands (@pxref{Expressions}):
@smallexample
(@value{GDBP}) watch *((char *) @var{address})@@@var{length}
(@value{GDBP}) watch @{char[@var{length}]@} @var{address}
@end smallexample
@value{GDBN} provides the following PowerPC-specific commands:
@ -18744,6 +18760,12 @@ arguments and return values. The valid options are @samp{auto};
registers. By default, @value{GDBN} selects the calling convention
based on the selected architecture and the provided executable file.
@item set powerpc exact-watchpoints
@itemx show powerpc exact-watchpoints
Allow @value{GDBN} to use only one debug register when watching a variable
of scalar type, thus assuming that the variable is accessed through the
address of its first byte.
@kindex target dink32
@item target dink32 @var{dev}
DINK32 ROM monitor.

View File

@ -1955,6 +1955,68 @@ is_integral_type (struct type *t)
|| (TYPE_CODE (t) == TYPE_CODE_BOOL)));
}
/* Return true if TYPE is scalar. */
static int
is_scalar_type (struct type *type)
{
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_SET:
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
return 0;
default:
return 1;
}
}
/* Return true if T is scalar, or a composite type which in practice has
the memory layout of a scalar type. E.g., an array or struct with only one
scalar element inside it, or a union with only scalar elements. */
int
is_scalar_type_recursive (struct type *t)
{
CHECK_TYPEDEF (t);
if (is_scalar_type (t))
return 1;
/* Are we dealing with an array or string of known dimensions? */
else if ((TYPE_CODE (t) == TYPE_CODE_ARRAY
|| TYPE_CODE (t) == TYPE_CODE_STRING) && TYPE_NFIELDS (t) == 1
&& TYPE_CODE (TYPE_INDEX_TYPE (t)) == TYPE_CODE_RANGE)
{
LONGEST low_bound, high_bound;
struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (t));
get_discrete_bounds (TYPE_INDEX_TYPE (t), &low_bound, &high_bound);
return high_bound == low_bound && is_scalar_type_recursive (elt_type);
}
/* Are we dealing with a struct with one element? */
else if (TYPE_CODE (t) == TYPE_CODE_STRUCT && TYPE_NFIELDS (t) == 1)
return is_scalar_type_recursive (TYPE_FIELD_TYPE (t, 0));
else if (TYPE_CODE (t) == TYPE_CODE_UNION)
{
int i, n = TYPE_NFIELDS (t);
/* If all elements of the union are scalar, then the union is scalar. */
for (i = 0; i < n; i++)
if (!is_scalar_type_recursive (TYPE_FIELD_TYPE (t, i)))
return 0;
return 1;
}
return 0;
}
/* A helper function which returns true if types A and B represent the
"same" class type. This is true if the types have the same main
type, or the same name. */

View File

@ -1476,6 +1476,8 @@ extern int can_dereference (struct type *);
extern int is_integral_type (struct type *);
extern int is_scalar_type_recursive (struct type *);
extern void maintenance_print_type (char *, int);
extern htab_t create_copied_types_hash (struct objfile *objfile);

View File

@ -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));

View File

@ -4183,6 +4183,16 @@ powerpc_set_vector_abi (char *args, int from_tty,
internal_error (__FILE__, __LINE__, _("could not update architecture"));
}
/* Show the current setting of the exact watchpoints flag. */
static void
show_powerpc_exact_watchpoints (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value);
}
/* Initialization code. */
/* -Wmissing-prototypes */
@ -4240,4 +4250,17 @@ _initialize_rs6000_tdep (void)
_("Show the vector ABI."),
NULL, powerpc_set_vector_abi, NULL,
&setpowerpccmdlist, &showpowerpccmdlist);
add_setshow_boolean_cmd ("exact-watchpoints", class_support,
&target_exact_watchpoints,
_("\
Set whether to use just one debug register for watchpoints on scalars."),
_("\
Show whether to use just one debug register for watchpoints on scalars."),
_("\
If true, GDB will use only one debug register when watching a variable of\n\
scalar type, thus assuming that the variable is accessed through the address\n\
of its first byte."),
NULL, show_powerpc_exact_watchpoints,
&setpowerpccmdlist, &showpowerpccmdlist);
}

View File

@ -453,7 +453,11 @@ struct target_ops
int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *);
int (*to_watchpoint_addr_within_range) (struct target_ops *,
CORE_ADDR, CORE_ADDR, int);
/* Documentation of this routine is provided with the corresponding
target_* macro. */
int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int);
int (*to_can_accel_watchpoint_condition) (CORE_ADDR, int, int,
struct expression *);
void (*to_terminal_init) (void);
@ -1308,6 +1312,9 @@ extern char *normal_pid_to_str (ptid_t ptid);
#define target_can_use_hardware_watchpoint(TYPE,CNT,OTHERTYPE) \
(*current_target.to_can_use_hw_breakpoint) (TYPE, CNT, OTHERTYPE);
/* Returns the number of debug registers needed to watch the given
memory region, or zero if not supported. */
#define target_region_ok_for_hw_watchpoint(addr, len) \
(*current_target.to_region_ok_for_hw_watchpoint) (addr, len)