This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

patch suggestion: conditional collect command


(had some mail problems, hoping it won't be sent more then once)

 This patch should allow conditional collect
expressions in tracepoints. The format is:

> collect expr2 if expr3
or
> collect expr1, expr2 if expr3, expr4 ....

in both cases, the expression expr2 will be collected
only if expr3 turned out to be true.

NOTE 1: if this patch will be accepted, the collect
        command's legend should be updated.
NOTE 2: targets should protect themselves from infinite
        loops.
NOTE 3: in gen_binop, I thought that pointer/integer
        operations are too powerful to be disallowed,
        fixme if I'm wrong.

Thanks -
Josef Ezra


*ax.h: (ax_append_const) new function
*ax-general.c: ditto
*ax-gdb.h: (gen_trace_for_expr) additional 'if' parameter
*ax-gdb.c: (require_rvalue) minor bug fixed
*ax-gdb.c: (gen_binop) allow ptr/int operation
*ax-gdb.c: (gen_expr) added compare operations (EQUAL, GTR etc.)
*ax-gdb.c: (gen_trace_for_expr) additional 'if' parameter, create
conditional trace
*ax-gdb.c: (agent_command) manipulate 'expr if expr' expresstions
*tracepoint.c: (validate_actionline) allow 'collect expr if expr' commands
*tracepoint.c: (encode_actions) ditto
*tracepoint.c: (trace_dump_command) outputing conditional traces




Index: ax-gdb.h
===================================================================
RCS file: /emc/ucode/cvsroot_0/sgdb6/gdb/ax-gdb.h,v
retrieving revision 1.1
diff -c -5 -p -r1.1 ax-gdb.h
*** ax-gdb.h 2000/09/07 16:34:30 1.1
--- ax-gdb.h 2000/10/26 21:07:55
*************** extern struct agent_expr *expr_to_addres
*** 107,114 ****
     The result will use the `trace' and `trace_quick' bytecodes to
     record the value of all memory touched by the expression, and leave
     no values on the stack.  The caller can then use the ax_reqs
     function to discover which registers the expression uses.  */
  extern struct agent_expr *gen_trace_for_expr PARAMS ((CORE_ADDR,
!       struct expression *));

  #endif /* AX_GDB_H */
--- 107,123 ----
     The result will use the `trace' and `trace_quick' bytecodes to
     record the value of all memory touched by the expression, and leave
     no values on the stack.  The caller can then use the ax_reqs
     function to discover which registers the expression uses.  */
  extern struct agent_expr *gen_trace_for_expr PARAMS ((CORE_ADDR,
!       struct expression *,
!                                                       struct expression
*));
!

  #endif /* AX_GDB_H */
Index: ax.h
===================================================================
RCS file: /emc/ucode/cvsroot_0/sgdb6/gdb/ax.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -5 -p -r1.1 -r1.2
*** ax.h 2000/09/07 16:34:30 1.1
--- ax.h 2000/10/19 13:33:25 1.2
*************** extern int ax_goto PARAMS ((struct agent
*** 174,183 ****
--- 180,193 ----
  extern void ax_label PARAMS ((struct agent_expr * EXPR, int patch, int
target));

  /* Assemble code to push a constant on the stack.  */
  extern void ax_const_l PARAMS ((struct agent_expr * EXPR, LONGEST l));
  extern void ax_const_d PARAMS ((struct agent_expr * EXPR, LONGEST d));
+
+
+ /* just add n low bytes of val to expression chain - jezra EMC */
+ extern void ax_append_const PARAMS ((struct agent_expr * x, unsigned long
val, int n));

  /* Assemble code to push the value of register number REG on the
     stack.  */
  extern void ax_reg PARAMS ((struct agent_expr * EXPR, int REG));


Index: ax-gdb.c
===================================================================
RCS file: /emc/ucode/cvsroot_0/sgdb6/gdb/ax-gdb.c,v
retrieving revision 1.1
diff -c -5 -p -r1.1 ax-gdb.c
*** ax-gdb.c 2000/09/07 16:34:30 1.1
--- ax-gdb.c 2000/11/01 15:27:06
*************** require_rvalue (ax, value)
*** 697,707 ****
        /* It's already an rvalue.  */
        break;

      case axs_lvalue_memory:
        /* The top of stack is the address of the object.  Dereference.  */
!       gen_fetch (ax, value->type);
        break;

      case axs_lvalue_register:
        /* There's nothing on the stack, but value->u.reg is the
           register number containing the value.
--- 697,707 ----
        /* It's already an rvalue.  */
        break;

      case axs_lvalue_memory:
        /* The top of stack is the address of the object.  Dereference.  */
!       gen_fetch (ax, CHECK_TYPEDEF( value->type ));
        break;

      case axs_lvalue_register:
        /* There's nothing on the stack, but value->u.reg is the
           register number containing the value.
*************** gen_binop (ax, value, value1, value2, op
*** 1106,1117 ****
       enum agent_op op, op_unsigned;
       int may_carry;
       char *name;
  {
    /* We only handle INT op INT.  */
!   if ((value1->type->code != TYPE_CODE_INT)
!       || (value2->type->code != TYPE_CODE_INT))
      error ("Illegal combination of types in %s.", name);

    ax_simple (ax,
       TYPE_UNSIGNED (value1->type) ? op_unsigned : op);
    if (may_carry)
--- 1106,1120 ----
       enum agent_op op, op_unsigned;
       int may_carry;
       char *name;
  {
    /* We only handle INT op INT.  */
!   /* FIXME: mmm.., ptr/int operations are too powerful to be disabled */
!   if (((value1->type->code != TYPE_CODE_INT) &&
!        (value1->type->code != TYPE_CODE_PTR)) ||
!       ((value2->type->code != TYPE_CODE_INT) &&
!        (value2->type->code != TYPE_CODE_PTR)))
      error ("Illegal combination of types in %s.", name);

    ax_simple (ax,
       TYPE_UNSIGNED (value1->type) ? op_unsigned : op);
    if (may_carry)
*************** gen_expr (pc, ax, value)
*** 1565,1574 ****
--- 1569,1586 ----
    }

    /* Otherwise, go ahead and generate code for it.  */
    switch (op)
      {
+       /* Binary Comparation operators */
+     case BINOP_EQUAL: /* == */
+     case BINOP_NOTEQUAL: /* != */
+     case BINOP_LESS: /* <  */
+     case BINOP_GTR: /* >  */
+     case BINOP_LEQ: /* <= */
+     case BINOP_GEQ:        /* >= */
+
        /* Binary arithmetic operators.  */
      case BINOP_ADD:
      case BINOP_SUB:
      case BINOP_MUL:
      case BINOP_DIV:
*************** gen_expr (pc, ax, value)
*** 1583,1592 ****
--- 1595,1627 ----
        gen_expr (pc, ax, &value2);
        gen_usual_unary (ax, &value2);
        gen_usual_arithmetic (ax, &value1, &value2);
        switch (op)
  {
+         case BINOP_EQUAL: /* == */
+           gen_binop (ax, value, &value1, &value2,
+                      aop_equal, aop_equal, 0, "isequal");
+           break;
+         case BINOP_NOTEQUAL: /* != */
+           gen_binop (ax, value, &value1, &value2,
+                      aop_equal, aop_equal, 0, "isequal");
+           ax_simple (ax, aop_log_not);
+           break;
+         case BINOP_GTR: /* >  */
+           ax_simple (ax, aop_swap);
+         case BINOP_LESS: /* <  */
+           gen_binop (ax, value, &value1, &value2,
+                      aop_less_signed, aop_less_unsigned, 1, "isless");
+           break;
+         case BINOP_LEQ: /* <= */
+           ax_simple (ax, aop_swap);
+         case BINOP_GEQ:        /* >= */
+           gen_binop (ax, value, &value1, &value2,
+                      aop_less_signed, aop_less_unsigned, 1, "isless");
+           ax_simple (ax, aop_log_not);
+           break;
+
  case BINOP_ADD:
    gen_add (ax, value, &value1, &value2, "addition");
    break;
  case BINOP_SUB:
    gen_sub (ax, value, &value1, &value2);
*************** expr_to_address_and_size (expr)
*** 1843,1865 ****
     The result will use the `trace' and `trace_quick' bytecodes to
     record the value of all memory touched by the expression.  The
     caller can then use the ax_reqs function to discover which
     registers it relies upon.  */
  struct agent_expr *
! gen_trace_for_expr (scope, expr)
       CORE_ADDR scope;
       struct expression *expr;
  {
    struct cleanup *old_chain = 0;
    struct agent_expr *ax = new_agent_expr (scope);
    union exp_element *pc;
    struct axs_value value;

    old_chain = make_cleanup ((make_cleanup_func) free_agent_expr, ax);

-   pc = expr->elts;
    trace_kludge = 1;
    gen_expr (&pc, ax, &value);

    /* Make sure we record the final object, and get rid of it.  */
    gen_traced_pop (ax, &value);

--- 1878,1912 ----
     The result will use the `trace' and `trace_quick' bytecodes to
     record the value of all memory touched by the expression.  The
     caller can then use the ax_reqs function to discover which
     registers it relies upon.  */
  struct agent_expr *
! gen_trace_for_expr (scope, expr, ifexpr)
       CORE_ADDR scope;
       struct expression *expr;
+      struct expression *ifexpr;
  {
    struct cleanup *old_chain = 0;
    struct agent_expr *ax = new_agent_expr (scope);
    union exp_element *pc;
    struct axs_value value;

    old_chain = make_cleanup ((make_cleanup_func) free_agent_expr, ax);

    trace_kludge = 1;
+   if (ifexpr != NULL)
+     {
+       pc = ifexpr->elts;
+       gen_expr (&pc, ax, &value) ;
+       require_rvalue (ax, &value) ;
+       ax_simple (ax, aop_if_goto) ;
+       ax_append_const (ax, (ax->len + 3), 2);
+       ax_simple (ax, aop_end) ;
+       /*                    >>==========>>
+          condition_expr, if_goto, end, collection_expr      */
+     }
+   pc = expr->elts;
    gen_expr (&pc, ax, &value);

    /* Make sure we record the final object, and get rid of it.  */
    gen_traced_pop (ax, &value);

*************** agent_command (exp, from_tty)
*** 1909,1918 ****
--- 2019,2030 ----
  {
    struct cleanup *old_chain = 0;
    struct expression *expr;
    struct agent_expr *agent;
    struct frame_info *fi = get_current_frame (); /* need current scope */
+   struct expression *ifexpr = NULL;
+   char *ifexp ;

    /* 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.  */
*************** agent_command (exp, from_tty)
*** 1920,1932 ****
      error ("GDB can't do agent expression translation with overlays.");

    if (exp == 0)
      error_no_arg ("expression to translate");

    expr = parse_expression (exp);
    old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
&expr);
!   agent = gen_trace_for_expr (fi->pc, expr);
    make_cleanup ((make_cleanup_func) free_agent_expr, agent);
    ax_print (gdb_stdout, agent);

    /* It would be nice to call ax_reqs here to gather some general info
       about the expression, and then print out the result.  */
--- 2032,2052 ----
      error ("GDB can't do agent expression translation with overlays.");

    if (exp == 0)
      error_no_arg ("expression to translate");

+   if ((ifexp = strstr (exp, " if ")) != NULL)   /* is it an if command?
*/
+     {
+       ifexpr = parse_expression (ifexp + 4);
+       *ifexp = '\0';
+     }
    expr = parse_expression (exp);
    old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
&expr);
!   if (ifexpr)
!     old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
&ifexpr);
!
!   agent = gen_trace_for_expr (fi->pc, expr, ifexpr);
    make_cleanup ((make_cleanup_func) free_agent_expr, agent);
    ax_print (gdb_stdout, agent);

    /* It would be nice to call ax_reqs here to gather some general info
       about the expression, and then print out the result.  */
Index: ax-general.c
===================================================================
RCS file: /emc/ucode/cvsroot_0/sgdb6/gdb/ax-general.c,v
retrieving revision 1.1
diff -c -5 -p -r1.1 ax-general.c
*** ax-general.c 2000/09/07 16:34:30 1.1
--- ax-general.c 2000/11/01 14:28:05
*************** grow_expr (x, n)
*** 78,87 ****
--- 78,96 ----
        x->buf = xrealloc (x->buf, x->size);
      }
  }


+ void
+ ax_append_const (x, val, n)
+      struct agent_expr *x;
+      unsigned long val;
+      int n;
+ {
+   append_const (x, (LONGEST) val, n);
+ }
+
  /* Append the low N bytes of VAL as an N-byte integer to the
     expression X, in big-endian order.  */
  static void
  append_const (x, val, n)
       struct agent_expr *x;
Index: tracepoint.c
===================================================================
RCS file: /emc/ucode/cvsroot_0/sgdb6/gdb/tracepoint.c,v
retrieving revision 1.1
diff -c -5 -p -r1.1 tracepoint.c
*** tracepoint.c 2000/09/07 16:35:13 1.1
--- tracepoint.c 2000/11/01 16:59:41
*************** validate_actionline (line, t)
*** 932,942 ****
--- 995,1007 ----
       char **line;
       struct tracepoint *t;
  {
    struct cmd_list_element *c;
    struct expression *exp = NULL;
+   struct expression *ifexp = NULL;
    struct cleanup *old_chain = NULL;
+
    char *p;

    for (p = *line; isspace ((int) *p);)
      p++;

*************** validate_actionline (line, t)
*** 967,986 ****

    if (*p == '$') /* look for special pseudo-symbols */
      {
        if ((0 == strncasecmp ("reg", p + 1, 3)) ||
    (0 == strncasecmp ("arg", p + 1, 3)) ||
!   (0 == strncasecmp ("loc", p + 1, 3)))
  {
    p = strchr (p, ',');
    continue;
  }
        /* else fall thru, treat p as an expression and parse it! */
      }
    exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
    old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
      &exp);

    if (exp->elts[0].opcode == OP_VAR_VALUE)
      {
        if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
  {
--- 1032,1100 ----

    if (*p == '$') /* look for special pseudo-symbols */
      {
        if ((0 == strncasecmp ("reg", p + 1, 3)) ||
    (0 == strncasecmp ("arg", p + 1, 3)) ||
!   (0 == strncasecmp ("loc", p + 1, 3)))
  {
    p = strchr (p, ',');
    continue;
  }
        /* else fall thru, treat p as an expression and parse it! */
      }
    exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
+           if (*p)
+             {
+               while (isspace ((int) *p)) p ++;
+               if ( p[0] == 'i' &&
+                    p[1] == 'f' &&
+                    p[2] == ' ')
+                 {                                       /* this is an if
command  */
+                   p += 3;
+                   ifexp = parse_exp_1 (&p, block_for_pc (t->address), 1);
+                 }
+             }
+
    old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
      &exp);
+           if (ifexp)
+             old_chain = make_cleanup ((make_cleanup_func)
free_current_contents,
+     &ifexp);

    if (exp->elts[0].opcode == OP_VAR_VALUE)
      {
        if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
  {
*************** validate_actionline (line, t)
*** 997,1007 ****
  }
      }

    /* we have something to collect, make sure that the expr to
       bytecode translator can handle it and that it's not too long */
!   aexpr = gen_trace_for_expr (t->address, exp);
    (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);

    if (aexpr->len > MAX_AGENT_EXPR_LEN)
      error ("expression too complicated, try simplifying");

--- 1111,1121 ----
  }
      }

    /* we have something to collect, make sure that the expr to
       bytecode translator can handle it and that it's not too long */
!   aexpr = gen_trace_for_expr (t->address, exp, ifexp);
    (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);

    if (aexpr->len > MAX_AGENT_EXPR_LEN)
      error ("expression too complicated, try simplifying");

*************** encode_actions (t, tdp_actions, stepping
*** 1514,1532 ****
       char ***stepping_actions;
  {
    static char tdp_buff[2048], step_buff[2048];
    char *action_exp;
    struct expression *exp = NULL;
    struct action_line *action;
    int i;
    value_ptr tempval;
    struct collection_list *collect;
    struct cmd_list_element *cmd;
    struct agent_expr *aexpr;
    long frame_reg, frame_offset;

-
    clear_collection_list (&tracepoint_list);
    clear_collection_list (&stepping_list);
    collect = &tracepoint_list;

    *tdp_actions = NULL;
--- 1629,1647 ----
       char ***stepping_actions;
  {
    static char tdp_buff[2048], step_buff[2048];
    char *action_exp;
    struct expression *exp = NULL;
+   struct expression *ifexp = NULL;
    struct action_line *action;
    int i;
    value_ptr tempval;
    struct collection_list *collect;
    struct cmd_list_element *cmd;
    struct agent_expr *aexpr;
    long frame_reg, frame_offset;

    clear_collection_list (&tracepoint_list);
    clear_collection_list (&stepping_list);
    collect = &tracepoint_list;

    *tdp_actions = NULL;
*************** encode_actions (t, tdp_actions, stepping
*** 1540,1550 ****
        action_exp = action->action;
        while (isspace ((int) *action_exp))
  action_exp++;

        if (*action_exp == '#') /* comment line */
! return;

        cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
        if (cmd == 0)
  error ("Bad action list item: %s", action_exp);

--- 1655,1665 ----
        action_exp = action->action;
        while (isspace ((int) *action_exp))
  action_exp++;

        if (*action_exp == '#') /* comment line */
! continue ;

        cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
        if (cmd == 0)
  error ("Bad action list item: %s", action_exp);

*************** encode_actions (t, tdp_actions, stepping
*** 1582,1625 ****
  }
        else
  {
    unsigned long addr, len;
    struct cleanup *old_chain = NULL;
!   struct cleanup *old_chain1 = NULL;
    struct agent_reqs areqs;
!
    exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
    old_chain = make_cleanup ((make_cleanup_func)
      free_current_contents, &exp);

!   switch (exp->elts[0].opcode)
!     {
!     case OP_REGISTER:
        i = exp->elts[1].longconst;
        if (info_verbose)
  printf_filtered ("OP_REGISTER: ");
        add_register (collect, i);
!       break;

!     case UNOP_MEMVAL:
        /* safe because we know it's a simple expression */
        tempval = evaluate_expression (exp);
        addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
        len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
        add_memrange (collect, -1, addr, len);
!       break;

!     case OP_VAR_VALUE:
        collect_symbol (collect,
        exp->elts[2].symbol,
        frame_reg,
        frame_offset);
!       break;

!     default: /* full-fledged expression */
!       aexpr = gen_trace_for_expr (t->address, exp);

        old_chain1 = make_cleanup ((make_cleanup_func)
  free_agent_expr, aexpr);

        ax_reqs (aexpr, &areqs);
        if (areqs.flaw != agent_flaw_none)
--- 1697,1804 ----
  }
        else
  {
    unsigned long addr, len;
    struct cleanup *old_chain = NULL;
!     struct cleanup *old_chain1 = NULL;
    struct agent_reqs areqs;
    exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
+                   if (*action_exp)                              /* is it
an if command?  */
+                     {
+                       while (isspace ((int) *action_exp)) action_exp ++;
+                       if ( action_exp[0] == 'i' &&
+                            action_exp[1] == 'f' &&
+                            action_exp[2] == ' ')
+                         {                                       /* this is
an if command  */
+                           action_exp += 3;
+                           ifexp = parse_exp_1 (&action_exp, block_for_pc
(t->address), 1);
+                         }
+                     }
+
    old_chain = make_cleanup ((make_cleanup_func)
      free_current_contents, &exp);
+                   if (ifexp)
+                     old_chain = make_cleanup ((make_cleanup_func)
+                                               free_current_contents,
&ifexp);

!                   if (!ifexp  && exp->elts[0].opcode == OP_REGISTER)
!                     {
        i = exp->elts[1].longconst;
        if (info_verbose)
  printf_filtered ("OP_REGISTER: ");
        add_register (collect, i);
!                     }

!                   else if (!ifexp && exp->elts[0].opcode == UNOP_MEMVAL)
!     {
        /* safe because we know it's a simple expression */
        tempval = evaluate_expression (exp);
        addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
        len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
        add_memrange (collect, -1, addr, len);
!                     }

!                   else if (!ifexp && exp->elts[0].opcode == OP_VAR_VALUE)
!     {
        collect_symbol (collect,
        exp->elts[2].symbol,
        frame_reg,
        frame_offset);
!                     }

!                   else /* full-fledged expression */
!                     {
+                     aexpr = gen_trace_for_expr (t->address, exp, ifexp);
+
        old_chain1 = make_cleanup ((make_cleanup_func)
  free_agent_expr, aexpr);

        ax_reqs (aexpr, &areqs);
        if (areqs.flaw != agent_flaw_none)
*************** encode_actions (t, tdp_actions, stepping
*** 1650,1664 ****
        /* it's used -- record it */
        add_register (collect, ndx1 * 8 + ndx2);
  }
      }
  }
!       break;
!     } /* switch */
    do_cleanups (old_chain);
! } /* do */
!     }
    while (action_exp && *action_exp++ == ',');
  } /* if */
        else if (cmd->function.cfunc == while_stepping_pseudocommand)
  {
    collect = &stepping_list;
--- 1829,1842 ----
        /* it's used -- record it */
        add_register (collect, ndx1 * 8 + ndx2);
  }
      }
  }
!     }
    do_cleanups (old_chain);
