This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Share the shared library list between inferiors


Hi,

(This is one of the last patches needed for correct
multi-process + non-stop debugging against Ericsson DICOS.  This one
may turn out useful for some embedded OSs, when multi-process
support for them is added.)

When debugging against DICOS, we only need/should query the shared
library list (using solib-target.c) once on initial connection --- not
whenever we attach to a new process.  (there's no notion of a main exec file
in DICOS, it's all shared libraries, with a bunch of possible entry points).
The same code is visible to all processes.  Although each process
has it's own address space, all code is loaded/relocated to the same
addresses in all inferiors.  It's like we're debugging a bunch of forks.  The
debug API then goes a step further, and makes it so that an
inserted breakpoint is visible to all processes.  Since both the
code and inserted breakpoint locations are visible to all processes, it is bad to
remove/clear them whenever we attach or detach to/from an inferior.

This patch teaches GDB about this property.

There are several ways to skin this cat.  This one seemed like
the smallest, most extensible and malleable one from GDB's side, because
it doesn't cast to stone any new protocol extension --- which may
prove limited to some systems (some memory regions shared, others not;
some shared but visible at different addresses in different
inferiors/cores, etc.).  I was hoping we'd cross that bridge when
we start seeing those systems reporting multi process support
to GDB.

What do people think about this?

-- 
Pedro Alves
2008-10-27  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (remote_start_remote): If the solib list is global,
	fetch libraries and insert breakpoints after connecting.
	* infcmd.c (post_create_inferior): If the solist is shared between
	inferiors, no need to refetch it on every new inferior.
	(detach_command): If the shared library list is shared between
	inferiors, then don't clear it on every inferior detach.
	* gdbarch.sh (has_global_solist): New.
	* i386-dicos-tdep.c (i386_dicos_init_abi): Set
	gdbarch_has_global_solist.
	* target.c (target_pre_inferior): If the shared library list is
	shared between inferiors, then don't clear it here, neither
	invalidate the memory regions or clear the target description.
	(target_detach): If the shared library list is shared between
	inferiors, then don't remove breakpoints from the target here.
	(target_disconnect): Remove breakpoints from the target here.
	* solib.c (update_solib_list): Check for null_ptid.
	* breakpoint.c (insert_breakpoints, update_global_location_list):
	If the shared library list is shared between inferiors, insert
	breakpoints even if there's no execution.
	(breakpoint_init_inferior): If the shared library list is shared
	between inferiors, don't delete breakpoints or mark them
	uninserted here.

	* gdbarch.c, gdbarch.h: Regenerate.

---
 gdb/breakpoint.c      |   17 +++++++++++++----
 gdb/gdbarch.c         |   23 +++++++++++++++++++++++
 gdb/gdbarch.h         |    6 ++++++
 gdb/gdbarch.sh        |    4 ++++
 gdb/i386-dicos-tdep.c |    4 ++++
 gdb/infcmd.c          |   13 +++++++++++--
 gdb/remote.c          |   11 +++++++++++
 gdb/solib.c           |    2 +-
 gdb/target.c          |   29 +++++++++++++++++++++--------
 9 files changed, 94 insertions(+), 15 deletions(-)

Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2008-10-27 22:40:09.000000000 +0000
+++ src/gdb/remote.c	2008-10-27 23:03:06.000000000 +0000
@@ -2554,6 +2554,11 @@ remote_start_remote (struct ui_out *uiou
       getpkt (&rs->buf, &rs->buf_size, 0);
     }
 
+  /* On OSs where the list of libraries is global to all
+     processes, we fetch them early.  */
+  if (gdbarch_has_global_solist (target_gdbarch))
+    solib_add (NULL, args->from_tty, args->target, auto_solib_add);
+
   /* Next, if the target can specify a description, read it.  We do
      this before anything involving memory or registers.  */
   target_find_description ();
@@ -2721,6 +2726,12 @@ remote_start_remote (struct ui_out *uiou
       if (exec_bfd) 	/* No use without an exec file.  */
 	remote_check_symbols (symfile_objfile);
     }
+
+  /* If code is shared between processes, then breakpoints are global
+     too; Insert them now.  */
+  if (gdbarch_has_global_solist (target_gdbarch)
+      && breakpoints_always_inserted_mode ())
+    insert_breakpoints ();
 }
 
 /* Open a connection to a remote debugger.
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2008-10-27 20:38:49.000000000 +0000
+++ src/gdb/infcmd.c	2008-10-27 22:46:52.000000000 +0000
@@ -385,7 +385,9 @@ post_create_inferior (struct target_ops 
      don't need to.  */
   target_find_description ();
 
