gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / dummy-frame.c
index a13601bddb983fb6afb31678ebdba616a8033662..d47cfd2d9a2dd57e0c035021978cc4c2d9675cb7 100644 (file)
@@ -1,6 +1,6 @@
 /* Code dealing with dummy stack frames, for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2014 Free Software Foundation, Inc.
+   Copyright (C) 1986-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "frame-unwind.h"
 #include "command.h"
 #include "gdbcmd.h"
-#include "observer.h"
+#include "observable.h"
 #include "gdbthread.h"
+#include "infcall.h"
+#include "gdbarch.h"
 
 struct dummy_frame_id
 {
@@ -36,7 +38,7 @@ struct dummy_frame_id
   struct frame_id id;
 
   /* The thread this dummy_frame relates to.  */
-  ptid_t ptid;
+  thread_info *thread;
 };
 
 /* Return whether dummy_frame_id *ID1 and *ID2 are equal.  */
@@ -45,9 +47,23 @@ static int
 dummy_frame_id_eq (struct dummy_frame_id *id1,
                   struct dummy_frame_id *id2)
 {
-  return frame_id_eq (id1->id, id2->id) && ptid_equal (id1->ptid, id2->ptid);
+  return frame_id_eq (id1->id, id2->id) && id1->thread == id2->thread;
 }
 
+/* List of dummy_frame destructors.  */
+
+struct dummy_frame_dtor_list
+{
+  /* Next element in the list or NULL if this is the last element.  */
+  struct dummy_frame_dtor_list *next;
+
+  /* If non-NULL, a destructor that is run when this dummy frame is freed.  */
+  dummy_frame_dtor_ftype *dtor;
+
+  /* Arbitrary data that is passed to DTOR.  */
+  void *dtor_data;
+};
+
 /* Dummy frame.  This saves the processor state just prior to setting
    up the inferior function call.  Older targets save the registers
    on the target stack (but that really slows down function calls).  */
@@ -61,6 +77,10 @@ struct dummy_frame
 
   /* The caller's state prior to the call.  */
   struct infcall_suspend_state *caller_state;
+
+  /* First element of destructors list or NULL if there are no
+     destructors registered for this dummy_frame.  */
+  struct dummy_frame_dtor_list *dtor_list;
 };
 
 static struct dummy_frame *dummy_frame_stack = NULL;
@@ -70,14 +90,14 @@ static struct dummy_frame *dummy_frame_stack = NULL;
 
 void
 dummy_frame_push (struct infcall_suspend_state *caller_state,
-                 const struct frame_id *dummy_id, ptid_t ptid)
+                 const frame_id *dummy_id, thread_info *thread)
 {
   struct dummy_frame *dummy_frame;
 
   dummy_frame = XCNEW (struct dummy_frame);
   dummy_frame->caller_state = caller_state;
   dummy_frame->id.id = (*dummy_id);
-  dummy_frame->id.ptid = ptid;
+  dummy_frame->id.thread = thread;
   dummy_frame->next = dummy_frame_stack;
   dummy_frame_stack = dummy_frame;
 }
