gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / progspace.c
index b1abcf929ed96b3f107c3a71758d1d7987f5c204..a0b14a6d2eb7cfec0af972e0343a57c11d3f3201 100644 (file)
@@ -1,6 +1,6 @@
 /* Program and address space management, for GDB, the GNU debugger.
 
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "arch-utils.h"
 #include "gdbcore.h"
 #include "solib.h"
+#include "solist.h"
 #include "gdbthread.h"
+#include "inferior.h"
+#include <algorithm>
 
 /* The last program space number assigned.  */
 int last_program_space_num = 0;
 
 /* The head of the program spaces list.  */
-struct program_space *program_spaces;
+std::vector<struct program_space *> program_spaces;
 
 /* Pointer to the current program space.  */
 struct program_space *current_program_space;
@@ -37,20 +40,19 @@ struct program_space *current_program_space;
 /* The last address space number assigned.  */
 static int highest_address_space_num;
 
-/* Prototypes for local functions */
-
-static void program_space_alloc_data (struct program_space *);
-static void program_space_free_data (struct program_space *);
 \f
 
-/* An address space.  Currently this is not used for much other than
-   for comparing if pspaces/inferior/threads see the same address
-   space.  */
+/* Keep a registry of per-program_space data-pointers required by other GDB
+   modules.  */
 
-struct address_space
-{
-  int num;
-};
+DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD)
+
+/* Keep a registry of per-address_space data-pointers required by other GDB
+   modules.  */
+
+DEFINE_REGISTRY (address_space, REGISTRY_ACCESS_FIELD)
+
+\f
 
 /* Create a new address space object, and add it to the list.  */
 
@@ -59,8 +61,9 @@ new_address_space (void)
 {
   struct address_space *aspace;
 
-  aspace = XZALLOC (struct address_space);
+  aspace = XCNEW (struct address_space);
   aspace->num = ++highest_address_space_num;
+  address_space_alloc_data (aspace);
 
   return aspace;
 }
@@ -72,12 +75,12 @@ new_address_space (void)
 struct address_space *
 maybe_new_address_space (void)
 {
-  int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch);
+  int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
 
   if (shared_aspace)
     {
       /* Just return the first in the list.  */
-      return program_spaces->aspace;
+      return program_spaces[0]->aspace;
     }
 
   return new_address_space ();
@@ -86,6 +89,7 @@ maybe_new_address_space (void)
 static void
 free_address_space (struct address_space *aspace)
 {
+  address_space_free_data (aspace);
   xfree (aspace);
 }
 
@@ -105,100 +109,132 @@ init_address_spaces (void)
 
 \f
 
-/* Adds a new empty program space to the program space list, and binds
-   it to ASPACE.  Returns the pointer to the new object.  */
+/* Remove a program space from the program spaces list.  */
 
-struct program_space *
-add_program_space (struct address_space *aspace)
+static void
+remove_program_space (program_space *pspace)
 {
-  struct program_space *pspace;
-
-  pspace = XZALLOC (struct program_space);
+  gdb_assert (pspace != NULL);
 
-  pspace->num = ++last_program_space_num;
-  pspace->aspace = aspace;
+  auto iter = std::find (program_spaces.begin (), program_spaces.end (),
+                        pspace);
+  gdb_assert (iter != program_spaces.end ());
+  program_spaces.erase (iter);
+}
 
-  program_space_alloc_data (pspace);
+/* See progspace.h.  */
 
-  pspace->next = program_spaces;
-  program_spaces = pspace;
+program_space::program_space (address_space *aspace_)
+  : num (++last_program_space_num),
+    aspace (aspace_)
+{
+  program_space_alloc_data (this);
 
-  return pspace;
+  program_spaces.push_back (this);
 }
 
-/* Releases program space PSPACE, and all its contents (shared
-   libraries, objfiles, and any other references to the PSPACE in
-   other modules).  It is an internal error to call this when PSPACE
-   is the current program space, since there should always be a
-   program space.  */
+/* See progspace.h.  */
 
