Add end_psymtab_common, have all debug info readers call it.
[deliverable/binutils-gdb.git] / gdb / record-btrace.c
index af7b65feda253181d79634c72edc88b5ff3cd4aa..2f4317161fec8de6f9e0dba0a4bf1a7de45831cb 100644 (file)
@@ -80,6 +80,10 @@ static struct cmd_list_element *record_btrace_cmdlist;
 static struct cmd_list_element *set_record_btrace_bts_cmdlist;
 static struct cmd_list_element *show_record_btrace_bts_cmdlist;
 
+/* Command lists for "set/show record btrace pt".  */
+static struct cmd_list_element *set_record_btrace_pt_cmdlist;
+static struct cmd_list_element *show_record_btrace_pt_cmdlist;
+
 /* Print a record-btrace debug message.  Use do ... while (0) to avoid
    ambiguities when used in if statements.  */
 
@@ -139,13 +143,15 @@ require_btrace (void)
 static void
 record_btrace_enable_warn (struct thread_info *tp)
 {
-  volatile struct gdb_exception error;
-
-  TRY_CATCH (error, RETURN_MASK_ERROR)
-    btrace_enable (tp, &record_btrace_conf);
-
-  if (error.message != NULL)
-    warning ("%s", error.message);
+  TRY
+    {
+      btrace_enable (tp, &record_btrace_conf);
+    }
+  CATCH (error, RETURN_MASK_ERROR)
+    {
+      warning ("%s", error.message);
+    }
+  END_CATCH
 }
 
 /* Callback function to disable branch tracing for one thread.  */
@@ -276,17 +282,14 @@ record_btrace_close (struct target_ops *self)
 /* The to_async method of target record-btrace.  */
 
 static void
-record_btrace_async (struct target_ops *ops,
-                    void (*callback) (enum inferior_event_type event_type,
-                                      void *context),
-                    void *context)
+record_btrace_async (struct target_ops *ops, int enable)
 {
-  if (callback != NULL)
+  if (enable)
     mark_async_event_handler (record_btrace_async_inferior_event_handler);
   else
     clear_async_event_handler (record_btrace_async_inferior_event_handler);
 
-  ops->beneath->to_async (ops->beneath, callback, context);
+  ops->beneath->to_async (ops->beneath, enable);
 }
 
 /* Adjusts the size and returns a human readable size suffix.  */
@@ -333,6 +336,22 @@ record_btrace_print_bts_conf (const struct btrace_config_bts *conf)
     }
 }
 
+/* Print an Intel(R) Processor Trace configuration.  */
+
+static void
+record_btrace_print_pt_conf (const struct btrace_config_pt *conf)
+{
+  const char *suffix;
+  unsigned int size;
+
+  size = conf->size;
+  if (size > 0)
+    {
+      suffix = record_btrace_adjust_size (&size);
+      printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+    }
+}
+
 /* Print a branch tracing configuration.  */
 
 static void
@@ -349,6 +368,10 @@ record_btrace_print_conf (const struct btrace_config *conf)
     case BTRACE_FORMAT_BTS:
       record_btrace_print_bts_conf (&conf->bts);
       return;
+
+    case BTRACE_FORMAT_PT:
+      record_btrace_print_pt_conf (&conf->pt);
+      return;
     }
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
@@ -459,6 +482,33 @@ btrace_ui_out_decode_error (struct ui_out *uiout, int errcode,
          break;
        }
       break;
+
+#if defined (HAVE_LIBIPT)
+    case BTRACE_FORMAT_PT:
+      switch (errcode)
+       {
+       case BDE_PT_USER_QUIT:
+         is_error = 0;
+         errstr = _("trace decode cancelled");
+         break;
+
+       case BDE_PT_DISABLED:
+         is_error = 0;
+         errstr = _("disabled");
+         break;
+
+       case BDE_PT_OVERFLOW:
+         is_error = 0;
+         errstr = _("overflow");
+         break;
+
+       default:
+         if (errcode < 0)
+           errstr = pt_errstr (pt_errcode (errcode));
+         break;
+       }
+      break;
+#endif /* defined (HAVE_LIBIPT)  */
     }
 
   ui_out_text (uiout, _("["));
