Introduce dwarf2/public.h
[deliverable/binutils-gdb.git] / gdb / progspace.c
index b37701eb442a8d41fb46f770194c8efa8461f466..ebbc784dcfbb5fb8f57aa80f1882d98ff063db82 100644 (file)
@@ -1,6 +1,6 @@
 /* Program and address space management, for GDB, the GNU debugger.
 
-   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   Copyright (C) 2009-2021 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;
+static 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;
@@ -44,18 +47,6 @@ static int highest_address_space_num;
 
 DEFINE_REGISTRY (program_space, REGISTRY_ACCESS_FIELD)
 
-/* An address space.  It is used for comparing if pspaces/inferior/threads
-   see the same address space and for associating caches to each address
-   space.  */
-
-struct address_space
-{
-  int num;
-
-  /* Per aspace data-pointers required by other GDB modules.  */
-  REGISTRY_FIELDS;
-};
-
 /* Keep a registry of per-address_space data-pointers required by other GDB
    modules.  */
 
@@ -89,7 +80,7 @@ maybe_new_address_space (void)
   if (shared_aspace)
     {
       /* Just return the first in the list.  */
-      return program_spaces->aspace;
+      return program_spaces[0]->aspace;
     }
 
   return new_address_space ();
@@ -118,63 +109,134 @@ 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 = XCNEW (struct program_space);
-
-  pspace->num = ++last_program_space_num;
-  pspace->aspace = aspace;
+  gdb_assert (pspace != NULL);
 
-  program_space_alloc_data (pspace);
+  auto iter = std::find (program_spaces.begin (), program_spaces.end (),
+                        pspace);
+  gdb_assert (iter != program_spaces.end ());
+  program_spaces.erase (iter);
+}
 
