2010-03-03 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Thu, 4 Mar 2010 00:32:50 +0000 (00:32 +0000)
committerStan Shebs <shebs@codesourcery.com>
Thu, 4 Mar 2010 00:32:50 +0000 (00:32 +0000)
* remote.c (remote_download_tracepoint): Iterate over locations.
* tracepoint.c (validate_actionline): Ditto.
(encode_actions): Add location argument.
(trace_dump_command): Check all locations to see if stepping
frame.

gdb/ChangeLog
gdb/remote.c
gdb/tracepoint.c

index b78e7b0..46010bd 100644 (file)
@@ -1,3 +1,11 @@
+2010-03-03 Stan Shebs  <stan@codesourcery.com>
+
+       * remote.c (remote_download_tracepoint): Iterate over locations.
+       * tracepoint.c (validate_actionline): Ditto.
+       (encode_actions): Add location argument.
+       (trace_dump_command): Check all locations to see if stepping
+       frame.
+       
 2010-03-03  H.J. Lu  <hongjiu.lu@intel.com>
            Eli Zaretskii  <eliz@gnu.org>
 
index 7f8ec58..4b11060 100644 (file)
@@ -72,8 +72,8 @@
 static char *target_buf;
 static long target_buf_size;
 /*static*/ void
-encode_actions (struct breakpoint *t, char ***tdp_actions,
-               char ***stepping_actions);
+encode_actions (struct breakpoint *t, struct bp_location *tloc,
+               char ***tdp_actions, char ***stepping_actions);
 
 /* The size to align memory write packets, when practical.  The protocol
    does not guarantee any alignment, and gdb will generate short
@@ -9253,6 +9253,7 @@ free_actions_list (char **actions_list)
 static void
 remote_download_tracepoint (struct breakpoint *t)
 {
+  struct bp_location *loc;
   CORE_ADDR tpaddr;
   char tmp[40];
   char buf[2048];
@@ -9264,111 +9265,116 @@ remote_download_tracepoint (struct breakpoint *t)
   struct cleanup *aexpr_chain = NULL;
   char *pkt;
 
-  encode_actions (t, &tdp_actions, &stepping_actions);
-  old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
-                           tdp_actions);
-  (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
-
-  tpaddr = t->loc->address;
-  sprintf_vma (tmp, (t->loc ? tpaddr : 0));
-  sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, 
-          tmp, /* address */
-          (t->enable_state == bp_enabled ? 'E' : 'D'),
-          t->step_count, t->pass_count);
-  /* Fast tracepoints are mostly handled by the target, but we can
-     tell the target how big of an instruction block should be moved
-     around.  */
-  if (t->type == bp_fast_tracepoint)
-    {
-      /* Only test for support at download time; we may not know
-        target capabilities at definition time.  */
-      if (remote_supports_fast_tracepoints ())
+  /* Iterate over all the tracepoint locations.  It's up to the target to
+     notice multiple tracepoint packets with the same number but different
+     addresses, and treat them as multiple locations.  */
+  for (loc = t->loc; loc; loc = loc->next)
+    {
+      encode_actions (t, loc, &tdp_actions, &stepping_actions);
+      old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
+                               tdp_actions);
+      (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
+
+      tpaddr = loc->address;
+      sprintf_vma (tmp, (loc ? tpaddr : 0));
+      sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, 
+              tmp, /* address */
+              (t->enable_state == bp_enabled ? 'E' : 'D'),
+              t->step_count, t->pass_count);
+      /* Fast tracepoints are mostly handled by the target, but we can
+        tell the target how big of an instruction block should be moved
+        around.  */
+      if (t->type == bp_fast_tracepoint)
        {
-         int isize;
+         /* Only test for support at download time; we may not know
+            target capabilities at definition time.  */
+         if (remote_supports_fast_tracepoints ())
+           {
+             int isize;
 
-         if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
-                                               tpaddr, &isize, NULL))
-           sprintf (buf + strlen (buf), ":F%x", isize);
+             if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
+                                                   tpaddr, &isize, NULL))
+               sprintf (buf + strlen (buf), ":F%x", isize);
+             else
+               /* If it passed validation at definition but fails now,
+                  something is very wrong.  */
+               internal_error (__FILE__, __LINE__,
+                               "Fast tracepoint not valid during download");
+           }
          else
-           /* If it passed validation at definition but fails now,
-              something is very wrong.  */
-           internal_error (__FILE__, __LINE__,
-                           "Fast tracepoint not valid during download");
+           /* Fast tracepoints are functionally identical to regular
+              tracepoints, so don't take lack of support as a reason to
+              give up on the trace run.  */
+           warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
        }
