X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fax-gdb.c;h=7c6cb6481fbba8c599f37c4a885aa9c9b871af44;hb=a12ac51333cf97f4da0597d049cc694b4535e7dd;hp=5776bb0ce6d9487dba27e69cb37e87a9c49a2198;hpb=00bf0b8586eece6ef4e508343e9896d309c2004e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 5776bb0ce6..7c6cb6481f 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 - Free Software Foundation, Inc. + Copyright (C) 1998-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -31,14 +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, @@ -58,7 +66,7 @@ -/* Prototypes for local functions. */ +/* Prototypes for local functions. */ /* There's a standard order to the arguments of these functions: union exp_element ** --- pointer into expression @@ -69,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 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 *); @@ -89,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); @@ -127,21 +134,30 @@ static void gen_logical_not (struct agent_expr *ax, struct axs_value *value, static void gen_complement (struct agent_expr *ax, struct axs_value *value); static void gen_deref (struct agent_expr *, struct axs_value *); static void gen_address_of (struct agent_expr *, struct axs_value *); -static int find_field (struct type *type, char *name); static void gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct type *type, int start, int end); +static void gen_primitive_field (struct expression *exp, + struct agent_expr *ax, + struct axs_value *value, + int offset, int fieldno, struct type *type); +static int gen_struct_ref_recursive (struct expression *exp, + struct agent_expr *ax, + struct axs_value *value, + 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); +static void gen_static_field (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + struct type *type, int fieldno); static void gen_repeat (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value); 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, @@ -207,6 +223,7 @@ const_expr (union exp_element **pc) { struct type *type = (*pc)[1].type; LONGEST k = (*pc)[2].longconst; + (*pc) += 4; return value_from_longest (type, k); } @@ -214,6 +231,7 @@ const_expr (union exp_element **pc) case OP_VAR_VALUE: { struct value *v = const_var_ref ((*pc)[2].symbol); + (*pc) += 4; return v; } @@ -294,71 +312,136 @@ maybe_const_expr (union exp_element **pc) sizes), and this is simpler.) */ -/* Generating bytecode from GDB expressions: the `trace' kludge */ +/* Scan for all static fields in the given class, including any base + classes, and generate tracing bytecodes for each. */ -/* 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. +static void +gen_trace_static_fields (struct gdbarch *gdbarch, + struct agent_expr *ax, + struct type *type) +{ + int i, nbases = TYPE_N_BASECLASSES (type); + struct axs_value value; - However, at the moment it is HOPELESSLY BRAIN-DAMAGED for the sake - of expediency. Let he who is without sin cast the first stone. + type = check_typedef (type); - 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. + for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) + { + if (field_is_static (&TYPE_FIELD (type, i))) + { + gen_static_field (gdbarch, ax, &value, type, i); + if (value.optimized_out) + continue; + switch (value.kind) + { + case axs_lvalue_memory: + { + /* 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; + + case axs_lvalue_register: + /* 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; + } + } + } - 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. + /* Now scan through base classes recursively. */ + for (i = 0; i < nbases; i++) + { + struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); - Setting the flag trace_kludge to non-zero enables the code that - emits the trace bytecodes at the appropriate points. */ -static int trace_kludge; + gen_trace_static_fields (gdbarch, ax, basetype); + } +} /* Trace the lvalue on the stack, if it needs it. In either case, pop the value. Useful on the left side of a comma, and at the end of an expression being used for tracing. */ static void -gen_traced_pop (struct agent_expr *ax, struct axs_value *value) +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; 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); + + /* 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 /* If we're not tracing, just pop the value. */ ax_simple (ax, aop_pop); + + /* To trace C++ classes with static fields stored elsewhere. */ + 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); } @@ -383,6 +466,7 @@ static void gen_extend (struct agent_expr *ax, struct type *type) { int bits = TYPE_LENGTH (type) * TARGET_CHAR_BIT; + /* I just had to. */ ((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits)); } @@ -394,12 +478,15 @@ 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: @@ -407,6 +494,7 @@ gen_fetch (struct agent_expr *ax, struct type *type) case TYPE_CODE_ENUM: case TYPE_CODE_INT: case TYPE_CODE_CHAR: + case TYPE_CODE_BOOL: /* It's a scalar value, so we know how to dereference it. How many bytes long is it? */ switch (TYPE_LENGTH (type)) @@ -437,12 +525,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)); } } @@ -540,8 +627,15 @@ static void gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value, struct symbol *var) { - /* Dereference any typedefs. */ + /* Dereference any typedefs. */ 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)) @@ -558,7 +652,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: @@ -617,29 +712,25 @@ 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: - error (_("The variable `%s' has been optimized out."), - SYMBOL_PRINT_NAME (var)); + /* Flag this, but don't say anything; leave it up to callers to + warn the user. */ + value->optimized_out = 1; break; default: @@ -669,9 +760,18 @@ 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 + to fit in a stack entry. */ + value->type = check_typedef (value->type); + if (TYPE_CODE (value->type) == TYPE_CODE_ARRAY + || TYPE_CODE (value->type) == TYPE_CODE_STRUCT + || TYPE_CODE (value->type) == TYPE_CODE_UNION + || TYPE_CODE (value->type) == TYPE_CODE_FUNC) + error (_("Value not scalar: cannot be an rvalue.")); + switch (value->kind) { case axs_rvalue: @@ -736,6 +836,7 @@ gen_usual_unary (struct expression *exp, struct agent_expr *ax, case TYPE_CODE_ARRAY: { struct type *elements = TYPE_TARGET_TYPE (value->type); + value->type = lookup_pointer_type (elements); value->kind = axs_rvalue; /* We don't need to generate any code; the address of the array @@ -748,11 +849,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, call it an integer. */ - case TYPE_CODE_ENUM: - value->type = builtin_type (exp->gdbarch)->builtin_int; - break; } /* If the value is an lvalue, dereference it. */ @@ -789,7 +885,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. */ @@ -814,7 +910,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 @@ -898,7 +994,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) /* GCC does allow casts to yield lvalues, so this should be fixed before merging these changes into the trunk. */ require_rvalue (ax, value); - /* Dereference typedefs. */ + /* Dereference typedefs. */ type = check_typedef (type); switch (TYPE_CODE (type)) @@ -916,6 +1012,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type) error (_("Invalid type cast: intended type must be scalar.")); case TYPE_CODE_ENUM: + case TYPE_CODE_BOOL: /* We don't have to worry about the size of the value, because all our integral values are fully sign-extended, and when casting pointers we can do anything we like. Is there any @@ -1013,6 +1110,33 @@ an integer nor a pointer of the same type.")); value->kind = axs_rvalue; } +static void +gen_equal (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) +{ + if (pointer_type (value1->type) || pointer_type (value2->type)) + ax_simple (ax, aop_equal); + else + gen_binop (ax, value, value1, value2, + aop_equal, aop_equal, 0, "equal"); + value->type = result_type; + value->kind = axs_rvalue; +} + +static void +gen_less (struct agent_expr *ax, struct axs_value *value, + struct axs_value *value1, struct axs_value *value2, + struct type *result_type) +{ + if (pointer_type (value1->type) || pointer_type (value2->type)) + ax_simple (ax, aop_less_unsigned); + else + gen_binop (ax, value, value1, value2, + aop_less_signed, aop_less_unsigned, 0, "less than"); + value->type = result_type; + value->kind = axs_rvalue; +} /* Generate code for a binary operator that doesn't do pointer magic. We set VALUE to describe the result value; we assume VALUE1 and @@ -1022,8 +1146,9 @@ an integer nor a pointer of the same type.")); 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, char *name) { /* We only handle INT op INT. */ if ((TYPE_CODE (value1->type) != TYPE_CODE_INT) @@ -1082,6 +1207,8 @@ gen_deref (struct agent_expr *ax, struct axs_value *value) T" to "T", and mark the value as an lvalue in memory. Leave it to the consumer to actually dereference it. */ value->type = check_typedef (TYPE_TARGET_TYPE (value->type)); + if (TYPE_CODE (value->type) == TYPE_CODE_VOID) + error (_("Attempt to dereference a generic pointer.")); value->kind = ((TYPE_CODE (value->type) == TYPE_CODE_FUNC) ? axs_rvalue : axs_lvalue_memory); } @@ -1114,46 +1241,6 @@ gen_address_of (struct agent_expr *ax, struct axs_value *value) } } - -/* A lot of this stuff will have to change to support C++. But we're - not going to deal with that at the moment. */ - -/* Find the field in the structure type TYPE named NAME, and return - its index in TYPE's field array. */ -static int -find_field (struct type *type, char *name) -{ - int i; - - CHECK_TYPEDEF (type); - - /* Make sure this isn't C++. */ - if (TYPE_N_BASECLASSES (type) != 0) - internal_error (__FILE__, __LINE__, - _("find_field: derived classes supported")); - - for (i = 0; i < TYPE_NFIELDS (type); i++) - { - char *this_name = TYPE_FIELD_NAME (type, i); - - if (this_name) - { - if (strcmp (name, this_name) == 0) - return i; - - if (this_name[0] == '\0') - internal_error (__FILE__, __LINE__, - _("find_field: anonymous unions not supported")); - } - } - - error (_("Couldn't find member named `%s' in struct/union `%s'"), - name, TYPE_TAG_NAME (type)); - - return 0; -} - - /* Generate code to push the value of a bitfield of a structure whose address is on the top of the stack. START and END give the starting and one-past-ending *bit* numbers of the field within the @@ -1165,8 +1252,7 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, { /* Note that ops[i] fetches 8 << i bits. */ static enum agent_op ops[] - = - {aop_ref8, aop_ref16, aop_ref32, aop_ref64}; + = {aop_ref8, aop_ref16, aop_ref32, aop_ref64}; static int num_ops = (sizeof (ops) / sizeof (ops[0])); /* We don't want to touch any byte that the bitfield doesn't @@ -1212,7 +1298,7 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, equal to the number of `one' bits in bytesize, but who cares? */ int fragment_count; - /* Dereference any typedefs. */ + /* Dereference any typedefs. */ type = check_typedef (type); /* Can we fetch the number of bits requested at all? */ @@ -1244,7 +1330,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); @@ -1314,6 +1400,95 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, value->type = type; } +/* Generate bytecodes for field number FIELDNO of type TYPE. OFFSET + is an accumulated offset (in bytes), will be nonzero for objects + embedded in other objects, like C++ base classes. Behavior should + generally follow value_primitive_field. */ + +static void +gen_primitive_field (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + int offset, int fieldno, struct type *type) +{ + /* Is this a bitfield? */ + if (TYPE_FIELD_PACKED (type, fieldno)) + gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, fieldno), + (offset * TARGET_CHAR_BIT + + TYPE_FIELD_BITPOS (type, fieldno)), + (offset * TARGET_CHAR_BIT + + TYPE_FIELD_BITPOS (type, fieldno) + + TYPE_FIELD_BITSIZE (type, fieldno))); + else + { + gen_offset (ax, offset + + TYPE_FIELD_BITPOS (type, fieldno) / TARGET_CHAR_BIT); + value->kind = axs_lvalue_memory; + value->type = TYPE_FIELD_TYPE (type, fieldno); + } +} + +/* Search for the given field in either the given type or one of its + base classes. Return 1 if found, 0 if not. */ + +static int +gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax, + struct axs_value *value, + char *field, int offset, struct type *type) +{ + int i, rslt; + int nbases = TYPE_N_BASECLASSES (type); + + type = check_typedef (type); + + for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) + { + const char *this_name = TYPE_FIELD_NAME (type, i); + + if (this_name) + { + if (strcmp (field, this_name) == 0) + { + /* Note that bytecodes for the struct's base (aka + "this") will have been generated already, which will + be unnecessary but not harmful if the static field is + being handled as a global. */ + if (field_is_static (&TYPE_FIELD (type, i))) + { + gen_static_field (exp->gdbarch, ax, value, type, i); + if (value->optimized_out) + error (_("static field `%s' has been " + "optimized out, cannot use"), + field); + return 1; + } + + gen_primitive_field (exp, ax, value, offset, i, type); + return 1; + } +#if 0 /* is this right? */ + if (this_name[0] == '\0') + internal_error (__FILE__, __LINE__, + _("find_field: anonymous unions not supported")); +#endif + } + } + + /* Now scan through base classes recursively. */ + for (i = 0; i < nbases; i++) + { + 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, + basetype); + if (rslt) + return 1; + } + + /* Not found anywhere, flag so caller can complain. */ + return 0; +} /* Generate code to reference the member named FIELD of a structure or union. The top of the stack, as described by VALUE, should have @@ -1326,7 +1501,7 @@ gen_struct_ref (struct expression *exp, struct agent_expr *ax, char *operator_name, char *operand_name) { struct type *type; - int i; + int found; /* Follow pointers until we reach a non-pointer. These aren't the C semantics, but they're what the normal GDB evaluator does, so we @@ -1349,24 +1524,172 @@ gen_struct_ref (struct expression *exp, struct agent_expr *ax, if (value->kind != axs_lvalue_memory) error (_("Structure does not live in memory.")); - i = find_field (type, field); + /* Search through fields and base classes recursively. */ + found = gen_struct_ref_recursive (exp, ax, value, field, 0, type); + + if (!found) + error (_("Couldn't find member named `%s' in struct/union/class `%s'"), + field, TYPE_TAG_NAME (type)); +} - /* Is this a bitfield? */ - if (TYPE_FIELD_PACKED (type, i)) - gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_BITPOS (type, i), - (TYPE_FIELD_BITPOS (type, i) - + TYPE_FIELD_BITSIZE (type, i))); - else +static int +gen_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name); +static int +gen_maybe_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name); + +static void +gen_static_field (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + struct type *type, int fieldno) +{ + if (TYPE_FIELD_LOC_KIND (type, fieldno) == FIELD_LOC_KIND_PHYSADDR) { - gen_offset (ax, TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT); + ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno)); value->kind = axs_lvalue_memory; - value->type = TYPE_FIELD_TYPE (type, i); + value->type = TYPE_FIELD_TYPE (type, fieldno); + value->optimized_out = 0; + } + else + { + const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); + struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0).symbol; + + if (sym) + { + gen_var_ref (gdbarch, ax, value, sym); + + /* Don't error if the value was optimized out, we may be + scanning all static fields and just want to pass over this + and continue with the rest. */ + } + else + { + /* Silently assume this was optimized out; class printing + will let the user know why the data is missing. */ + value->optimized_out = 1; + } + } +} + +static int +gen_struct_elt_for_reference (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + struct type *type, char *fieldname) +{ + struct type *t = type; + int i; + + if (TYPE_CODE (t) != TYPE_CODE_STRUCT + && TYPE_CODE (t) != TYPE_CODE_UNION) + internal_error (__FILE__, __LINE__, + _("non-aggregate type to gen_struct_elt_for_reference")); + + for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) + { + const char *t_field_name = TYPE_FIELD_NAME (t, i); + + if (t_field_name && strcmp (t_field_name, fieldname) == 0) + { + if (field_is_static (&TYPE_FIELD (t, i))) + { + gen_static_field (exp->gdbarch, ax, value, t, i); + if (value->optimized_out) + error (_("static field `%s' has been " + "optimized out, cannot use"), + fieldname); + return 1; + } + if (TYPE_FIELD_PACKED (t, i)) + error (_("pointers to bitfield members not allowed")); + + /* FIXME we need a way to do "want_address" equivalent */ + + error (_("Cannot reference non-static field \"%s\""), fieldname); + } } + + /* FIXME add other scoped-reference cases here */ + + /* Do a last-ditch lookup. */ + return gen_maybe_namespace_elt (exp, ax, value, type, fieldname); } +/* C++: Return the member NAME of the namespace given by the type + CURTYPE. */ + +static int +gen_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name) +{ + int found = gen_maybe_namespace_elt (exp, ax, value, curtype, name); -/* Generate code for GDB's magical `repeat' operator. + if (!found) + error (_("No symbol \"%s\" in namespace \"%s\"."), + name, TYPE_TAG_NAME (curtype)); + + return found; +} + +/* A helper function used by value_namespace_elt and + value_struct_elt_for_reference. It looks up NAME inside the + context CURTYPE; this works if CURTYPE is a namespace or if CURTYPE + is a class and NAME refers to a type in CURTYPE itself (as opposed + to, say, some base class of CURTYPE). */ + +static int +gen_maybe_namespace_elt (struct expression *exp, + struct agent_expr *ax, struct axs_value *value, + const struct type *curtype, char *name) +{ + const char *namespace_name = TYPE_TAG_NAME (curtype); + struct block_symbol sym; + + sym = cp_lookup_symbol_namespace (namespace_name, name, + block_for_pc (ax->scope), + VAR_DOMAIN); + + if (sym.symbol == NULL) + return 0; + + 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)); + + return 1; +} + + +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) +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + return gen_struct_elt_for_reference (exp, ax, value, type, field); + break; + case TYPE_CODE_NAMESPACE: + return gen_namespace_elt (exp, ax, value, type, field); + break; + default: + internal_error (__FILE__, __LINE__, + _("non-aggregate type in gen_aggregate_elt_ref")); + } + + return 0; +} + +/* Generate code for GDB's magical `repeat' operator. LVALUE @ INT creates an array INT elements long, and whose elements have the same type as LVALUE, located in memory so that LVALUE is its first element. For example, argv[0]@argc gives you the array @@ -1382,6 +1705,7 @@ gen_repeat (struct expression *exp, union exp_element **pc, struct agent_expr *ax, struct axs_value *value) { struct axs_value value1; + /* We don't want to turn this into an rvalue, so no conversions here. */ gen_expr (exp, pc, ax, &value1); @@ -1394,7 +1718,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); @@ -1430,6 +1755,7 @@ gen_sizeof (struct expression *exp, union exp_element **pc, So we generate code for the operand, and then throw it away, replacing it with code that simply pushes its size. */ int start = ax->len; + gen_expr (exp, pc, ax, value); /* Throw away the code we just generated. */ @@ -1446,7 +1772,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) { @@ -1454,6 +1780,7 @@ gen_expr (struct expression *exp, union exp_element **pc, struct axs_value value1, value2, value3; enum exp_opcode op = (*pc)[0].opcode, op2; int if1, go1, if2, go2, end; + struct type *int_type = builtin_type (exp->gdbarch)->builtin_int; /* If we're looking at a constant expression, just push its value. */ { @@ -1477,6 +1804,8 @@ gen_expr (struct expression *exp, union exp_element **pc, case BINOP_MUL: case BINOP_DIV: case BINOP_REM: + case BINOP_LSH: + case BINOP_RSH: case BINOP_SUBSCRIPT: case BINOP_BITWISE_AND: case BINOP_BITWISE_IOR: @@ -1513,7 +1842,7 @@ gen_expr (struct expression *exp, union exp_element **pc, ax_const_l (ax, 0); ax_label (ax, end, ax->len); value->kind = axs_rvalue; - value->type = language_bool_type (exp->language_defn, exp->gdbarch); + value->type = int_type; break; case BINOP_LOGICAL_OR: @@ -1532,7 +1861,7 @@ gen_expr (struct expression *exp, union exp_element **pc, ax_const_l (ax, 1); ax_label (ax, end, ax->len); value->kind = axs_rvalue; - value->type = language_bool_type (exp->language_defn, exp->gdbarch); + value->type = int_type; break; case TERNOP_COND: @@ -1543,8 +1872,7 @@ gen_expr (struct expression *exp, union exp_element **pc, bytecodes in order, but if_goto jumps on true, so we invert the sense of A. Then we can do B by dropping through, and jump to do C. */ - gen_logical_not (ax, &value1, - language_bool_type (exp->language_defn, exp->gdbarch)); + gen_logical_not (ax, &value1, int_type); if1 = ax_goto (ax, aop_if_goto); gen_expr (exp, pc, ax, &value2); gen_usual_unary (exp, ax, &value2); @@ -1564,17 +1892,19 @@ gen_expr (struct expression *exp, union exp_element **pc, { char *name = internalvar_name ((*pc)[1].internalvar); struct trace_state_variable *tsv; + (*pc) += 3; gen_expr (exp, pc, ax, value); tsv = find_trace_state_variable (name); 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")); @@ -1589,13 +1919,14 @@ gen_expr (struct expression *exp, union exp_element **pc, { char *name = internalvar_name ((*pc)[1].internalvar); struct trace_state_variable *tsv; + (*pc) += 3; tsv = find_trace_state_variable (name); if (tsv) { /* 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; @@ -1604,11 +1935,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")); @@ -1626,7 +1958,7 @@ gen_expr (struct expression *exp, union exp_element **pc, /* Don't just dispose of the left operand. We might be tracing, in which case we want to emit code to trace it if it's an lvalue. */ - gen_traced_pop (ax, &value1); + gen_traced_pop (exp->gdbarch, ax, &value1); gen_expr (exp, pc, ax, value); /* It's the consumer's responsibility to trace the right operand. */ break; @@ -1635,6 +1967,7 @@ gen_expr (struct expression *exp, union exp_element **pc, { struct type *type = (*pc)[1].type; LONGEST k = (*pc)[2].longconst; + (*pc) += 4; gen_int_literal (ax, value, k, type); } @@ -1642,6 +1975,11 @@ gen_expr (struct expression *exp, union exp_element **pc, case OP_VAR_VALUE: gen_var_ref (exp->gdbarch, ax, value, (*pc)[2].symbol); + + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME ((*pc)[2].symbol)); + (*pc) += 4; break; @@ -1649,14 +1987,17 @@ gen_expr (struct expression *exp, union exp_element **pc, { const char *name = &(*pc)[2].string; int reg; + (*pc) += 4 + BYTES_TO_EXP_ELEM ((*pc)[1].longconst + 1); reg = user_reg_map_name_to_regnum (exp->gdbarch, name, strlen (name)); if (reg == -1) internal_error (__FILE__, __LINE__, _("Register $%s not available"), name); - if (reg >= gdbarch_num_regs (exp->gdbarch)) - error (_("'%s' is a pseudo-register; " - "GDB cannot yet trace pseudoregister contents."), + /* No support for tracing user registers yet. */ + if (reg >= gdbarch_num_regs (exp->gdbarch) + + gdbarch_num_pseudo_regs (exp->gdbarch)) + error (_("'%s' is a user-register; " + "GDB cannot yet trace user-register contents."), name); value->kind = axs_lvalue_register; value->u.reg = reg; @@ -1666,21 +2007,24 @@ 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; tsv = find_trace_state_variable (name); 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; @@ -1694,25 +2038,68 @@ gen_expr (struct expression *exp, union exp_element **pc, case UNOP_CAST: { struct type *type = (*pc)[1].type; + (*pc) += 3; gen_expr (exp, pc, ax, value); gen_cast (ax, value, type); } 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; } @@ -1720,7 +2107,7 @@ gen_expr (struct expression *exp, union exp_element **pc, case UNOP_PLUS: (*pc)++; - /* + FOO is equivalent to 0 + FOO, which can be optimized. */ + /* + FOO is equivalent to 0 + FOO, which can be optimized. */ gen_expr (exp, pc, ax, value); gen_usual_unary (exp, ax, value); break; @@ -1741,8 +2128,7 @@ gen_expr (struct expression *exp, union exp_element **pc, (*pc)++; gen_expr (exp, pc, ax, value); gen_usual_unary (exp, ax, value); - gen_logical_not (ax, value, - language_bool_type (exp->language_defn, exp->gdbarch)); + gen_logical_not (ax, value, int_type); break; case UNOP_COMPLEMENT: @@ -1800,30 +2186,51 @@ 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, NULL, 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); + + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME (sym)); + (*pc) += 2; } break; + case OP_SCOPE: + { + struct type *type = (*pc)[1].type; + int length = longest_to_int ((*pc)[2].longconst); + char *name = &(*pc)[3].string; + int found; + + found = gen_aggregate_elt_ref (exp, ax, value, type, name, + "?", "??"); + if (!found) + error (_("There is no field named %s"), name); + (*pc) += 5 + BYTES_TO_EXP_ELEM (length + 1); + } + break; + case OP_TYPE: + case OP_TYPEOF: + case OP_DECLTYPE: error (_("Attempt to use a type name as an expression.")); default: - error (_("Unsupported operator in expression.")); + error (_("Unsupported operator %s (%d) in expression."), + op_name (exp, op), op); } } @@ -1837,6 +2244,8 @@ gen_expr_binop_rest (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct axs_value *value1, struct axs_value *value2) { + struct type *int_type = builtin_type (exp->gdbarch)->builtin_int; + gen_expr (exp, pc, ax, value2); gen_usual_unary (exp, ax, value2); gen_usual_arithmetic (exp, ax, value1, value2); @@ -1882,12 +2291,48 @@ gen_expr_binop_rest (struct expression *exp, gen_binop (ax, value, value1, value2, aop_rem_signed, aop_rem_unsigned, 1, "remainder"); break; - case BINOP_SUBSCRIPT: - gen_ptradd (ax, value, value1, value2); - if (!pointer_type (value->type)) - error (_("Invalid combination of types in array subscripting.")); - gen_deref (ax, value); + case BINOP_LSH: + gen_binop (ax, value, value1, value2, + aop_lsh, aop_lsh, 1, "left shift"); + break; + case BINOP_RSH: + gen_binop (ax, value, value1, value2, + aop_rsh_signed, aop_rsh_unsigned, 1, "right shift"); break; + case BINOP_SUBSCRIPT: + { + struct type *type; + + if (binop_types_user_defined_p (op, value1->type, value2->type)) + { + error (_("cannot subscript requested type: " + "cannot call user defined functions")); + } + else + { + /* If the user attempts to subscript something that is not + an array or pointer type (like a plain int variable for + example), then report this as an error. */ + type = check_typedef (value1->type); + if (TYPE_CODE (type) != TYPE_CODE_ARRAY + && TYPE_CODE (type) != TYPE_CODE_PTR) + { + if (TYPE_NAME (type)) + error (_("cannot subscript something of type `%s'"), + TYPE_NAME (type)); + else + error (_("cannot subscript requested type")); + } + } + + if (!is_integral_type (value2->type)) + error (_("Argument to arithmetic operation " + "not a number or boolean.")); + + gen_ptradd (ax, value, value1, value2); + gen_deref (ax, value); + break; + } case BINOP_BITWISE_AND: gen_binop (ax, value, value1, value2, aop_bit_and, aop_bit_and, 0, "bitwise and"); @@ -1904,44 +2349,32 @@ gen_expr_binop_rest (struct expression *exp, break; case BINOP_EQUAL: - gen_binop (ax, value, value1, value2, - aop_equal, aop_equal, 0, "equal"); + gen_equal (ax, value, value1, value2, int_type); break; case BINOP_NOTEQUAL: - gen_binop (ax, value, value1, value2, - aop_equal, aop_equal, 0, "equal"); - gen_logical_not (ax, value, - language_bool_type (exp->language_defn, - exp->gdbarch)); + gen_equal (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); break; case BINOP_LESS: - gen_binop (ax, value, value1, value2, - aop_less_signed, aop_less_unsigned, 0, "less than"); + gen_less (ax, value, value1, value2, int_type); break; case BINOP_GTR: ax_simple (ax, aop_swap); - gen_binop (ax, value, value1, value2, - aop_less_signed, aop_less_unsigned, 0, "less than"); + gen_less (ax, value, value1, value2, int_type); break; case BINOP_LEQ: ax_simple (ax, aop_swap); - gen_binop (ax, value, value1, value2, - aop_less_signed, aop_less_unsigned, 0, "less than"); - gen_logical_not (ax, value, - language_bool_type (exp->language_defn, - exp->gdbarch)); + gen_less (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); break; case BINOP_GEQ: - gen_binop (ax, value, value1, value2, - aop_less_signed, aop_less_unsigned, 0, "less than"); - gen_logical_not (ax, value, - language_bool_type (exp->language_defn, - exp->gdbarch)); + gen_less (ax, value, value1, value2, int_type); + gen_logical_not (ax, value, int_type); break; default: @@ -1959,19 +2392,29 @@ gen_expr_binop_rest (struct expression *exp, name comes from a list of local variables of a function. */ struct agent_expr * -gen_trace_for_var (CORE_ADDR scope, struct symbol *var) +gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, + struct symbol *var, int trace_string) { 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); - trace_kludge = 1; - gen_var_ref (NULL, ax, &value, var); + 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 + an empty agent expression. */ + if (value.optimized_out) + { + do_cleanups (old_chain); + return NULL; + } /* Make sure we record the final object, and get rid of it. */ - gen_traced_pop (ax, &value); + gen_traced_pop (gdbarch, ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); @@ -1991,21 +2434,24 @@ gen_trace_for_var (CORE_ADDR scope, struct symbol *var) 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 (scope); + struct agent_expr *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); /* Make sure we record the final object, and get rid of it. */ - gen_traced_pop (ax, &value); + gen_traced_pop (expr->gdbarch, ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); @@ -2028,16 +2474,19 @@ 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; 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); + require_rvalue (ax, &value); + /* Oh, and terminate. */ ax_simple (ax, aop_end); @@ -2048,14 +2497,135 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) return ax; } +struct agent_expr * +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); + struct axs_value value; + + old_chain = make_cleanup_free_agent_expr (ax); + + ax->tracing = 1; + ax->trace_string = trace_string; + + gdbarch_gen_return_address (gdbarch, ax, &value, scope); + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (gdbarch, ax, &value); + + /* Oh, and terminate. */ + ax_simple (ax, 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; +} + +/* Given a collection of printf-style arguments, generate code to + evaluate the arguments and pass everything to a special + bytecode. */ + +struct agent_expr * +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) +{ + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (gdbarch, scope); + union exp_element *pc; + struct axs_value value; + int tem; + + 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; + value.optimized_out = 0; + gen_expr (exprs[tem], &pc, ax, &value); + require_rvalue (ax, &value); + } + + /* Push function and channel. */ + ax_const_l (ax, channel); + ax_const_l (ax, function); + + /* Issue the printf bytecode proper. */ + ax_simple (ax, aop_printf); + ax_raw_byte (ax, nargs); + ax_string (ax, format, fmtlen); + + /* And terminate. */ + ax_simple (ax, 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); + } + + arg = exp; + if (!eval && strcmp (arg, "$_ret") == 0) + { + agent = gen_trace_for_return_address (pc, get_current_arch (), + trace_string); + old_chain = make_cleanup_free_agent_expr (agent); + } + else + { + expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0); + old_chain = make_cleanup (free_current_contents, &expr); + if (eval) + { + gdb_assert (trace_string == 0); + agent = gen_eval_for_expr (pc, expr); + } + else + agent = gen_trace_for_expr (pc, expr, trace_string); + 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 + about the expression, and then print out the result. */ + + do_cleanups (old_chain); + 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 @@ -2066,30 +2636,74 @@ 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_print (gdb_stdout, agent); - - /* It would be nice to call ax_reqs here to gather some general info - about the expression, and then print out the result. */ + if (check_for_argument (&exp, "-at", sizeof ("-at") - 1)) + { + struct linespec_result canonical; + int ix; + struct linespec_sals *iter; + struct cleanup *old_chain; + struct event_location *location; + + exp = skip_spaces (exp); + init_linespec_result (&canonical); + location = new_linespec_location (&exp); + old_chain = make_cleanup_delete_event_location (location); + decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL, + (struct symtab *) NULL, 0, &canonical, + NULL, NULL); + make_cleanup_destroy_linespec_result (&canonical); + 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; + + for (i = 0; i < iter->sals.nelts; i++) + agent_eval_command_one (exp, eval, iter->sals.sals[i].pc); + } + do_cleanups (old_chain); + } + 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 expression *argvec[100]; struct agent_expr *agent; 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 @@ -2101,10 +2715,54 @@ 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); + 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; + expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1); + argvec[nargs] = expr; + ++nargs; + cmdrest = cmd1; + if (*cmdrest == ',') + ++cmdrest; + /* else complain? */ + } + + + agent = gen_printf (get_frame_pc (fi), get_current_arch (), 0, 0, + format_start, format_end - format_start, + fpieces, nargs, argvec); 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 @@ -2122,10 +2780,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); }