* tracepoint.h (decode_agent_options): Add 'trace_string'

argument.
	* tracepoint.c (decode_agent_options): Add 'trace_string'
	argument.
	(validate_actionline): Update.
	(collect_symbol): Add 'trace_string' argument.
	(struct add_local_symbols_data) <trace_string>: New field.
	(do_collect_symbol): Update.
	(add_local_symbols): Add 'trace_string' argument.
	(encode_actions_1): Update.
	(trace_dump_actions): Update.
	* dwarf2loc.c (access_memory): Update.
	* ax.h (struct agent_expr) <tracing, trace_string>: New fields.
	* ax-general.c (new_agent_expr): Update.
	* ax-gdb.h (gen_trace_for_expr, gen_trace_for_var)
	(gen_trace_for_return_address): Add argument.
	(trace_kludge, trace_string_kludge): Remove.
	* ax-gdb.c (trace_kludge, trace_string_kludge): Remove.
	(gen_traced_pop, gen_fetch, gen_bitfield_ref, gen_expr): Update.
	(gen_trace_for_var): Add 'trace_string' argument.
	(gen_trace_for_expr, gen_trace_for_return_address): Likewise.
	(gen_printf, agent_eval_command_one): Update.
This commit is contained in:
Tom Tromey
2013-03-21 16:09:27 +00:00
parent 81f5558e3d
commit 92bc6a2064
8 changed files with 120 additions and 82 deletions

View File

@@ -1,3 +1,28 @@
2013-03-11 Tom Tromey <tromey@redhat.com>
* tracepoint.h (decode_agent_options): Add 'trace_string'
argument.
* tracepoint.c (decode_agent_options): Add 'trace_string'
argument.
(validate_actionline): Update.
(collect_symbol): Add 'trace_string' argument.
(struct add_local_symbols_data) <trace_string>: New field.
(do_collect_symbol): Update.
(add_local_symbols): Add 'trace_string' argument.
(encode_actions_1): Update.
(trace_dump_actions): Update.
* dwarf2loc.c (access_memory): Update.
* ax.h (struct agent_expr) <tracing, trace_string>: New fields.
* ax-general.c (new_agent_expr): Update.
* ax-gdb.h (gen_trace_for_expr, gen_trace_for_var)
(gen_trace_for_return_address): Add argument.
(trace_kludge, trace_string_kludge): Remove.
* ax-gdb.c (trace_kludge, trace_string_kludge): Remove.
(gen_traced_pop, gen_fetch, gen_bitfield_ref, gen_expr): Update.
(gen_trace_for_var): Add 'trace_string' argument.
(gen_trace_for_expr, gen_trace_for_return_address): Likewise.
(gen_printf, agent_eval_command_one): Update.
2013-03-21 Tom Tromey <tromey@redhat.com>
PR exp/15109:

View File