-      else
-       /* Fast tracepoints are functionally identical to regular
-          tracepoints, so don't take lack of support as a reason to
-          give up on the trace run.  */
-       warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
-    }
-  /* If the tracepoint has a conditional, make it into an agent
-     expression and append to the definition.  */
-  if (t->loc->cond)
-    {
-      /* Only test support at download time, we may not know target
-        capabilities at definition time.  */
-      if (remote_supports_cond_tracepoints ())
+      /* If the tracepoint has a conditional, make it into an agent
+        expression and append to the definition.  */
+      if (loc->cond)
        {
-         aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
-         aexpr_chain = make_cleanup_free_agent_expr (aexpr);
-         sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
-         pkt = buf + strlen (buf);
-         for (ndx = 0; ndx < aexpr->len; ++ndx)
-           pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
-         *pkt = '\0';
-         do_cleanups (aexpr_chain);
+         /* Only test support at download time, we may not know target
+            capabilities at definition time.  */
+         if (remote_supports_cond_tracepoints ())
+           {
+             aexpr = gen_eval_for_expr (tpaddr, loc->cond);
+             aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+             sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
+             pkt = buf + strlen (buf);
+             for (ndx = 0; ndx < aexpr->len; ++ndx)
+               pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
+             *pkt = '\0';
+             do_cleanups (aexpr_chain);
+           }
+         else
+           warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
        }
-      else
-       warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
-    }
 
-  if (t->actions || *default_collect)
-    strcat (buf, "-");
-  putpkt (buf);
-  remote_get_noisy_reply (&target_buf, &target_buf_size);
-  if (strcmp (target_buf, "OK"))
-    error (_("Target does not support tracepoints."));
+      if (t->actions || *default_collect)
+       strcat (buf, "-");
+      putpkt (buf);
+      remote_get_noisy_reply (&target_buf, &target_buf_size);
+      if (strcmp (target_buf, "OK"))
+       error (_("Target does not support tracepoints."));
 
-  if (!t->actions && !*default_collect)
-    return;
+      if (!t->actions && !*default_collect)
+       continue;
 
-  /* do_single_steps (t); */
-  if (tdp_actions)
-    {
-      for (ndx = 0; tdp_actions[ndx]; ndx++)
+      /* do_single_steps (t); */
+      if (tdp_actions)
        {
-         QUIT; /* allow user to bail out with ^C */
-         sprintf (buf, "QTDP:-%x:%s:%s%c",
-                  t->number, tmp, /* address */
-                  tdp_actions[ndx],
-                  ((tdp_actions[ndx + 1] || stepping_actions)
-                   ? '-' : 0));
-         putpkt (buf);
-         remote_get_noisy_reply (&target_buf,
-                                 &target_buf_size);
-         if (strcmp (target_buf, "OK"))
-           error (_("Error on target while setting tracepoints."));
+         for (ndx = 0; tdp_actions[ndx]; ndx++)
+           {
+             QUIT;     /* allow user to bail out with ^C */
+             sprintf (buf, "QTDP:-%x:%s:%s%c",
+                      t->number, tmp, /* address */
+                      tdp_actions[ndx],
+                      ((tdp_actions[ndx + 1] || stepping_actions)
+                       ? '-' : 0));
+             putpkt (buf);
+             remote_get_noisy_reply (&target_buf,
+                                     &target_buf_size);
+             if (strcmp (target_buf, "OK"))
+               error (_("Error on target while setting tracepoints."));
+           }
        }
-    }
-  if (stepping_actions)
-    {
-      for (ndx = 0; stepping_actions[ndx]; ndx++)
+      if (stepping_actions)
        {
-         QUIT; /* allow user to bail out with ^C */
-         sprintf (buf, "QTDP:-%x:%s:%s%s%s",
-                  t->number, tmp, /* address */
-                  ((ndx == 0) ? "S" : ""),
-                  stepping_actions[ndx],
-                  (stepping_actions[ndx + 1] ? "-" : ""));
-         putpkt (buf);
-         remote_get_noisy_reply (&target_buf,
-                                 &target_buf_size);
-         if (strcmp (target_buf, "OK"))
-           error (_("Error on target while setting tracepoints."));
+         for (ndx = 0; stepping_actions[ndx]; ndx++)
+           {
+             QUIT;     /* allow user to bail out with ^C */
+             sprintf (buf, "QTDP:-%x:%s:%s%s%s",
+                      t->number, tmp, /* address */
+                      ((ndx == 0) ? "S" : ""),
+                      stepping_actions[ndx],
+                      (stepping_actions[ndx + 1] ? "-" : ""));
+             putpkt (buf);
+             remote_get_noisy_reply (&target_buf,
+                                     &target_buf_size);
+             if (strcmp (target_buf, "OK"))
+               error (_("Error on target while setting tracepoints."));
+           }
        }
+      do_cleanups (old_chain);
     }