-static void
-release_program_space (struct program_space *pspace)
+program_space::~program_space ()
 {
-  struct cleanup *old_chain = save_current_program_space ();
+  gdb_assert (this != current_program_space);
+
+  remove_program_space (this);
 
-  gdb_assert (pspace != current_program_space);
+  scoped_restore_current_program_space restore_pspace;
 
-  set_current_program_space (pspace);
+  set_current_program_space (this);
 
-  breakpoint_program_space_exit (pspace);
+  breakpoint_program_space_exit (this);
   no_shared_libraries (NULL, 0);
   exec_close ();
   free_all_objfiles ();
-  if (!gdbarch_has_shared_address_space (target_gdbarch))
-    free_address_space (pspace->aspace);
-  resize_section_table (&pspace->target_sections,
-                       -resize_section_table (&pspace->target_sections, 0));
+  /* Defer breakpoint re-set because we don't want to create new
+     locations for this pspace which we're tearing down.  */
+  clear_symtab_users (SYMFILE_DEFER_BP_RESET);
+  if (!gdbarch_has_shared_address_space (target_gdbarch ()))
+    free_address_space (this->aspace);
+  clear_section_table (&this->target_sections);
+  clear_program_space_solib_cache (this);
     /* Discard any data modules have associated with the PSPACE.  */
-  program_space_free_data (pspace);
-  xfree (pspace);
-
-  do_cleanups (old_chain);
+  program_space_free_data (this);
 }
 
-/* Unlinks PSPACE from the pspace list, and releases it.  */
+/* See progspace.h.  */
 
 void
-remove_program_space (struct program_space *pspace)
+program_space::free_all_objfiles ()
 {
-  struct program_space *ss, **ss_link;
+  /* Any objfile reference would become stale.  */
+  for (struct so_list *so : current_program_space->solibs ())
+    gdb_assert (so->objfile == NULL);
+
+  while (!objfiles_list.empty ())
+    objfiles_list.front ()->unlink ();
+}
+
+/* See progspace.h.  */
 
-  ss = program_spaces;
-  ss_link = &program_spaces;
-  while (ss)
+void
+program_space::add_objfile (std::shared_ptr<objfile> &&objfile,
+                           struct objfile *before)
+{
+  if (before == nullptr)
+    objfiles_list.push_back (std::move (objfile));
+  else
     {
-      if (ss != pspace)
-       {
-         ss_link = &ss->next;
-         ss = *ss_link;
-         continue;
-       }
-
-      *ss_link = ss->next;
-      release_program_space (ss);
-      ss = *ss_link;
+      auto iter = std::find_if (objfiles_list.begin (), objfiles_list.end (),
+                               [=] (const std::shared_ptr<::objfile> &objf)
+                               {
+                                 return objf.get () == before;
+                               });
+      gdb_assert (iter != objfiles_list.end ());
+      objfiles_list.insert (iter, std::move (objfile));
     }
 }
 
+/* See progspace.h.  */
+
+void
+program_space::remove_objfile (struct objfile *objfile)
+{
+  auto iter = std::find_if (objfiles_list.begin (), objfiles_list.end (),
+                           [=] (const std::shared_ptr<::objfile> &objf)
+                           {
+                             return objf.get () == objfile;
+                           });
+  gdb_assert (iter != objfiles_list.end ());
+  objfiles_list.erase (iter);
+
+  if (objfile == symfile_object_file)
+    symfile_object_file = NULL;
+}
+
+/* See progspace.h.  */
+
+next_adapter<struct so_list>
+program_space::solibs () const
+{
+  return next_adapter<struct so_list> (this->so_list);
+}
+
 /* Copies program space SRC to DEST.  Copies the main executable file,
    and the main symbol file.  Returns DEST.  */
 
 struct program_space *
 clone_program_space (struct program_space *dest, struct program_space *src)
 {
-  struct cleanup *old_chain;
-
-  old_chain = save_current_program_space ();
+  scoped_restore_current_program_space restore_pspace;
 
   set_current_program_space (dest);
 
-  if (src->ebfd != NULL)
-    exec_file_attach (bfd_get_filename (src->ebfd), 0);
+  if (src->pspace_exec_filename != NULL)
+    exec_file_attach (src->pspace_exec_filename, 0);
 
   if (src->symfile_object_file != NULL)
-    symbol_file_add_main (src->symfile_object_file->name, 0);
+    symbol_file_add_main (objfile_name (src->symfile_object_file),
+                         SYMFILE_DEFER_BP_RESET);
 
-  do_cleanups (old_chain);
   return dest;
 }
 