@@ -517,14 +567,35 @@ btrace_insn_history (struct ui_out *uiout,
        }
       else
        {
+         char prefix[4];
+
+         /* We may add a speculation prefix later.  We use the same space
+            that is used for the pc prefix.  */
+         if ((flags & DISASSEMBLY_OMIT_PC) == 0)
+           strncpy (prefix, pc_prefix (insn->pc), 3);
+         else
+           {
+             prefix[0] = ' ';
+             prefix[1] = ' ';
+             prefix[2] = ' ';
+           }
+         prefix[3] = 0;
+
          /* Print the instruction index.  */
          ui_out_field_uint (uiout, "index", btrace_insn_number (&it));
          ui_out_text (uiout, "\t");
 
+         /* Indicate speculative execution by a leading '?'.  */
+         if ((insn->flags & BTRACE_INSN_FLAG_SPECULATIVE) != 0)
+           prefix[0] = '?';
+
+         /* Print the prefix; we tell gdb_disassembly below to omit it.  */
+         ui_out_field_fmt (uiout, "prefix", "%s", prefix);
+
          /* Disassembly with '/m' flag may not produce the expected result.
             See PR gdb/11833.  */
-         gdb_disassembly (gdbarch, uiout, NULL, flags, 1, insn->pc,
-                          insn->pc + 1);
+         gdb_disassembly (gdbarch, uiout, NULL, flags | DISASSEMBLY_OMIT_PC,
+                          1, insn->pc, insn->pc + 1);
        }
     }
 }
@@ -1140,7 +1211,6 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
                                 struct gdbarch *gdbarch,
                                 struct bp_target_info *bp_tgt)
 {
-  volatile struct gdb_exception except;
   const char *old;
   int ret;
 
@@ -1150,14 +1220,18 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
   replay_memory_access = replay_memory_access_read_write;
 
   ret = 0;
-  TRY_CATCH (except, RETURN_MASK_ALL)
-    ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
-
+  TRY
+    {
+      ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      replay_memory_access = old;
+      throw_exception (except);
+    }
+  END_CATCH
   replay_memory_access = old;
 
-  if (except.reason < 0)
-    throw_exception (except);
-
   return ret;
 }
 
@@ -1168,7 +1242,6 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
                                 struct gdbarch *gdbarch,
                                 struct bp_target_info *bp_tgt)
 {
-  volatile struct gdb_exception except;
   const char *old;
   int ret;
 
@@ -1178,14 +1251,18 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
   replay_memory_access = replay_memory_access_read_write;
 
   ret = 0;
-  TRY_CATCH (except, RETURN_MASK_ALL)
-    ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
-
+  TRY
+    {
+      ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt);
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      replay_memory_access = old;
+      throw_exception (except);
+    }
+  END_CATCH
   replay_memory_access = old;
 
-  if (except.reason < 0)
-    throw_exception (except);
-
   return ret;
 }
 
@@ -1622,7 +1699,6 @@ record_btrace_find_resume_thread (ptid_t ptid)
 static struct btrace_insn_iterator *
 record_btrace_start_replaying (struct thread_info *tp)
 {
-  volatile struct gdb_exception except;
   struct btrace_insn_iterator *replay;
   struct btrace_thread_info *btinfo;
   int executing;
@@ -1649,7 +1725,7 @@ record_btrace_start_replaying (struct thread_info *tp)
      Since frames are computed differently when we're replaying, we need to
      recompute those stored frames and fix them up so we can still detect
      subroutines after we started replaying.  */
-  TRY_CATCH (except, RETURN_MASK_ALL)
+  TRY
     {
       struct frame_info *frame;
       struct frame_id frame_id;
@@ -1697,12 +1773,11 @@ record_btrace_start_replaying (struct thread_info *tp)
       if (upd_step_stack_frame_id)
        tp->control.step_stack_frame_id = frame_id;
     }
-
-  /* Restore the previous execution state.  */
-  set_executing (tp->ptid, executing);
-
-  if (except.reason < 0)
+  CATCH (except, RETURN_MASK_ALL)
     {
+      /* Restore the previous execution state.  */
+      set_executing (tp->ptid, executing);
+
       xfree (btinfo->replay);
       btinfo->replay = NULL;
 
@@ -1710,6 +1785,10 @@ record_btrace_start_replaying (struct thread_info *tp)
 
       throw_exception (except);
     }
+  END_CATCH
+
+  /* Restore the previous execution state.  */
+  set_executing (tp->ptid, executing);
 
   return replay;
 }