-  if (program_spaces == NULL)
-    program_spaces = pspace;
-  else
-    {
-      struct program_space *last;
+/* See progspace.h.  */
 
-      for (last = program_spaces; last->next != NULL; last = last->next)
-       ;
-      last->next = 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 ();
+  /* 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 (pspace->aspace);
-  clear_section_table (&pspace->target_sections);
-  clear_program_space_solib_cache (pspace);
+    free_address_space (this->aspace);
     /* Discard any data modules have associated with the PSPACE.  */
-  program_space_free_data (pspace);
-  xfree (pspace);
+  program_space_free_data (this);
+}
+
+/* See progspace.h.  */
+
+void
+program_space::free_all_objfiles ()
+{
+  /* 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.  */
 
-  do_cleanups (old_chain);
+void
+program_space::add_objfile (std::shared_ptr<objfile> &&objfile,
+                           struct objfile *before)
+{
+  if (before == nullptr)
+    objfiles_list.push_back (std::move (objfile));
+  else
+    {
+      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)
+{
+  /* Removing an objfile from the objfile list invalidates any frame
+     that was built using frame info found in the objfile.  Reinit the
+     frame cache to get rid of any frame that might otherwise
+     reference stale info.  */
+  reinit_frame_cache ();
+
+  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);
+}
+
+/* See progspace.h.  */
+
+void
+program_space::exec_close ()
+{
+  if (ebfd != nullptr)
+    {
+      /* Removing target sections may close the exec_ops target.
+        Clear ebfd before doing so to prevent recursion.  */
+      ebfd.reset (nullptr);
+      ebfd_mtime = 0;
+
+      remove_target_sections (&ebfd);
+
+      exec_filename.reset (nullptr);
+    }
 }
 
 /* Copies program space SRC to DEST.  Copies the main executable file,
@@ -183,19 +245,17 @@ release_program_space (struct program_space *pspace)
 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->pspace_exec_filename != NULL)
-    exec_file_attach (src->pspace_exec_filename, 0);
+  if (src->exec_filename != NULL)
+    exec_file_attach (src->exec_filename.get (), 0);
 
   if (src->symfile_object_file != NULL)
-    symbol_file_add_main (objfile_name (src->symfile_object_file), 0);
+    symbol_file_add_main (objfile_name (src->symfile_object_file),
+                         SYMFILE_DEFER_BP_RESET);
 
-  do_cleanups (old_chain);
   return dest;
 }
 
@@ -217,66 +277,12 @@ 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 = (struct program_space *) 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.  */
 
-int
-program_space_empty_p (struct program_space *pspace)
-{
-  if (find_inferior_for_program_space (pspace) != NULL)
-      return 0;
-
-  return 1;
-}
-
-/* Remove a program space from the program spaces list and release it.  It is
-   an error to call this function while PSPACE is the current program space. */
-
-void
-delete_program_space (struct program_space *pspace)
+bool
+program_space::empty ()
 {
-  struct program_space *ss, **ss_link;
-  gdb_assert (pspace != NULL);
-  gdb_assert (pspace != current_program_space);
-
-  ss = program_spaces;
-  ss_link = &program_spaces;
-  while (ss != NULL)
-    {
-      if (ss == pspace)
-       {
-         *ss_link = ss->next;
-         break;
-       }
-
-      ss_link = &ss->next;
-      ss = *ss_link;
-    }
-
-  release_program_space (pspace);
+  return find_inferior_for_program_space (this) == nullptr;
 }
 
 /* Prints the list of program spaces and their details on UIOUT.  If
@@ -286,12 +292,10 @@ delete_program_space (struct program_space *pspace)
 static void
 print_program_space (struct ui_out *uiout, int requested)
 {
-  struct program_space *pspace;
   int count = 0;
-  struct cleanup *old_chain;
 
   /* Compute number of pspaces we will print.  */
-  ALL_PSPACES (pspace)
+  for (struct program_space *pspace : program_spaces)
     {
       if (requested != -1 && pspace->num != requested)
        continue;
@@ -302,15 +306,14 @@ 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_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 inferior *inf;
       int printed_header;
 
       if (requested != -1 && requested != pspace->num)
@@ -323,10 +326,10 @@ print_program_space (struct ui_out *uiout, int requested)
       else
        uiout->field_skip ("current");
 
-      uiout->field_int ("id", pspace->num);
+      uiout->field_signed ("id", pspace->num);
 
-      if (pspace->pspace_exec_filename)
-       uiout->field_string ("exec", pspace->pspace_exec_filename);
+      if (pspace->exec_filename != nullptr)
+       uiout->field_string ("exec", pspace->exec_filename.get ());
       else
        uiout->field_skip ("exec");
 
@@ -336,26 +339,31 @@ print_program_space (struct ui_out *uiout, int requested)
         e.g., both parent/child inferiors in a vfork, or, on targets
         that share pspaces between inferiors.  */
       printed_header = 0;
-      for (inf = inferior_list; inf; inf = inf->next)
+
+      /* We're going to switch inferiors.  */
+      scoped_restore_current_thread restore_thread;
+
+      for (inferior *inf : all_inferiors ())
        if (inf->pspace == pspace)
          {
+           /* Switch to inferior in order to call target methods.  */
+           switch_to_inferior_no_thread (inf);
+
            if (!printed_header)
              {
                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 ());
          }
 
       uiout->text ("\n");
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Boolean test for an already-known program space id.  */
@@ -363,9 +371,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;
 
@@ -377,7 +383,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;
 
@@ -391,20 +397,6 @@ maintenance_info_program_spaces_command (char *args, int from_tty)
   print_program_space (current_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;
-}
-
 /* Update all program spaces matching to address spaces.  The user may
    have created several program spaces, and loaded executables into
    them before connecting to the target interface that will create the
@@ -420,7 +412,6 @@ void
 update_address_spaces (void)
 {
   int shared_aspace = gdbarch_has_shared_address_space (target_gdbarch ());
-  struct program_space *pspace;
   struct inferior *inf;
 
   init_address_spaces ();
@@ -430,11 +421,11 @@ 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 ();
@@ -447,62 +438,15 @@ update_address_spaces (void)
       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 ();
-  /* There's no need to save the current inferior here.
-     That is handled by make_cleanup_restore_current_thread.  */
-  make_cleanup_restore_current_thread ();
-
-  return old_chain;
-}
-
-/* See progspace.h  */
-
-void
-switch_to_program_space_and_thread (struct program_space *pspace)
-{
-  struct inferior *inf;
-
-  inf = find_inferior_for_program_space (pspace);
-  if (inf != NULL && inf->pid != 0)
-    {
-      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
 
 /* See progspace.h.  */
 
 void
-clear_program_space_solib_cache (struct program_space *pspace)
+program_space::clear_solib_cache ()
 {
-  VEC_free (so_list_ptr, pspace->added_solibs);
-
-  free_char_ptr_vec (pspace->deleted_solibs);
-  pspace->deleted_solibs = NULL;
+  added_solibs.clear ();
+  deleted_solibs.clear ();
 }
 
 \f
@@ -520,7 +464,7 @@ initialize_progspace (void)
      _initialize_foo routines may need to install their per-pspace
      data keys.  We can only allocate a progspace when all those
      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 ());
+     initialize_current_architecture, because that accesses the ebfd
+     of current_program_space.  */
+  current_program_space = new program_space (new_address_space ());
 }
This page took 0.031494 seconds and 4 git commands to generate.