@@ -220,34 +256,10 @@ set_current_program_space (struct program_space *pspace)
   reinit_frame_cache ();
 }
 
-/* A cleanups callback, helper for save_current_program_space
-   below.  */
-
-static void
-restore_program_space (void *arg)
-{
-  struct program_space *saved_pspace = arg;
-
-  set_current_program_space (saved_pspace);
-}
-
-/* Save the current program space so that it may be restored by a later
-   call to do_cleanups.  Returns the struct cleanup pointer needed for
-   later doing the cleanup.  */
-
-struct cleanup *
-save_current_program_space (void)
-{
-  struct cleanup *old_chain = make_cleanup (restore_program_space,
-                                           current_program_space);
-
-  return old_chain;
-}
-
 /* Returns true iff there's no inferior bound to PSPACE.  */
 
-static int
-pspace_empty_p (struct program_space *pspace)
+int
+program_space_empty_p (struct program_space *pspace)
 {
   if (find_inferior_for_program_space (pspace) != NULL)
       return 0;
@@ -255,32 +267,6 @@ pspace_empty_p (struct program_space *pspace)
   return 1;
 }
 
-/* Prune away automatically added program spaces that aren't required
-   anymore.  */
-
-void
-prune_program_spaces (void)
-{
-  struct program_space *ss, **ss_link;
-  struct program_space *current = current_program_space;
-
-  ss = program_spaces;
-  ss_link = &program_spaces;
-  while (ss)
-    {
-      if (ss == current || !pspace_empty_p (ss))
-       {
-         ss_link = &ss->next;
-         ss = *ss_link;
-         continue;
-       }
-
-      *ss_link = ss->next;
-      release_program_space (ss);
-      ss = *ss_link;
-    }
-}
-
 /* Prints the list of program spaces and their details on UIOUT.  If
    REQUESTED is not -1, it's the ID of the pspace that should be
    printed.  Otherwise, all spaces are printed.  */
