2010-07-07 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>

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

	Support for hw accelerated condition watchpoints in booke powerpc.

	* breakpoint.c (fetch_watchpoint_value): Rename to fetch_subexp_value
	and move to eval.c.  Change callers.
	(insert_bp_location): Pass watchpoint condition in
	target_insert_watchpoint.
	(remove_breakpoint_1) Pass watchpoint condition in
	target_remove_watchpoint.
	(watchpoint_locations_match): Call
	target_can_accel_watchpoint_condition.
	* eval.c: Include wrapper.h.
	(fetch_subexp_value): Moved from breakpoint.c.
	* ppc-linux-nat.c (ppc_linux_region_ok_for_hw_watchpoint):
	Formatting fix.
	(can_use_watchpoint_cond_accel): New function.
	(calculate_dvc): Likewise.
	(num_memory_accesses): Likewise.
	(check_condition): Likewise.
	(ppc_linux_can_accel_watchpoint_condition): Likewise
	(ppc_linux_insert_watchpoint): Call can_use_watchpoint_cond_accel,
	check_condition and calculate_dvc.
	(ppc_linux_remove_watchpoint): Likewise.
	(_initialize_ppc_linux_nat): Set to_can_accel_watchpoint_condition to
	ppc_linux_can_accel_watchpoint_condition
	* target.c (debug_to_insert_watchpoint): Add argument for watchpoint
	condition.
	(debug_to_remove_watchpoint): Likewise.
	(debug_to_can_accel_watchpoint_condition): New function.
	(update_current_target): Set to_can_accel_watchpoint_condition.
	(setup_target_debug): Set to_can_accel_watchpoint_condition.
	* target.h: Add opaque declaration for struct expression.
	(struct target_ops) <to_insert_watchpoint>,
	<to_remove_watchpoint>: Add new arguments to pass the watchpoint
	<to_can_accel_watchpoint_condition>: New member.
	condition.  Update all callers and implementations.
	(target_can_accel_watchpoint_condition): New macro.
	* value.c (free_value_chain): New function.
	* value.h (fetch_subexp_value): New prototype.
	(free_value_chain): Likewise.
This commit is contained in:
Thiago Jung Bauermann
2010-07-07 16:15:18 +00:00
parent 6bd3187468
commit 0cf6dd1543
18 changed files with 503 additions and 132 deletions

View File