-  if (exec_bfd)
+  /* If the solist is global across processes, there's no need to
+     refetch it here.  */
+  if (exec_bfd && !gdbarch_has_global_solist (target_gdbarch))
     {
       /* Sometimes the platform-specific hook loads initial shared
 	 libraries, and sometimes it doesn't.  Try to do so first, so
@@ -397,7 +399,10 @@ post_create_inferior (struct target_ops 
 #else
       solib_add (NULL, from_tty, target, auto_solib_add);
 #endif
+    }
 
+  if (exec_bfd)
+    {
       /* Create the hooks to handle shared library load and unload
 	 events.  */
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
@@ -2313,7 +2318,11 @@ detach_command (char *args, int from_tty
 {
   dont_repeat ();		/* Not for the faint of heart.  */
   target_detach (args, from_tty);
-  no_shared_libraries (NULL, from_tty);
+
+  /* If the solist is global across inferiors, don't clear it when we
+     detach from a single inferior.  */
+  if (!gdbarch_has_global_solist (target_gdbarch))
+    no_shared_libraries (NULL, from_tty);
 
   /* If the current target interface claims there's still execution,
      then don't mess with threads of other processes.  */
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/gdbarch.c	2008-10-27 22:40:31.000000000 +0000
@@ -240,6 +240,7 @@ struct gdbarch
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
+  int has_global_solist;
 };
 
 
@@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch =
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
   0,  /* record_special_symbol */
+  0,  /* has_global_solist */
   /* startup_gdbarch() */
 };
 
@@ -623,6 +625,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
   /* Skip verify of record_special_symbol, has predicate */
+  /* Skip verify of has_global_solist, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &dummy);
   make_cleanup (xfree, buf);
   if (strlen (buf) > 0)
@@ -832,6 +835,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: get_longjmp_target = <0x%lx>\n",
                       (long) gdbarch->get_longjmp_target);
   fprintf_unfiltered (file,
+                      "gdbarch_dump: has_global_solist = %s\n",
+                      plongest (gdbarch->has_global_solist));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: have_nonsteppable_watchpoint = %s\n",
                       plongest (gdbarch->have_nonsteppable_watchpoint));
   fprintf_unfiltered (file,
@@ -3237,6 +3243,23 @@ set_gdbarch_record_special_symbol (struc
   gdbarch->record_special_symbol = record_special_symbol;
 }
 
+int
+gdbarch_has_global_solist (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  /* Skip verify of has_global_solist, invalid_p == 0 */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_has_global_solist called\n");
+  return gdbarch->has_global_solist;
+}
+
+void
+set_gdbarch_has_global_solist (struct gdbarch *gdbarch,
+                               int has_global_solist)
+{
+  gdbarch->has_global_solist = has_global_solist;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules. */
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/gdbarch.h	2008-10-27 22:40:31.000000000 +0000
@@ -811,6 +811,12 @@ typedef void (gdbarch_record_special_sym
 extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym);
 extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol);
 
+/* True if the list of shared libraries is one and only for all
+   processes, as opposed to a list of shared libraries per inferior. */
+
+extern int gdbarch_has_global_solist (struct gdbarch *gdbarch);
+extern void set_gdbarch_has_global_solist (struct gdbarch *gdbarch, int has_global_solist);
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/gdbarch.sh	2008-10-27 22:40:31.000000000 +0000
@@ -707,6 +707,10 @@ m:int:target_signal_to_host:enum target_
 
 # Record architecture-specific information from the symbol table.
 M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym
+
+# True if the list of shared libraries is one and only for all
+# processes, as opposed to a list of shared libraries per inferior.
+v:int:has_global_solist:::0:0::0
 EOF
 }
 
