2010-03-17 Stan Shebs <stan@codesourcery.com>

* ax-gdb.h (struct axs_value): New field optimized_out.
	(gen_trace_for_var): Add gdbarch argument.
	* ax-gdb.c (gen_trace_static_fields): New function.
	(gen_traced_pop): Call it, add gdbarch argument.
	(gen_trace_for_expr): Update call to it.
	(gen_trace_for_var): Ditto, and report optimized-out variables.
	(gen_struct_ref_recursive): Check for optimized-out value.
	(gen_struct_elt_for_reference): Ditto.
	(gen_static_field): Pass gdbarch instead of expression, assume
	optimization if field not found.
	(gen_var_ref): Set the optimized_out flag.
	(gen_expr): Error on optimized-out variable.
	* tracepoint.c (collect_symbol): Handle struct-valued vars as
	expressions, skip optimized-out variables with computed locations.
	* dwarf2loc.c (dwarf2_tracepoint_var_ref): Flag instead of
	erroring out if location expression missing.
	(loclist_tracepoint_var_ref): Don't error out here.
This commit is contained in:
Stan Shebs 2010-03-17 22:04:43 +00:00
parent a3b2a86bb7
commit 400c6af037
5 changed files with 210 additions and 66 deletions

View File

@ -1,3 +1,23 @@
2010-03-17 Stan Shebs <stan@codesourcery.com>
* ax-gdb.h (struct axs_value): New field optimized_out.
(gen_trace_for_var): Add gdbarch argument.
* ax-gdb.c (gen_trace_static_fields): New function.
(gen_traced_pop): Call it, add gdbarch argument.
(gen_trace_for_expr): Update call to it.
(gen_trace_for_var): Ditto, and report optimized-out variables.
(gen_struct_ref_recursive): Check for optimized-out value.
(gen_struct_elt_for_reference): Ditto.
(gen_static_field): Pass gdbarch instead of expression, assume
optimization if field not found.
(gen_var_ref): Set the optimized_out flag.
(gen_expr): Error on optimized-out variable.
* tracepoint.c (collect_symbol): Handle struct-valued vars as
expressions, skip optimized-out variables with computed locations.
* dwarf2loc.c (dwarf2_tracepoint_var_ref): Flag instead of
erroring out if location expression missing.
(loclist_tracepoint_var_ref): Don't error out here.
2010-03-17 Tom Tromey <tromey@redhat.com> 2010-03-17 Tom Tromey <tromey@redhat.com>
* dwarf2read.c (dwarf2_get_section_info): Handle case where no * dwarf2read.c (dwarf2_get_section_info): Handle case where no

View File