@@ -1779,7 +1858,7 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
   /* Async support.  */
   if (target_can_async_p ())
     {
-      target_async (inferior_event_handler, 0);
+      target_async (1);
       mark_async_event_handler (record_btrace_async_inferior_event_handler);
     }
 }
@@ -1954,7 +2033,8 @@ record_btrace_step_thread (struct thread_info *tp)
                 target_pid_to_str (tp->ptid),
                 core_addr_to_string_nz (insn->pc));
 
-         if (breakpoint_here_p (aspace, insn->pc))
+         if (record_check_stopped_by_breakpoint (aspace, insn->pc,
+                                                 &btinfo->stop_reason))
            return btrace_step_stopped ();
        }
 
@@ -1986,7 +2066,8 @@ record_btrace_step_thread (struct thread_info *tp)
                 target_pid_to_str (tp->ptid),
                 core_addr_to_string_nz (insn->pc));
 
-         if (breakpoint_here_p (aspace, insn->pc))
+         if (record_check_stopped_by_breakpoint (aspace, insn->pc,
+                                                 &btinfo->stop_reason))
            return btrace_step_stopped ();
        }
     }
@@ -2044,18 +2125,58 @@ record_btrace_can_execute_reverse (struct target_ops *self)
   return 1;
 }
 
-/* The to_decr_pc_after_break method of target record-btrace.  */
+/* The to_stopped_by_sw_breakpoint method of target record-btrace.  */
 
-static CORE_ADDR
-record_btrace_decr_pc_after_break (struct target_ops *ops,
-                                  struct gdbarch *gdbarch)
+static int
+record_btrace_stopped_by_sw_breakpoint (struct target_ops *ops)
 {
-  /* When replaying, we do not actually execute the breakpoint instruction
-     so there is no need to adjust the PC after hitting a breakpoint.  */
   if (record_btrace_is_replaying (ops))
-    return 0;
+    {
+      struct thread_info *tp = inferior_thread ();
+
+      return tp->btrace.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+    }
+
+  return ops->beneath->to_stopped_by_sw_breakpoint (ops->beneath);
+}
+
+/* The to_supports_stopped_by_sw_breakpoint method of target
+   record-btrace.  */
+
+static int
+record_btrace_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+  if (record_btrace_is_replaying (ops))
+    return 1;
+
+  return ops->beneath->to_supports_stopped_by_sw_breakpoint (ops->beneath);
+}
+
+/* The to_stopped_by_sw_breakpoint method of target record-btrace.  */
+
+static int
+record_btrace_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  if (record_btrace_is_replaying (ops))
+    {
+      struct thread_info *tp = inferior_thread ();
+
+      return tp->btrace.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+    }
+
+  return ops->beneath->to_stopped_by_hw_breakpoint (ops->beneath);
+}
+
+/* The to_supports_stopped_by_hw_breakpoint method of target
+   record-btrace.  */
+
+static int
+record_btrace_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+  if (record_btrace_is_replaying (ops))
+    return 1;
 
-  return ops->beneath->to_decr_pc_after_break (ops->beneath, gdbarch);
+  return ops->beneath->to_supports_stopped_by_hw_breakpoint (ops->beneath);
 }
 
 /* The to_update_thread_list method of target record-btrace.  */
@@ -2112,6 +2233,9 @@ record_btrace_set_replay (struct thread_info *tp,
 
   /* Start anew from the new replay position.  */
   record_btrace_clear_histories (btinfo);
+
+  stop_pc = regcache_read_pc (get_current_regcache ());
+  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
 /* The to_goto_record_begin method of target record-btrace.  */
@@ -2126,8 +2250,6 @@ record_btrace_goto_begin (struct target_ops *self)
 
   btrace_insn_begin (&begin, &tp->btrace);
   record_btrace_set_replay (tp, &begin);
-
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
 /* The to_goto_record_end method of target record-btrace.  */
@@ -2140,8 +2262,6 @@ record_btrace_goto_end (struct target_ops *ops)
   tp = require_btrace_thread ();
 
   record_btrace_set_replay (tp, NULL);
-
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
 /* The to_goto_record method of target record-btrace.  */
@@ -2167,8 +2287,6 @@ record_btrace_goto (struct target_ops *self, ULONGEST insn)
     error (_("No such instruction."));
 
   record_btrace_set_replay (tp, &it);
-
-  print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
 }
 
 /* The to_execution_direction target method.  */