Index: src/gdb/i386-dicos-tdep.c
===================================================================
--- src.orig/gdb/i386-dicos-tdep.c	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/i386-dicos-tdep.c	2008-10-27 22:40:31.000000000 +0000
@@ -49,6 +49,10 @@ i386_dicos_init_abi (struct gdbarch_info
 
   set_solib_ops (gdbarch, &solib_target_so_ops);
 
+  /* Every process, although has its own address space, sees the same
+     list of shared libraries.  */
+  set_gdbarch_has_global_solist (gdbarch, 1);
+
   /* There's no (standard definition of) entry point or a guaranteed
      text location we could find with a symbol where to place the call
      dummy, so we put it on the stack.  */
Index: src/gdb/target.c
===================================================================
--- src.orig/gdb/target.c	2008-10-27 22:40:09.000000000 +0000
+++ src/gdb/target.c	2008-10-27 22:40:31.000000000 +0000
@@ -1756,11 +1756,18 @@ target_pre_inferior (int from_tty)
      (gdb) attach 4712
      Cannot access memory at address 0xdeadbeef
   */
-  no_shared_libraries (NULL, from_tty);
 
-  invalidate_target_mem_regions ();
+  /* In some OSs, the shared library list is the same/global/shared
+     across inferiors.  If code is shared between processes, so are
+     memory regions and features.  */
+  if (!gdbarch_has_global_solist (target_gdbarch))
+    {
+      no_shared_libraries (NULL, from_tty);
+
+      invalidate_target_mem_regions ();
 
-  target_clear_description ();
+      target_clear_description ();
+    }
 }
 
 /* This is to be called by the open routine before it does
@@ -1794,9 +1801,14 @@ target_preopen (int from_tty)
 void
 target_detach (char *args, int from_tty)
 {
-  /* If we're in breakpoints-always-inserted mode, have to
-     remove them before detaching.  */
-  remove_breakpoints ();
+  if (gdbarch_has_global_solist (target_gdbarch))
+    /* Don't remove global breakpoints here.  They're removed on
+       disconnection from the target.  */
+    ;
+  else
+    /* If we're in breakpoints-always-inserted mode, have to remove
+       them before detaching.  */
+    remove_breakpoints ();
 
   (current_target.to_detach) (args, from_tty);
 }
@@ -1806,8 +1818,9 @@ target_disconnect (char *args, int from_
 {
   struct target_ops *t;
 
-  /* If we're in breakpoints-always-inserted mode, have to
-     remove them before disconnecting.  */  
+  /* If we're in breakpoints-always-inserted mode or if breakpoints
+     are global across processes, we have to remove them before
+     disconnecting.  */
   remove_breakpoints ();
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
Index: src/gdb/solib.c
===================================================================
--- src.orig/gdb/solib.c	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/solib.c	2008-10-27 22:40:31.000000000 +0000
@@ -510,7 +510,7 @@ update_solib_list (int from_tty, struct 
 
   /* We can reach here due to changing solib-search-path or the
      sysroot, before having any inferior.  */
-  if (target_has_execution)
+  if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid))
     {
       struct inferior *inf = current_inferior ();
 
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c	2008-10-27 20:38:28.000000000 +0000
+++ src/gdb/breakpoint.c	2008-10-27 22:42:16.000000000 +0000
@@ -1274,7 +1274,10 @@ insert_breakpoints (void)
 
   update_global_location_list (1);
 
-  if (!breakpoints_always_inserted_mode () && target_has_execution)
+  if (!breakpoints_always_inserted_mode ()
+      && (target_has_execution
+ 	  || (gdbarch_has_global_solist (target_gdbarch)
+	      && target_supports_multi_process ())))
     /* update_global_location_list does not insert breakpoints
        when always_inserted_mode is not enabled.  Explicitly
        insert them now.  */
@@ -1743,6 +1746,11 @@ breakpoint_init_inferior (enum inf_conte
   struct bp_location *bpt;
   int ix;
 
+  /* If breakpoint locations are shared across processes, then there's
+     nothing to do.  */
+  if (gdbarch_has_global_solist (target_gdbarch))
+    return;
+
   ALL_BP_LOCATIONS (bpt)
     if (bpt->owner->enable_state != bp_permanent)
       bpt->inserted = 0;
@@ -7272,9 +7280,10 @@ update_global_location_list (int should_
       check_duplicates (b);
     }
 
-  if (breakpoints_always_inserted_mode ()
-      && should_insert
-      && target_has_execution)
+  if (breakpoints_always_inserted_mode () && should_insert
+      && (target_has_execution
+	  || (gdbarch_has_global_solist (target_gdbarch)
+	      && target_supports_multi_process ())))
     insert_breakpoint_locations ();
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]