@@ -1234,84 +1234,6 @@ is_watchpoint (const struct breakpoint *bpt)
|| bpt->type == bp_watchpoint);
}
/* Find the current value of a watchpoint on EXP. Return the value in
*VALP and *RESULTP and the chain of intermediate and final values
in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does
not need them.
If a memory error occurs while evaluating the expression, *RESULTP will
be set to NULL. *RESULTP may be a lazy value, if the result could
not be read from memory. It is used to determine whether a value
is user-specified (we should watch the whole value) or intermediate
(we should watch only the bit used to locate the final value).
If the final value, or any intermediate value, could not be read
from memory, *VALP will be set to NULL. *VAL_CHAIN will still be
set to any referenced values. *VALP will never be a lazy value.
This is the value which we store in struct breakpoint.
If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the
value chain. The caller must free the values individually. If
VAL_CHAIN is NULL, all generated values will be left on the value
chain. */
static void
fetch_watchpoint_value (struct expression *exp, struct value **valp,
struct value **resultp, struct value **val_chain)
{
struct value *mark, *new_mark, *result;
volatile struct gdb_exception ex;
*valp = NULL;
if (resultp)
*resultp = NULL;
if (val_chain)
*val_chain = NULL;
/* Evaluate the expression. */
mark = value_mark ();
result = NULL;
TRY_CATCH (ex, RETURN_MASK_ALL)
{
result = evaluate_expression (exp);
}
if (ex.reason < 0)
{
/* Ignore memory errors, we want watchpoints pointing at
inaccessible memory to still be created; otherwise, throw the
error to some higher catcher. */
switch (ex.error)
{
case MEMORY_ERROR:
break;
default:
throw_exception (ex);
break;
}
}
new_mark = value_mark ();
if (mark == new_mark)
return;
if (resultp)
*resultp = result;
/* Make sure it's not lazy, so that after the target stops again we
have a non-lazy previous value to compare with. */
if (result != NULL
&& (!value_lazy (result) || gdb_value_fetch_lazy (result)))
*valp = result;
if (val_chain)
{
/* Return the chain of intermediate values. We use this to
decide which addresses to watch. */
*val_chain = new_mark;
value_release_to_mark (mark);
}
}
/* Assuming that B is a watchpoint: returns true if the current thread
and its running state are safe to evaluate or update watchpoint B.
Watchpoints on local expressions need to be evaluated in the
@@ -1469,10 +1391,11 @@ update_watchpoint (struct breakpoint *b, int reparse)
}
else if (within_current_scope && b->exp)
{
int pc = 0;
struct value *val_chain, *v, *result, *next;
struct program_space *frame_pspace;
fetch_watchpoint_value (b->exp, &v, &result, &val_chain);
fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain);
/* Avoid setting b->val if it's already set. The meaning of
b->val is 'the last value' user saw, and we should update
@@ -1828,7 +1751,8 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
{
val = target_insert_watchpoint (bpt->address,
bpt->length,
bpt->watchpoint_type);
bpt->watchpoint_type,
bpt->owner->cond_exp);
/* If trying to set a read-watchpoint, and it turns out it's not
supported, try emulating one with an access watchpoint. */
@@ -1856,7 +1780,8 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
{
val = target_insert_watchpoint (bpt->address,
bpt->length,
hw_access);
hw_access,
bpt->owner->cond_exp);
if (val == 0)
bpt->watchpoint_type = hw_access;
}
@@ -2525,8 +2450,8 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is)
else if (b->loc_type == bp_loc_hardware_watchpoint)
{
b->inserted = (is == mark_inserted);
val = target_remove_watchpoint (b->address, b->length,
b->watchpoint_type);
val = target_remove_watchpoint (b->address, b->length,
b->watchpoint_type, b->owner->cond_exp);
/* Failure to remove any of the hardware watchpoints comes here. */
if ((is == mark_uninserted) && (b->inserted))
@@ -3679,10 +3604,11 @@ watchpoint_check (void *p)
call free_all_values. We can't call free_all_values because
we might be in the middle of evaluating a function call. */
int pc = 0;
struct value *mark = value_mark ();
struct value *new_val;
fetch_watchpoint_value (b->exp, &new_val, NULL, NULL);
fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL);
/* We use value_equal_contents instead of value_equal because the latter
coerces an array to a pointer, thus comparing just the address of the
@@ -5262,6 +5188,21 @@ watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2)
gdb_assert (loc1->owner != NULL);
gdb_assert (loc2->owner != NULL);
/* If the target can evaluate the condition expression in hardware, then we
we need to insert both watchpoints even if they are at the same place.
Otherwise the watchpoint will only trigger when the condition of whichever
watchpoint was inserted evaluates to true, not giving a chance for GDB to
check the condition of the other watchpoint. */
if ((loc1->owner->cond_exp
&& target_can_accel_watchpoint_condition (loc1->address, loc1->length,
loc1->watchpoint_type,
loc1->owner->cond_exp))
|| (loc2->owner->cond_exp
&& target_can_accel_watchpoint_condition (loc2->address, loc2->length,
loc2->watchpoint_type,
loc2->owner->cond_exp)))
return 0;
/* Note that this checks the owner's type, not the location's. In
case the target does not support read watchpoints, but does
support access watchpoints, we'll have bp_read_watchpoint
@@ -8057,6 +7998,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
enum bptype bp_type;
int mem_cnt = 0;
int thread = -1;
int pc = 0;
/* Make sure that we actually have parameters to parse. */
if (arg != NULL && arg[0] != '\0')
@@ -8143,7 +8085,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
exp_valid_block = innermost_block;
mark = value_mark ();
fetch_watchpoint_value (exp, &val, NULL, NULL);
fetch_subexp_value (exp, &pc, &val, NULL, NULL);
if (val != NULL)
release_value (val);