@@ -2238,7 +2356,12 @@ init_record_btrace_ops (void)
   ops->to_goto_record_end = record_btrace_goto_end;
   ops->to_goto_record = record_btrace_goto;
   ops->to_can_execute_reverse = record_btrace_can_execute_reverse;
-  ops->to_decr_pc_after_break = record_btrace_decr_pc_after_break;
+  ops->to_stopped_by_sw_breakpoint = record_btrace_stopped_by_sw_breakpoint;
+  ops->to_supports_stopped_by_sw_breakpoint
+    = record_btrace_supports_stopped_by_sw_breakpoint;
+  ops->to_stopped_by_hw_breakpoint = record_btrace_stopped_by_hw_breakpoint;
+  ops->to_supports_stopped_by_hw_breakpoint
+    = record_btrace_supports_stopped_by_hw_breakpoint;
   ops->to_execution_direction = record_btrace_execution_direction;
   ops->to_prepare_to_generate_core = record_btrace_prepare_to_generate_core;
   ops->to_done_generating_core = record_btrace_done_generating_core;
@@ -2251,21 +2374,43 @@ init_record_btrace_ops (void)
 static void
 cmd_record_btrace_bts_start (char *args, int from_tty)
 {
-  volatile struct gdb_exception exception;
-
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
   record_btrace_conf.format = BTRACE_FORMAT_BTS;
 
-  TRY_CATCH (exception, RETURN_MASK_ALL)
-    execute_command ("target record-btrace", from_tty);
+  TRY
+    {
+      execute_command ("target record-btrace", from_tty);
+    }
+  CATCH (exception, RETURN_MASK_ALL)
+    {
+      record_btrace_conf.format = BTRACE_FORMAT_NONE;
+      throw_exception (exception);
+    }
+  END_CATCH
+}
+
+/* Start recording Intel(R) Processor Trace.  */
 
-  if (exception.error != 0)
+static void
+cmd_record_btrace_pt_start (char *args, int from_tty)
+{
+  if (args != NULL && *args != 0)
+    error (_("Invalid argument."));
+
+  record_btrace_conf.format = BTRACE_FORMAT_PT;
+
+  TRY
+    {
+      execute_command ("target record-btrace", from_tty);
+    }
+  CATCH (exception, RETURN_MASK_ALL)
     {
       record_btrace_conf.format = BTRACE_FORMAT_NONE;
       throw_exception (exception);
     }
+  END_CATCH
 }
 
 /* Alias for "target record".  */
@@ -2273,21 +2418,31 @@ cmd_record_btrace_bts_start (char *args, int from_tty)
 static void
 cmd_record_btrace_start (char *args, int from_tty)
 {
-  volatile struct gdb_exception exception;
-
   if (args != NULL && *args != 0)
     error (_("Invalid argument."));
 
-  record_btrace_conf.format = BTRACE_FORMAT_BTS;
-
-  TRY_CATCH (exception, RETURN_MASK_ALL)
-    execute_command ("target record-btrace", from_tty);
+  record_btrace_conf.format = BTRACE_FORMAT_PT;
 
-  if (exception.error == 0)
-    return;
+  TRY
+    {
+      execute_command ("target record-btrace", from_tty);
+    }
+  CATCH (exception, RETURN_MASK_ALL)
+    {
+      record_btrace_conf.format = BTRACE_FORMAT_BTS;
 
-  record_btrace_conf.format = BTRACE_FORMAT_NONE;
-  throw_exception (exception);
+      TRY
+       {
+         execute_command ("target record-btrace", from_tty);
+       }
+      CATCH (exception, RETURN_MASK_ALL)
+       {
+         record_btrace_conf.format = BTRACE_FORMAT_NONE;
+         throw_exception (exception);
+       }
+      END_CATCH
+    }
+  END_CATCH
 }
 
 /* The "set record btrace" command.  */
@@ -2322,7 +2477,7 @@ static void
 cmd_set_record_btrace_bts (char *args, int from_tty)
 {
   printf_unfiltered (_("\"set record btrace bts\" must be followed "
-                      "by an apporpriate subcommand.\n"));
+                      "by an appropriate subcommand.\n"));
   help_list (set_record_btrace_bts_cmdlist, "set record btrace bts ",
             all_commands, gdb_stdout);
 }