! }
!     }   /* do */
    while (action_exp && *action_exp++ == ',');
  } /* if */
        else if (cmd->function.cfunc == while_stepping_pseudocommand)
  {
    collect = &stepping_list;
*************** trace_dump_command (args, from_tty)
*** 2536,2546 ****
       char *args;
       int from_tty;
  {
    struct tracepoint *t;
    struct action_line *action;
!   char *action_exp, *next_comma;
    struct cleanup *old_cleanups;
    int stepping_actions = 0;
    int stepping_frame = 0;

    if (!target_is_remote ())
--- 2722,2732 ----
       char *args;
       int from_tty;
  {
    struct tracepoint *t;
    struct action_line *action;
!   char *action_exp, *next_comma, *ifexpr;
    struct cleanup *old_cleanups;
    int stepping_actions = 0;
    int stepping_frame = 0;

    if (!target_is_remote ())
*************** trace_dump_command (args, from_tty)
*** 2627,2639 ****
--- 2814,2858 ----
        if (next_comma)
  {
    make_cleanup (replace_comma, next_comma);
    *next_comma = '\0';
  }
+                                 /* always try to show conditional traces
*/
+                       if ((ifexpr = strstr (action_exp, " if ")) != NULL)
+                         *ifexpr = '\0' ;
        printf_filtered ("%s = ", action_exp);
        output_command (action_exp, from_tty);
        printf_filtered ("\n");
+                       if (ifexpr != NULL)
+                         *ifexpr = ' ' ;
      }
    if (next_comma)
      *next_comma = ',';
    action_exp = next_comma;
  }



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]