Index: gdb/ax-gdb.c |
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c |
index 845153da8c9272385ee9b4a546b858ad30860d54..4f68128cd854a5285724e6638de9217aa5848584 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-2001, 2003, 2007-2012 Free Software Foundation, |
- Inc. |
+ Copyright (C) 1998-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -31,7 +30,7 @@ |
#include "target.h" |
#include "ax.h" |
#include "ax-gdb.h" |
-#include "gdb_string.h" |
+#include <string.h> |
#include "block.h" |
#include "regcache.h" |
#include "user-regs.h" |
@@ -313,36 +312,6 @@ maybe_const_expr (union exp_element **pc) |
sizes), and this is simpler.) */ |
-/* Generating bytecode from GDB expressions: the `trace' kludge */ |
- |
-/* The compiler in this file is a general-purpose mechanism for |
- translating GDB expressions into bytecode. One ought to be able to |
- find a million and one uses for it. |
- |
- However, at the moment it is HOPELESSLY BRAIN-DAMAGED for the sake |
- of expediency. Let he who is without sin cast the first stone. |
- |
- For the data tracing facility, we need to insert `trace' bytecodes |
- before each data fetch; this records all the memory that the |
- expression touches in the course of evaluation, so that memory will |
- be available when the user later tries to evaluate the expression |
- in GDB. |
- |
- This should be done (I think) in a post-processing pass, that walks |
- an arbitrary agent expression and inserts `trace' operations at the |
- appropriate points. But it's much faster to just hack them |
- directly into the code. And since we're in a crunch, that's what |
- I've done. |
- |
- Setting the flag trace_kludge to non-zero enables the code that |
- emits the trace bytecodes at the appropriate points. */ |
-int trace_kludge; |
- |
-/* Inspired by trace_kludge, this indicates that pointers to chars |
- should get an added tracenz bytecode to record nonzero bytes, up to |
- a length that is the value of trace_string_kludge. */ |
-int trace_string_kludge; |
- |
/* Scan for all static fields in the given class, including any base |
classes, and generate tracing bytecodes for each. */ |
@@ -367,9 +336,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; |
@@ -402,19 +371,19 @@ gen_traced_pop (struct gdbarch *gdbarch, |
struct agent_expr *ax, struct axs_value *value) |
{ |
int string_trace = 0; |
- if (trace_string_kludge |
+ if (ax->trace_string |
&& TYPE_CODE (value->type) == TYPE_CODE_PTR |
&& c_textual_element_type (check_typedef (TYPE_TARGET_TYPE (value->type)), |
's')) |
string_trace = 1; |
- if (trace_kludge) |
+ if (ax->tracing) |
switch (value->kind) |
{ |
case axs_rvalue: |
if (string_trace) |
{ |
- ax_const_l (ax, trace_string_kludge); |
+ ax_const_l (ax, ax->trace_string); |
ax_simple (ax, aop_tracenz); |
} |
else |
@@ -425,23 +394,24 @@ gen_traced_pop (struct gdbarch *gdbarch, |
case axs_lvalue_memory: |
{ |
- int length = TYPE_LENGTH (check_typedef (value->type)); |
- |
if (string_trace) |
ax_simple (ax, aop_dup); |
+ /* Initialize the TYPE_LENGTH if it is a typedef. */ |
+ 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_const_l (ax, TYPE_LENGTH (value->type)); |
ax_simple (ax, aop_trace); |
if (string_trace) |
{ |
ax_simple (ax, aop_ref32); |
- ax_const_l (ax, trace_string_kludge); |
+ ax_const_l (ax, ax->trace_string); |
ax_simple (ax, aop_tracenz); |
} |
} |
@@ -459,7 +429,7 @@ gen_traced_pop (struct gdbarch *gdbarch, |
if (string_trace) |
{ |
ax_reg (ax, value->u.reg); |
- ax_const_l (ax, trace_string_kludge); |
+ ax_const_l (ax, ax->trace_string); |
ax_simple (ax, aop_tracenz); |
} |
break; |
@@ -469,7 +439,7 @@ gen_traced_pop (struct gdbarch *gdbarch, |
ax_simple (ax, aop_pop); |
/* To trace C++ classes with static fields stored elsewhere. */ |
- if (trace_kludge |
+ if (ax->tracing |
&& (TYPE_CODE (value->type) == TYPE_CODE_STRUCT |
|| TYPE_CODE (value->type) == TYPE_CODE_UNION)) |
gen_trace_static_fields (gdbarch, ax, value->type); |
@@ -509,7 +479,7 @@ gen_extend (struct agent_expr *ax, struct type *type) |
static void |
gen_fetch (struct agent_expr *ax, struct type *type) |
{ |
- if (trace_kludge) |
+ if (ax->tracing) |
{ |
/* Record the area of memory we're about to fetch. */ |
ax_trace_quick (ax, TYPE_LENGTH (type)); |
@@ -662,6 +632,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)) |
{ |
@@ -750,13 +726,7 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax, |
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 |
@@ -1361,7 +1331,7 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax, |
/* Add the offset. */ |
gen_offset (ax, offset / TARGET_CHAR_BIT); |
- if (trace_kludge) |
+ if (ax->tracing) |
{ |
/* Record the area of memory we're about to fetch. */ |
ax_trace_quick (ax, op_size / TARGET_CHAR_BIT); |
@@ -1930,7 +1900,7 @@ gen_expr (struct expression *exp, union exp_element **pc, |
if (tsv) |
{ |
ax_tsv (ax, aop_setv, tsv->number); |
- if (trace_kludge) |
+ if (ax->tracing) |
ax_tsv (ax, aop_tracev, tsv->number); |
} |
else |
@@ -1957,7 +1927,7 @@ gen_expr (struct expression *exp, union exp_element **pc, |
{ |
/* The tsv will be the left half of the binary operation. */ |
ax_tsv (ax, aop_getv, tsv->number); |
- if (trace_kludge) |
+ if (ax->tracing) |
ax_tsv (ax, aop_tracev, tsv->number); |
/* Trace state variables are always 64-bit integers. */ |
value1.kind = axs_rvalue; |
@@ -1966,7 +1936,7 @@ gen_expr (struct expression *exp, union exp_element **pc, |
gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2); |
/* We have a result of the binary op, set the tsv. */ |
ax_tsv (ax, aop_setv, tsv->number); |
- if (trace_kludge) |
+ if (ax->tracing) |
ax_tsv (ax, aop_tracev, tsv->number); |
} |
else |
@@ -2047,7 +2017,7 @@ gen_expr (struct expression *exp, union exp_element **pc, |
if (tsv) |
{ |
ax_tsv (ax, aop_getv, tsv->number); |
- if (trace_kludge) |
+ if (ax->tracing) |
ax_tsv (ax, aop_tracev, tsv->number); |
/* Trace state variables are always 64-bit integers. */ |
value->kind = axs_rvalue; |
@@ -2076,6 +2046,23 @@ 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); |
@@ -2094,6 +2081,31 @@ gen_expr (struct expression *exp, union exp_element **pc, |
} |
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; |
+ } |
+ break; |
+ |
case UNOP_PLUS: |
(*pc)++; |
/* + FOO is equivalent to 0 + FOO, which can be optimized. */ |
@@ -2213,6 +2225,8 @@ 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: |
@@ -2380,7 +2394,7 @@ gen_expr_binop_rest (struct expression *exp, |
struct agent_expr * |
gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, |
- struct symbol *var) |
+ struct symbol *var, int trace_string) |
{ |
struct cleanup *old_chain = 0; |
struct agent_expr *ax = new_agent_expr (gdbarch, scope); |
@@ -2388,7 +2402,8 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, |
old_chain = make_cleanup_free_agent_expr (ax); |
- trace_kludge = 1; |
+ ax->tracing = 1; |
+ ax->trace_string = trace_string; |
gen_var_ref (gdbarch, ax, &value, var); |
/* If there is no actual variable to trace, flag it by returning |
@@ -2420,7 +2435,8 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch, |
caller can then use the ax_reqs function to discover which |
registers it relies upon. */ |
struct agent_expr * |
-gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) |
+gen_trace_for_expr (CORE_ADDR scope, struct expression *expr, |
+ int trace_string) |
{ |
struct cleanup *old_chain = 0; |
struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope); |
@@ -2430,7 +2446,8 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr) |
old_chain = make_cleanup_free_agent_expr (ax); |
pc = expr->elts; |
- trace_kludge = 1; |
+ ax->tracing = 1; |
+ ax->trace_string = trace_string; |
value.optimized_out = 0; |
gen_expr (expr, &pc, ax, &value); |
@@ -2465,7 +2482,7 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) |
old_chain = make_cleanup_free_agent_expr (ax); |
pc = expr->elts; |
- trace_kludge = 0; |
+ ax->tracing = 0; |
value.optimized_out = 0; |
gen_expr (expr, &pc, ax, &value); |
@@ -2482,7 +2499,8 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) |
} |
struct agent_expr * |
-gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch) |
+gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch, |
+ int trace_string) |
{ |
struct cleanup *old_chain = 0; |
struct agent_expr *ax = new_agent_expr (gdbarch, scope); |
@@ -2490,7 +2508,8 @@ gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch) |
old_chain = make_cleanup_free_agent_expr (ax); |
- trace_kludge = 1; |
+ ax->tracing = 1; |
+ ax->trace_string = trace_string; |
gdbarch_gen_return_address (gdbarch, ax, &value, scope); |
@@ -2514,27 +2533,26 @@ gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch) |
struct agent_expr * |
gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch, |
CORE_ADDR function, LONGEST channel, |
- char *format, int fmtlen, |
+ const char *format, int fmtlen, |
struct format_piece *frags, |
int nargs, struct expression **exprs) |
{ |
- struct expression *expr; |
struct cleanup *old_chain = 0; |
struct agent_expr *ax = new_agent_expr (gdbarch, scope); |
union exp_element *pc; |
struct axs_value value; |
- int i, tem, bot, fr, flen; |
- char *fmt; |
+ 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; |
- /* We're computing values, not doing side effects. */ |
- trace_kludge = 0; |
value.optimized_out = 0; |
gen_expr (exprs[tem], &pc, ax, &value); |
require_rvalue (ax, &value); |
@@ -2561,32 +2579,38 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch, |
} |
static void |
-agent_eval_command_one (char *exp, int eval, CORE_ADDR pc) |
+agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc) |
{ |
struct cleanup *old_chain = 0; |
struct expression *expr; |
struct agent_expr *agent; |
+ const char *arg; |
+ int trace_string = 0; |
if (!eval) |
{ |
- trace_string_kludge = 0; |
if (*exp == '/') |
- exp = decode_agent_options (exp); |
+ exp = decode_agent_options (exp, &trace_string); |
} |
- if (!eval && strcmp (exp, "$_ret") == 0) |
+ arg = exp; |
+ if (!eval && strcmp (arg, "$_ret") == 0) |
{ |
- agent = gen_trace_for_return_address (pc, get_current_arch ()); |
+ agent = gen_trace_for_return_address (pc, get_current_arch (), |
+ trace_string); |
old_chain = make_cleanup_free_agent_expr (agent); |
} |
else |
{ |
- expr = parse_exp_1 (&exp, pc, block_for_pc (pc), 0); |
+ expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0); |
old_chain = make_cleanup (free_current_contents, &expr); |
if (eval) |
- agent = gen_eval_for_expr (pc, expr); |
+ { |
+ gdb_assert (trace_string == 0); |
+ agent = gen_eval_for_expr (pc, expr); |
+ } |
else |
- agent = gen_trace_for_expr (pc, expr); |
+ agent = gen_trace_for_expr (pc, expr, trace_string); |
make_cleanup_free_agent_expr (agent); |
} |
@@ -2674,8 +2698,8 @@ maint_agent_printf_command (char *exp, int from_tty) |
struct expression *argvec[100]; |
struct agent_expr *agent; |
struct frame_info *fi = get_current_frame (); /* need current scope */ |
- char *cmdrest; |
- char *format_start, *format_end; |
+ const char *cmdrest; |
+ const char *format_start, *format_end; |
struct format_piece *fpieces; |
int nargs; |
@@ -2691,7 +2715,7 @@ maint_agent_printf_command (char *exp, int from_tty) |
cmdrest = exp; |
- cmdrest = skip_spaces (cmdrest); |
+ cmdrest = skip_spaces_const (cmdrest); |
if (*cmdrest++ != '"') |
error (_("Must start with a format string.")); |
@@ -2707,19 +2731,19 @@ maint_agent_printf_command (char *exp, int from_tty) |
if (*cmdrest++ != '"') |
error (_("Bad format string, non-terminated '\"'.")); |
- cmdrest = skip_spaces (cmdrest); |
+ cmdrest = skip_spaces_const (cmdrest); |
if (*cmdrest != ',' && *cmdrest != 0) |
error (_("Invalid argument syntax")); |
if (*cmdrest == ',') |
cmdrest++; |
- cmdrest = skip_spaces (cmdrest); |
+ cmdrest = skip_spaces_const (cmdrest); |
nargs = 0; |
while (*cmdrest != '\0') |
{ |
- char *cmd1; |
+ const char *cmd1; |
cmd1 = cmdrest; |
expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1); |