@@ -288,16 +274,10 @@ prune_program_spaces (void)
 static void
 print_program_space (struct ui_out *uiout, int requested)
 {
-  struct program_space *pspace;
   int count = 0;
-  struct cleanup *old_chain;
-
-  /* Might as well prune away unneeded ones, so the user doesn't even
-     seem them.  */
-  prune_program_spaces ();
 
   /* Compute number of pspaces we will print.  */
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       if (requested != -1 && pspace->num != requested)
        continue;
@@ -308,35 +288,33 @@ print_program_space (struct ui_out *uiout, int requested)
   /* There should always be at least one.  */
   gdb_assert (count > 0);
 
-  old_chain = make_cleanup_ui_out_table_begin_end (uiout, 3, count, "pspaces");
-  ui_out_table_header (uiout, 1, ui_left, "current", "");
-  ui_out_table_header (uiout, 4, ui_left, "id", "Id");
-  ui_out_table_header (uiout, 17, ui_left, "exec", "Executable");
-  ui_out_table_body (uiout);
+  ui_out_emit_table table_emitter (uiout, 3, count, "pspaces");
+  uiout->table_header (1, ui_left, "current", "");
+  uiout->table_header (4, ui_left, "id", "Id");
+  uiout->table_header (17, ui_left, "exec", "Executable");
+  uiout->table_body ();
 
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
-      struct cleanup *chain2;
       struct inferior *inf;
       int printed_header;
 
       if (requested != -1 && requested != pspace->num)
        continue;
 
-      chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+      ui_out_emit_tuple tuple_emitter (uiout, NULL);
 
       if (pspace == current_program_space)
-       ui_out_field_string (uiout, "current", "*");
+       uiout->field_string ("current", "*");
       else
-       ui_out_field_skip (uiout, "current");
+       uiout->field_skip ("current");
 
-      ui_out_field_int (uiout, "id", pspace->num);
+      uiout->field_signed ("id", pspace->num);
 
-      if (pspace->ebfd)
-       ui_out_field_string (uiout, "exec",
-                            bfd_get_filename (pspace->ebfd));
+      if (pspace->pspace_exec_filename)
+       uiout->field_string ("exec", pspace->pspace_exec_filename);
       else
-       ui_out_field_skip (uiout, "exec");
+       uiout->field_skip ("exec");
 
       /* Print extra info that doesn't really fit in tabular form.
         Currently, we print the list of inferiors bound to a pspace.
@@ -352,19 +330,16 @@ print_program_space (struct ui_out *uiout, int requested)
                printed_header = 1;
                printf_filtered ("\n\tBound inferiors: ID %d (%s)",
                                 inf->num,
-                                target_pid_to_str (pid_to_ptid (inf->pid)));
+                                target_pid_to_str (ptid_t (inf->pid)).c_str ());
              }
            else
              printf_filtered (", ID %d (%s)",
                               inf->num,
-                              target_pid_to_str (pid_to_ptid (inf->pid)));
+                              target_pid_to_str (ptid_t (inf->pid)).c_str ());
          }
 
-      ui_out_text (uiout, "\n");
-      do_cleanups (chain2);
+      uiout->text ("\n");
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Boolean test for an already-known program space id.  */
@@ -372,9 +347,7 @@ print_program_space (struct ui_out *uiout, int requested)
 static int
 valid_program_space_id (int num)
 {
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     if (pspace->num == num)
       return 1;
 
@@ -386,7 +359,7 @@ valid_program_space_id (int num)
    indicating which the program space to print information about.  */
 
 static void
-maintenance_info_program_spaces_command (char *args, int from_tty)
+maintenance_info_program_spaces_command (const char *args, int from_tty)
 {
   int requested = -1;
 
@@ -397,21 +370,7 @@ maintenance_info_program_spaces_command (char *args, int from_tty)
        error (_("program space ID %d not known."), requested);
     }
 
-  print_program_space (uiout, requested);
-}
-
-/* Simply returns the count of program spaces.  */
-
-int
-number_of_program_spaces (void)
-{
-  struct program_space *pspace;
-  int count = 0;
-
-  ALL_PSPACES (pspace)
-    count++;
-
-  return count;
+  print_program_space (current_uiout, requested);
 }
 
 /* Update all program spaces matching to address spaces.  The user may
@@ -428,8 +387,7 @@ number_of_program_spaces (void)
 void
 update_address_spaces (void)
 {
-  int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch);
-  struct program_space *pspace;
+  int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
   struct inferior *inf;
 
   init_address_spaces ();
@@ -439,167 +397,32 @@ update_address_spaces (void)
       struct address_space *aspace = new_address_space ();
 
       free_address_space (current_program_space->aspace);
-      ALL_PSPACES (pspace)
+      for (struct program_space *pspace : program_spaces)
        pspace->aspace = aspace;
     }
   else
-    ALL_PSPACES (pspace)
+    for (struct program_space *pspace : program_spaces)
       {
        free_address_space (pspace->aspace);
        pspace->aspace = new_address_space ();
       }
 
   for (inf = inferior_list; inf; inf = inf->next)
-    if (gdbarch_has_global_solist (target_gdbarch))
+    if (gdbarch_has_global_solist (target_gdbarch ()))
       inf->aspace = maybe_new_address_space ();
     else
       inf->aspace = inf->pspace->aspace;
 }
 
-/* Save the current program space so that it may be restored by a later
-   call to do_cleanups.  Returns the struct cleanup pointer needed for
-   later doing the cleanup.  */
-
-struct cleanup *
-save_current_space_and_thread (void)
-{
-  struct cleanup *old_chain;
-
-  /* If restoring to null thread, we need to restore the pspace as
-     well, hence, we need to save the current program space first.  */
-  old_chain = save_current_program_space ();
-  save_current_inferior ();
-  make_cleanup_restore_current_thread ();
-
-  return old_chain;
-}
-
-/* Switches full context to program space PSPACE.  Switches to the
-   first thread found bound to PSPACE.  */
-
-void
-switch_to_program_space_and_thread (struct program_space *pspace)
-{
-  struct inferior *inf;
-
-  inf = find_inferior_for_program_space (pspace);
-  if (inf != NULL)
-    {
-      struct thread_info *tp;
-
-      tp = any_live_thread_of_process (inf->pid);
-      if (tp != NULL)
-       {
-         switch_to_thread (tp->ptid);
-         /* Switching thread switches pspace implicitly.  We're
-            done.  */
-         return;
-       }
-    }
-
-  switch_to_thread (null_ptid);
-  set_current_program_space (pspace);
-}
-
 \f
 
-/* Keep a registry of per-program_space data-pointers required by other GDB
-   modules.  */
-
-struct program_space_data
-{
-  unsigned index;
-  void (*cleanup) (struct program_space *, void *);
-};
-
-struct program_space_data_registration
-{
-  struct program_space_data *data;
-  struct program_space_data_registration *next;
-};
-
-struct program_space_data_registry
-{
-  struct program_space_data_registration *registrations;
-  unsigned num_registrations;
-};
-
-static struct program_space_data_registry program_space_data_registry
-  = { NULL, 0 };
-
-const struct program_space_data *
-register_program_space_data_with_cleanup
-  (void (*cleanup) (struct program_space *, void *))
-{
-  struct program_space_data_registration **curr;
-
-  /* Append new registration.  */
-  for (curr = &program_space_data_registry.registrations;
-       *curr != NULL; curr = &(*curr)->next);
-
-  *curr = XMALLOC (struct program_space_data_registration);
-  (*curr)->next = NULL;
-  (*curr)->data = XMALLOC (struct program_space_data);
-  (*curr)->data->index = program_space_data_registry.num_registrations++;
-  (*curr)->data->cleanup = cleanup;
-
-  return (*curr)->data;
-}
-
-const struct program_space_data *
-register_program_space_data (void)
-{
-  return register_program_space_data_with_cleanup (NULL);
-}
-
-static void
-program_space_alloc_data (struct program_space *pspace)
-{
-  gdb_assert (pspace->data == NULL);
-  pspace->num_data = program_space_data_registry.num_registrations;
-  pspace->data = XCALLOC (pspace->num_data, void *);
-}
-
-static void
-program_space_free_data (struct program_space *pspace)
-{
-  gdb_assert (pspace->data != NULL);
-  clear_program_space_data (pspace);
-  xfree (pspace->data);
-  pspace->data = NULL;
-}
-
-void
-clear_program_space_data (struct program_space *pspace)
-{
-  struct program_space_data_registration *registration;
-  int i;
-
-  gdb_assert (pspace->data != NULL);
-
-  for (registration = program_space_data_registry.registrations, i = 0;
-       i < pspace->num_data;
-       registration = registration->next, i++)
-    if (pspace->data[i] != NULL && registration->data->cleanup)
-      registration->data->cleanup (pspace, pspace->data[i]);
-
-  memset (pspace->data, 0, pspace->num_data * sizeof (void *));
-}
+/* See progspace.h.  */
 
 void
-set_program_space_data (struct program_space *pspace,
-                      const struct program_space_data *data,
-                      void *value)
-{
-  gdb_assert (data->index < pspace->num_data);
-  pspace->data[data->index] = value;
-}
-
-void *
-program_space_data (struct program_space *pspace, const struct program_space_data *data)
+clear_program_space_solib_cache (struct program_space *pspace)
 {
-  gdb_assert (data->index < pspace->num_data);
-  return pspace->data[data->index];
+  pspace->added_solibs.clear ();
+  pspace->deleted_solibs.clear ();
 }
 
 \f
@@ -608,8 +431,8 @@ void
 initialize_progspace (void)
 {
   add_cmd ("program-spaces", class_maintenance,
-          maintenance_info_program_spaces_command, _("\
-Info about currently known program spaces."),
+          maintenance_info_program_spaces_command,
+          _("Info about currently known program spaces."),
           &maintenanceinfolist);
 
   /* There's always one program space.  Note that this function isn't
@@ -619,5 +442,5 @@ Info about currently known program spaces."),
      modules have done that.  Do this before
      initialize_current_architecture, because that accesses exec_bfd,
      which in turn dereferences current_program_space.  */
-  current_program_space = add_program_space (new_address_space ());
+  current_program_space = new program_space (new_address_space ());
 }
This page took 0.033156 seconds and 4 git commands to generate.