Index: ax-gdb.c =================================================================== RCS file: /cvs/src/src/gdb/ax-gdb.c,v retrieving revision 1.68 diff -p -r1.68 ax-gdb.c *** ax-gdb.c 16 Mar 2010 00:52:54 -0000 1.68 --- ax-gdb.c 17 Mar 2010 22:02:00 -0000 *************** static struct value *const_var_ref (stru *** 70,76 **** 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_sign_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *); --- 70,76 ---- 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_sign_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *); *************** static void gen_struct_ref (struct expre *** 144,150 **** struct axs_value *value, char *field, char *operator_name, char *operand_name); ! static void gen_static_field (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct type *type, int fieldno); static void gen_repeat (struct expression *exp, union exp_element **pc, --- 144,150 ---- 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, *************** maybe_const_expr (union exp_element **pc *** 331,341 **** emits the trace bytecodes at the appropriate points. */ static int trace_kludge; /* 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) { if (trace_kludge) switch (value->kind) --- 331,394 ---- emits the trace bytecodes at the appropriate points. */ static int trace_kludge; + /* Scan for all static fields in the given class, including any base + classes, and generate tracing bytecodes for each. */ + + 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; + + CHECK_TYPEDEF (type); + + 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: + { + int length = TYPE_LENGTH (check_typedef (value.type)); + + ax_const_l (ax, length); + 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); + + default: + break; + } + } + } + + /* Now scan through base classes recursively. */ + for (i = 0; i < nbases; i++) + { + struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); + + 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 gdbarch *gdbarch, ! struct agent_expr *ax, struct axs_value *value) { if (trace_kludge) switch (value->kind) *************** gen_traced_pop (struct agent_expr *ax, s *** 371,376 **** --- 424,435 ---- 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 (trace_kludge + && (TYPE_CODE (value->type) == TYPE_CODE_STRUCT + || TYPE_CODE (value->type) == TYPE_CODE_UNION)) + gen_trace_static_fields (gdbarch, ax, value->type); } *************** gen_var_ref (struct gdbarch *gdbarch, st *** 554,559 **** --- 613,619 ---- { /* Dereference any typedefs. */ value->type = check_typedef (SYMBOL_TYPE (var)); + value->optimized_out = 0; /* I'm imitating the code in read_var_value. */ switch (SYMBOL_CLASS (var)) *************** gen_var_ref (struct gdbarch *gdbarch, st *** 650,657 **** break; case LOC_OPTIMIZED_OUT: ! error (_("The variable `%s' has been optimized out."), ! SYMBOL_PRINT_NAME (var)); break; default: --- 710,718 ---- break; case LOC_OPTIMIZED_OUT: ! /* Flag this, but don't say anything; leave it up to callers to ! warn the user. */ ! value->optimized_out = 1; break; default: *************** gen_struct_ref_recursive (struct express *** 1342,1348 **** being handled as a global. */ if (field_is_static (&TYPE_FIELD (type, i))) { ! gen_static_field (exp, ax, value, type, i); return 1; } --- 1403,1412 ---- 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_maybe_namespace_elt (struct expressi *** 1425,1431 **** const struct type *curtype, char *name); static void ! gen_static_field (struct expression *exp, struct agent_expr *ax, struct axs_value *value, struct type *type, int fieldno) { --- 1489,1495 ---- 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) { *************** gen_static_field (struct expression *exp *** 1434,1448 **** ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno)); value->kind = axs_lvalue_memory; value->type = TYPE_FIELD_TYPE (type, fieldno); } else { char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); - if (sym == NULL) - error (_("symbol not found")); ! gen_var_ref (exp->gdbarch, ax, value, sym); } } --- 1498,1524 ---- ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno)); value->kind = axs_lvalue_memory; value->type = TYPE_FIELD_TYPE (type, fieldno); + value->optimized_out = 0; } else { char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); ! 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; ! } } } *************** gen_struct_elt_for_reference (struct exp *** 1468,1474 **** { if (field_is_static (&TYPE_FIELD (t, i))) { ! gen_static_field (exp, ax, value, t, i); return 1; } if (TYPE_FIELD_PACKED (t, i)) --- 1544,1553 ---- { 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)) *************** gen_maybe_namespace_elt (struct expressi *** 1526,1531 **** --- 1605,1614 ---- gen_var_ref (exp->gdbarch, ax, value, sym); + if (value->optimized_out) + error (_("`%s' has been optimized out, cannot use"), + SYMBOL_PRINT_NAME (sym)); + return 1; } *************** gen_expr (struct expression *exp, union *** 1815,1821 **** /* 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_expr (exp, pc, ax, value); /* It's the consumer's responsibility to trace the right operand. */ break; --- 1898,1904 ---- /* 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 (exp->gdbarch, ax, &value1); gen_expr (exp, pc, ax, value); /* It's the consumer's responsibility to trace the right operand. */ break; *************** gen_expr (struct expression *exp, union *** 1831,1836 **** --- 1914,1924 ---- 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; *************** gen_expr (struct expression *exp, union *** 2004,2009 **** --- 2092,2102 ---- error (_("no `%s' found"), this_name); 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; *************** cannot subscript requested type: cannot *** 2199,2205 **** name comes from a list of local variables of a function. */ struct agent_expr * ! gen_trace_for_var (CORE_ADDR scope, struct symbol *var) { struct cleanup *old_chain = 0; struct agent_expr *ax = new_agent_expr (scope); --- 2292,2299 ---- name comes from a list of local variables of a function. */ struct agent_expr * ! gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, ! struct symbol *var) { struct cleanup *old_chain = 0; struct agent_expr *ax = new_agent_expr (scope); *************** gen_trace_for_var (CORE_ADDR scope, stru *** 2208,2217 **** old_chain = make_cleanup_free_agent_expr (ax); trace_kludge = 1; ! gen_var_ref (NULL, ax, &value, var); /* Make sure we record the final object, and get rid of it. */ ! gen_traced_pop (ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); --- 2302,2319 ---- old_chain = make_cleanup_free_agent_expr (ax); trace_kludge = 1; ! 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 (gdbarch, ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); *************** gen_trace_for_expr (CORE_ADDR scope, str *** 2245,2251 **** gen_expr (expr, &pc, ax, &value); /* Make sure we record the final object, and get rid of it. */ ! gen_traced_pop (ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); --- 2347,2353 ---- gen_expr (expr, &pc, ax, &value); /* Make sure we record the final object, and get rid of it. */ ! gen_traced_pop (expr->gdbarch, ax, &value); /* Oh, and terminate. */ ax_simple (ax, aop_end); Index: ax-gdb.h =================================================================== RCS file: /cvs/src/src/gdb/ax-gdb.h,v retrieving revision 1.14 diff -p -r1.14 ax-gdb.h *** ax-gdb.h 1 Jan 2010 07:31:30 -0000 1.14 --- ax-gdb.h 17 Mar 2010 22:02:00 -0000 *************** struct axs_value *** 81,86 **** --- 81,90 ---- "pointer to" an object of this type. */ struct type *type; + /* If nonzero, this is a variable which does not actually exist in + the program. */ + char optimized_out; + union { /* if kind == axs_lvalue_register, this is the register number */ *************** struct axs_value *** 99,105 **** 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_var (CORE_ADDR, struct symbol *); extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *); --- 103,110 ---- 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_var (CORE_ADDR, struct gdbarch *, ! struct symbol *); extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *); Index: dwarf2loc.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2loc.c,v retrieving revision 1.73 diff -p -r1.73 dwarf2loc.c *** dwarf2loc.c 26 Feb 2010 12:48:18 -0000 1.73 --- dwarf2loc.c 17 Mar 2010 22:02:00 -0000 *************** dwarf2_tracepoint_var_ref (struct symbol *** 619,629 **** struct agent_expr *ax, struct axs_value *value, gdb_byte *data, int size) { ! if (size == 0) ! error (_("Symbol \"%s\" has been optimized out."), ! SYMBOL_PRINT_NAME (symbol)); ! ! if (size == 1 && data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31) { --- 619,629 ---- struct agent_expr *ax, struct axs_value *value, gdb_byte *data, int size) { ! if (!data || size == 0) ! { ! value->optimized_out = 1; ! } ! else if (size == 1 && data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31) { *************** loclist_tracepoint_var_ref (struct symbo *** 883,890 **** size_t size; data = find_location_expression (dlbaton, &size, ax->scope); - if (data == NULL) - error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol)); dwarf2_tracepoint_var_ref (symbol, gdbarch, ax, value, data, size); } --- 883,888 ---- Index: tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/tracepoint.c,v retrieving revision 1.146 diff -p -r1.146 tracepoint.c *** tracepoint.c 12 Mar 2010 03:54:45 -0000 1.146 --- tracepoint.c 17 Mar 2010 22:02:00 -0000 *************** collect_symbol (struct collection_list * *** 949,954 **** --- 949,955 ---- unsigned long len; unsigned int reg; bfd_signed_vma offset; + int treat_as_expr = 0; len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))); switch (SYMBOL_CLASS (sym)) *************** collect_symbol (struct collection_list * *** 973,979 **** SYMBOL_PRINT_NAME (sym), len, tmp /* address */); } ! add_memrange (collect, memrange_absolute, offset, len); break; case LOC_REGISTER: reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); --- 974,985 ---- SYMBOL_PRINT_NAME (sym), len, tmp /* address */); } ! /* A struct may be a C++ class with static fields, go to general ! expression handling. */ ! if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT) ! treat_as_expr = 1; ! else ! add_memrange (collect, memrange_absolute, offset, len); break; case LOC_REGISTER: reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); *************** collect_symbol (struct collection_list * *** 1038,1086 **** break; case LOC_COMPUTED: ! { ! struct agent_expr *aexpr; ! struct cleanup *old_chain1 = NULL; ! struct agent_reqs areqs; ! ! aexpr = gen_trace_for_var (scope, sym); ! ! old_chain1 = make_cleanup_free_agent_expr (aexpr); ! ! ax_reqs (aexpr, &areqs); ! if (areqs.flaw != agent_flaw_none) ! error (_("malformed expression")); ! ! if (areqs.min_height < 0) ! error (_("gdb: Internal error: expression has min height < 0")); ! if (areqs.max_height > 20) ! error (_("expression too complicated, try simplifying")); ! ! discard_cleanups (old_chain1); ! add_aexpr (collect, aexpr); ! ! /* take care of the registers */ ! if (areqs.reg_mask_len > 0) ! { ! int ndx1, ndx2; ! ! for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++) ! { ! QUIT; /* allow user to bail out with ^C */ ! if (areqs.reg_mask[ndx1] != 0) ! { ! /* assume chars have 8 bits */ ! for (ndx2 = 0; ndx2 < 8; ndx2++) ! if (areqs.reg_mask[ndx1] & (1 << ndx2)) ! /* it's used -- record it */ ! add_register (collect, ! ndx1 * 8 + ndx2); ! } ! } ! } ! } break; } } /* Add all locals (or args) symbols to collection list */ --- 1044,1105 ---- break; case LOC_COMPUTED: ! treat_as_expr = 1; break; } + + /* Expressions are the most general case. */ + if (treat_as_expr) + { + struct agent_expr *aexpr; + struct cleanup *old_chain1 = NULL; + struct agent_reqs areqs; + + aexpr = gen_trace_for_var (scope, gdbarch, sym); + + /* It can happen that the symbol is recorded as a computed + location, but it's been optimized away and doesn't actually + have a location expression. */ + if (!aexpr) + { + printf_filtered ("%s has been optimized out of existence.\n", + SYMBOL_PRINT_NAME (sym)); + return; + } + + old_chain1 = make_cleanup_free_agent_expr (aexpr); + + ax_reqs (aexpr, &areqs); + if (areqs.flaw != agent_flaw_none) + error (_("malformed expression")); + + if (areqs.min_height < 0) + error (_("gdb: Internal error: expression has min height < 0")); + if (areqs.max_height > 20) + error (_("expression too complicated, try simplifying")); + + discard_cleanups (old_chain1); + add_aexpr (collect, aexpr); + + /* take care of the registers */ + if (areqs.reg_mask_len > 0) + { + int ndx1, ndx2; + + for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++) + { + QUIT; /* allow user to bail out with ^C */ + if (areqs.reg_mask[ndx1] != 0) + { + /* assume chars have 8 bits */ + for (ndx2 = 0; ndx2 < 8; ndx2++) + if (areqs.reg_mask[ndx1] & (1 << ndx2)) + /* it's used -- record it */ + add_register (collect, ndx1 * 8 + ndx2); + } + } + } + } } /* Add all locals (or args) symbols to collection list */