X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fax-gdb.c;h=fae2e2d4836fa1ccc1b0a8069c20ca82baf23acf;hb=957f6b39cab6cac0e4c54e650c7f75109544ac1d;hp=e85f0030879b91ba85d93c8c7f93bcad56f26e52;hpb=7b6bb8daaceb9ecf3f42dea57ae82733d6a3b2f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index e85f003087..fae2e2d483 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -1,7 +1,6 @@ /* GDB-specific functions for operating on agent expressions. - Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -31,15 +30,23 @@ #include "target.h" #include "ax.h" #include "ax-gdb.h" -#include "gdb_string.h" #include "block.h" #include "regcache.h" #include "user-regs.h" -#include "language.h" #include "dictionary.h" #include "breakpoint.h" #include "tracepoint.h" #include "cp-support.h" +#include "arch-utils.h" +#include "cli/cli-utils.h" +#include "linespec.h" +#include "location.h" +#include "objfiles.h" + +#include "valprint.h" +#include "c-lang.h" + +#include "format.h" /* To make sense of this file, you should read doc/agentexpr.texi. Then look at the types and enums in ax-gdb.h. For the code itself, @@ -70,7 +77,8 @@ static struct value *const_var_ref (struct symbol *var); static struct value *const_expr (union exp_element **pc); static struct value *maybe_const_expr (union exp_element **pc); -static void gen_traced_pop (struct gdbarch *, struct agent_expr *, struct axs_value *); +static void gen_traced_pop (struct gdbarch *, struct agent_expr *, + struct axs_value *); static void gen_sign_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *); @@ -90,8 +98,6 @@ static void gen_int_literal (struct agent_expr *ax, struct axs_value *value, LONGEST k, struct type *type); - -static void require_rvalue (struct agent_expr *ax, struct axs_value *value); static void gen_usual_unary (struct expression *exp, struct agent_expr *ax, struct axs_value *value); static int type_wider_than (struct type *type1, struct type *type2); @@ -122,7 +128,8 @@ static void gen_binop (struct agent_expr *ax, struct axs_value *value1, struct axs_value *value2, enum agent_op op, - enum agent_op op_unsigned, int may_carry, char *name); + enum agent_op op_unsigned, int may_carry, + const char *name); static void gen_logical_not (struct agent_expr *ax, struct axs_value *value, struct type *result_type); static void gen_complement (struct agent_expr *ax, struct axs_value *value); @@ -138,12 +145,13 @@ static void gen_primitive_field (struct expression *exp, static int gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, struct axs_value *value, - char *field, int offset, + const char *field, int offset, struct type *type); static void gen_struct_ref (struct expression *exp, struct agent_expr *ax, struct axs_value *value, - char *field, - char *operator_name, char *operand_name); + const char *field, + const char *operator_name, + const char *operand_name); static void gen_static_field (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, struct type *type, int fieldno); @@ -152,8 +160,6 @@ static void gen_repeat (struct expression *exp, union exp_element **pc, static void gen_sizeof (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value, struct type *size_type); -static void gen_expr (struct expression *exp, union exp_element **pc, - struct agent_expr *ax, struct axs_value *value); static void gen_expr_binop_rest (struct expression *exp, enum exp_opcode op, union exp_element **pc, struct agent_expr *ax, @@ -308,31 +314,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; - /* Scan for all static fields in the given class, including any base classes, and generate tracing bytecodes for each. */ @@ -344,7 +325,7 @@ gen_trace_static_fields (struct gdbarch *gdbarch, int i, nbases = TYPE_N_BASECLASSES (type); struct axs_value value; - CHECK_TYPEDEF (type); + type = check_typedef (type); for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) { @@ -357,9 +338,9 @@ gen_trace_static_fields (struct gdbarch *gdbarch, { case axs_lvalue_memory: { - int length = TYPE_LENGTH (check_typedef (value.type)); - - ax_const_l (ax, length); + /* Initialize the TYPE_LENGTH if it is a typedef. */ + check_typedef (value.type); + ax_const_l (ax, TYPE_LENGTH (value.type)); ax_simple (ax, aop_trace); } break; @@ -391,26 +372,49 @@ static void gen_traced_pop (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value) { - if (trace_kludge) + int string_trace = 0; + 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 (ax->tracing) switch (value->kind) { case axs_rvalue: - /* We don't trace rvalues, just the lvalues necessary to - produce them. So just dispose of this value. */ - ax_simple (ax, aop_pop); + if (string_trace) + { + ax_const_l (ax, ax->trace_string); + ax_simple (ax, aop_tracenz); + } + else + /* We don't trace rvalues, just the lvalues necessary to + produce them. So just dispose of this value. */ + ax_simple (ax, aop_pop); break; case axs_lvalue_memory: { - int length = TYPE_LENGTH (check_typedef (value->type)); - - /* There's no point in trying to use a trace_quick bytecode - here, since "trace_quick SIZE pop" is three bytes, whereas - "const8 SIZE trace" is also three bytes, does the same - thing, and the simplest code which generates that will also - work correctly for objects with large sizes. */ - ax_const_l (ax, length); - ax_simple (ax, aop_trace); + /* Initialize the TYPE_LENGTH if it is a typedef. */ + check_typedef (value->type); + + if (string_trace) + { + gen_fetch (ax, value->type); + ax_const_l (ax, ax->trace_string); + ax_simple (ax, aop_tracenz); + } + else + { + /* There's no point in trying to use a trace_quick bytecode + here, since "trace_quick SIZE pop" is three bytes, whereas + "const8 SIZE trace" is also three bytes, does the same + thing, and the simplest code which generates that will also + work correctly for objects with large sizes. */ + ax_const_l (ax, TYPE_LENGTH (value->type)); + ax_simple (ax, aop_trace); + } } break; @@ -420,6 +424,15 @@ gen_traced_pop (struct gdbarch *gdbarch, 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); + + /* But if the register points to a string, assume the value + will fit on the stack and push it anyway. */ + if (string_trace) + { + ax_reg (ax, value->u.reg); + ax_const_l (ax, ax->trace_string); + ax_simple (ax, aop_tracenz); + } break; } else @@ -427,7 +440,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); @@ -467,16 +480,20 @@ 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)); } + if (TYPE_CODE (type) == TYPE_CODE_RANGE) + type = TYPE_TARGET_TYPE (type); + switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: case TYPE_CODE_REF: + case TYPE_CODE_RVALUE_REF: case TYPE_CODE_ENUM: case TYPE_CODE_INT: case TYPE_CODE_CHAR: @@ -511,12 +528,11 @@ gen_fetch (struct agent_expr *ax, struct type *type) break; default: - /* Either our caller shouldn't have asked us to dereference that - pointer (other code's fault), or we're not implementing - something we should be (this code's fault). In any case, - it's a bug the user shouldn't see. */ - internal_error (__FILE__, __LINE__, - _("gen_fetch: bad type code")); + /* Our caller requested us to dereference a pointer from an unsupported + type. Error out and give callers a chance to handle the failure + gracefully. */ + error (_("gen_fetch: Unsupported type code `%s'."), + TYPE_NAME (type)); } } @@ -618,6 +634,12 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, value->type = check_typedef (SYMBOL_TYPE (var)); value->optimized_out = 0; + if (SYMBOL_COMPUTED_OPS (var) != NULL) + { + SYMBOL_COMPUTED_OPS (var)->tracepoint_var_ref (var, gdbarch, ax, value); + return; + } + /* I'm imitating the code in read_var_value. */ switch (SYMBOL_CLASS (var)) { @@ -633,7 +655,8 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, case LOC_CONST_BYTES: internal_error (__FILE__, __LINE__, - _("gen_var_ref: LOC_CONST_BYTES symbols are not supported")); + _("gen_var_ref: LOC_CONST_BYTES " + "symbols are not supported")); /* Variable at a fixed location in memory. Easy. */ case LOC_STATIC: @@ -692,26 +715,20 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, case LOC_UNRESOLVED: { - struct minimal_symbol *msym + struct bound_minimal_symbol msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL); - if (!msym) + if (!msym.minsym) error (_("Couldn't resolve symbol `%s'."), SYMBOL_PRINT_NAME (var)); /* Push the address of the variable. */ - ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym)); + ax_const_l (ax, BMSYMBOL_VALUE_ADDRESS (msym)); value->kind = axs_lvalue_memory; } break; case LOC_COMPUTED: - /* FIXME: cagney/2004-01-26: It should be possible to - unconditionally call the SYMBOL_COMPUTED_OPS method when available. - Unfortunately DWARF 2 stores the frame-base (instead of the - function) location in a function's symbol. Oops! For the - moment enable this when/where applicable. */ - SYMBOL_COMPUTED_OPS (var)->tracepoint_var_ref (var, gdbarch, ax, value); - break; + gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method")); case LOC_OPTIMIZED_OUT: /* Flag this, but don't say anything; leave it up to callers to @@ -746,7 +763,7 @@ gen_int_literal (struct agent_expr *ax, struct axs_value *value, LONGEST k, /* Take what's on the top of the stack (as described by VALUE), and try to make an rvalue out of it. Signal an error if we can't do that. */ -static void +void require_rvalue (struct agent_expr *ax, struct axs_value *value) { /* Only deal with scalars, structs and such may be too large @@ -835,12 +852,6 @@ gen_usual_unary (struct expression *exp, struct agent_expr *ax, case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: return; - - /* If the value is an enum or a bool, call it an integer. */ - case TYPE_CODE_ENUM: - case TYPE_CODE_BOOL: - value->type = builtin_type (exp->gdbarch)->builtin_int; - break; } /* If the value is an lvalue, dereference it. */ @@ -877,7 +888,7 @@ gen_conversion (struct agent_expr *ax, struct type *from, struct type *to) /* If we're converting to a narrower type, then we need to clear out the upper bits. */ if (TYPE_LENGTH (to) < TYPE_LENGTH (from)) - gen_extend (ax, from); + gen_extend (ax, to); /* If the two values have equal width, but different signednesses, then we need to extend. */ @@ -902,7 +913,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 (NULL, 0); + agent_expr_up ax (new agent_expr (NULL, 0)); int nontrivial; /* Actually generate the code, and see if anything came out. At the @@ -911,9 +922,8 @@ is_nontrivial_conversion (struct type *from, struct type *to) floating point and the like, it may not be. Doing things this way allows this function to be independent of the logic in gen_conversion. */ - gen_conversion (ax, from, to); + gen_conversion (ax.get (), from, to); nontrivial = ax->len > 0; - free_agent_expr (ax); return nontrivial; } @@ -993,6 +1003,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) { case TYPE_CODE_PTR: case TYPE_CODE_REF: + case TYPE_CODE_RVALUE_REF: /* It's implementation-defined, and I'll bet this is what GCC does. */ break; @@ -1138,8 +1149,9 @@ gen_less (struct agent_expr *ax, struct axs_value *value, operator, used in error messages */ static void gen_binop (struct agent_expr *ax, struct axs_value *value, - struct axs_value *value1, struct axs_value *value2, enum agent_op op, - enum agent_op op_unsigned, int may_carry, char *name) + struct axs_value *value1, struct axs_value *value2, + enum agent_op op, enum agent_op op_unsigned, + int may_carry, const char *name) { /* We only handle INT op INT. */ if ((TYPE_CODE (value1->type) != TYPE_CODE_INT) @@ -1321,7 +1333,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); @@ -1424,16 +1436,16 @@ gen_primitive_field (struct expression *exp, static int gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, struct axs_value *value, - char *field, int offset, struct type *type) + const char *field, int offset, struct type *type) { int i, rslt; int nbases = TYPE_N_BASECLASSES (type); - CHECK_TYPEDEF (type); + type = check_typedef (type); for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) { - char *this_name = TYPE_FIELD_NAME (type, i); + const char *this_name = TYPE_FIELD_NAME (type, i); if (this_name) { @@ -1447,7 +1459,8 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, { gen_static_field (exp->gdbarch, ax, value, type, i); if (value->optimized_out) - error (_("static field `%s' has been optimized out, cannot use"), + error (_("static field `%s' has been " + "optimized out, cannot use"), field); return 1; } @@ -1469,7 +1482,8 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); rslt = gen_struct_ref_recursive (exp, ax, value, field, - offset + TYPE_BASECLASS_BITPOS (type, i) / TARGET_CHAR_BIT, + offset + TYPE_BASECLASS_BITPOS (type, i) + / TARGET_CHAR_BIT, basetype); if (rslt) return 1; @@ -1486,8 +1500,8 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, it operates on; we use them in error messages. */ static void gen_struct_ref (struct expression *exp, struct agent_expr *ax, - struct axs_value *value, char *field, - char *operator_name, char *operand_name) + struct axs_value *value, const char *field, + const char *operator_name, const char *operand_name) { struct type *type; int found; @@ -1544,8 +1558,8 @@ gen_static_field (struct gdbarch *gdbarch, } else { - char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); - struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); + const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); + struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0).symbol; if (sym) { @@ -1579,7 +1593,7 @@ gen_struct_elt_for_reference (struct expression *exp, for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) { - char *t_field_name = TYPE_FIELD_NAME (t, i); + const char *t_field_name = TYPE_FIELD_NAME (t, i); if (t_field_name && strcmp (t_field_name, fieldname) == 0) { @@ -1587,7 +1601,8 @@ gen_struct_elt_for_reference (struct expression *exp, { gen_static_field (exp->gdbarch, ax, value, t, i); if (value->optimized_out) - error (_("static field `%s' has been optimized out, cannot use"), + error (_("static field `%s' has been " + "optimized out, cannot use"), fieldname); return 1; } @@ -1635,20 +1650,20 @@ gen_maybe_namespace_elt (struct expression *exp, const struct type *curtype, char *name) { const char *namespace_name = TYPE_TAG_NAME (curtype); - struct symbol *sym; + struct block_symbol sym; sym = cp_lookup_symbol_namespace (namespace_name, name, block_for_pc (ax->scope), VAR_DOMAIN); - if (sym == NULL) + if (sym.symbol == NULL) return 0; - gen_var_ref (exp->gdbarch, ax, value, sym); + gen_var_ref (exp->gdbarch, ax, value, sym.symbol); if (value->optimized_out) error (_("`%s' has been optimized out, cannot use"), - SYMBOL_PRINT_NAME (sym)); + SYMBOL_PRINT_NAME (sym.symbol)); return 1; } @@ -1658,7 +1673,8 @@ static int gen_aggregate_elt_ref (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct type *type, char *field, - char *operator_name, char *operand_name) + const char *operator_name, + const char *operand_name) { switch (TYPE_CODE (type)) { @@ -1706,7 +1722,8 @@ gen_repeat (struct expression *exp, union exp_element **pc, int length; if (!v) - error (_("Right operand of `@' must be a constant, in agent expressions.")); + error (_("Right operand of `@' must be a " + "constant, in agent expressions.")); if (TYPE_CODE (value_type (v)) != TYPE_CODE_INT) error (_("Right operand of `@' must be an integer.")); length = value_as_long (v); @@ -1759,7 +1776,7 @@ gen_sizeof (struct expression *exp, union exp_element **pc, /* XXX: i18n */ /* A gen_expr function written by a Gen-X'er guy. Append code for the subexpression of EXPR starting at *POS_P to AX. */ -static void +void gen_expr (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value) { @@ -1886,11 +1903,12 @@ 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 - error (_("$%s is not a trace state variable, may not assign to it"), name); + error (_("$%s is not a trace state variable, " + "may not assign to it"), name); } else error (_("May only assign to trace state variables")); @@ -1912,7 +1930,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; @@ -1921,11 +1939,12 @@ 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 - error (_("$%s is not a trace state variable, may not assign to it"), name); + error (_("$%s is not a trace state variable, " + "may not assign to it"), name); } else error (_("May only assign to trace state variables")); @@ -1992,7 +2011,8 @@ gen_expr (struct expression *exp, union exp_element **pc, case OP_INTERNALVAR: { - const char *name = internalvar_name ((*pc)[1].internalvar); + struct internalvar *var = (*pc)[1].internalvar; + const char *name = internalvar_name (var); struct trace_state_variable *tsv; (*pc) += 3; @@ -2000,14 +2020,15 @@ 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; value->type = builtin_type (exp->gdbarch)->builtin_long_long; } - else - error (_("$%s is not a trace state variable; GDB agent expressions cannot use convenience variables."), name); + else if (! compile_internalvar_to_ax (var, ax, value)) + error (_("$%s is not a trace state variable; GDB agent " + "expressions cannot use convenience variables."), name); } break; @@ -2028,20 +2049,61 @@ gen_expr (struct expression *exp, union exp_element **pc, } break; + case UNOP_CAST_TYPE: + { + int offset; + struct value *val; + struct type *type; + + ++*pc; + offset = *pc - exp->elts; + val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS); + type = value_type (val); + *pc = &exp->elts[offset]; + + gen_expr (exp, pc, ax, value); + gen_cast (ax, value, type); + } + break; + case UNOP_MEMVAL: { struct type *type = check_typedef ((*pc)[1].type); (*pc) += 3; gen_expr (exp, pc, ax, value); - /* I'm not sure I understand UNOP_MEMVAL entirely. I think - it's just a hack for dealing with minsyms; you take some - integer constant, pretend it's the address of an lvalue of - the given type, and dereference it. */ - if (value->kind != axs_rvalue) - /* This would be weird. */ - internal_error (__FILE__, __LINE__, - _("gen_expr: OP_MEMVAL operand isn't an rvalue???")); + + /* If we have an axs_rvalue or an axs_lvalue_memory, then we + already have the right value on the stack. For + axs_lvalue_register, we must convert. */ + if (value->kind == axs_lvalue_register) + require_rvalue (ax, value); + + value->type = type; + value->kind = axs_lvalue_memory; + } + break; + + case UNOP_MEMVAL_TYPE: + { + int offset; + struct value *val; + struct type *type; + + ++*pc; + offset = *pc - exp->elts; + val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS); + type = value_type (val); + *pc = &exp->elts[offset]; + + gen_expr (exp, pc, ax, value); + + /* If we have an axs_rvalue or an axs_lvalue_memory, then we + already have the right value on the stack. For + axs_lvalue_register, we must convert. */ + if (value->kind == axs_lvalue_register) + require_rvalue (ax, value); + value->type = type; value->kind = axs_lvalue_memory; } @@ -2128,19 +2190,17 @@ gen_expr (struct expression *exp, union exp_element **pc, case OP_THIS: { - char *this_name; - struct symbol *func, *sym; - struct block *b; + struct symbol *sym, *func; + const struct block *b; + const struct language_defn *lang; - func = block_linkage_function (block_for_pc (ax->scope)); - this_name = language_def (SYMBOL_LANGUAGE (func))->la_name_of_this; - b = SYMBOL_BLOCK_VALUE (func); + b = block_for_pc (ax->scope); + func = block_linkage_function (b); + lang = language_def (SYMBOL_LANGUAGE (func)); - /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER - symbol instead of the LOC_ARG one (if both exist). */ - sym = lookup_block_symbol (b, this_name, VAR_DOMAIN); + sym = lookup_language_this (lang, b).symbol; if (!sym) - error (_("no `%s' found"), this_name); + error (_("no `%s' found"), lang->la_name_of_this); gen_var_ref (exp->gdbarch, ax, value, sym); @@ -2168,11 +2228,13 @@ gen_expr (struct expression *exp, union exp_element **pc, break; case OP_TYPE: + case OP_TYPEOF: + case OP_DECLTYPE: error (_("Attempt to use a type name as an expression.")); default: error (_("Unsupported operator %s (%d) in expression."), - op_string (op), op); + op_name (exp, op), op); } } @@ -2247,8 +2309,8 @@ gen_expr_binop_rest (struct expression *exp, if (binop_types_user_defined_p (op, value1->type, value2->type)) { - error (_("\ -cannot subscript requested type: cannot call user defined functions")); + error (_("cannot subscript requested type: " + "cannot call user defined functions")); } else { @@ -2268,7 +2330,8 @@ cannot subscript requested type: cannot call user defined functions")); } if (!is_integral_type (value2->type)) - error (_("Argument to arithmetic operation not a number or boolean.")); + error (_("Argument to arithmetic operation " + "not a number or boolean.")); gen_ptradd (ax, value, value1, value2); gen_deref (ax, value); @@ -2332,37 +2395,28 @@ cannot subscript requested type: cannot call user defined functions")); variable's name, and no parsed expression; for instance, when the name comes from a list of local variables of a function. */ -struct agent_expr * +agent_expr_up 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); + agent_expr_up ax (new agent_expr (gdbarch, scope)); struct axs_value value; - old_chain = make_cleanup_free_agent_expr (ax); - - trace_kludge = 1; - gen_var_ref (gdbarch, ax, &value, var); + ax->tracing = 1; + ax->trace_string = trace_string; + gen_var_ref (gdbarch, ax.get (), &value, var); /* If there is no actual variable to trace, flag it by returning an empty agent expression. */ if (value.optimized_out) - { - do_cleanups (old_chain); - return NULL; - } + return agent_expr_up (); /* Make sure we record the final object, and get rid of it. */ - gen_traced_pop (gdbarch, ax, &value); + gen_traced_pop (gdbarch, ax.get (), &value); /* Oh, and terminate. */ - ax_simple (ax, aop_end); + ax_simple (ax.get (), aop_end); - /* We have successfully built the agent expr, so cancel the cleanup - request. If we add more cleanups that we always want done, this - will have to get more complicated. */ - discard_cleanups (old_chain); return ax; } @@ -2373,31 +2427,27 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, record the value of all memory touched by the expression. The 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) + +agent_expr_up +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); + agent_expr_up ax (new agent_expr (expr->gdbarch, scope)); union exp_element *pc; struct axs_value value; - 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); + gen_expr (expr, &pc, ax.get (), &value); /* Make sure we record the final object, and get rid of it. */ - gen_traced_pop (expr->gdbarch, ax, &value); + gen_traced_pop (expr->gdbarch, ax.get (), &value); /* Oh, and terminate. */ - ax_simple (ax, aop_end); + ax_simple (ax.get (), aop_end); - /* We have successfully built the agent expr, so cancel the cleanup - request. If we add more cleanups that we always want done, this - will have to get more complicated. */ - discard_cleanups (old_chain); return ax; } @@ -2408,41 +2458,136 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) gen_trace_for_expr does. The generated bytecode sequence leaves the result of expression evaluation on the top of the stack. */ -struct agent_expr * +agent_expr_up gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) { - struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope); + agent_expr_up ax (new agent_expr (expr->gdbarch, scope)); union exp_element *pc; struct axs_value value; - 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); + gen_expr (expr, &pc, ax.get (), &value); + + require_rvalue (ax.get (), &value); + + /* Oh, and terminate. */ + ax_simple (ax.get (), aop_end); + + return ax; +} - require_rvalue (ax, &value); +agent_expr_up +gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch, + int trace_string) +{ + agent_expr_up ax (new agent_expr (gdbarch, scope)); + struct axs_value value; + + ax->tracing = 1; + ax->trace_string = trace_string; + + gdbarch_gen_return_address (gdbarch, ax.get (), &value, scope); + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (gdbarch, ax.get (), &value); /* Oh, and terminate. */ - ax_simple (ax, aop_end); + ax_simple (ax.get (), aop_end); + + return ax; +} + +/* Given a collection of printf-style arguments, generate code to + evaluate the arguments and pass everything to a special + bytecode. */ + +agent_expr_up +gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch, + CORE_ADDR function, LONGEST channel, + const char *format, int fmtlen, + struct format_piece *frags, + int nargs, struct expression **exprs) +{ + agent_expr_up ax (new agent_expr (gdbarch, scope)); + union exp_element *pc; + struct axs_value value; + int tem; + + /* 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; + value.optimized_out = 0; + gen_expr (exprs[tem], &pc, ax.get (), &value); + require_rvalue (ax.get (), &value); + } + + /* Push function and channel. */ + ax_const_l (ax.get (), channel); + ax_const_l (ax.get (), function); + + /* Issue the printf bytecode proper. */ + ax_simple (ax.get (), aop_printf); + ax_raw_byte (ax.get (), nargs); + ax_string (ax.get (), format, fmtlen); + + /* And terminate. */ + ax_simple (ax.get (), aop_end); - /* We have successfully built the agent expr, so cancel the cleanup - request. If we add more cleanups that we always want done, this - will have to get more complicated. */ - discard_cleanups (old_chain); return ax; } static void -agent_command (char *exp, int from_tty) +agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc) { - struct cleanup *old_chain = 0; - struct expression *expr; - struct agent_expr *agent; - struct frame_info *fi = get_current_frame (); /* need current scope */ + const char *arg; + int trace_string = 0; + + if (!eval) + { + if (*exp == '/') + exp = decode_agent_options (exp, &trace_string); + } + + agent_expr_up agent; + + arg = exp; + if (!eval && strcmp (arg, "$_ret") == 0) + { + agent = gen_trace_for_return_address (pc, get_current_arch (), + trace_string); + } + else + { + expression_up expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0); + + if (eval) + { + gdb_assert (trace_string == 0); + agent = gen_eval_for_expr (pc, expr.get ()); + } + else + agent = gen_trace_for_expr (pc, expr.get (), trace_string); + } + + ax_reqs (agent.get ()); + ax_print (gdb_stdout, agent.get ()); + + /* It would be nice to call ax_reqs here to gather some general info + about the expression, and then print out the result. */ + + dont_repeat (); +} +static void +agent_command_1 (char *exp, int eval) +{ /* We don't deal with overlay debugging at the moment. We need to think more carefully about this. If you copy this code into another command, change the error message; the user shouldn't @@ -2453,31 +2598,67 @@ agent_command (char *exp, int from_tty) if (exp == 0) error_no_arg (_("expression to translate")); - expr = parse_expression (exp); - 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); + if (check_for_argument (&exp, "-at", sizeof ("-at") - 1)) + { + struct linespec_result canonical; + int ix; + struct linespec_sals *iter; + + exp = skip_spaces (exp); + + event_location_up location = new_linespec_location (&exp); + decode_line_full (location.get (), DECODE_LINE_FUNFIRSTLINE, NULL, + (struct symtab *) NULL, 0, &canonical, + NULL, NULL); + exp = skip_spaces (exp); + if (exp[0] == ',') + { + exp++; + exp = skip_spaces (exp); + } + for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix) + { + int i; - /* It would be nice to call ax_reqs here to gather some general info - about the expression, and then print out the result. */ + for (i = 0; i < iter->sals.nelts; i++) + agent_eval_command_one (exp, eval, iter->sals.sals[i].pc); + } + } + else + agent_eval_command_one (exp, eval, get_frame_pc (get_current_frame ())); - do_cleanups (old_chain); dont_repeat (); } +static void +agent_command (char *exp, int from_tty) +{ + agent_command_1 (exp, 0); +} + /* Parse the given expression, compile it into an agent expression that does direct evaluation, and display the resulting expression. */ static void agent_eval_command (char *exp, int from_tty) +{ + agent_command_1 (exp, 1); +} + +/* Parse the given expression, compile it into an agent expression + that does a printf, and display the resulting expression. */ + +static void +maint_agent_printf_command (char *exp, int from_tty) { struct cleanup *old_chain = 0; - struct expression *expr; - struct agent_expr *agent; + struct expression *argvec[100]; struct frame_info *fi = get_current_frame (); /* need current scope */ + const char *cmdrest; + const char *format_start, *format_end; + struct format_piece *fpieces; + int nargs; /* We don't deal with overlay debugging at the moment. We need to think more carefully about this. If you copy this code into @@ -2489,12 +2670,55 @@ agent_eval_command (char *exp, int from_tty) if (exp == 0) error_no_arg (_("expression to translate")); - expr = parse_expression (exp); - 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); + cmdrest = exp; + + cmdrest = skip_spaces_const (cmdrest); + + if (*cmdrest++ != '"') + error (_("Must start with a format string.")); + + format_start = cmdrest; + + fpieces = parse_format_string (&cmdrest); + + old_chain = make_cleanup (free_format_pieces_cleanup, &fpieces); + + format_end = cmdrest; + + if (*cmdrest++ != '"') + error (_("Bad format string, non-terminated '\"'.")); + + cmdrest = skip_spaces_const (cmdrest); + + if (*cmdrest != ',' && *cmdrest != 0) + error (_("Invalid argument syntax")); + + if (*cmdrest == ',') + cmdrest++; + cmdrest = skip_spaces_const (cmdrest); + + nargs = 0; + while (*cmdrest != '\0') + { + const char *cmd1; + + cmd1 = cmdrest; + expression_up expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1); + argvec[nargs] = expr.release (); + ++nargs; + cmdrest = cmd1; + if (*cmdrest == ',') + ++cmdrest; + /* else complain? */ + } + + + agent_expr_up agent = gen_printf (get_frame_pc (fi), get_current_arch (), + 0, 0, + format_start, format_end - format_start, + fpieces, nargs, argvec); + ax_reqs (agent.get ()); + ax_print (gdb_stdout, agent.get ()); /* It would be nice to call ax_reqs here to gather some general info about the expression, and then print out the result. */ @@ -2511,10 +2735,23 @@ void _initialize_ax_gdb (void) { add_cmd ("agent", class_maintenance, agent_command, - _("Translate an expression into remote agent bytecode for tracing."), + _("\ +Translate an expression into remote agent bytecode for tracing.\n\ +Usage: maint agent [-at location,] EXPRESSION\n\ +If -at is given, generate remote agent bytecode for this location.\n\ +If not, generate remote agent bytecode for current frame pc address."), &maintenancelist); add_cmd ("agent-eval", class_maintenance, agent_eval_command, - _("Translate an expression into remote agent bytecode for evaluation."), + _("\ +Translate an expression into remote agent bytecode for evaluation.\n\ +Usage: maint agent-eval [-at location,] EXPRESSION\n\ +If -at is given, generate remote agent bytecode for this location.\n\ +If not, generate remote agent bytecode for current frame pc address."), + &maintenancelist); + + add_cmd ("agent-printf", class_maintenance, maint_agent_printf_command, + _("Translate an expression into remote " + "agent bytecode for evaluation and display the bytecodes."), &maintenancelist); }