-  do_cleanups (old_chain);
-  return;
 }
 
 static void
index 1d2785f..d248db4 100644 (file)
@@ -625,7 +625,8 @@ validate_actionline (char **line, struct breakpoint *t)
   struct cmd_list_element *c;
   struct expression *exp = NULL;
   struct cleanup *old_chain = NULL;
-  char *p;
+  char *p, *tmp_p;
+  struct bp_location *loc;
 
   /* if EOF is typed, *line is NULL */
   if (*line == NULL)
@@ -671,48 +672,53 @@ validate_actionline (char **line, struct breakpoint *t)
                }
              /* else fall thru, treat p as an expression and parse it!  */
            }
-         exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1);
-         old_chain = make_cleanup (free_current_contents, &exp);
-
-         if (exp->elts[0].opcode == OP_VAR_VALUE)
+         tmp_p = p;
+         for (loc = t->loc; loc; loc = loc->next)
            {
-             if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
-               {
-                 warning (_("constant %s (value %ld) will not be collected."),
-                          SYMBOL_PRINT_NAME (exp->elts[2].symbol),
-                          SYMBOL_VALUE (exp->elts[2].symbol));
-                 return BADLINE;
-               }
-             else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
+             p = tmp_p;
+             exp = parse_exp_1 (&p, block_for_pc (loc->address), 1);
+             old_chain = make_cleanup (free_current_contents, &exp);
+
+             if (exp->elts[0].opcode == OP_VAR_VALUE)
                {
-                 warning (_("%s is optimized away and cannot be collected."),
-                          SYMBOL_PRINT_NAME (exp->elts[2].symbol));
-                 return BADLINE;
+                 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
+                   {
+                     warning (_("constant %s (value %ld) will not be collected."),
+                              SYMBOL_PRINT_NAME (exp->elts[2].symbol),
+                              SYMBOL_VALUE (exp->elts[2].symbol));
+                     return BADLINE;
+                   }
+                 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
+                   {
+                     warning (_("%s is optimized away and cannot be collected."),
+                              SYMBOL_PRINT_NAME (exp->elts[2].symbol));
+                     return BADLINE;
+                   }
                }
-           }
 
-         /* 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->loc->address, exp);
-         make_cleanup_free_agent_expr (aexpr);
+             /* 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 (loc->address, exp);
+             make_cleanup_free_agent_expr (aexpr);
 
-         if (aexpr->len > MAX_AGENT_EXPR_LEN)
-           error (_("expression too complicated, try simplifying"));
+             if (aexpr->len > MAX_AGENT_EXPR_LEN)
+               error (_("expression too complicated, try simplifying"));
 
-         ax_reqs (aexpr, &areqs);
-         (void) make_cleanup (xfree, areqs.reg_mask);
+             ax_reqs (aexpr, &areqs);
+             (void) make_cleanup (xfree, areqs.reg_mask);
 
-         if (areqs.flaw != agent_flaw_none)
-           error (_("malformed expression"));
+             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.min_height < 0)
+               error (_("gdb: Internal error: expression has min height < 0"));
 
-         if (areqs.max_height > 20)
-           error (_("expression too complicated, try simplifying"));
+             if (areqs.max_height > 20)
+               error (_("expression too complicated, try simplifying"));
 
-         do_cleanups (old_chain);
+             do_cleanups (old_chain);
+           }
        }
       while (p && *p++ == ',');
       return GENERIC;
@@ -727,20 +733,25 @@ validate_actionline (char **line, struct breakpoint *t)
          while (isspace ((int) *p))
            p++;
 
-         /* Only expressions are allowed for this action.  */
-         exp = parse_exp_1 (&p, block_for_pc (t->loc->address), 1);
-         old_chain = make_cleanup (free_current_contents, &exp);
+         tmp_p = p;
+         for (loc = t->loc; loc; loc = loc->next)
+           {
+             p = tmp_p;
+             /* Only expressions are allowed for this action.  */
+             exp = parse_exp_1 (&p, block_for_pc (loc->address), 1);
+             old_chain = make_cleanup (free_current_contents, &exp);
 
-         /* We have something to evaluate, make sure that the expr to
-            bytecode translator can handle it and that it's not too
-            long.  */
-         aexpr = gen_eval_for_expr (t->loc->address, exp);
-         make_cleanup_free_agent_expr (aexpr);
+             /* We have something to evaluate, make sure that the expr to
+                bytecode translator can handle it and that it's not too
+                long.  */
+             aexpr = gen_eval_for_expr (loc->address, exp);
+             make_cleanup_free_agent_expr (aexpr);
 
-         if (aexpr->len > MAX_AGENT_EXPR_LEN)
-           error (_("expression too complicated, try simplifying"));
+             if (aexpr->len > MAX_AGENT_EXPR_LEN)
+               error (_("expression too complicated, try simplifying"));
 
-         do_cleanups (old_chain);
+             do_cleanups (old_chain);
+           }
        }
       while (p && *p++ == ',');
       return GENERIC;