@ -70,7 +70,7 @@ static struct value *const_var_ref (struct symbol *var);
static struct value *const_expr (union exp_element **pc); static struct value *const_expr (union exp_element **pc);
static struct value *maybe_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_sign_extend (struct agent_expr *, struct type *);
static void gen_extend (struct agent_expr *, struct type *); static void gen_extend (struct agent_expr *, struct type *);
@ -144,7 +144,7 @@ static void gen_struct_ref (struct expression *exp, struct agent_expr *ax,
struct axs_value *value, struct axs_value *value,
char *field, char *field,
char *operator_name, char *operand_name); char *operator_name, char *operand_name);
static void gen_static_field (struct expression *exp, static void gen_static_field (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value, struct agent_expr *ax, struct axs_value *value,
struct type *type, int fieldno); struct type *type, int fieldno);
static void gen_repeat (struct expression *exp, union exp_element **pc, static void gen_repeat (struct expression *exp, union exp_element **pc,
@ -331,11 +331,64 @@ maybe_const_expr (union exp_element **pc)
emits the trace bytecodes at the appropriate points. */ emits the trace bytecodes at the appropriate points. */
static int trace_kludge; 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 /* 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 the value. Useful on the left side of a comma, and at the end of
an expression being used for tracing. */ an expression being used for tracing. */
static void 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) if (trace_kludge)
switch (value->kind) switch (value->kind)
@ -371,6 +424,12 @@ gen_traced_pop (struct agent_expr *ax, struct axs_value *value)
else else
/* If we're not tracing, just pop the value. */ /* If we're not tracing, just pop the value. */
ax_simple (ax, aop_pop); 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);
} }
@ -554,6 +613,7 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax,
{ {
/* Dereference any typedefs. */ /* Dereference any typedefs. */
value->type = check_typedef (SYMBOL_TYPE (var)); value->type = check_typedef (SYMBOL_TYPE (var));
value->optimized_out = 0;
/* I'm imitating the code in read_var_value. */ /* I'm imitating the code in read_var_value. */
switch (SYMBOL_CLASS (var)) switch (SYMBOL_CLASS (var))
@ -650,8 +710,9 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax,
break; break;
case LOC_OPTIMIZED_OUT: case LOC_OPTIMIZED_OUT:
error (_("The variable `%s' has been optimized out."), /* Flag this, but don't say anything; leave it up to callers to
SYMBOL_PRINT_NAME (var)); warn the user. */
value->optimized_out = 1;
break; break;
default: default:
@ -1342,7 +1403,10 @@ gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax,
being handled as a global. */ being handled as a global. */
if (field_is_static (&TYPE_FIELD (type, i))) if (field_is_static (&TYPE_FIELD (type, i)))
{ {
gen_static_field (exp, ax, value, 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; return 1;
} }
@ -1425,7 +1489,7 @@ gen_maybe_namespace_elt (struct expression *exp,
const struct type *curtype, char *name); const struct type *curtype, char *name);
static void static void
gen_static_field (struct expression *exp, gen_static_field (struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value, struct agent_expr *ax, struct axs_value *value,
struct type *type, int fieldno) struct type *type, int fieldno)
{ {
@ -1434,15 +1498,27 @@ gen_static_field (struct expression *exp,
ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno)); ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno));
value->kind = axs_lvalue_memory; value->kind = axs_lvalue_memory;
value->type = TYPE_FIELD_TYPE (type, fieldno); value->type = TYPE_FIELD_TYPE (type, fieldno);
value->optimized_out = 0;
} }
else else
{ {
char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); 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); 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;
}
} }
} }
@ -1468,7 +1544,10 @@ gen_struct_elt_for_reference (struct expression *exp,
{ {
if (field_is_static (&TYPE_FIELD (t, i))) if (field_is_static (&TYPE_FIELD (t, i)))
{ {
gen_static_field (exp, ax, value, 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; return 1;
} }
if (TYPE_FIELD_PACKED (t, i)) if (TYPE_FIELD_PACKED (t, i))
@ -1526,6 +1605,10 @@ gen_maybe_namespace_elt (struct expression *exp,
gen_var_ref (exp->gdbarch, ax, value, sym); 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; return 1;
} }
@ -1815,7 +1898,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
/* Don't just dispose of the left operand. We might be tracing, /* 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 in which case we want to emit code to trace it if it's an
lvalue. */ lvalue. */
gen_traced_pop (ax, &value1); gen_traced_pop (exp->gdbarch, ax, &value1);
gen_expr (exp, pc, ax, value); gen_expr (exp, pc, ax, value);
/* It's the consumer's responsibility to trace the right operand. */ /* It's the consumer's responsibility to trace the right operand. */
break; break;
@ -1831,6 +1914,11 @@ gen_expr (struct expression *exp, union exp_element **pc,
case OP_VAR_VALUE: case OP_VAR_VALUE:
gen_var_ref (exp->gdbarch, ax, value, (*pc)[2].symbol); 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; (*pc) += 4;
break; break;
@ -2004,6 +2092,11 @@ gen_expr (struct expression *exp, union exp_element **pc,
error (_("no `%s' found"), this_name); error (_("no `%s' found"), this_name);
gen_var_ref (exp->gdbarch, ax, value, sym); 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; (*pc) += 2;
} }
break; break;
@ -2199,7 +2292,8 @@ cannot subscript requested type: cannot call user defined functions"));
name comes from a list of local variables of a function. */ name comes from a list of local variables of a function. */
struct agent_expr * 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)
{ {
struct cleanup *old_chain = 0; struct cleanup *old_chain = 0;
struct agent_expr *ax = new_agent_expr (scope); struct agent_expr *ax = new_agent_expr (scope);
@ -2208,10 +2302,18 @@ gen_trace_for_var (CORE_ADDR scope, struct symbol *var)
old_chain = make_cleanup_free_agent_expr (ax); old_chain = make_cleanup_free_agent_expr (ax);
trace_kludge = 1; trace_kludge = 1;
gen_var_ref (NULL, ax, &value, var); 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. */ /* 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. */ /* Oh, and terminate. */
ax_simple (ax, aop_end); ax_simple (ax, aop_end);
@ -2245,7 +2347,7 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
gen_expr (expr, &pc, ax, &value); gen_expr (expr, &pc, ax, &value);
/* Make sure we record the final object, and get rid of it. */ /* 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. */ /* Oh, and terminate. */
ax_simple (ax, aop_end); ax_simple (ax, aop_end);

View File

@ -81,6 +81,10 @@ struct axs_value
"pointer to" an object of this type. */ "pointer to" an object of this type. */
struct type *type; struct type *type;
/* If nonzero, this is a variable which does not actually exist in
the program. */
char optimized_out;
union union
{ {
/* if kind == axs_lvalue_register, this is the register number */ /* if kind == axs_lvalue_register, this is the register number */
@ -99,7 +103,8 @@ struct axs_value
function to discover which registers the expression uses. */ function to discover which registers the expression uses. */
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *); extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct symbol *); 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 *); extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);

View File

@ -619,11 +619,11 @@ dwarf2_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
struct agent_expr *ax, struct axs_value *value, struct agent_expr *ax, struct axs_value *value,
gdb_byte *data, int size) gdb_byte *data, int size)
{ {
if (size == 0) if (!data || size == 0)
error (_("Symbol \"%s\" has been optimized out."), {
SYMBOL_PRINT_NAME (symbol)); value->optimized_out = 1;
}
if (size == 1 else if (size == 1
&& data[0] >= DW_OP_reg0 && data[0] >= DW_OP_reg0
&& data[0] <= DW_OP_reg31) && data[0] <= DW_OP_reg31)
{ {
@ -883,8 +883,6 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
size_t size; size_t size;
data = find_location_expression (dlbaton, &size, ax->scope); 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); dwarf2_tracepoint_var_ref (symbol, gdbarch, ax, value, data, size);
} }

View File

@ -949,6 +949,7 @@ collect_symbol (struct collection_list *collect,
unsigned long len; unsigned long len;
unsigned int reg; unsigned int reg;
bfd_signed_vma offset; bfd_signed_vma offset;
int treat_as_expr = 0;
len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))); len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
switch (SYMBOL_CLASS (sym)) switch (SYMBOL_CLASS (sym))
@ -973,7 +974,12 @@ collect_symbol (struct collection_list *collect,
SYMBOL_PRINT_NAME (sym), len, SYMBOL_PRINT_NAME (sym), len,
tmp /* address */); tmp /* address */);
} }
add_memrange (collect, memrange_absolute, offset, len); /* 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; break;
case LOC_REGISTER: case LOC_REGISTER:
reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch); reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
@ -1038,49 +1044,62 @@ collect_symbol (struct collection_list *collect,
break; break;
case LOC_COMPUTED: case LOC_COMPUTED:
{ treat_as_expr = 1;
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; 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 */ /* Add all locals (or args) symbols to collection list */