@@ -312,36 +312,6 @@ maybe_const_expr (union exp_element **pc)
sizes), and this is simpler.) */
/* Generating bytecode from GDB expressions: the `trace' kludge */
/* The compiler in this file is a general-purpose mechanism for
translating GDB expressions into bytecode. One ought to be able to
find a million and one uses for it.
However, at the moment it is HOPELESSLY BRAIN-DAMAGED for the sake
of expediency. Let he who is without sin cast the first stone.
For the data tracing facility, we need to insert `trace' bytecodes
before each data fetch; this records all the memory that the
expression touches in the course of evaluation, so that memory will
be available when the user later tries to evaluate the expression
in GDB.
This should be done (I think) in a post-processing pass, that walks
an arbitrary agent expression and inserts `trace' operations at the
appropriate points. But it's much faster to just hack them
directly into the code. And since we're in a crunch, that's what
I've done.
Setting the flag trace_kludge to non-zero enables the code that
emits the trace bytecodes at the appropriate points. */
int trace_kludge;
/* Inspired by trace_kludge, this indicates that pointers to chars
should get an added tracenz bytecode to record nonzero bytes, up to
a length that is the value of trace_string_kludge. */
int trace_string_kludge;
/* Scan for all static fields in the given class, including any base
classes, and generate tracing bytecodes for each. */
@@ -401,19 +371,19 @@ gen_traced_pop (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value)
{
int string_trace = 0;
if (trace_string_kludge
if (ax->trace_string
&& TYPE_CODE (value->type) == TYPE_CODE_PTR
&& c_textual_element_type (check_typedef (TYPE_TARGET_TYPE (value->type)),
's'))
string_trace = 1;
if (trace_kludge)
if (ax->tracing)
switch (value->kind)
{
case axs_rvalue:
if (string_trace)
{
ax_const_l (ax, trace_string_kludge);
ax_const_l (ax, ax->trace_string);
ax_simple (ax, aop_tracenz);
}
else
@@ -441,7 +411,7 @@ gen_traced_pop (struct gdbarch *gdbarch,
if (string_trace)
{
ax_simple (ax, aop_ref32);
ax_const_l (ax, trace_string_kludge);
ax_const_l (ax, ax->trace_string);
ax_simple (ax, aop_tracenz);
}
}
@@ -459,7 +429,7 @@ gen_traced_pop (struct gdbarch *gdbarch,
if (string_trace)
{
ax_reg (ax, value->u.reg);
ax_const_l (ax, trace_string_kludge);
ax_const_l (ax, ax->trace_string);
ax_simple (ax, aop_tracenz);
}
break;
@@ -469,7 +439,7 @@ gen_traced_pop (struct gdbarch *gdbarch,
ax_simple (ax, aop_pop);
/* To trace C++ classes with static fields stored elsewhere. */
if (trace_kludge
if (ax->tracing
&& (TYPE_CODE (value->type) == TYPE_CODE_STRUCT
|| TYPE_CODE (value->type) == TYPE_CODE_UNION))
gen_trace_static_fields (gdbarch, ax, value->type);
@@ -509,7 +479,7 @@ gen_extend (struct agent_expr *ax, struct type *type)
static void
gen_fetch (struct agent_expr *ax, struct type *type)
{
if (trace_kludge)
if (ax->tracing)
{
/* Record the area of memory we're about to fetch. */
ax_trace_quick (ax, TYPE_LENGTH (type));
@@ -1361,7 +1331,7 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax,
/* Add the offset. */
gen_offset (ax, offset / TARGET_CHAR_BIT);
if (trace_kludge)
if (ax->tracing)
{
/* Record the area of memory we're about to fetch. */
ax_trace_quick (ax, op_size / TARGET_CHAR_BIT);
@@ -1930,7 +1900,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
if (tsv)
{
ax_tsv (ax, aop_setv, tsv->number);
if (trace_kludge)
if (ax->tracing)
ax_tsv (ax, aop_tracev, tsv->number);
}
else
@@ -1957,7 +1927,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
{
/* The tsv will be the left half of the binary operation. */
ax_tsv (ax, aop_getv, tsv->number);
if (trace_kludge)
if (ax->tracing)
ax_tsv (ax, aop_tracev, tsv->number);
/* Trace state variables are always 64-bit integers. */
value1.kind = axs_rvalue;
@@ -1966,7 +1936,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
/* We have a result of the binary op, set the tsv. */
ax_tsv (ax, aop_setv, tsv->number);
if (trace_kludge)
if (ax->tracing)
ax_tsv (ax, aop_tracev, tsv->number);
}
else
@@ -2047,7 +2017,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
if (tsv)
{
ax_tsv (ax, aop_getv, tsv->number);
if (trace_kludge)
if (ax->tracing)
ax_tsv (ax, aop_tracev, tsv->number);
/* Trace state variables are always 64-bit integers. */
value->kind = axs_rvalue;
@@ -2424,7 +2394,7 @@ gen_expr_binop_rest (struct expression *exp,
struct agent_expr *
gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
struct symbol *var)
struct symbol *var, int trace_string)
{
struct cleanup *old_chain = 0;
struct agent_expr *ax = new_agent_expr (gdbarch, scope);
@@ -2432,7 +2402,8 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
old_chain = make_cleanup_free_agent_expr (ax);
trace_kludge = 1;
ax->tracing = 1;
ax->trace_string = trace_string;
gen_var_ref (gdbarch, ax, &value, var);
/* If there is no actual variable to trace, flag it by returning
@@ -2464,7 +2435,8 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
caller can then use the ax_reqs function to discover which
registers it relies upon. */
struct agent_expr *
gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
gen_trace_for_expr (CORE_ADDR scope, struct expression *expr,
int trace_string)
{
struct cleanup *old_chain = 0;
struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
@@ -2474,7 +2446,8 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
old_chain = make_cleanup_free_agent_expr (ax);
pc = expr->elts;
trace_kludge = 1;
ax->tracing = 1;
ax->trace_string = trace_string;
value.optimized_out = 0;
gen_expr (expr, &pc, ax, &value);
@@ -2509,7 +2482,7 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
old_chain = make_cleanup_free_agent_expr (ax);
pc = expr->elts;
trace_kludge = 0;
ax->tracing = 0;
value.optimized_out = 0;
gen_expr (expr, &pc, ax, &value);
@@ -2526,7 +2499,8 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
}
struct agent_expr *
gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch)
gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch,
int trace_string)
{
struct cleanup *old_chain = 0;
struct agent_expr *ax = new_agent_expr (gdbarch, scope);
@@ -2534,7 +2508,8 @@ gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch)
old_chain = make_cleanup_free_agent_expr (ax);
trace_kludge = 1;
ax->tracing = 1;
ax->trace_string = trace_string;
gdbarch_gen_return_address (gdbarch, ax, &value, scope);
@@ -2570,13 +2545,14 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
old_chain = make_cleanup_free_agent_expr (ax);
/* We're computing values, not doing side effects. */
ax->tracing = 0;
/* Evaluate and push the args on the stack in reverse order,
for simplicity of collecting them on the target side. */
for (tem = nargs - 1; tem >= 0; --tem)
{
pc = exprs[tem]->elts;
/* We're computing values, not doing side effects. */
trace_kludge = 0;
value.optimized_out = 0;
gen_expr (exprs[tem], &pc, ax, &value);
require_rvalue (ax, &value);
@@ -2609,18 +2585,19 @@ agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
struct expression *expr;
struct agent_expr *agent;
const char *arg;
int trace_string = 0;
if (!eval)
{
trace_string_kludge = 0;
if (*exp == '/')
exp = decode_agent_options (exp);
exp = decode_agent_options (exp, &trace_string);
}
arg = exp;
if (!eval && strcmp (arg, "$_ret") == 0)
{
agent = gen_trace_for_return_address (pc, get_current_arch ());
agent = gen_trace_for_return_address (pc, get_current_arch (),
trace_string);
old_chain = make_cleanup_free_agent_expr (agent);
}
else
@@ -2628,9 +2605,12 @@ agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0);
old_chain = make_cleanup (free_current_contents, &expr);
if (eval)
agent = gen_eval_for_expr (pc, expr);
{
gdb_assert (trace_string == 0);
agent = gen_eval_for_expr (pc, expr);
}
else
agent = gen_trace_for_expr (pc, expr);
agent = gen_trace_for_expr (pc, expr, trace_string);
make_cleanup_free_agent_expr (agent);
}

View File

@@ -100,13 +100,15 @@ struct axs_value
record the value of all memory touched by the expression, and leave
no values on the stack. The caller can then use the ax_reqs
function to discover which registers the expression uses. */
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *,
int);
extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct gdbarch *,
struct symbol *);
struct symbol *, int);
extern struct agent_expr *gen_trace_for_return_address (CORE_ADDR,
struct gdbarch *);
struct gdbarch *,
int);
extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
@@ -121,7 +123,4 @@ extern struct agent_expr *gen_printf (CORE_ADDR, struct gdbarch *,
struct format_piece *,
int, struct expression **);
extern int trace_kludge;
extern int trace_string_kludge;
#endif /* AX_GDB_H */

View File

@@ -58,6 +58,9 @@ new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
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]));
x->tracing = 0;
x->trace_string = 0;
return x;
}