@@ -1238,8 +1249,8 @@ stringify_collection_list (struct collection_list *list, char *string)
 
 /* Render all actions into gdb protocol.  */
 /*static*/ void
-encode_actions (struct breakpoint *t, char ***tdp_actions,
-               char ***stepping_actions)
+encode_actions (struct breakpoint *t, struct bp_location *tloc,
+               char ***tdp_actions, char ***stepping_actions)
 {
   static char tdp_buff[2048], step_buff[2048];
   char *action_exp;
@@ -1263,7 +1274,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
   *stepping_actions = NULL;
 
   gdbarch_virtual_frame_pointer (t->gdbarch,
-                                t->loc->address, &frame_reg, &frame_offset);
+                                tloc->address, &frame_reg, &frame_offset);
 
   action = t->actions;
 
@@ -1322,7 +1333,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                {
                  add_local_symbols (collect,
                                     t->gdbarch,
-                                    t->loc->address,
+                                    tloc->address,
                                     frame_reg,
                                     frame_offset,
                                     'A');
@@ -1332,7 +1343,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                {
                  add_local_symbols (collect,
                                     t->gdbarch,
-                                    t->loc->address,
+                                    tloc->address,
                                     frame_reg,
                                     frame_offset,
                                     'L');
@@ -1346,7 +1357,7 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                  struct agent_reqs areqs;
 
                  exp = parse_exp_1 (&action_exp, 
-                                    block_for_pc (t->loc->address), 1);
+                                    block_for_pc (tloc->address), 1);
                  old_chain = make_cleanup (free_current_contents, &exp);
 
                  switch (exp->elts[0].opcode)
@@ -1381,11 +1392,11 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                                      t->gdbarch,
                                      frame_reg,
                                      frame_offset,
-                                     t->loc->address);
+                                     tloc->address);
                      break;
 
                    default:    /* full-fledged expression */
-                     aexpr = gen_trace_for_expr (t->loc->address, exp);
+                     aexpr = gen_trace_for_expr (tloc->address, exp);
 
                      old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
@@ -1443,10 +1454,10 @@ encode_actions (struct breakpoint *t, char ***tdp_actions,
                  struct agent_reqs areqs;
 
                  exp = parse_exp_1 (&action_exp, 
-                                    block_for_pc (t->loc->address), 1);
+                                    block_for_pc (tloc->address), 1);
                  old_chain = make_cleanup (free_current_contents, &exp);
 
-                 aexpr = gen_eval_for_expr (t->loc->address, exp);
+                 aexpr = gen_eval_for_expr (tloc->address, exp);
                  old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
                  ax_reqs (aexpr, &areqs);
@@ -2224,6 +2235,7 @@ trace_dump_command (char *args, int from_tty)
   struct cleanup *old_cleanups;
   int stepping_actions = 0;
   int stepping_frame = 0;
+  struct bp_location *loc;
 
   if (tracepoint_number == -1)
     {
@@ -2249,7 +2261,14 @@ trace_dump_command (char *args, int from_tty)
   regcache = get_current_regcache ();
   gdbarch = get_regcache_arch (regcache);
 
-  stepping_frame = (t->loc->address != (regcache_read_pc (regcache)));
+  /* If the traceframe's address matches any of the tracepoint's
+     locations, assume it is a direct hit rather than a while-stepping
+     frame.  (FIXME this is not reliable, should record each frame's
+     type.)  */
+  stepping_frame = 1;
+  for (loc = t->loc; loc; loc = loc->next)
+    if (loc->address == regcache_read_pc (regcache))
+      stepping_frame = 0;
 
   for (action = t->actions; action; action = action->next)
     {
@@ -3239,6 +3258,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
     error (_("Premature end of file while reading trace file"));
 
   tp = get_tracepoint_by_number_on_target (tpnum);
+  /* FIXME this is a poor heuristic if multiple locations */
   if (tp && tp->loc)
     addr = tp->loc->address;