PR ld/12549
[binutils-gdb.git] / gdb / ax-gdb.c
index a76e7817206f6becec6b430863be248990129b68..202988256893eb0f6c7e6cf4225ccaba94950dc1 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-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "tracepoint.h"
 #include "cp-support.h"
 #include "arch-utils.h"
+#include "cli/cli-utils.h"
+#include "linespec.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,
    look at gen_expr, towards the bottom; that's the main function that
@@ -95,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);
@@ -157,8 +158,6 @@ static void gen_repeat (struct expression *exp, union exp_element **pc,
 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,
@@ -367,9 +366,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;
@@ -425,17 +424,18 @@ 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)
@@ -791,7 +791,7 @@ 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
@@ -1803,7 +1803,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)
 {
@@ -2038,7 +2038,8 @@ 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;
@@ -2052,7 +2053,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
            value->kind = axs_rvalue;
            value->type = builtin_type (exp->gdbarch)->builtin_long_long;
          }
-       else
+       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);
       }
@@ -2075,6 +2076,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);
@@ -2093,6 +2111,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.  */
@@ -2174,7 +2217,6 @@ gen_expr (struct expression *exp, union exp_element **pc,
 
     case OP_THIS:
       {
-       char *this_name;
        struct symbol *sym, *func;
        struct block *b;
        const struct language_defn *lang;
@@ -2213,11 +2255,13 @@ 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:
       error (_("Unsupported operator %s (%d) in expression."),
-            op_string (op), op);
+            op_name (exp, op), op);
     }
 }
 
@@ -2507,41 +2551,84 @@ gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch)
   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,
+           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);
+
+  /* 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);
+    }
+
+  /* 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_simple (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 (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 */
 
-  /* 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
-     have to know anything about agent expressions.  */
-  if (overlay_debugging)
-    error (_("GDB can't do agent expression translation with overlays."));
-
-  if (exp == 0)
-    error_no_arg (_("expression to translate"));
-
-  trace_string_kludge = 0;
-  if (*exp == '/')
-    exp = decode_agent_options (exp);
+  if (!eval)
+    {
+      trace_string_kludge = 0;
+      if (*exp == '/')
+        exp = decode_agent_options (exp);
+    }
 
-  /* Recognize the return address collection directive specially.  Note
-     that it is not really an expression of any sort.  */
-  if (strcmp (exp, "$_ret") == 0)
+  if (!eval && strcmp (exp, "$_ret") == 0)
     {
-      agent = gen_trace_for_return_address (get_frame_pc (fi),
-                                           get_current_arch ());
+      agent = gen_trace_for_return_address (pc, get_current_arch ());
       old_chain = make_cleanup_free_agent_expr (agent);
     }
   else
     {
-      expr = parse_expression (exp);
+      expr = parse_exp_1 (&exp, pc, block_for_pc (pc), 0);
       old_chain = make_cleanup (free_current_contents, &expr);
-      agent = gen_trace_for_expr (get_frame_pc (fi), expr);
+      if (eval)
+       agent = gen_eval_for_expr (pc, expr);
+      else
+       agent = gen_trace_for_expr (pc, expr);
       make_cleanup_free_agent_expr (agent);
     }
 
@@ -2555,17 +2642,84 @@ agent_command (char *exp, int from_tty)
   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
+     have to know anything about agent expressions.  */
+  if (overlay_debugging)
+    error (_("GDB can't do agent expression translation with overlays."));
+
+  if (exp == 0)
+    error_no_arg (_("expression to translate"));
+
+  if (check_for_argument (&exp, "-at", sizeof ("-at") - 1))
+    {
+      struct linespec_result canonical;
+      int ix;
+      struct linespec_sals *iter;
+      struct cleanup *old_chain;
+
+      exp = skip_spaces (exp);
+      init_linespec_result (&canonical);
+      decode_line_full (&exp, DECODE_LINE_FUNFIRSTLINE,
+                       (struct symtab *) NULL, 0, &canonical,
+                       NULL, NULL);
+      old_chain = 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 ()));
+
+  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 */
+  char *cmdrest;
+  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
@@ -2577,9 +2731,52 @@ 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 (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 (cmdrest);
+
+  if (*cmdrest != ',' && *cmdrest != 0)
+    error (_("Invalid argument syntax"));
+
+  if (*cmdrest == ',')
+    cmdrest++;
+  cmdrest = skip_spaces (cmdrest);
+
+  nargs = 0;
+  while (*cmdrest != '\0')
+    {
+      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);
@@ -2599,12 +2796,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.\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."),
+            "agent bytecode for evaluation and display the bytecodes."),
           &maintenancelist);
 }