From 92bc6a206434a8b6922846d064e9c701a5a10a0e Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 21 Mar 2013 16:09:27 +0000 Subject: [PATCH] * 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) : 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) : 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. --- gdb/ChangeLog | 25 +++++++++++++++ gdb/ax-gdb.c | 92 ++++++++++++++++++++++---------------------------------- gdb/ax-gdb.h | 11 +++---- gdb/ax-general.c | 3 ++ gdb/ax.h | 17 +++++++++++ gdb/dwarf2loc.c | 2 +- gdb/tracepoint.c | 50 +++++++++++++++++++----------- gdb/tracepoint.h | 2 +- 8 files changed, 120 insertions(+), 82 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7aab4ef..6aac6d7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,28 @@ +2013-03-11 Tom Tromey + + * 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) : 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) : 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 PR exp/15109: diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 25179ad..4196655 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -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); } diff --git a/gdb/ax-gdb.h b/gdb/ax-gdb.h index 04772b7..65e703e 100644 --- a/gdb/ax-gdb.h +++ b/gdb/ax-gdb.h @@ -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 */ diff --git a/gdb/ax-general.c b/gdb/ax-general.c index 8bd4df6..78d7f7e 100644 --- a/gdb/ax-general.c +++ b/gdb/ax-general.c @@ -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; } diff --git a/gdb/ax.h b/gdb/ax.h index 32887ef..3bb2d5b 100644 --- a/gdb/ax.h +++ b/gdb/ax.h @@ -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. */ diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 700d194..18699e0 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -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) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 66533f7..9a2425b 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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. */ diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index 2a809c7..c7eef7b 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -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); -- 2.7.4