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
@ -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>
|
||||
Paul Pluzhnikov <ppluzhnikov@google.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;
|
||||
|
||||
case axs_lvalue_register:
|
||||
/* We need to mention the register somewhere in the bytecode,
|
||||
so ax_reqs will pick it up and add it to the mask of
|
||||
registers used. */
|
||||
ax_reg (ax, value.u.reg);
|
||||
/* We don't actually need the register's value to be pushed,
|
||||
just note that we need it to be collected. */
|
||||
ax_reg_mask (ax, value.u.reg);
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -414,11 +413,11 @@ gen_traced_pop (struct gdbarch *gdbarch,
|
||||
break;
|
||||
|
||||
case axs_lvalue_register:
|
||||
/* We need to mention the register somewhere in the bytecode,
|
||||
so ax_reqs will pick it up and add it to the mask of
|
||||
registers used. */
|
||||
ax_reg (ax, value->u.reg);
|
||||
ax_simple (ax, aop_pop);
|
||||
/* We don't actually need the register's value to be on the
|
||||
stack, and the target will get heartburn if the register is
|
||||
larger than will fit in a stack, so just mark it for
|
||||
collection and be done with it. */
|
||||
ax_reg_mask (ax, value->u.reg);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -898,7 +897,7 @@ gen_conversion (struct agent_expr *ax, struct type *from, struct type *to)
|
||||
static int
|
||||
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;
|
||||
|
||||
/* 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 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;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
struct axs_value value;
|
||||
|
||||
@ -2372,6 +2371,7 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||
|
||||
pc = expr->elts;
|
||||
trace_kludge = 1;
|
||||
value.optimized_out = 0;
|
||||
gen_expr (expr, &pc, ax, &value);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
struct axs_value value;
|
||||
|
||||
@ -2406,8 +2406,11 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
|
||||
|
||||
pc = expr->elts;
|
||||
trace_kludge = 0;
|
||||
value.optimized_out = 0;
|
||||
gen_expr (expr, &pc, ax, &value);
|
||||
|
||||
require_rvalue (ax, &value);
|
||||
|
||||
/* Oh, and terminate. */
|
||||
ax_simple (ax, aop_end);
|
||||
|
||||
@ -2440,6 +2443,7 @@ agent_command (char *exp, int from_tty)
|
||||
old_chain = make_cleanup (free_current_contents, &expr);
|
||||
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
|
||||
make_cleanup_free_agent_expr (agent);
|
||||
ax_reqs (agent);
|
||||
ax_print (gdb_stdout, agent);
|
||||
|
||||
/* 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);
|
||||
agent = gen_eval_for_expr (get_frame_pc (fi), expr);
|
||||
make_cleanup_free_agent_expr (agent);
|
||||
ax_reqs (agent);
|
||||
ax_print (gdb_stdout, agent);
|
||||
|
||||
/* 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. */
|
||||
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));
|
||||
|
||||
x->len = 0;
|
||||
x->size = 1; /* Change this to a larger value once
|
||||
reallocation code is tested. */
|
||||
x->buf = xmalloc (x->size);
|
||||
|
||||
x->gdbarch = gdbarch;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -57,6 +65,7 @@ void
|
||||
free_agent_expr (struct agent_expr *x)
|
||||
{
|
||||
xfree (x->buf);
|
||||
xfree (x->reg_mask);
|
||||
xfree (x);
|
||||
}
|
||||
|
||||
@ -355,6 +364,12 @@ ax_print (struct ui_file *f, struct agent_expr *x)
|
||||
int i;
|
||||
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
|
||||
the enum, to catch additions that people didn't sync. */
|
||||
if ((sizeof (aop_map) / sizeof (aop_map[0]))
|
||||
@ -394,19 +409,37 @@ ax_print (struct ui_file *f, struct agent_expr *x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Given an agent expression AX, fill in an agent_reqs structure REQS
|
||||
describing it. */
|
||||
/* Add register REG to the register mask for expression AX. */
|
||||
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 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 to offset i. */
|
||||
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. */
|
||||
struct aop_map *op;
|
||||
|
||||
memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
|
||||
memset (targets, 0, ax->len * sizeof (targets[0]));
|
||||
memset (boundary, 0, ax->len * sizeof (boundary[0]));
|
||||
|
||||
reqs->max_height = reqs->min_height = height = 0;
|
||||
reqs->flaw = agent_flaw_none;
|
||||
reqs->max_data_size = 0;
|
||||
ax->max_height = ax->min_height = height = 0;
|
||||
ax->flaw = agent_flaw_none;
|
||||
ax->max_data_size = 0;
|
||||
|
||||
for (i = 0; i < ax->len; i += 1 + op->op_size)
|
||||
{
|
||||
if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_instruction;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_bad_instruction;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -444,15 +475,13 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
|
||||
if (!op->name)
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_instruction;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_bad_instruction;
|
||||
return;
|
||||
}
|
||||
|
||||
if (i + 1 + op->op_size > ax->len)
|
||||
{
|
||||
reqs->flaw = agent_flaw_incomplete_instruction;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_incomplete_instruction;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -461,8 +490,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
source? */
|
||||
if (targets[i] && (heights[i] != height))
|
||||
{
|
||||
reqs->flaw = agent_flaw_height_mismatch;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_height_mismatch;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -470,14 +498,14 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
heights[i] = height;
|
||||
|
||||
height -= op->consumed;
|
||||
if (height < reqs->min_height)
|
||||
reqs->min_height = height;
|
||||
if (height < ax->min_height)
|
||||
ax->min_height = height;
|
||||
height += op->produced;
|
||||
if (height > reqs->max_height)
|
||||
reqs->max_height = height;
|
||||
if (height > ax->max_height)
|
||||
ax->max_height = height;
|
||||
|
||||
if (op->data_size > reqs->max_data_size)
|
||||
reqs->max_data_size = op->data_size;
|
||||
if (op->data_size > ax->max_data_size)
|
||||
ax->max_data_size = op->data_size;
|
||||
|
||||
/* For jump instructions, check that the target is a valid
|
||||
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);
|
||||
if (target < 0 || target >= ax->len)
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_jump;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_bad_jump;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -499,8 +526,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
{
|
||||
if (heights[target] != height)
|
||||
{
|
||||
reqs->flaw = agent_flaw_height_mismatch;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_height_mismatch;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -517,8 +543,7 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
{
|
||||
if (!targets[i + 3])
|
||||
{
|
||||
reqs->flaw = agent_flaw_hole;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_hole;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -529,22 +554,8 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
if (aop_reg == op - aop_map)
|
||||
{
|
||||
int reg = read_const (ax, i + 1, 2);
|
||||
int byte = reg / 8;
|
||||
|
||||
/* Grow the bit mask if necessary. */
|
||||
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);
|
||||
ax_reg_mask (ax, reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,12 +563,9 @@ ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
for (i = 0; i < ax->len; i++)
|
||||
if (targets[i] && !boundary[i])
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_jump;
|
||||
xfree (reg_mask);
|
||||
ax->flaw = agent_flaw_bad_jump;
|
||||
return;
|
||||
}
|
||||
|
||||
reqs->final_height = height;
|
||||
reqs->reg_mask_len = reg_mask_len;
|
||||
reqs->reg_mask = reg_mask;
|
||||
ax->final_height = height;
|
||||
}
|
||||
|
152
gdb/ax.h
152
gdb/ax.h
@ -51,6 +51,33 @@
|
||||
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. */
|
||||
|
||||
/* The type of an element of the agent expression stack.
|
||||
@ -67,15 +94,57 @@ union agent_val
|
||||
/* A buffer containing a agent expression. */
|
||||
struct agent_expr
|
||||
{
|
||||
/* The bytes of the expression. */
|
||||
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;
|
||||
|
||||
/* 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.
|
||||
|
||||
Other independent implementations of the agent bytecode engine will
|
||||
@ -143,7 +212,7 @@ enum agent_op
|
||||
/* Functions for building expressions. */
|
||||
|
||||
/* 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. */
|
||||
extern void free_agent_expr (struct agent_expr *);
|
||||
@ -186,6 +255,9 @@ extern void ax_const_d (struct agent_expr *EXPR, LONGEST d);
|
||||
stack. */
|
||||
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. */
|
||||
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. */
|
||||
extern struct aop_map aop_map[];
|
||||
|
||||
/* Different kinds of flaws an agent expression might have, as
|
||||
detected by agent_reqs. */
|
||||
enum agent_flaws
|
||||
{
|
||||
agent_flaw_none = 0, /* code is good */
|
||||
/* Given an agent expression AX, analyze and update its requirements. */
|
||||
|
||||
/* 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,
|
||||
|
||||
/* 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);
|
||||
extern void ax_reqs (struct agent_expr *ax);
|
||||
|
||||
#endif /* AGENTEXPR_H */
|
||||
|
@ -560,16 +560,16 @@ trace_actions_command (char *args, int from_tty)
|
||||
internal errors. */
|
||||
|
||||
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
|
||||
should never occur. */
|
||||
if (areqs->flaw != agent_flaw_none)
|
||||
if (aexpr->flaw != agent_flaw_none)
|
||||
internal_error (__FILE__, __LINE__, _("expression is malformed"));
|
||||
|
||||
/* If analysis shows a stack underflow, GDB must have done something
|
||||
badly wrong in its bytecode generation. */
|
||||
if (areqs->min_height < 0)
|
||||
if (aexpr->min_height < 0)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("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
|
||||
amounts to 20 levels of expression nesting, which is actually
|
||||
a pretty big hairy expression. */
|
||||
if (areqs->max_height > 20)
|
||||
if (aexpr->max_height > 20)
|
||||
error (_("Expression is too complicated."));
|
||||
}
|
||||
|
||||
@ -593,7 +593,6 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||
char *p, *tmp_p;
|
||||
struct bp_location *loc;
|
||||
struct agent_expr *aexpr;
|
||||
struct agent_reqs areqs;
|
||||
|
||||
/* if EOF is typed, *line is NULL */
|
||||
if (*line == NULL)
|
||||
@ -663,10 +662,9 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
||||
error (_("Expression is too complicated."));
|
||||
|
||||
ax_reqs (aexpr, &areqs);
|
||||
(void) make_cleanup (xfree, areqs.reg_mask);
|
||||
ax_reqs (aexpr);
|
||||
|
||||
report_agent_reqs_errors (aexpr, &areqs);
|
||||
report_agent_reqs_errors (aexpr);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
@ -699,10 +697,8 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||
if (aexpr->len > MAX_AGENT_EXPR_LEN)
|
||||
error (_("Expression is too complicated."));
|
||||
|
||||
ax_reqs (aexpr, &areqs);
|
||||
(void) make_cleanup (xfree, areqs.reg_mask);
|
||||
|
||||
report_agent_reqs_errors (aexpr, &areqs);
|
||||
ax_reqs (aexpr);
|
||||
report_agent_reqs_errors (aexpr);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
@ -974,7 +970,6 @@ collect_symbol (struct collection_list *collect,
|
||||
{
|
||||
struct agent_expr *aexpr;
|
||||
struct cleanup *old_chain1 = NULL;
|
||||
struct agent_reqs areqs;
|
||||
|
||||
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);
|
||||
|
||||
ax_reqs (aexpr, &areqs);
|
||||
ax_reqs (aexpr);
|
||||
|
||||
report_agent_reqs_errors (aexpr, &areqs);
|
||||
report_agent_reqs_errors (aexpr);
|
||||
|
||||
discard_cleanups (old_chain1);
|
||||
add_aexpr (collect, aexpr);
|
||||
|
||||
/* take care of the registers */
|
||||
if (areqs.reg_mask_len > 0)
|
||||
if (aexpr->reg_mask_len > 0)
|
||||
{
|
||||
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 */
|
||||
if (areqs.reg_mask[ndx1] != 0)
|
||||
if (aexpr->reg_mask[ndx1] != 0)
|
||||
{
|
||||
/* assume chars have 8 bits */
|
||||
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 */
|
||||
add_register (collect, ndx1 * 8 + ndx2);
|
||||
}
|
||||
@ -1287,7 +1282,6 @@ encode_actions_1 (struct command_line *action,
|
||||
unsigned long addr, len;
|
||||
struct cleanup *old_chain = NULL;
|
||||
struct cleanup *old_chain1 = NULL;
|
||||
struct agent_reqs areqs;
|
||||
|
||||
exp = parse_exp_1 (&action_exp,
|
||||
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);
|
||||
|
||||
ax_reqs (aexpr, &areqs);
|
||||
ax_reqs (aexpr);
|
||||
|
||||
report_agent_reqs_errors (aexpr, &areqs);
|
||||
report_agent_reqs_errors (aexpr);
|
||||
|
||||
discard_cleanups (old_chain1);
|
||||
add_aexpr (collect, aexpr);
|
||||
|
||||
/* take care of the registers */
|
||||
if (areqs.reg_mask_len > 0)
|
||||
if (aexpr->reg_mask_len > 0)
|
||||
{
|
||||
int ndx1;
|
||||
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 */
|
||||
if (areqs.reg_mask[ndx1] != 0)
|
||||
if (aexpr->reg_mask[ndx1] != 0)
|
||||
{
|
||||
/* assume chars have 8 bits */
|
||||
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 */
|
||||
add_register (collect,
|
||||
ndx1 * 8 + ndx2);
|
||||
@ -1379,7 +1373,6 @@ encode_actions_1 (struct command_line *action,
|
||||
unsigned long addr, len;
|
||||
struct cleanup *old_chain = NULL;
|
||||
struct cleanup *old_chain1 = NULL;
|
||||
struct agent_reqs areqs;
|
||||
|
||||
exp = parse_exp_1 (&action_exp,
|
||||
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);
|
||||
old_chain1 = make_cleanup_free_agent_expr (aexpr);
|
||||
|
||||
ax_reqs (aexpr, &areqs);
|
||||
|
||||
report_agent_reqs_errors (aexpr, &areqs);
|
||||
ax_reqs (aexpr);
|
||||
report_agent_reqs_errors (aexpr);
|
||||
|
||||
discard_cleanups (old_chain1);
|
||||
/* Even though we're not officially collecting, add
|
||||
|
Loading…
Reference in New Issue
Block a user