2010-04-23 Stan Shebs <stan@codesourcery.com>
* ax.h (struct agent_expr): Merge in agent_reqs fields, add some comments. (struct agent_reqs): Remove. (ax_reg_mask): Declare. * ax-general.c (new_agent_expr): Add gdbarch argument, set new fields. (free_agent_expr): Free reg_mask. (ax_print): Add scope and register mask info. (ax_reqs): Remove agent_reqs argument, use agent expression fields, and move part of register mask computation to... (ax_reg_mask): New function. * ax-gdb.c (gen_trace_static_fields): Call it. (gen_traced_pop): Ditto. (is_nontrivial_conversion): Add dummy gdbarch to new_agent_expr. (gen_trace_for_var): Pass gdbarch to new_agent_expr. (gen_trace_for_expr): Ditto, and clear optimized_out flag. (gen_eval_for_expr): Ditto, and require an rvalue. (agent_command): Call ax_reqs. (agent_eval_command): Ditto. * tracepoint.c (report_agent_reqs_errors): Use agent expression fields. (validate_action_line): Ditto. (collect_symbol): Ditto. (encode_actions_1): Ditto.
This commit is contained in:
parent
492928e407
commit
35c9c7ba77
5 changed files with 206 additions and 168 deletions
|
@ -1,3 +1,28 @@
|
||||||
|
2010-04-23 Stan Shebs <stan@codesourcery.com>
|
||||||
|
|
||||||
|
* ax.h (struct agent_expr): Merge in agent_reqs fields, add some
|
||||||
|
comments.
|
||||||
|
(struct agent_reqs): Remove.
|
||||||
|
(ax_reg_mask): Declare.
|
||||||
|
* ax-general.c (new_agent_expr): Add gdbarch argument, set new fields.
|
||||||
|
(free_agent_expr): Free reg_mask.
|
||||||
|
(ax_print): Add scope and register mask info.
|
||||||
|
(ax_reqs): Remove agent_reqs argument, use agent expression
|
||||||
|
fields, and move part of register mask computation to...
|
||||||
|
(ax_reg_mask): New function.
|
||||||
|
* ax-gdb.c (gen_trace_static_fields): Call it.
|
||||||
|
(gen_traced_pop): Ditto.
|
||||||
|
(is_nontrivial_conversion): Add dummy gdbarch to new_agent_expr.
|
||||||
|
(gen_trace_for_var): Pass gdbarch to new_agent_expr.
|
||||||
|
(gen_trace_for_expr): Ditto, and clear optimized_out flag.
|
||||||
|
(gen_eval_for_expr): Ditto, and require an rvalue.
|
||||||
|
(agent_command): Call ax_reqs.
|
||||||
|
(agent_eval_command): Ditto.
|
||||||
|
* tracepoint.c (report_agent_reqs_errors): Use agent expression fields.
|
||||||
|
(validate_action_line): Ditto.
|
||||||
|
(collect_symbol): Ditto.
|
||||||
|
(encode_actions_1): Ditto.
|
||||||
|
|
||||||
2010-04-23 Daniel Jacobowitz <dan@codesourcery.com>
|
2010-04-23 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
Paul Pluzhnikov <ppluzhnikov@google.com>
|
Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||||
Jan Kratochvil <jan.kratochvil@redhat.com>
|
Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
31
gdb/ax-gdb.c
31
gdb/ax-gdb.c
|
@ -363,10 +363,9 @@ gen_trace_static_fields (struct gdbarch *gdbarch,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case axs_lvalue_register:
|
case axs_lvalue_register:
|
||||||
/* We need to mention the register somewhere in the bytecode,
|
/* We don't actually need the register's value to be pushed,
|
||||||
so ax_reqs will pick it up and add it to the mask of
|
just note that we need it to be collected. */
|
||||||
registers used. */
|
ax_reg_mask (ax, value.u.reg);
|
||||||
ax_reg (ax, value.u.reg);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -414,11 +413,11 @@ gen_traced_pop (struct gdbarch *gdbarch,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case axs_lvalue_register:
|
case axs_lvalue_register:
|
||||||
/* We need to mention the register somewhere in the bytecode,
|
/* We don't actually need the register's value to be on the
|
||||||
so ax_reqs will pick it up and add it to the mask of
|
stack, and the target will get heartburn if the register is
|
||||||
registers used. */
|
larger than will fit in a stack, so just mark it for
|
||||||
ax_reg (ax, value->u.reg);
|
collection and be done with it. */
|
||||||
ax_simple (ax, aop_pop);
|
ax_reg_mask (ax, value->u.reg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -898,7 +897,7 @@ gen_conversion (struct agent_expr *ax, struct type *from, struct type *to)
|
||||||
static int
|
static int
|
||||||
is_nontrivial_conversion (struct type *from, struct type *to)
|
is_nontrivial_conversion (struct type *from, struct type *to)
|
||||||
{
|
{
|
||||||
struct agent_expr *ax = new_agent_expr (0);
|
struct agent_expr *ax = new_agent_expr (NULL, 0);
|
||||||
int nontrivial;
|
int nontrivial;
|
||||||
|
|
||||||
/* Actually generate the code, and see if anything came out. At the
|
/* Actually generate the code, and see if anything came out. At the
|
||||||
|
@ -2324,7 +2323,7 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
|
||||||
struct symbol *var)
|
struct symbol *var)
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain = 0;
|
struct cleanup *old_chain = 0;
|
||||||
struct agent_expr *ax = new_agent_expr (scope);
|
struct agent_expr *ax = new_agent_expr (gdbarch, scope);
|
||||||
struct axs_value value;
|
struct axs_value value;
|
||||||
|
|
||||||
old_chain = make_cleanup_free_agent_expr (ax);
|
old_chain = make_cleanup_free_agent_expr (ax);
|
||||||
|
@ -2364,7 +2363,7 @@ struct agent_expr *
|
||||||
gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
|
gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain = 0;
|
struct cleanup *old_chain = 0;
|
||||||
struct agent_expr *ax = new_agent_expr (scope);
|
struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
|
||||||
union exp_element *pc;
|
union exp_element *pc;
|
||||||
struct axs_value value;
|
struct axs_value value;
|
||||||
|
|
||||||
|
@ -2372,6 +2371,7 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||||
|
|
||||||
pc = expr->elts;
|
pc = expr->elts;
|
||||||
trace_kludge = 1;
|
trace_kludge = 1;
|
||||||
|
value.optimized_out = 0;
|
||||||
gen_expr (expr, &pc, ax, &value);
|
gen_expr (expr, &pc, ax, &value);
|
||||||
|
|
||||||
/* Make sure we record the final object, and get rid of it. */
|
/* Make sure we record the final object, and get rid of it. */
|
||||||
|
@ -2398,7 +2398,7 @@ struct agent_expr *
|
||||||
gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain = 0;
|
struct cleanup *old_chain = 0;
|
||||||
struct agent_expr *ax = new_agent_expr (scope);
|
struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
|
||||||
union exp_element *pc;
|
union exp_element *pc;
|
||||||
struct axs_value value;
|
struct axs_value value;
|
||||||
|
|
||||||
|
@ -2406,8 +2406,11 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||||
|
|
||||||
pc = expr->elts;
|
pc = expr->elts;
|
||||||
trace_kludge = 0;
|
trace_kludge = 0;
|
||||||
|
value.optimized_out = 0;
|
||||||
gen_expr (expr, &pc, ax, &value);
|
gen_expr (expr, &pc, ax, &value);
|
||||||
|
|
||||||
|
require_rvalue (ax, &value);
|
||||||
|
|
||||||
/* Oh, and terminate. */
|
/* Oh, and terminate. */
|
||||||
ax_simple (ax, aop_end);
|
ax_simple (ax, aop_end);
|
||||||
|
|
||||||
|
@ -2440,6 +2443,7 @@ agent_command (char *exp, int from_tty)
|
||||||
old_chain = make_cleanup (free_current_contents, &expr);
|
old_chain = make_cleanup (free_current_contents, &expr);
|
||||||
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
|
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
|
||||||
make_cleanup_free_agent_expr (agent);
|
make_cleanup_free_agent_expr (agent);
|
||||||
|
ax_reqs (agent);
|
||||||
ax_print (gdb_stdout, agent);
|
ax_print (gdb_stdout, agent);
|
||||||
|
|
||||||
/* It would be nice to call ax_reqs here to gather some general info
|
/* It would be nice to call ax_reqs here to gather some general info
|
||||||
|
@ -2475,6 +2479,7 @@ agent_eval_command (char *exp, int from_tty)
|
||||||
old_chain = make_cleanup (free_current_contents, &expr);
|
old_chain = make_cleanup (free_current_contents, &expr);
|
||||||
agent = gen_eval_for_expr (get_frame_pc (fi), expr);
|
agent = gen_eval_for_expr (get_frame_pc (fi), expr);
|
||||||
make_cleanup_free_agent_expr (agent);
|
make_cleanup_free_agent_expr (agent);
|
||||||
|
ax_reqs (agent);
|
||||||
ax_print (gdb_stdout, agent);
|
ax_print (gdb_stdout, agent);
|
||||||
|
|
||||||
/* It would be nice to call ax_reqs here to gather some general info
|
/* It would be nice to call ax_reqs here to gather some general info
|
||||||
|
|
114
gdb/ax-general.c
114
gdb/ax-general.c
|
@ -40,15 +40,23 @@ static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
|
||||||
|
|
||||||
/* Allocate a new, empty agent expression. */
|
/* Allocate a new, empty agent expression. */
|
||||||
struct agent_expr *
|
struct agent_expr *
|
||||||
new_agent_expr (CORE_ADDR scope)
|
new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
|
||||||
{
|
{
|
||||||
struct agent_expr *x = xmalloc (sizeof (*x));
|
struct agent_expr *x = xmalloc (sizeof (*x));
|
||||||
|
|
||||||
x->len = 0;
|
x->len = 0;
|
||||||
x->size = 1; /* Change this to a larger value once
|
x->size = 1; /* Change this to a larger value once
|
||||||
reallocation code is tested. */
|
reallocation code is tested. */
|
||||||
x->buf = xmalloc (x->size);
|
x->buf = xmalloc (x->size);
|
||||||
|
|
||||||
|
x->gdbarch = gdbarch;
|
||||||
x->scope = scope;
|
x->scope = scope;
|
||||||
|
|
||||||
|
/* Bit vector for registers used. */
|
||||||
|
x->reg_mask_len = 1;
|
||||||
|
x->reg_mask = xmalloc (x->reg_mask_len * sizeof (x->reg_mask[0]));
|
||||||
|
memset (x->reg_mask, 0, x->reg_mask_len * sizeof (x->reg_mask[0]));
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +65,7 @@ void
|
||||||
free_agent_expr (struct agent_expr *x)
|
free_agent_expr (struct agent_expr *x)
|
||||||
{
|
{
|
||||||
xfree (x->buf);
|
xfree (x->buf);
|
||||||
|
xfree (x->reg_mask);
|
||||||
xfree (x);
|
xfree (x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,6 +364,12 @@ ax_print (struct ui_file *f, struct agent_expr *x)
|
||||||
int i;
|
int i;
|
||||||
int is_float = 0;
|
int is_float = 0;
|
||||||
|
|
||||||
|
fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope));
|
||||||
|
fprintf_filtered (f, _("Reg mask:"));
|
||||||
|
for (i = 0; i < x->reg_mask_len; ++i)
|
||||||
|
fprintf_filtered (f, _(" %02x"), x->reg_mask[i]);
|
||||||
|
fprintf_filtered (f, _("\n"));
|
||||||
|
|
||||||
/* Check the size of the name array against the number of entries in
|
/* Check the size of the name array against the number of entries in
|
||||||
the enum, to catch additions that people didn't sync. */
|
the enum, to catch additions that people didn't sync. */
|
||||||
if ((sizeof (aop_map) / sizeof (aop_map[0]))
|
if ((sizeof (aop_map) / sizeof (aop_map[0]))
|
||||||
|
@ -394,19 +409,37 @@ ax_print (struct ui_file *f, struct agent_expr *x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add register REG to the register mask for expression AX. */
|
||||||
/* Given an agent expression AX, fill in an agent_reqs structure REQS
|
|
||||||
describing it. */
|
|
||||||
void
|
void
|
||||||
ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
ax_reg_mask (struct agent_expr *ax, int reg)
|
||||||
|
{
|
||||||
|
int byte = reg / 8;
|
||||||
|
|
||||||
|
/* Grow the bit mask if necessary. */
|
||||||
|
if (byte >= ax->reg_mask_len)
|
||||||
|
{
|
||||||
|
/* It's not appropriate to double here. This isn't a
|
||||||
|
string buffer. */
|
||||||
|
int new_len = byte + 1;
|
||||||
|
unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
|
||||||
|
new_len * sizeof (ax->reg_mask[0]));
|
||||||
|
memset (new_reg_mask + ax->reg_mask_len, 0,
|
||||||
|
(new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
|
||||||
|
ax->reg_mask_len = new_len;
|
||||||
|
ax->reg_mask = new_reg_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
ax->reg_mask[byte] |= 1 << (reg % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an agent expression AX, fill in requirements and other descriptive
|
||||||
|
bits. */
|
||||||
|
void
|
||||||
|
ax_reqs (struct agent_expr *ax)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
/* Bit vector for registers used. */
|
|
||||||
int reg_mask_len = 1;
|
|
||||||
unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
|
|
||||||
|
|
||||||
/* Jump target table. targets[i] is non-zero iff we have found a
|
/* Jump target table. targets[i] is non-zero iff we have found a
|
||||||
jump to offset i. */
|
jump to offset i. */
|
||||||
char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
|
char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
|
||||||
|
@ -423,20 +456,18 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
/* Pointer to a description of the present op. */
|
/* Pointer to a description of the present op. */
|
||||||
struct aop_map *op;
|
struct aop_map *op;
|
||||||
|
|
||||||
memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
|
|
||||||
memset (targets, 0, ax->len * sizeof (targets[0]));
|
memset (targets, 0, ax->len * sizeof (targets[0]));
|
||||||
memset (boundary, 0, ax->len * sizeof (boundary[0]));
|
memset (boundary, 0, ax->len * sizeof (boundary[0]));
|
||||||
|
|
||||||
reqs->max_height = reqs->min_height = height = 0;
|
ax->max_height = ax->min_height = height = 0;
|
||||||
reqs->flaw = agent_flaw_none;
|
ax->flaw = agent_flaw_none;
|
||||||
reqs->max_data_size = 0;
|
ax->max_data_size = 0;
|
||||||
|
|
||||||
for (i = 0; i < ax->len; i += 1 + op->op_size)
|
for (i = 0; i < ax->len; i += 1 + op->op_size)
|
||||||
{
|
{
|
||||||
if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
|
if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_bad_instruction;
|
ax->flaw = agent_flaw_bad_instruction;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,15 +475,13 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
|
|
||||||
if (!op->name)
|
if (!op->name)
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_bad_instruction;
|
ax->flaw = agent_flaw_bad_instruction;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i + 1 + op->op_size > ax->len)
|
if (i + 1 + op->op_size > ax->len)
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_incomplete_instruction;
|
ax->flaw = agent_flaw_incomplete_instruction;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,8 +490,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
source? */
|
source? */
|
||||||
if (targets[i] && (heights[i] != height))
|
if (targets[i] && (heights[i] != height))
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_height_mismatch;
|
ax->flaw = agent_flaw_height_mismatch;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,14 +498,14 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
heights[i] = height;
|
heights[i] = height;
|
||||||
|
|
||||||
height -= op->consumed;
|
height -= op->consumed;
|
||||||
if (height < reqs->min_height)
|
if (height < ax->min_height)
|
||||||
reqs->min_height = height;
|
ax->min_height = height;
|
||||||
height += op->produced;
|
height += op->produced;
|
||||||
if (height > reqs->max_height)
|
if (height > ax->max_height)
|
||||||
reqs->max_height = height;
|
ax->max_height = height;
|
||||||
|
|
||||||
if (op->data_size > reqs->max_data_size)
|
if (op->data_size > ax->max_data_size)
|
||||||
reqs->max_data_size = op->data_size;
|
ax->max_data_size = op->data_size;
|
||||||
|
|
||||||
/* For jump instructions, check that the target is a valid
|
/* For jump instructions, check that the target is a valid
|
||||||
offset. If it is, record the fact that that location is a
|
offset. If it is, record the fact that that location is a
|
||||||
|
@ -488,8 +516,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
int target = read_const (ax, i + 1, 2);
|
int target = read_const (ax, i + 1, 2);
|
||||||
if (target < 0 || target >= ax->len)
|
if (target < 0 || target >= ax->len)
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_bad_jump;
|
ax->flaw = agent_flaw_bad_jump;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,8 +526,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
{
|
{
|
||||||
if (heights[target] != height)
|
if (heights[target] != height)
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_height_mismatch;
|
ax->flaw = agent_flaw_height_mismatch;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,8 +543,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
{
|
{
|
||||||
if (!targets[i + 3])
|
if (!targets[i + 3])
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_hole;
|
ax->flaw = agent_flaw_hole;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,22 +554,8 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
if (aop_reg == op - aop_map)
|
if (aop_reg == op - aop_map)
|
||||||
{
|
{
|
||||||
int reg = read_const (ax, i + 1, 2);
|
int reg = read_const (ax, i + 1, 2);
|
||||||
int byte = reg / 8;
|
|
||||||
|
|
||||||
/* Grow the bit mask if necessary. */
|
ax_reg_mask (ax, reg);
|
||||||
if (byte >= reg_mask_len)
|
|
||||||
{
|
|
||||||
/* It's not appropriate to double here. This isn't a
|
|
||||||
string buffer. */
|
|
||||||
int new_len = byte + 1;
|
|
||||||
reg_mask = xrealloc (reg_mask,
|
|
||||||
new_len * sizeof (reg_mask[0]));
|
|
||||||
memset (reg_mask + reg_mask_len, 0,
|
|
||||||
(new_len - reg_mask_len) * sizeof (reg_mask[0]));
|
|
||||||
reg_mask_len = new_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_mask[byte] |= 1 << (reg % 8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,12 +563,9 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||||
for (i = 0; i < ax->len; i++)
|
for (i = 0; i < ax->len; i++)
|
||||||
if (targets[i] && !boundary[i])
|
if (targets[i] && !boundary[i])
|
||||||
{
|
{
|
||||||
reqs->flaw = agent_flaw_bad_jump;
|
ax->flaw = agent_flaw_bad_jump;
|
||||||
xfree (reg_mask);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reqs->final_height = height;
|
ax->final_height = height;
|
||||||
reqs->reg_mask_len = reg_mask_len;
|
|
||||||
reqs->reg_mask = reg_mask;
|
|
||||||
}
|
}
|
||||||
|
|
152
gdb/ax.h
152
gdb/ax.h
|
@ -51,6 +51,33 @@
|
||||||
to the host GDB. */
|
to the host GDB. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Different kinds of flaws an agent expression might have, as
|
||||||
|
detected by ax_reqs. */
|
||||||
|
enum agent_flaws
|
||||||
|
{
|
||||||
|
agent_flaw_none = 0, /* code is good */
|
||||||
|
|
||||||
|
/* There is an invalid instruction in the stream. */
|
||||||
|
agent_flaw_bad_instruction,
|
||||||
|
|
||||||
|
/* There is an incomplete instruction at the end of the expression. */
|
||||||
|
agent_flaw_incomplete_instruction,
|
||||||
|
|
||||||
|
/* ax_reqs was unable to prove that every jump target is to a
|
||||||
|
valid offset. Valid offsets are within the bounds of the
|
||||||
|
expression, and to a valid instruction boundary. */
|
||||||
|
agent_flaw_bad_jump,
|
||||||
|
|
||||||
|
/* ax_reqs was unable to prove to its satisfaction that, for each
|
||||||
|
jump target location, the stack will have the same height whether
|
||||||
|
that location is reached via a jump or by straight execution. */
|
||||||
|
agent_flaw_height_mismatch,
|
||||||
|
|
||||||
|
/* ax_reqs was unable to prove that every instruction following
|
||||||
|
an unconditional jump was the target of some other jump. */
|
||||||
|
agent_flaw_hole
|
||||||
|
};
|
||||||
|
|
||||||
/* Agent expression data structures. */
|
/* Agent expression data structures. */
|
||||||
|
|
||||||
/* The type of an element of the agent expression stack.
|
/* The type of an element of the agent expression stack.
|
||||||
|
@ -67,15 +94,57 @@ union agent_val
|
||||||
/* A buffer containing a agent expression. */
|
/* A buffer containing a agent expression. */
|
||||||
struct agent_expr
|
struct agent_expr
|
||||||
{
|
{
|
||||||
|
/* The bytes of the expression. */
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
int len; /* number of characters used */
|
|
||||||
int size; /* allocated size */
|
/* The number of bytecode in the expression. */
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Allocated space available currently. */
|
||||||
|
int size;
|
||||||
|
|
||||||
|
/* The target architecture assumed to be in effect. */
|
||||||
|
struct gdbarch *gdbarch;
|
||||||
|
|
||||||
|
/* The address to which the expression applies. */
|
||||||
CORE_ADDR scope;
|
CORE_ADDR scope;
|
||||||
|
|
||||||
|
/* If the following is not equal to agent_flaw_none, the rest of the
|
||||||
|
information in this structure is suspect. */
|
||||||
|
enum agent_flaws flaw;
|
||||||
|
|
||||||
|
/* Number of elements left on stack at end; may be negative if expr
|
||||||
|
only consumes elements. */
|
||||||
|
int final_height;
|
||||||
|
|
||||||
|
/* Maximum and minimum stack height, relative to initial height. */
|
||||||
|
int max_height, min_height;
|
||||||
|
|
||||||
|
/* Largest `ref' or `const' opcode used, in bits. Zero means the
|
||||||
|
expression has no such instructions. */
|
||||||
|
int max_data_size;
|
||||||
|
|
||||||
|
/* Bit vector of registers needed. Register R is needed iff
|
||||||
|
|
||||||
|
reg_mask[R / 8] & (1 << (R % 8))
|
||||||
|
|
||||||
|
is non-zero. Note! You may not assume that this bitmask is long
|
||||||
|
enough to hold bits for all the registers of the machine; the
|
||||||
|
agent expression code has no idea how many registers the machine
|
||||||
|
has. However, the bitmask is reg_mask_len bytes long, so the
|
||||||
|
valid register numbers run from 0 to reg_mask_len * 8 - 1.
|
||||||
|
|
||||||
|
Also note that this mask may contain registers that are needed
|
||||||
|
for the original collection expression to work, but that are
|
||||||
|
not referenced by any bytecode. This could, for example, occur
|
||||||
|
when collecting a local variable allocated to a register; the
|
||||||
|
compiler sets the mask bit and skips generating a bytecode whose
|
||||||
|
result is going to be discarded anyway.
|
||||||
|
*/
|
||||||
|
int reg_mask_len;
|
||||||
|
unsigned char *reg_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The actual values of the various bytecode operations.
|
/* The actual values of the various bytecode operations.
|
||||||
|
|
||||||
Other independent implementations of the agent bytecode engine will
|
Other independent implementations of the agent bytecode engine will
|
||||||
|
@ -143,7 +212,7 @@ enum agent_op
|
||||||
/* Functions for building expressions. */
|
/* Functions for building expressions. */
|
||||||
|
|
||||||
/* Allocate a new, empty agent expression. */
|
/* Allocate a new, empty agent expression. */
|
||||||
extern struct agent_expr *new_agent_expr (CORE_ADDR);
|
extern struct agent_expr *new_agent_expr (struct gdbarch *, CORE_ADDR);
|
||||||
|
|
||||||
/* Free a agent expression. */
|
/* Free a agent expression. */
|
||||||
extern void free_agent_expr (struct agent_expr *);
|
extern void free_agent_expr (struct agent_expr *);
|
||||||
|
@ -186,6 +255,9 @@ extern void ax_const_d (struct agent_expr *EXPR, LONGEST d);
|
||||||
stack. */
|
stack. */
|
||||||
extern void ax_reg (struct agent_expr *EXPR, int REG);
|
extern void ax_reg (struct agent_expr *EXPR, int REG);
|
||||||
|
|
||||||
|
/* Add the given register to the register mask of the expression. */
|
||||||
|
extern void ax_reg_mask (struct agent_expr *ax, int reg);
|
||||||
|
|
||||||
/* Assemble code to operate on a trace state variable. */
|
/* Assemble code to operate on a trace state variable. */
|
||||||
extern void ax_tsv (struct agent_expr *expr, enum agent_op op, int num);
|
extern void ax_tsv (struct agent_expr *expr, enum agent_op op, int num);
|
||||||
|
|
||||||
|
@ -226,72 +298,8 @@ struct aop_map
|
||||||
/* Map of the bytecodes, indexed by bytecode number. */
|
/* Map of the bytecodes, indexed by bytecode number. */
|
||||||
extern struct aop_map aop_map[];
|
extern struct aop_map aop_map[];
|
||||||
|
|
||||||
/* Different kinds of flaws an agent expression might have, as
|
/* Given an agent expression AX, analyze and update its requirements. */
|
||||||
detected by agent_reqs. */
|
|
||||||
enum agent_flaws
|
|
||||||
{
|
|
||||||
agent_flaw_none = 0, /* code is good */
|
|
||||||
|
|
||||||
/* There is an invalid instruction in the stream. */
|
extern void ax_reqs (struct agent_expr *ax);
|
||||||
agent_flaw_bad_instruction,
|
|
||||||
|
|
||||||
/* There is an incomplete instruction at the end of the expression. */
|
|
||||||
agent_flaw_incomplete_instruction,
|
|
||||||
|
|
||||||
/* agent_reqs was unable to prove that every jump target is to a
|
|
||||||
valid offset. Valid offsets are within the bounds of the
|
|
||||||
expression, and to a valid instruction boundary. */
|
|
||||||
agent_flaw_bad_jump,
|
|
||||||
|
|
||||||
/* agent_reqs was unable to prove to its satisfaction that, for each
|
|
||||||
jump target location, the stack will have the same height whether
|
|
||||||
that location is reached via a jump or by straight execution. */
|
|
||||||
agent_flaw_height_mismatch,
|
|
||||||
|
|
||||||
/* agent_reqs was unable to prove that every instruction following
|
|
||||||
an unconditional jump was the target of some other jump. */
|
|
||||||
agent_flaw_hole
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Structure describing the requirements of a bytecode expression. */
|
|
||||||
struct agent_reqs
|
|
||||||
{
|
|
||||||
|
|
||||||
/* If the following is not equal to agent_flaw_none, the rest of the
|
|
||||||
information in this structure is suspect. */
|
|
||||||
enum agent_flaws flaw;
|
|
||||||
|
|
||||||
/* Number of elements left on stack at end; may be negative if expr
|
|
||||||
only consumes elements. */
|
|
||||||
int final_height;
|
|
||||||
|
|
||||||
/* Maximum and minimum stack height, relative to initial height. */
|
|
||||||
int max_height, min_height;
|
|
||||||
|
|
||||||
/* Largest `ref' or `const' opcode used, in bits. Zero means the
|
|
||||||
expression has no such instructions. */
|
|
||||||
int max_data_size;
|
|
||||||
|
|
||||||
/* Bit vector of registers used. Register R is used iff
|
|
||||||
|
|
||||||
reg_mask[R / 8] & (1 << (R % 8))
|
|
||||||
|
|
||||||
is non-zero. Note! You may not assume that this bitmask is long
|
|
||||||
enough to hold bits for all the registers of the machine; the
|
|
||||||
agent expression code has no idea how many registers the machine
|
|
||||||
has. However, the bitmask is reg_mask_len bytes long, so the
|
|
||||||
valid register numbers run from 0 to reg_mask_len * 8 - 1.
|
|
||||||
|
|
||||||
We're assuming eight-bit bytes. So sue me.
|
|
||||||
|
|
||||||
The caller should free reg_list when done. */
|
|
||||||
int reg_mask_len;
|
|
||||||
unsigned char *reg_mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Given an agent expression AX, fill in an agent_reqs structure REQS
|
|
||||||
describing it. */
|
|
||||||
extern void ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs);
|
|
||||||
|
|
||||||
#endif /* AGENTEXPR_H */
|
#endif /* AGENTEXPR_H */
|
||||||
|
|
|
@ -560,16 +560,16 @@ trace_actions_command (char *args, int from_tty)
|
||||||
internal errors. */
|
internal errors. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
report_agent_reqs_errors (struct agent_expr *aexpr, struct agent_reqs *areqs)
|
report_agent_reqs_errors (struct agent_expr *aexpr)
|
||||||
{
|
{
|
||||||
/* All of the "flaws" are serious bytecode generation issues that
|
/* All of the "flaws" are serious bytecode generation issues that
|
||||||
should never occur. */
|
should never occur. */
|
||||||
if (areqs->flaw != agent_flaw_none)
|
if (aexpr->flaw != agent_flaw_none)
|
||||||
internal_error (__FILE__, __LINE__, _("expression is malformed"));
|
internal_error (__FILE__, __LINE__, _("expression is malformed"));
|
||||||
|
|
||||||
/* If analysis shows a stack underflow, GDB must have done something
|
/* If analysis shows a stack underflow, GDB must have done something
|
||||||
badly wrong in its bytecode generation. */
|
badly wrong in its bytecode generation. */
|
||||||
if (areqs->min_height < 0)
|
if (aexpr->min_height < 0)
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("expression has min height < 0"));
|
_("expression has min height < 0"));
|
||||||
|
|
||||||
|
@ -579,7 +579,7 @@ report_agent_reqs_errors (struct agent_expr *aexpr, struct agent_reqs *areqs)
|
||||||
depth roughly corresponds to parenthesization, so a limit of 20
|
depth roughly corresponds to parenthesization, so a limit of 20
|
||||||
amounts to 20 levels of expression nesting, which is actually
|
amounts to 20 levels of expression nesting, which is actually
|
||||||
a pretty big hairy expression. */
|
a pretty big hairy expression. */
|
||||||
if (areqs->max_height > 20)
|
if (aexpr->max_height > 20)
|
||||||
error (_("Expression is too complicated."));
|
error (_("Expression is too complicated."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +593,6 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||||
char *p, *tmp_p;
|
char *p, *tmp_p;
|
||||||
struct bp_location *loc;
|
struct bp_location *loc;
|
||||||
struct agent_expr *aexpr;
|
struct agent_expr *aexpr;
|
||||||
struct agent_reqs areqs;
|
|
||||||
|
|
||||||
/* if EOF is typed, *line is NULL */
|
/* if EOF is typed, *line is NULL */
|
||||||
if (*line == NULL)
|
if (*line == NULL)
|
||||||
|
@ -663,10 +662,9 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||||
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
||||||
error (_("Expression is too complicated."));
|
error (_("Expression is too complicated."));
|
||||||
|
|
||||||
ax_reqs (aexpr, &areqs);
|
ax_reqs (aexpr);
|
||||||
(void) make_cleanup (xfree, areqs.reg_mask);
|
|
||||||
|
|
||||||
report_agent_reqs_errors (aexpr, &areqs);
|
report_agent_reqs_errors (aexpr);
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
}
|
}
|
||||||
|
@ -699,10 +697,8 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||||
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
||||||
error (_("Expression is too complicated."));
|
error (_("Expression is too complicated."));
|
||||||
|
|
||||||
ax_reqs (aexpr, &areqs);
|
ax_reqs (aexpr);
|
||||||
(void) make_cleanup (xfree, areqs.reg_mask);
|
report_agent_reqs_errors (aexpr);
|
||||||
|
|
||||||
report_agent_reqs_errors (aexpr, &areqs);
|
|
||||||
|
|
||||||
do_cleanups (old_chain);
|
do_cleanups (old_chain);
|
||||||
}
|
}
|
||||||
|
@ -974,7 +970,6 @@ collect_symbol (struct collection_list *collect,
|
||||||
{
|
{
|
||||||
struct agent_expr *aexpr;
|
struct agent_expr *aexpr;
|
||||||
struct cleanup *old_chain1 = NULL;
|
struct cleanup *old_chain1 = NULL;
|
||||||
struct agent_reqs areqs;
|
|
||||||
|
|
||||||
aexpr = gen_trace_for_var (scope, gdbarch, sym);
|
aexpr = gen_trace_for_var (scope, gdbarch, sym);
|
||||||
|
|
||||||
|
@ -990,26 +985,26 @@ collect_symbol (struct collection_list *collect,
|
||||||
|
|
||||||
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
||||||
|
|
||||||
ax_reqs (aexpr, &areqs);
|
ax_reqs (aexpr);
|
||||||
|
|
||||||
report_agent_reqs_errors (aexpr, &areqs);
|
report_agent_reqs_errors (aexpr);
|
||||||
|
|
||||||
discard_cleanups (old_chain1);
|
discard_cleanups (old_chain1);
|
||||||
add_aexpr (collect, aexpr);
|
add_aexpr (collect, aexpr);
|
||||||
|
|
||||||
/* take care of the registers */
|
/* take care of the registers */
|
||||||
if (areqs.reg_mask_len > 0)
|
if (aexpr->reg_mask_len > 0)
|
||||||
{
|
{
|
||||||
int ndx1, ndx2;
|
int ndx1, ndx2;
|
||||||
|
|
||||||
for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
|
for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
||||||
{
|
{
|
||||||
QUIT; /* allow user to bail out with ^C */
|
QUIT; /* allow user to bail out with ^C */
|
||||||
if (areqs.reg_mask[ndx1] != 0)
|
if (aexpr->reg_mask[ndx1] != 0)
|
||||||
{
|
{
|
||||||
/* assume chars have 8 bits */
|
/* assume chars have 8 bits */
|
||||||
for (ndx2 = 0; ndx2 < 8; ndx2++)
|
for (ndx2 = 0; ndx2 < 8; ndx2++)
|
||||||
if (areqs.reg_mask[ndx1] & (1 << ndx2))
|
if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
||||||
/* it's used -- record it */
|
/* it's used -- record it */
|
||||||
add_register (collect, ndx1 * 8 + ndx2);
|
add_register (collect, ndx1 * 8 + ndx2);
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1282,6 @@ encode_actions_1 (struct command_line *action,
|
||||||
unsigned long addr, len;
|
unsigned long addr, len;
|
||||||
struct cleanup *old_chain = NULL;
|
struct cleanup *old_chain = NULL;
|
||||||
struct cleanup *old_chain1 = NULL;
|
struct cleanup *old_chain1 = NULL;
|
||||||
struct agent_reqs areqs;
|
|
||||||
|
|
||||||
exp = parse_exp_1 (&action_exp,
|
exp = parse_exp_1 (&action_exp,
|
||||||
block_for_pc (tloc->address), 1);
|
block_for_pc (tloc->address), 1);
|
||||||
|
@ -1333,27 +1327,27 @@ encode_actions_1 (struct command_line *action,
|
||||||
|
|
||||||
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
||||||
|
|
||||||
ax_reqs (aexpr, &areqs);
|
ax_reqs (aexpr);
|
||||||
|
|
||||||
report_agent_reqs_errors (aexpr, &areqs);
|
report_agent_reqs_errors (aexpr);
|
||||||
|
|
||||||
discard_cleanups (old_chain1);
|
discard_cleanups (old_chain1);
|
||||||
add_aexpr (collect, aexpr);
|
add_aexpr (collect, aexpr);
|
||||||
|
|
||||||
/* take care of the registers */
|
/* take care of the registers */
|
||||||
if (areqs.reg_mask_len > 0)
|
if (aexpr->reg_mask_len > 0)
|
||||||
{
|
{
|
||||||
int ndx1;
|
int ndx1;
|
||||||
int ndx2;
|
int ndx2;
|
||||||
|
|
||||||
for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
|
for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
|
||||||
{
|
{
|
||||||
QUIT; /* allow user to bail out with ^C */
|
QUIT; /* allow user to bail out with ^C */
|
||||||
if (areqs.reg_mask[ndx1] != 0)
|
if (aexpr->reg_mask[ndx1] != 0)
|
||||||
{
|
{
|
||||||
/* assume chars have 8 bits */
|
/* assume chars have 8 bits */
|
||||||
for (ndx2 = 0; ndx2 < 8; ndx2++)
|
for (ndx2 = 0; ndx2 < 8; ndx2++)
|
||||||
if (areqs.reg_mask[ndx1] & (1 << ndx2))
|
if (aexpr->reg_mask[ndx1] & (1 << ndx2))
|
||||||
/* it's used -- record it */
|
/* it's used -- record it */
|
||||||
add_register (collect,
|
add_register (collect,
|
||||||
ndx1 * 8 + ndx2);
|
ndx1 * 8 + ndx2);
|
||||||
|
@ -1379,7 +1373,6 @@ encode_actions_1 (struct command_line *action,
|
||||||
unsigned long addr, len;
|
unsigned long addr, len;
|
||||||
struct cleanup *old_chain = NULL;
|
struct cleanup *old_chain = NULL;
|
||||||
struct cleanup *old_chain1 = NULL;
|
struct cleanup *old_chain1 = NULL;
|
||||||
struct agent_reqs areqs;
|
|
||||||
|
|
||||||
exp = parse_exp_1 (&action_exp,
|
exp = parse_exp_1 (&action_exp,
|
||||||
block_for_pc (tloc->address), 1);
|
block_for_pc (tloc->address), 1);
|
||||||
|
@ -1388,9 +1381,8 @@ encode_actions_1 (struct command_line *action,
|
||||||
aexpr = gen_eval_for_expr (tloc->address, exp);
|
aexpr = gen_eval_for_expr (tloc->address, exp);
|
||||||
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
||||||
|
|
||||||
ax_reqs (aexpr, &areqs);
|
ax_reqs (aexpr);
|
||||||
|
report_agent_reqs_errors (aexpr);
|
||||||
report_agent_reqs_errors (aexpr, &areqs);
|
|
||||||
|
|
||||||
discard_cleanups (old_chain1);
|
discard_cleanups (old_chain1);
|
||||||
/* Even though we're not officially collecting, add
|
/* Even though we're not officially collecting, add
|
||||||
|
|
Loading…
Reference in a new issue