2010-01-21 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 58102ec1e177c9f98e544ddafdf34eab866cc936..d404ee7e8d512229858b80995aba3e1222c12465 100644 (file)
@@ -187,8 +187,6 @@ static void stopat_command (char *arg, int from_tty);
 
 static char *ep_parse_optional_if_clause (char **arg);
 
-static char *ep_parse_optional_filename (char **arg);
-
 static void catch_exception_command_1 (enum exception_event_kind ex_event, 
                                       char *arg, int tempflag, int from_tty);
 
@@ -353,7 +351,7 @@ static int overlay_events_enabled;
 
 #define ALL_TRACEPOINTS(B)  \
   for (B = breakpoint_chain; B; B = B->next)  \
-    if ((B)->type == bp_tracepoint)
+    if (tracepoint_type (B))
 
 /* Chains of all breakpoints defined.  */
 
@@ -422,6 +420,14 @@ clear_breakpoint_hit_counts (void)
     b->hit_count = 0;
 }
 
+/* Encapsulate tests for different types of tracepoints.  */
+
+static int
+tracepoint_type (const struct breakpoint *b)
+{
+  return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
+}
+  
 /* Default address, symtab and line to put a breakpoint at
    for "break" command with no arg.
    if default_breakpoint_valid is zero, the other three are
@@ -1282,7 +1288,7 @@ should_be_inserted (struct bp_location *bpt)
 
   /* Tracepoints are inserted by the target at a time of its choosing,
      not by us.  */
-  if (bpt->owner->type == bp_tracepoint)
+  if (tracepoint_type (bpt->owner))
     return 0;
 
   return 1;
@@ -2977,6 +2983,7 @@ print_it_typical (bpstat bs)
     case bp_watchpoint_scope:
     case bp_call_dummy:
     case bp_tracepoint:
+    case bp_fast_tracepoint:
     case bp_jit_event:
     default:
       result = PRINT_UNKNOWN;
@@ -3210,6 +3217,17 @@ watchpoint_check (void *p)
       struct gdbarch *frame_arch = get_frame_arch (frame);
       CORE_ADDR frame_pc = get_frame_pc (frame);
 
+      /* in_function_epilogue_p() returns a non-zero value if we're still
+        in the function but the stack frame has already been invalidated.
+        Since we can't rely on the values of local variables after the
+        stack has been destroyed, we are treating the watchpoint in that
+        state as `not changed' without further checking.  Don't mark
+        watchpoints as changed if the current frame is in an epilogue -
+        even if they are in some other frame, our view of the stack
+        is likely to be wrong and frame_find_by_id could error out.  */
+      if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+       return WP_VALUE_NOT_CHANGED;
+
       fr = frame_find_by_id (b->watchpoint_frame);
       within_current_scope = (fr != NULL);
 
@@ -3226,17 +3244,6 @@ watchpoint_check (void *p)
            within_current_scope = 0;
        }
 
-      /* in_function_epilogue_p() returns a non-zero value if we're still
-        in the function but the stack frame has already been invalidated.
-        Since we can't rely on the values of local variables after the
-        stack has been destroyed, we are treating the watchpoint in that
-        state as `not changed' without further checking.  Don't mark
-        watchpoints as changed if the current frame is in an epilogue -
-        even if they are in some other frame, our view of the stack
-        is likely to be wrong.  */
-      if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
-       return WP_VALUE_NOT_CHANGED;
-
       if (within_current_scope)
        /* If we end up stopping, the current frame will get selected
           in normal_stop.  So this call to select_frame won't affect
@@ -3322,7 +3329,7 @@ bpstat_check_location (const struct bp_location *bl,
 
   /* By definition, the inferior does not report stops at
      tracepoints.  */
-  if (b->type == bp_tracepoint)
+  if (tracepoint_type (b))
     return 0;
 
   if (b->type != bp_watchpoint
@@ -3914,11 +3921,12 @@ bpstat_what (bpstat bs)
          retval.call_dummy = 1;
          break;
        case bp_tracepoint:
+       case bp_fast_tracepoint:
          /* Tracepoint hits should not be reported back to GDB, and
             if one got through somehow, it should have been filtered
             out already.  */
          internal_error (__FILE__, __LINE__,
-                         _("bpstat_what: bp_tracepoint encountered"));
+                         _("bpstat_what: tracepoint encountered"));
          break;
        }
       current_action = table[(int) bs_class][(int) current_action];
@@ -4044,6 +4052,7 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_longjmp_master, "longjmp master"},
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
+    {bp_fast_tracepoint, "fast tracepoint"},
     {bp_jit_event, "jit events"},
   };
   
@@ -4173,6 +4182,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_overlay_event:
       case bp_longjmp_master:
       case bp_tracepoint:
+      case bp_fast_tracepoint:
       case bp_jit_event:
        if (opts.addressprint)
          {
@@ -4258,7 +4268,7 @@ print_one_breakpoint_location (struct breakpoint *b,
          because the condition is an internal implementation detail
          that we do not want to expose to the user.  */
       annotate_field (7);
-      if (b->type == bp_tracepoint)
+      if (tracepoint_type (b))
        ui_out_text (uiout, "\ttrace only if ");
       else
        ui_out_text (uiout, "\tstop only if ");
@@ -4451,7 +4461,7 @@ user_settable_breakpoint (const struct breakpoint *b)
   return (b->type == bp_breakpoint
          || b->type == bp_catchpoint
          || b->type == bp_hardware_breakpoint
-         || b->type == bp_tracepoint
+         || tracepoint_type (b)
          || b->type == bp_watchpoint
          || b->type == bp_read_watchpoint
          || b->type == bp_access_watchpoint
@@ -4804,6 +4814,7 @@ allocate_bp_location (struct breakpoint *bpt)
     {
     case bp_breakpoint:
     case bp_tracepoint:
+    case bp_fast_tracepoint:
     case bp_until:
     case bp_finish:
     case bp_longjmp:
@@ -4900,7 +4911,7 @@ set_breakpoint_location_function (struct bp_location *loc)
 {
   if (loc->owner->type == bp_breakpoint
       || loc->owner->type == bp_hardware_breakpoint
-      || loc->owner->type == bp_tracepoint)
+      || tracepoint_type (loc->owner))
     {
       find_pc_partial_function (loc->address, &(loc->function_name), 
                                NULL, NULL);
@@ -5159,7 +5170,7 @@ disable_breakpoints_in_shlibs (void)
        to insert those breakpoints and fail.  */
     if (((b->type == bp_breakpoint)
         || (b->type == bp_hardware_breakpoint)
-        || (b->type == bp_tracepoint))
+        || (tracepoint_type (b)))
        && loc->pspace == current_program_space
        && !loc->shlib_disabled
 #ifdef PC_SOLIB
@@ -6091,6 +6102,16 @@ mention (struct breakpoint *b)
        printf_filtered (_(" %d"), b->number);
        say_where = 1;
        break;
+      case bp_fast_tracepoint:
+       if (ui_out_is_mi_like_p (uiout))
+         {
+           say_where = 0;
+           break;
+         }
+       printf_filtered (_("Fast tracepoint"));
+       printf_filtered (_(" %d"), b->number);
+       say_where = 1;
+       break;
 
       case bp_until:
       case bp_finish:
@@ -6593,6 +6614,38 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
     resolve_sal_pc (&sals->sals[i]);
 }
 
+/* Fast tracepoints may have restrictions on valid locations.  For
+   instance, a fast tracepoint using a jump instead of a trap will
+   likely have to overwrite more bytes than a trap would, and so can
+   only be placed where the instruction is longer than the jump, or a
+   multi-instruction sequence does not have a jump into the middle of
+   it, etc.  */
+
+static void
+check_fast_tracepoint_sals (struct gdbarch *gdbarch,
+                           struct symtabs_and_lines *sals)
+{
+  int i, rslt;
+  struct symtab_and_line *sal;
+  char *msg;
+  struct cleanup *old_chain;
+
+  for (i = 0; i < sals->nelts; i++)
+    {
+      sal = &sals->sals[i];
+
+      rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc,
+                                              NULL, &msg);
+      old_chain = make_cleanup (xfree, msg);
+
+      if (!rslt)
+       error (_("May not have a fast tracepoint at 0x%s%s"),
+              paddress (gdbarch, sal->pc), (msg ? msg : ""));
+
+      do_cleanups (old_chain);
+    }
+}
+
 static void
 do_captured_parse_breakpoint (struct ui_out *ui, void *data)
 {
@@ -6794,9 +6847,13 @@ break_command_really (struct gdbarch *gdbarch,
     breakpoint_sals_to_pc (&sals, addr_start);
 
   type_wanted = (traceflag
-                ? bp_tracepoint
+                ? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
                 : (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
 
+  /* Fast tracepoints may have additional restrictions on location.  */
+  if (type_wanted == bp_fast_tracepoint)
+    check_fast_tracepoint_sals (gdbarch, &sals);
+
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
      breakpoint. */
@@ -7592,42 +7649,6 @@ ep_parse_optional_if_clause (char **arg)
   return cond_string;
 }
 
-/* This function attempts to parse an optional filename from the arg
-   string.  If one is not found, it returns NULL.
-
-   Else, it returns a pointer to the parsed filename.  (This function
-   makes no attempt to verify that a file of that name exists, or is
-   accessible.)  And, it updates arg to point to the first character
-   following the parsed filename in the arg string.
-
-   Note that clients needing to preserve the returned filename for
-   future access should copy it to their own buffers. */
-static char *
-ep_parse_optional_filename (char **arg)
-{
-  static char filename[1024];
-  char *arg_p = *arg;
-  int i;
-  char c;
-
-  if ((*arg_p == '\0') || isspace (*arg_p))
-    return NULL;
-
-  for (i = 0;; i++)
-    {
-      c = *arg_p;
-      if (isspace (c))
-       c = '\0';
-      filename[i] = c;
-      if (c == '\0')
-       break;
-      arg_p++;
-    }
-  *arg = arg_p;
-
-  return filename;
-}
-
 /* Commands to deal with catching events, such as signals, exceptions,
    process start/exit, etc.  */
 
@@ -8970,6 +8991,7 @@ breakpoint_re_set_one (void *bint)
     case bp_breakpoint:
     case bp_hardware_breakpoint:
     case bp_tracepoint:
+    case bp_fast_tracepoint:
       /* Do not attempt to re-set breakpoints disabled during startup.  */
       if (b->enable_state == bp_startup_disabled)
        return 0;
@@ -9369,6 +9391,7 @@ disable_command (char *args, int from_tty)
        continue;
       case bp_breakpoint:
       case bp_tracepoint:
+      case bp_fast_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -9462,6 +9485,7 @@ enable_command (char *args, int from_tty)
        continue;
       case bp_breakpoint:
       case bp_tracepoint:
+      case bp_fast_tracepoint:
       case bp_catchpoint:
       case bp_hardware_breakpoint:
       case bp_watchpoint:
@@ -9769,6 +9793,77 @@ trace_command (char *arg, int from_tty)
   set_tracepoint_count (breakpoint_count);
 }
 
+void
+ftrace_command (char *arg, int from_tty)
+{
+  break_command_really (get_current_arch (),
+                       arg, 
+                       NULL, 0, 1 /* parse arg */,
+                       0 /* tempflag */, 1 /* hardwareflag */,
+                       1 /* traceflag */,
+                       0 /* Ignore count */,
+                       pending_break_support, 
+                       NULL,
+                       from_tty,
+                       1 /* enabled */);
+  set_tracepoint_count (breakpoint_count);
+}
+
+/* Given information about a tracepoint as recorded on a target (which
+   can be either a live system or a trace file), attempt to create an
+   equivalent GDB tracepoint.  This is not a reliable process, since
+   the target does not necessarily have all the information used when
+   the tracepoint was originally defined.  */
+  
+struct breakpoint *
+create_tracepoint_from_upload (struct uploaded_tp *utp)
+{
+  char buf[100];
+  struct breakpoint *tp;
+  
+  /* In the absence of a source location, fall back to raw address.  */
+  sprintf (buf, "*%s", paddress (get_current_arch(), utp->addr));
+
+  break_command_really (get_current_arch (),
+                       buf, 
+                       NULL, 0, 1 /* parse arg */,
+                       0 /* tempflag */,
+                       (utp->type == bp_fast_tracepoint) /* hardwareflag */,
+                       1 /* traceflag */,
+                       0 /* Ignore count */,
+                       pending_break_support, 
+                       NULL,
+                       0 /* from_tty */,
+                       utp->enabled /* enabled */);
+  set_tracepoint_count (breakpoint_count);
+  
+    tp = get_tracepoint (tracepoint_count);
+
+  if (utp->pass > 0)
+    {
+      sprintf (buf, "%d %d", utp->pass, tp->number);
+
+      trace_pass_command (buf, 0);
+    }
+
+  if (utp->cond)
+    {
+      printf_filtered ("Want to restore a condition\n");
+    }
+
+  if (utp->numactions > 0)
+    {
+      printf_filtered ("Want to restore action list\n");
+    }
+
+  if (utp->num_step_actions > 0)
+    {
+      printf_filtered ("Want to restore action list\n");
+    }
+
+  return tp;
+  }
+  
 /* Print information on tracepoint number TPNUM_EXP, or all if
    omitted.  */
 
@@ -9846,7 +9941,7 @@ delete_trace_command (char *arg, int from_tty)
        {
          ALL_BREAKPOINTS_SAFE (b, temp)
          {
-           if (b->type == bp_tracepoint
+           if (tracepoint_type (b)
                && b->number >= 0)
              delete_breakpoint (b);
          }
@@ -9919,6 +10014,22 @@ get_tracepoint (int num)
   return NULL;
 }
 
+/* Find the tracepoint with the given target-side number (which may be
+   different from the tracepoint number after disconnecting and
+   reconnecting).  */
+
+struct breakpoint *
+get_tracepoint_by_number_on_target (int num)
+{
+  struct breakpoint *t;
+
+  ALL_TRACEPOINTS (t)
+    if (t->number_on_target == num)
+      return t;
+
+  return NULL;
+}
+
 /* Utility: parse a tracepoint number and look it up in the list.
    If MULTI_P is true, there might be a range of tracepoints in ARG.
    if OPTIONAL_P is true, then if the argument is missing, the most
@@ -10501,6 +10612,13 @@ Do \"help tracepoints\" for info on other tracepoint commands."));
   add_com_alias ("tra", "trace", class_alias, 1);
   add_com_alias ("trac", "trace", class_alias, 1);
 
+  c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
+Set a fast tracepoint at specified line or function.\n\
+\n"
+BREAK_ARGS_HELP ("ftrace") "\n\
+Do \"help tracepoints\" for info on other tracepoint commands."));
+  set_cmd_completer (c, location_completer);
+
   add_info ("tracepoints", tracepoints_info, _("\
 Status of tracepoints, or tracepoint number NUMBER.\n\
 Convenience variable \"$tpnum\" contains the number of the\n\
This page took 0.030918 seconds and 4 git commands to generate.