@@ -2335,6 +2490,47 @@ cmd_show_record_btrace_bts (char *args, int from_tty)
   cmd_show_list (show_record_btrace_bts_cmdlist, from_tty, "");
 }
 
+/* The "set record btrace pt" command.  */
+
+static void
+cmd_set_record_btrace_pt (char *args, int from_tty)
+{
+  printf_unfiltered (_("\"set record btrace pt\" must be followed "
+                      "by an appropriate subcommand.\n"));
+  help_list (set_record_btrace_pt_cmdlist, "set record btrace pt ",
+            all_commands, gdb_stdout);
+}
+
+/* The "show record btrace pt" command.  */
+
+static void
+cmd_show_record_btrace_pt (char *args, int from_tty)
+{
+  cmd_show_list (show_record_btrace_pt_cmdlist, from_tty, "");
+}
+
+/* The "record bts buffer-size" show value function.  */
+
+static void
+show_record_bts_buffer_size_value (struct ui_file *file, int from_tty,
+                                  struct cmd_list_element *c,
+                                  const char *value)
+{
+  fprintf_filtered (file, _("The record/replay bts buffer size is %s.\n"),
+                   value);
+}
+
+/* The "record pt buffer-size" show value function.  */
+
+static void
+show_record_pt_buffer_size_value (struct ui_file *file, int from_tty,
+                                 struct cmd_list_element *c,
+                                 const char *value)
+{
+  fprintf_filtered (file, _("The record/replay pt buffer size is %s.\n"),
+                   value);
+}
+
 void _initialize_record_btrace (void);
 
 /* Initialize btrace commands.  */
@@ -2355,6 +2551,13 @@ This format may not be available on all processors."),
           &record_btrace_cmdlist);
   add_alias_cmd ("bts", "btrace bts", class_obscure, 1, &record_cmdlist);
 
+  add_cmd ("pt", class_obscure, cmd_record_btrace_pt_start,
+          _("\
+Start branch trace recording in Intel(R) Processor Trace format.\n\n\
+This format may not be available on all processors."),
+          &record_btrace_cmdlist);
+  add_alias_cmd ("pt", "btrace pt", class_obscure, 1, &record_cmdlist);
+
   add_prefix_cmd ("btrace", class_support, cmd_set_record_btrace,
                  _("Set record options"), &set_record_btrace_cmdlist,
                  "set record btrace ", 0, &set_record_cmdlist);
@@ -2397,10 +2600,32 @@ The actual buffer size may differ from the requested size.  \
 Use \"info record\" to see the actual buffer size.\n\n\
 Bigger buffers allow longer recording but also take more time to process \
 the recorded execution trace.\n\n\
-The trace buffer size may not be changed while recording."), NULL, NULL,
+The trace buffer size may not be changed while recording."), NULL,
+                           show_record_bts_buffer_size_value,
                            &set_record_btrace_bts_cmdlist,
                            &show_record_btrace_bts_cmdlist);
 
+  add_prefix_cmd ("pt", class_support, cmd_set_record_btrace_pt,
+                 _("Set record btrace pt options"),
+                 &set_record_btrace_pt_cmdlist,
+                 "set record btrace pt ", 0, &set_record_btrace_cmdlist);
+
+  add_prefix_cmd ("pt", class_support, cmd_show_record_btrace_pt,
+                 _("Show record btrace pt options"),
+                 &show_record_btrace_pt_cmdlist,
+                 "show record btrace pt ", 0, &show_record_btrace_cmdlist);
+
+  add_setshow_uinteger_cmd ("buffer-size", no_class,
+                           &record_btrace_conf.pt.size,
+                           _("Set the record/replay pt buffer size."),
+                           _("Show the record/replay pt buffer size."), _("\
+Bigger buffers allow longer recording but also take more time to process \
+the recorded execution.\n\
+The actual buffer size may differ from the requested size.  Use \"info record\" \
+to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
+                           &set_record_btrace_pt_cmdlist,
+                           &show_record_btrace_pt_cmdlist);
+
   init_record_btrace_ops ();
   add_target (&record_btrace_ops);
 
@@ -2408,4 +2633,5 @@ The trace buffer size may not be changed while recording."), NULL, NULL,
                               xcalloc, xfree);
 
   record_btrace_conf.bts.size = 64 * 1024;
+  record_btrace_conf.pt.size = 16 * 1024;
 }
This page took 0.032206 seconds and 4 git commands to generate.