@@ -89,6 +109,15 @@ remove_dummy_frame (struct dummy_frame **dummy_ptr)
 {
   struct dummy_frame *dummy = *dummy_ptr;
 
+  while (dummy->dtor_list != NULL)
+    {
+      struct dummy_frame_dtor_list *list = dummy->dtor_list;
+
+      dummy->dtor_list = list->next;
+      list->dtor (list->dtor_data, 0);
+      xfree (list);
+    }
+
   *dummy_ptr = dummy->next;
   discard_infcall_suspend_state (dummy->caller_state);
   xfree (dummy);
@@ -97,12 +126,10 @@ remove_dummy_frame (struct dummy_frame **dummy_ptr)
 /* Delete any breakpoint B which is a momentary breakpoint for return from
    inferior call matching DUMMY_VOIDP.  */
 
-static int
-pop_dummy_frame_bpt (struct breakpoint *b, void *dummy_voidp)
+static bool
+pop_dummy_frame_bpt (struct breakpoint *b, struct dummy_frame *dummy)
 {
-  struct dummy_frame *dummy = dummy_voidp;
-
-  if (b->thread == pid_to_thread_id (dummy->id.ptid)
+  if (b->thread == dummy->id.thread->global_num
       && b->disposition == disp_del && frame_id_eq (b->frame_id, dummy->id.id))
     {
       while (b->related_breakpoint != b)
@@ -111,11 +138,11 @@ pop_dummy_frame_bpt (struct breakpoint *b, void *dummy_voidp)
       delete_breakpoint (b);
 
       /* Stop the traversal.  */
-      return 1;
+      return true;
     }
 
   /* Continue the traversal.  */
-  return 0;
+  return false;
 }
 
 /* Pop *DUMMY_PTR, restoring program state to that before the
@@ -126,10 +153,23 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr)
 {
   struct dummy_frame *dummy = *dummy_ptr;
 
-  gdb_assert (ptid_equal (dummy->id.ptid, inferior_ptid));
+  gdb_assert (dummy->id.thread == inferior_thread ());
+
+  while (dummy->dtor_list != NULL)
+    {
+      struct dummy_frame_dtor_list *list = dummy->dtor_list;
+
+      dummy->dtor_list = list->next;
+      list->dtor (list->dtor_data, 1);
+      xfree (list);
+    }
+
   restore_infcall_suspend_state (dummy->caller_state);
 
-  iterate_over_breakpoints (pop_dummy_frame_bpt, dummy);
+  iterate_over_breakpoints ([dummy] (breakpoint* bp)
+    {
+      return pop_dummy_frame_bpt (bp, dummy);
+    });
 
   /* restore_infcall_control_state frees inf_state,
      all that remains is to pop *dummy_ptr.  */
@@ -158,16 +198,16 @@ lookup_dummy_frame (struct dummy_frame_id *dummy_id)
   return NULL;
 }
 
-/* Find the dummy frame by DUMMY_ID and PTID, and pop it, restoring
+/* Find the dummy frame by DUMMY_ID and THREAD, and pop it, restoring
    program state to that before the frame was created.
    On return reinit_frame_cache has been called.
    If the frame isn't found, flag an internal error.  */
 
 void
-dummy_frame_pop (struct frame_id dummy_id, ptid_t ptid)
+dummy_frame_pop (frame_id dummy_id, thread_info *thread)
 {
   struct dummy_frame **dp;
-  struct dummy_frame_id id = { dummy_id, ptid };
+  struct dummy_frame_id id = { dummy_id, thread };
 
   dp = lookup_dummy_frame (&id);
   gdb_assert (dp != NULL);
@@ -180,16 +220,54 @@ dummy_frame_pop (struct frame_id dummy_id, ptid_t ptid)
    free its memory.  */
 
 void
-dummy_frame_discard (struct frame_id dummy_id, ptid_t ptid)
+dummy_frame_discard (struct frame_id dummy_id, thread_info *thread)
 {
   struct dummy_frame **dp;
-  struct dummy_frame_id id = { dummy_id, ptid };
+  struct dummy_frame_id id = { dummy_id, thread };
 
   dp = lookup_dummy_frame (&id);
   if (dp)
     remove_dummy_frame (dp);
 }
 
+/* See dummy-frame.h.  */
+
+void
+register_dummy_frame_dtor (frame_id dummy_id, thread_info *thread,
+                          dummy_frame_dtor_ftype *dtor, void *dtor_data)
+{
+  struct dummy_frame_id id = { dummy_id, thread };
+  struct dummy_frame **dp, *d;
+  struct dummy_frame_dtor_list *list;
+
+  dp = lookup_dummy_frame (&id);
+  gdb_assert (dp != NULL);
+  d = *dp;
+  list = XNEW (struct dummy_frame_dtor_list);
+  list->next = d->dtor_list;
+  d->dtor_list = list;
+  list->dtor = dtor;
+  list->dtor_data = dtor_data;
+}
+
+/* See dummy-frame.h.  */
+
+int
+find_dummy_frame_dtor (dummy_frame_dtor_ftype *dtor, void *dtor_data)
+{
+  struct dummy_frame *d;
+
+  for (d = dummy_frame_stack; d != NULL; d = d->next)
+    {
+      struct dummy_frame_dtor_list *list;
+
+      for (list = d->dtor_list; list != NULL; list = list->next)
+       if (list->dtor == dtor && list->dtor_data == dtor_data)
+         return 1;
+    }
+  return 0;
+}
+
 /* There may be stale dummy frames, perhaps left over from when an uncaught
    longjmp took us out of a function that was called by the debugger.  Clean
    them up at least once whenever we start a new inferior.  */
@@ -206,7 +284,7 @@ cleanup_dummy_frames (struct target_ops *target, int from_tty)
 struct dummy_frame_cache
 {
   struct frame_id this_id;
-  struct regcache *prev_regcache;
+  readonly_detached_regcache *prev_regcache;
 };
 
 static int
@@ -230,7 +308,7 @@ dummy_frame_sniffer (const struct frame_unwind *self,
         dummy ID, assuming it is a dummy frame.  */
       struct frame_id this_id
        = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
-      struct dummy_frame_id dummy_id = { this_id, inferior_ptid };
+      struct dummy_frame_id dummy_id = { this_id, inferior_thread () };
 
       /* Use that ID to find the corresponding cache entry.  */
       for (dummyframe = dummy_frame_stack;
@@ -261,7 +339,8 @@ dummy_frame_prev_register (struct frame_info *this_frame,
                           void **this_prologue_cache,
                           int regnum)
 {
-  struct dummy_frame_cache *cache = (*this_prologue_cache);
+  struct dummy_frame_cache *cache
+    = (struct dummy_frame_cache *) *this_prologue_cache;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct value *reg_val;
 
@@ -275,8 +354,8 @@ dummy_frame_prev_register (struct frame_info *this_frame,
   /* Use the regcache_cooked_read() method so that it, on the fly,
      constructs either a raw or pseudo register from the raw
      register cache.  */
-  regcache_cooked_read (cache->prev_regcache, regnum,
-                       value_contents_writeable (reg_val));
+  cache->prev_regcache->cooked_read (regnum,
+                                    value_contents_writeable (reg_val));
   return reg_val;
 }
 
@@ -291,7 +370,8 @@ dummy_frame_this_id (struct frame_info *this_frame,
                     struct frame_id *this_id)
 {
   /* The dummy-frame sniffer always fills in the cache.  */
-  struct dummy_frame_cache *cache = (*this_prologue_cache);
+  struct dummy_frame_cache *cache
+    = (struct dummy_frame_cache *) *this_prologue_cache;
 
   gdb_assert (cache != NULL);
   (*this_id) = cache->this_id;
@@ -307,6 +387,18 @@ const struct frame_unwind dummy_frame_unwind =
   dummy_frame_sniffer,
 };
 
+/* See dummy-frame.h.  */
+
+struct frame_id
+default_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  CORE_ADDR sp, pc;
+
+  sp = get_frame_sp (this_frame);
+  pc = get_frame_pc (this_frame);
+  return frame_id_build (sp, pc);
+}
+
 static void
 fprint_dummy_frames (struct ui_file *file)
 {
@@ -319,37 +411,33 @@ fprint_dummy_frames (struct ui_file *file)
       fprintf_unfiltered (file, " id=");
       fprint_frame_id (file, s->id.id);
       fprintf_unfiltered (file, ", ptid=%s",
-                         target_pid_to_str (s->id.ptid));
+                         target_pid_to_str (s->id.thread->ptid).c_str ());
       fprintf_unfiltered (file, "\n");
     }
 }
 
 static void
-maintenance_print_dummy_frames (char *args, int from_tty)
+maintenance_print_dummy_frames (const char *args, int from_tty)
 {
   if (args == NULL)
     fprint_dummy_frames (gdb_stdout);
   else
     {
-      struct cleanup *cleanups;
-      struct ui_file *file = gdb_fopen (args, "w");
+      stdio_file file;
 
-      if (file == NULL)
+      if (!file.open (args, "w"))
        perror_with_name (_("maintenance print dummy-frames"));
-      cleanups = make_cleanup_ui_file_delete (file);
-      fprint_dummy_frames (file);    
-      do_cleanups (cleanups);
+      fprint_dummy_frames (&file);
     }
 }
 
-extern void _initialize_dummy_frame (void);
-
+void _initialize_dummy_frame ();
 void
-_initialize_dummy_frame (void)
+_initialize_dummy_frame ()
 {
   add_cmd ("dummy-frames", class_maintenance, maintenance_print_dummy_frames,
           _("Print the contents of the internal dummy-frame stack."),
           &maintenanceprintlist);
 
-  observer_attach_inferior_created (cleanup_dummy_frames);
+  gdb::observers::inferior_created.attach (cleanup_dummy_frames);
 }
This page took 0.037455 seconds and 4 git commands to generate.