View File

@@ -143,6 +143,23 @@ struct agent_expr
*/
int reg_mask_len;
unsigned char *reg_mask;
/* For the data tracing facility, we need to insert `trace' bytecodes
before each data fetch; this records all the memory that the
expression touches in the course of evaluation, so that memory will
be available when the user later tries to evaluate the expression
in GDB.
Setting the flag 'tracing' to non-zero enables the code that
emits the trace bytecodes at the appropriate points. */
unsigned int tracing : 1;
/* This indicates that pointers to chars should get an added
tracenz bytecode to record nonzero bytes, up to a length that
is the value of trace_string. */
int trace_string;
};
/* Pointer to an agent_expr structure. */

View File

@@ -2568,7 +2568,7 @@ access_memory (struct gdbarch *arch, struct agent_expr *expr, ULONGEST nbits)
gdb_assert (nbytes > 0 && nbytes <= sizeof (LONGEST));
if (trace_kludge)
if (expr->tracing)
ax_trace_quick (expr, nbytes);
if (nbits <= 8)

View File

@@ -612,10 +612,12 @@ teval_pseudocommand (char *args, int from_tty)
/* Parse any collection options, such as /s for strings. */
const char *
decode_agent_options (const char *exp)
decode_agent_options (const char *exp, int *trace_string)
{
struct value_print_options opts;
*trace_string = 0;
if (*exp != '/')
return exp;
@@ -631,10 +633,10 @@ decode_agent_options (const char *exp)
/* Allow an optional decimal number giving an explicit maximum
string length, defaulting it to the "print elements" value;
so "collect/s80 mystr" gets at most 80 bytes of string. */
trace_string_kludge = opts.print_max;
*trace_string = opts.print_max;
exp++;
if (*exp >= '0' && *exp <= '9')
trace_string_kludge = atoi (exp);
*trace_string = atoi (exp);
while (*exp >= '0' && *exp <= '9')
exp++;
}
@@ -731,9 +733,10 @@ validate_actionline (const char *line, struct breakpoint *b)
if (cmd_cfunc_eq (c, collect_pseudocommand))
{
trace_string_kludge = 0;
int trace_string = 0;
if (*p == '/')
p = decode_agent_options (p);
p = decode_agent_options (p, &trace_string);
do
{ /* Repeat over a comma-separated list. */
@@ -782,7 +785,7 @@ validate_actionline (const char *line, struct breakpoint *b)
/* We have something to collect, make sure that the expr to
bytecode translator can handle it and that it's not too
long. */
aexpr = gen_trace_for_expr (loc->address, exp);
aexpr = gen_trace_for_expr (loc->address, exp, trace_string);
make_cleanup_free_agent_expr (aexpr);
if (aexpr->len > MAX_AGENT_EXPR_LEN)
@@ -989,7 +992,8 @@ collect_symbol (struct collection_list *collect,
struct symbol *sym,
struct gdbarch *gdbarch,
long frame_regno, long frame_offset,
CORE_ADDR scope)
CORE_ADDR scope,
int trace_string)
{
unsigned long len;
unsigned int reg;
@@ -1100,7 +1104,7 @@ collect_symbol (struct collection_list *collect,
struct agent_expr *aexpr;
struct cleanup *old_chain1 = NULL;
aexpr = gen_trace_for_var (scope, gdbarch, sym);
aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string);
/* It can happen that the symbol is recorded as a computed
location, but it's been optimized away and doesn't actually
@@ -1153,6 +1157,7 @@ struct add_local_symbols_data
long frame_regno;
long frame_offset;
int count;
int trace_string;
};
/* The callback for the locals and args iterators. */
@@ -1165,7 +1170,7 @@ do_collect_symbol (const char *print_name,
struct add_local_symbols_data *p = cb_data;
collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno,
p->frame_offset, p->pc);
p->frame_offset, p->pc, p->trace_string);
p->count++;
}
@@ -1173,7 +1178,8 @@ do_collect_symbol (const char *print_name,
static void
add_local_symbols (struct collection_list *collect,
struct gdbarch *gdbarch, CORE_ADDR pc,
long frame_regno, long frame_offset, int type)
long frame_regno, long frame_offset, int type,
int trace_string)
{
struct block *block;
struct add_local_symbols_data cb_data;
@@ -1184,6 +1190,7 @@ add_local_symbols (struct collection_list *collect,
cb_data.frame_regno = frame_regno;
cb_data.frame_offset = frame_offset;
cb_data.count = 0;
cb_data.trace_string = trace_string;
if (type == 'L')
{
@@ -1391,9 +1398,10 @@ encode_actions_1 (struct command_line *action,
if (cmd_cfunc_eq (cmd, collect_pseudocommand))
{
trace_string_kludge = 0;
int trace_string = 0;
if (*action_exp == '/')
action_exp = decode_agent_options (action_exp);
action_exp = decode_agent_options (action_exp, &trace_string);
do
{ /* Repeat over a comma-separated list. */
@@ -1413,7 +1421,8 @@ encode_actions_1 (struct command_line *action,
tloc->address,
frame_reg,
frame_offset,
'A');
'A',
trace_string);
action_exp = strchr (action_exp, ','); /* more? */
}
else if (0 == strncasecmp ("$loc", action_exp, 4))
@@ -1423,7 +1432,8 @@ encode_actions_1 (struct command_line *action,
tloc->address,
frame_reg,
frame_offset,
'L');
'L',
trace_string);
action_exp = strchr (action_exp, ','); /* more? */
}
else if (0 == strncasecmp ("$_ret", action_exp, 5))
@@ -1431,7 +1441,8 @@ encode_actions_1 (struct command_line *action,
struct cleanup *old_chain1 = NULL;
aexpr = gen_trace_for_return_address (tloc->address,
tloc->gdbarch);
tloc->gdbarch,
trace_string);
old_chain1 = make_cleanup_free_agent_expr (aexpr);
@@ -1512,11 +1523,13 @@ encode_actions_1 (struct command_line *action,
tloc->gdbarch,
frame_reg,
frame_offset,
tloc->address);
tloc->address,
trace_string);
break;
default: /* Full-fledged expression. */
aexpr = gen_trace_for_expr (tloc->address, exp);
aexpr = gen_trace_for_expr (tloc->address, exp,
trace_string);
old_chain1 = make_cleanup_free_agent_expr (aexpr);
@@ -2846,9 +2859,10 @@ trace_dump_actions (struct command_line *action,
char *cmd = NULL;
struct cleanup *old_chain
= make_cleanup (free_current_contents, &cmd);
int trace_string = 0;
if (*action_exp == '/')
action_exp = decode_agent_options (action_exp);
action_exp = decode_agent_options (action_exp, &trace_string);
do
{ /* Repeat over a comma-separated list. */

View File

@@ -342,7 +342,7 @@ struct cleanup *make_cleanup_restore_traceframe_number (void);
void free_actions (struct breakpoint *);
extern const char *decode_agent_options (const char *exp);
extern const char *decode_agent_options (const char *exp, int *trace_string);
extern void encode_actions (struct breakpoint *t, struct bp_location *tloc,
char ***tdp_actions, char ***stepping_actions);