Fix all failing FPXX tests for tx39-elf.
[platform/upstream/binutils.git] / gdb / ax-gdb.c
index 9cb8fe9..a60603f 100644 (file)
@@ -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-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #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"
@@ -43,6 +40,7 @@
 #include "arch-utils.h"
 #include "cli/cli-utils.h"
 #include "linespec.h"
+#include "objfiles.h"
 
 #include "valprint.h"
 #include "c-lang.h"
@@ -313,36 +311,6 @@ maybe_const_expr (union exp_element **pc)
    sizes), and this is simpler.)  */
 \f
 
-/* 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.  */
 
@@ -402,19 +370,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
@@ -442,7 +410,7 @@ gen_traced_pop (struct gdbarch *gdbarch,
          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);
            }
        }
@@ -460,7 +428,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;
@@ -470,7 +438,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);
@@ -510,7 +478,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));
@@ -663,6 +631,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))
     {
@@ -738,26 +712,20 @@ gen_var_ref (struct gdbarch *gdbarch, struct agent_expr *ax,
 
     case LOC_UNRESOLVED:
       {
-       struct minimal_symbol *msym
+       struct bound_minimal_symbol msym
          = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL);
 
-       if (!msym)
+       if (!msym.minsym)
          error (_("Couldn't resolve symbol `%s'."), SYMBOL_PRINT_NAME (var));
 
        /* Push the address of the variable.  */
-       ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym));
+       ax_const_l (ax, BMSYMBOL_VALUE_ADDRESS (msym));
        value->kind = axs_lvalue_memory;
       }
       break;
 
     case LOC_COMPUTED:
-      /* FIXME: cagney/2004-01-26: It should be possible to
-        unconditionally call the SYMBOL_COMPUTED_OPS method when available.
-        Unfortunately DWARF 2 stores the frame-base (instead of the
-        function) location in a function's symbol.  Oops!  For the
-        moment enable this when/where applicable.  */
-      SYMBOL_COMPUTED_OPS (var)->tracepoint_var_ref (var, gdbarch, ax, value);
-      break;
+      gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
 
     case LOC_OPTIMIZED_OUT:
       /* Flag this, but don't say anything; leave it up to callers to
@@ -1362,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);
@@ -1931,7 +1899,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
@@ -1958,7 +1926,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;
@@ -1967,7 +1935,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
@@ -2048,7 +2016,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;
@@ -2219,7 +2187,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
     case OP_THIS:
       {
        struct symbol *sym, *func;
-       struct block *b;
+       const struct block *b;
        const struct language_defn *lang;
 
        b = block_for_pc (ax->scope);
@@ -2425,7 +2393,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);
@@ -2433,7 +2401,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
@@ -2465,7 +2434,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);
@@ -2475,7 +2445,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);
 
@@ -2510,7 +2481,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);
 
@@ -2527,7 +2498,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);
@@ -2535,7 +2507,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);
 
@@ -2559,27 +2532,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);
@@ -2606,32 +2578,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);
     }
 
@@ -2719,8 +2697,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;
 
@@ -2736,7 +2714,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."));
@@ -2752,19 +2730,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);