30f2069
gdb/
30f2069
2012-07-30  Gary Benson  <gbenson@redhat.com>
30f2069
30f2069
	* breakpoint.h (handle_solib_event): Moved function definition
30f2069
	to solib.h, and added a new parameter.
30f2069
	* breakpoint.c (handle_solib_event): Moved function to solib.c
30f2069
	and added a new parameter.
30f2069
	(bpstat_stop_status): Pass new argument to handle_solib_event.
30f2069
	* solib.h (breakpoint.h): New include.
30f2069
	(handle_solib_event): Moved function definition from breakpoint.h
30f2069
	and added a new parameter.
30f2069
	(update_solib_breakpoints): New function definition.
30f2069
	* solib.c (handle_solib_event): Moved function from breakpoint.c
30f2069
	and added a new parameter.
30f2069
	(update_solib_breakpoints): New function.
30f2069
	* solist.h (breakpoint.h): New include.
30f2069
	(target_so_ops): New fields "handle_solib_event" and
30f2069
	"update_breakpoints".
30f2069
	* infrun.c (set_stop_on_solib_events): New function.
30f2069
	(_initialize_infrun): Use the above for "set stop-on-solib-events".
30f2069
	(handle_inferior_event): Pass new argument to handle_solib_event.
30f2069
	* solib-svr4.c (probe.h): New include.
30f2069
	(namespace_table_flatten): New forward declaration.
30f2069
	(lm_info): New fields "lmid" and "in_initial_ns".
30f2069
	(probe_action): New enum.
30f2069
	(probe_info): New struct.
30f2069
	(probe_info): New static variable.
30f2069
	(NUM_PROBES): New definition.
30f2069
	(svr4_info): New fields  "using_probes", "probes" and
30f2069
	"namespace_table".
30f2069
	(free_probes): New function.
30f2069
	(free_namespace_table): Likewise.
30f2069
	(svr4_pspace_data_cleanup): Free probes and namespace table.
30f2069
	(svr4_same): Also compare namespaces if using probes.
30f2069
	(lm_addr_check): Only print .dynamic section at wrong address
30f2069
	warning for initial namespace if using probes.
30f2069
	(r_map_from_debug_base): New function.
30f2069
	(solib_svr4_r_map): Call the above.
30f2069
	(svr4_read_so_list): New parameter "prev_lm".
30f2069
	Changed	return type from void to int.
30f2069
	Return nonzero on success, zero on error.
30f2069
	(svr4_current_sos_from_debug_base): New function.
30f2069
	(svr4_current_sos): Create result from namespace table if available.
30f2069
	Use svr4_current_sos_from_debug_base to generate list otherwise.
30f2069
	(probe_and_info): New struct.
30f2069
	(solib_event_probe_at): New function.
30f2069
	(solib_event_probe_action): Likewise.
30f2069
	(namespace): New struct.
30f2069
	(hash_namespace): New function.
30f2069
	(equal_namespace): Likewise.
30f2069
	(free_namespace): Likewise.
30f2069
	(namespace_update_full): Likewise.
30f2069
	(namespace_update_incremental): Likewise.
30f2069
	(svr4_handle_solib_event): Likewise.
30f2069
	(namespace_table_flatten_helper): Likewise.
30f2069
	(namespace_table_flatten): Likewise.
30f2069
	(svr4_update_solib_event_breakpoint): Likewise.
30f2069
	(svr4_update_solib_event_breakpoints): Likewise.
30f2069
	(svr4_create_solib_event_breakpoints): Likewise.
30f2069
	(enable_break): Free probes before creating breakpoints.
30f2069
	Use svr4_create_solib_event_breakpoints to create breakpoints.
30f2069
	(svr4_solib_create_inferior_hook): Free the namespace table.
30f2069
	(_initialize_svr4_solib): Initialise svr4_so_ops.handle_solib_event
30f2069
	and svr4_so_ops.update_breakpoints.
30f2069
30f2069
gdb/testsuite
30f2069
2012-07-30  Gary Benson  <gbenson@redhat.com>
30f2069
30f2069
	* gdb.base/break-interp.exp (solib_bp): New constant.
30f2069
	(reach_1): Use the above instead of "_dl_debug_state".
30f2069
	(test_attach): Likewise.
30f2069
	(test_ld): Likewise.
30f2069
	* gdb.base/break-probes.exp: New file.
30f2069
	* gdb.base/break-probes.c: Likewise.
30f2069
	* gdb.base/break-probes-solib.c: Likewise.
30f2069
	* gdb.base/info-shared.exp: New file.
30f2069
	* gdb.base/info-shared.c: Likewise.
30f2069
	* gdb.base/info-shared-solib1.c: Likewise.
30f2069
	* gdb.base/info-shared-solib2.c: Likewise.
30f2069
	* gdb.base/break-dlmopen.exp: Likewise.
30f2069
	* gdb.base/break-dlmopen.c: Likewise.
30f2069
	* gdb.base/break-dlmopen-solib.c: Likewise.
30f2069
556378e
Index: gdb-7.5.50.20130118/gdb/breakpoint.h
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/breakpoint.h	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/breakpoint.h	2013-01-18 23:57:50.511792890 +0100
556378e
@@ -1548,8 +1548,6 @@ extern int user_breakpoint_p (struct bre
30f2069
 /* Attempt to determine architecture of location identified by SAL.  */
30f2069
 extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
30f2069
 
30f2069
-extern void handle_solib_event (void);
30f2069
-
30f2069
 extern void breakpoints_relocate (struct objfile *objfile,
30f2069
 				  struct section_offsets *delta);
30f2069
 
556378e
Index: gdb-7.5.50.20130118/gdb/breakpoint.c
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/breakpoint.c	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/breakpoint.c	2013-01-18 23:57:50.514792879 +0100
556378e
@@ -5254,7 +5254,7 @@ bpstat_stop_status (struct address_space
30f2069
     {
30f2069
       if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event)
30f2069
 	{
30f2069
-	  handle_solib_event ();
30f2069
+	  handle_solib_event (bs);
30f2069
 	  break;
30f2069
 	}
30f2069
     }
556378e
@@ -5350,25 +5350,6 @@ handle_jit_event (void)
30f2069
   target_terminal_inferior ();
30f2069
 }
30f2069
 
30f2069
-/* Handle an solib event by calling solib_add.  */
30f2069
-
30f2069
-void
30f2069
-handle_solib_event (void)
30f2069
-{
30f2069
-  clear_program_space_solib_cache (current_inferior ()->pspace);
30f2069
-
30f2069
-  /* Check for any newly added shared libraries if we're supposed to
30f2069
-     be adding them automatically.  Switch terminal for any messages
30f2069
-     produced by breakpoint_re_set.  */
30f2069
-  target_terminal_ours_for_output ();
30f2069
-#ifdef SOLIB_ADD
30f2069
-  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
30f2069
-#else
30f2069
-  solib_add (NULL, 0, &current_target, auto_solib_add);
30f2069
-#endif
30f2069
-  target_terminal_inferior ();
30f2069
-}
30f2069
-
30f2069
 /* Prepare WHAT final decision for infrun.  */
30f2069
 
30f2069
 /* Decide what infrun needs to do with this bpstat.  */
556378e
Index: gdb-7.5.50.20130118/gdb/solib.h
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/solib.h	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/solib.h	2013-01-18 23:57:50.515792875 +0100
556378e
@@ -20,6 +20,9 @@
30f2069
 #ifndef SOLIB_H
30f2069
 #define SOLIB_H
30f2069
 
30f2069
+/* For bpstat.  */
30f2069
+#include "breakpoint.h"
30f2069
+
30f2069
 /* Forward decl's for prototypes */
30f2069
 struct so_list;
30f2069
 struct target_ops;
556378e
@@ -90,4 +93,15 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f
30f2069
 								      void *),
30f2069
 						    void *data);
30f2069
 
30f2069
+/* Handle an solib event by calling solib_add.  Targets which handle
30f2069
+   solib events using breakpoints must pass a valid bpstat.  Targets
30f2069
+   which handle solib events using some other mechanism should pass
30f2069
+   NULL.  */
30f2069
+
30f2069
+extern void handle_solib_event (bpstat bs);
30f2069
+
30f2069
+/* Enable or disable optional solib event breakpoints as appropriate.  */
30f2069
+
30f2069
+extern void update_solib_breakpoints (void);
30f2069
+
30f2069
 #endif /* SOLIB_H */
556378e
Index: gdb-7.5.50.20130118/gdb/solib.c
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/solib.c	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/solib.c	2013-01-18 23:58:09.144716601 +0100
556378e
@@ -1221,6 +1221,42 @@ no_shared_libraries (char *ignored, int
30f2069
   objfile_purge_solibs ();
30f2069
 }
30f2069
 
30f2069
+/* See solib.h.  */
30f2069
+
30f2069
+void
30f2069
+handle_solib_event (bpstat bs)
30f2069
+{
556378e
+  struct target_so_ops *ops = solib_ops (target_gdbarch ());
30f2069
+
30f2069
+  if (ops->handle_solib_event != NULL)
30f2069
+    ops->handle_solib_event (bs);
30f2069
+
30f2069
+  clear_program_space_solib_cache (current_inferior ()->pspace);
30f2069
+
30f2069
+  /* Check for any newly added shared libraries if we're supposed to
30f2069
+     be adding them automatically.  Switch terminal for any messages
30f2069
+     produced by breakpoint_re_set.  */
30f2069
+  target_terminal_ours_for_output ();
30f2069
+#ifdef SOLIB_ADD
30f2069
+  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
30f2069
+#else
30f2069
+  solib_add (NULL, 0, &current_target, auto_solib_add);
30f2069
+#endif
30f2069
+  target_terminal_inferior ();
30f2069
+}
30f2069
+
30f2069
+/* See solib.h.  */
30f2069
+
30f2069
+void
30f2069
+update_solib_breakpoints (void)
30f2069
+{
556378e
+  struct target_so_ops *ops = solib_ops (target_gdbarch ());
30f2069
+
30f2069
+  if (ops->update_breakpoints != NULL)
30f2069
+    ops->update_breakpoints ();
30f2069
+}
30f2069
+
30f2069
+
30f2069
 /* Reload shared libraries, but avoid reloading the same symbol file
30f2069
    we already have loaded.  */
30f2069
 
556378e
Index: gdb-7.5.50.20130118/gdb/solist.h
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/solist.h	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/solist.h	2013-01-18 23:57:50.515792875 +0100
556378e
@@ -22,6 +22,8 @@
30f2069
 #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
30f2069
 /* For domain_enum domain.  */
30f2069
 #include "symtab.h"
30f2069
+/* For bpstat.  */
30f2069
+#include "breakpoint.h"
30f2069
 
30f2069
 /* Forward declaration for target specific link map information.  This
30f2069
    struct is opaque to all but the target specific file.  */
556378e
@@ -148,6 +150,20 @@ struct target_so_ops
30f2069
        core file (in particular, for readonly sections).  */
30f2069
     int (*keep_data_in_core) (CORE_ADDR vaddr,
30f2069
 			      unsigned long size);
30f2069
+
30f2069
+    /* Target-specific handling of solib events.  For targets which
30f2069
+       handle solib events using breakpoints a valid bpstat must be
30f2069
+       passed.  Targets which handle solib events using some other
30f2069
+       mechanism should pass NULL.  This pointer can be NULL, in which
30f2069
+       case no specific handling is necessary for this target.  */
30f2069
+    void (*handle_solib_event) (bpstat bs);
30f2069
+
30f2069
+    /* Enable or disable optional solib event breakpoints as
30f2069
+       appropriate.  This should be called whenever
30f2069
+       stop_on_solib_events is changed.  This pointer can be
30f2069
+       NULL, in which case no enabling or disabling is necessary
30f2069
+       for this target.  */
30f2069
+    void (*update_breakpoints) (void);
30f2069
   };
30f2069
 
30f2069
 /* Free the memory associated with a (so_list *).  */
556378e
Index: gdb-7.5.50.20130118/gdb/infrun.c
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/infrun.c	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/infrun.c	2013-01-18 23:57:50.517792865 +0100
556378e
@@ -369,6 +369,16 @@ static struct symbol *step_start_functio
30f2069
 /* Nonzero if we want to give control to the user when we're notified
30f2069
    of shared library events by the dynamic linker.  */
30f2069
 int stop_on_solib_events;
30f2069
+
30f2069
+/* Enable or disable optional shared library event breakpoints
30f2069
+   as appropriate when the above flag is changed.  */
30f2069
+
30f2069
+static void
30f2069
+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
30f2069
+{
30f2069
+  update_solib_breakpoints ();
30f2069
+}
30f2069
+
30f2069
 static void
30f2069
 show_stop_on_solib_events (struct ui_file *file, int from_tty,
30f2069
 			   struct cmd_list_element *c, const char *value)
556378e
@@ -3347,7 +3357,7 @@ handle_inferior_event (struct execution_
30f2069
 	    context_switch (ecs->ptid);
30f2069
 	  regcache = get_thread_regcache (ecs->ptid);
30f2069
 
30f2069
-	  handle_solib_event ();
30f2069
+	  handle_solib_event (NULL);
30f2069
 
30f2069
 	  ecs->event_thread->control.stop_bpstat
30f2069
 	    = bpstat_stop_status (get_regcache_aspace (regcache),
556378e
@@ -7327,7 +7337,7 @@ Show stopping for shared library events.
30f2069
 If nonzero, gdb will give control to the user when the dynamic linker\n\
30f2069
 notifies gdb of shared library events.  The most common event of interest\n\
30f2069
 to the user would be loading/unloading of a new library."),
30f2069
-			    NULL,
30f2069
+			    set_stop_on_solib_events,
30f2069
 			    show_stop_on_solib_events,
30f2069
 			    &setlist, &showlist);
30f2069
 
556378e
Index: gdb-7.5.50.20130118/gdb/solib-svr4.c
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/solib-svr4.c	2013-01-18 23:57:45.430815943 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/solib-svr4.c	2013-01-18 23:57:50.519792858 +0100
556378e
@@ -46,10 +46,12 @@
30f2069
 #include "auxv.h"
30f2069
 #include "exceptions.h"
30f2069
 #include "gdb_bfd.h"
30f2069
+#include "probe.h"
30f2069
 
30f2069
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
30f2069
 static int svr4_have_link_map_offsets (void);
30f2069
 static void svr4_relocate_main_executable (void);
30f2069
+static struct so_list *namespace_table_flatten (htab_t namespace_table);
30f2069
 
30f2069
 /* Link map info to include in an allocated so_list entry.  */
30f2069
 
556378e
@@ -70,6 +72,16 @@ struct lm_info
30f2069
 
30f2069
     /* Values read in from inferior's fields of the same name.  */
30f2069
     CORE_ADDR l_ld, l_next, l_prev, l_name;
30f2069
+
30f2069
+    /* Numeric link-map ID of the namespace this object is loaded
30f2069
+       into.  This value is only valid when using the probes-based
30f2069
+       interface.  */
30f2069
+    LONGEST lmid;
30f2069
+
30f2069
+    /* Nonzero if the namespace list this object is loaded into is the
30f2069
+       application's initial namespace (LM_ID_BASE).  This value is
30f2069
+       only valid when using the probes-based interface.  */
30f2069
+    unsigned int in_initial_ns : 1;
30f2069
   };
30f2069
 
30f2069
 /* On SVR4 systems, a list of symbols in the dynamic linker where
556378e
@@ -106,6 +118,53 @@ static const  char * const main_name_lis
30f2069
   NULL
30f2069
 };
30f2069
 
30f2069
+/* What to do with the namespace table when a probe stop occurs.  */
30f2069
+
30f2069
+enum probe_action
30f2069
+  {
30f2069
+    /* Something went seriously wrong.  Stop using probes and
30f2069
+       revert to using the older interface.  */
30f2069
+    NAMESPACE_TABLE_INVALIDATE,
30f2069
+
30f2069
+    /* No action is required.  This namespace is still valid.  */
30f2069
+    NAMESPACE_NO_ACTION,
30f2069
+
30f2069
+    /* This namespace should be reloaded entirely.  */
30f2069
+    NAMESPACE_RELOAD,
30f2069
+
30f2069
+    /* Attempt to incrementally update this namespace. If the
30f2069
+       update fails or is not possible, fall back to reloading
30f2069
+       the namespace in full.  */
30f2069
+    NAMESPACE_UPDATE_OR_RELOAD,
30f2069
+  };
30f2069
+
30f2069
+/* A probe's name and its associated action.  */
30f2069
+
30f2069
+struct probe_info
30f2069
+{
30f2069
+  /* The name of the probe.  */
30f2069
+  const char *name;
30f2069
+
30f2069
+  /* What to do with the namespace table when a probe stop occurs.  */
30f2069
+  enum probe_action action;
30f2069
+};
30f2069
+
30f2069
+/* A list of named probes and their associated actions.  If all
30f2069
+   probes are present in the dynamic linker then the probes-based
30f2069
+   interface will be used.  */
30f2069
+
30f2069
+static const struct probe_info probe_info[] =
30f2069
+{
30f2069
+  { "init_start", NAMESPACE_NO_ACTION },
30f2069
+  { "init_complete", NAMESPACE_RELOAD },
30f2069
+  { "map_start", NAMESPACE_NO_ACTION },
30f2069
+  { "reloc_complete", NAMESPACE_UPDATE_OR_RELOAD },
30f2069
+  { "unmap_start", NAMESPACE_NO_ACTION },
30f2069
+  { "unmap_complete", NAMESPACE_RELOAD },
30f2069
+};
30f2069
+
30f2069
+#define NUM_PROBES ARRAY_SIZE (probe_info)
30f2069
+
30f2069
 /* Per pspace SVR4 specific data.  */
30f2069
 
30f2069
 struct svr4_info
556378e
@@ -128,17 +187,58 @@ struct svr4_info
30f2069
   CORE_ADDR interp_text_sect_high;
30f2069
   CORE_ADDR interp_plt_sect_low;
30f2069
   CORE_ADDR interp_plt_sect_high;
30f2069
+
30f2069
+  /* Nonzero if we are using the probes-based interface.  */
30f2069
+  unsigned int using_probes : 1;
30f2069
+
30f2069
+  /* Named probes in the dynamic linker.  */
30f2069
+  VEC (probe_p) *probes[NUM_PROBES];
30f2069
+
30f2069
+  /* Table of dynamic linker namespaces, used by the probes-based
30f2069
+     interface.  */
30f2069
+  htab_t namespace_table;
30f2069
 };
30f2069
 
30f2069
 /* Per-program-space data key.  */
30f2069
 static const struct program_space_data *solib_svr4_pspace_data;
30f2069
 
30f2069
+/* Free any allocated probe vectors.  */
30f2069
+
30f2069
+static void
30f2069
+free_probes (struct svr4_info *info)
30f2069
+{
30f2069
+  int i;
30f2069
+
30f2069
+  for (i = 0; i < NUM_PROBES; i++)
30f2069
+    VEC_free (probe_p, info->probes[i]);
30f2069
+
30f2069
+  memset (info->probes, 0, sizeof (info->probes));
30f2069
+}
30f2069
+
30f2069
+/* Free the namespace table.  */
30f2069
+
30f2069
+static void
30f2069
+free_namespace_table (struct svr4_info *info)
30f2069
+{
30f2069
+  if (info->namespace_table == NULL)
30f2069
+    return;
30f2069
+
30f2069
+  htab_delete (info->namespace_table);
30f2069
+  info->namespace_table = NULL;
30f2069
+}
30f2069
+
30f2069
 static void
30f2069
 svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
30f2069
 {
30f2069
   struct svr4_info *info;
30f2069
 
30f2069
   info = program_space_data (pspace, solib_svr4_pspace_data);
30f2069
+  if (info == NULL)
30f2069
+    return;
30f2069
+
30f2069
+  free_probes (info);
30f2069
+  free_namespace_table (info);
30f2069
+
30f2069
   xfree (info);
30f2069
 }
30f2069
 
556378e
@@ -187,10 +287,21 @@ svr4_same_1 (const char *gdb_so_name, co
30f2069
   return 0;
30f2069
 }
30f2069
 
30f2069
+/* Return non-zero if GDB and INFERIOR represent the same shared
30f2069
+   library.  */
30f2069
+
30f2069
 static int
30f2069
 svr4_same (struct so_list *gdb, struct so_list *inferior)
30f2069
 {
30f2069
-  return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
+
30f2069
+  if (info->using_probes)
30f2069
+    {
30f2069
+      if (gdb->lm_info->lmid != inferior->lm_info->lmid)
30f2069
+	return 0;
30f2069
+    }
30f2069
+
30f2069
+  return svr4_same_1 (gdb->so_original_name, inferior->so_original_name);
30f2069
 }
30f2069
 
30f2069
 static struct lm_info *
556378e
@@ -321,18 +432,26 @@ lm_addr_check (struct so_list *so, bfd *
30f2069
 	    }
30f2069
 	  else
30f2069
 	    {
30f2069
-	      /* There is no way to verify the library file matches.  prelink
30f2069
-		 can during prelinking of an unprelinked file (or unprelinking
30f2069
-		 of a prelinked file) shift the DYNAMIC segment by arbitrary
30f2069
-		 offset without any page size alignment.  There is no way to
30f2069
-		 find out the ELF header and/or Program Headers for a limited
30f2069
-		 verification if it they match.  One could do a verification
30f2069
-		 of the DYNAMIC segment.  Still the found address is the best
30f2069
-		 one GDB could find.  */
30f2069
-
30f2069
-	      warning (_(".dynamic section for \"%s\" "
30f2069
-			 "is not at the expected address "
30f2069
-			 "(wrong library or version mismatch?)"), so->so_name);
30f2069
+	      struct svr4_info *info = get_svr4_info ();
30f2069
+
30f2069
+	      if (!info->using_probes || so->lm_info->in_initial_ns)
30f2069
+		{
30f2069
+		  /* There is no way to verify the library file
30f2069
+		     matches.  prelink can during prelinking of an
30f2069
+		     unprelinked file (or unprelinking of a prelinked
30f2069
+		     file) shift the DYNAMIC segment by arbitrary
30f2069
+		     offset without any page size alignment.  There is
30f2069
+		     no way to find out the ELF header and/or Program
30f2069
+		     Headers for a limited verification if it they
30f2069
+		     match.  One could do a verification of the
30f2069
+		     DYNAMIC segment.  Still the found address is the
30f2069
+		     best one GDB could find.  */
30f2069
+
30f2069
+		  warning (_(".dynamic section for \"%s\" "
30f2069
+			     "is not at the expected address "
30f2069
+			     "(wrong library or version mismatch?)"),
30f2069
+			   so->so_name);
30f2069
+		}
30f2069
 	    }
30f2069
 	}
30f2069
 
556378e
@@ -774,16 +893,10 @@ locate_base (struct svr4_info *info)
30f2069
   return info->debug_base;
30f2069
 }
30f2069
 
30f2069
-/* Find the first element in the inferior's dynamic link map, and
30f2069
-   return its address in the inferior.  Return zero if the address
30f2069
-   could not be determined.
30f2069
-
30f2069
-   FIXME: Perhaps we should validate the info somehow, perhaps by
30f2069
-   checking r_version for a known version number, or r_state for
30f2069
-   RT_CONSISTENT.  */
30f2069
+/* Read the r_map field from the supplied r_debug structure.  */
30f2069
 
30f2069
 static CORE_ADDR
30f2069
-solib_svr4_r_map (struct svr4_info *info)
30f2069
+r_map_from_debug_base (CORE_ADDR debug_base)
30f2069
 {
30f2069
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
556378e
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
556378e
@@ -792,13 +905,27 @@ solib_svr4_r_map (struct svr4_info *info
30f2069
 
30f2069
   TRY_CATCH (ex, RETURN_MASK_ERROR)
30f2069
     {
30f2069
-      addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
30f2069
+      addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
30f2069
                                         ptr_type);
30f2069
     }
30f2069
   exception_print (gdb_stderr, ex);
30f2069
   return addr;
30f2069
 }
30f2069
 
30f2069
+/* Find the first element in the inferior's dynamic link map, and
30f2069
+   return its address in the inferior.  Return zero if the address
30f2069
+   could not be determined.
30f2069
+
30f2069
+   FIXME: Perhaps we should validate the info somehow, perhaps by
30f2069
+   checking r_version for a known version number, or r_state for
30f2069
+   RT_CONSISTENT.  */
30f2069
+
30f2069
+static CORE_ADDR
30f2069
+solib_svr4_r_map (struct svr4_info *info)
30f2069
+{
30f2069
+  return r_map_from_debug_base (info->debug_base);
30f2069
+}
30f2069
+
30f2069
 /* Find r_brk from the inferior's debug base.  */
30f2069
 
30f2069
 static CORE_ADDR
556378e
@@ -1163,15 +1290,17 @@ svr4_default_sos (void)
30f2069
   return new;
30f2069
 }
30f2069
 
30f2069
-/* Read the whole inferior libraries chain starting at address LM.  Add the
30f2069
-   entries to the tail referenced by LINK_PTR_PTR.  Ignore the first entry if
30f2069
-   IGNORE_FIRST and set global MAIN_LM_ADDR according to it.  */
30f2069
+/* Read the whole inferior libraries chain starting at address LM.
30f2069
+   Expect the first entry in the chain's previous entry to be PREV_LM.
30f2069
+   Add the entries to the tail referenced by LINK_PTR_PTR.  Ignore the
30f2069
+   first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according
30f2069
+   to it.  Returns nonzero upon success.  */
30f2069
 
30f2069
-static void
30f2069
-svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr,
30f2069
-		   int ignore_first)
30f2069
+static int
30f2069
+svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
30f2069
+		   struct so_list ***link_ptr_ptr, int ignore_first)
30f2069
 {
30f2069
-  CORE_ADDR prev_lm = 0, next_lm;
30f2069
+  CORE_ADDR next_lm;
30f2069
 
30f2069
   for (; lm != 0; prev_lm = lm, lm = next_lm)
30f2069
     {
556378e
@@ -1188,7 +1317,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
30f2069
       if (new->lm_info == NULL)
30f2069
 	{
30f2069
 	  do_cleanups (old_chain);
30f2069
-	  break;
30f2069
+	  return 0;
30f2069
 	}
30f2069
 
30f2069
       next_lm = new->lm_info->l_next;
556378e
@@ -1199,7 +1328,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
556378e
 		   paddress (target_gdbarch (), prev_lm),
556378e
 		   paddress (target_gdbarch (), new->lm_info->l_prev));
30f2069
 	  do_cleanups (old_chain);
30f2069
-	  break;
30f2069
+	  return 0;
30f2069
 	}
30f2069
 
30f2069
       /* For SVR4 versions, the first entry in the link map is for the
556378e
@@ -1294,20 +1423,61 @@ svr4_read_so_list (CORE_ADDR lm, struct
30f2069
       **link_ptr_ptr = new;
30f2069
       *link_ptr_ptr = &new->next;
30f2069
     }
30f2069
+
30f2069
+  return 1;
30f2069
 }
30f2069
 
30f2069
-/* Implement the "current_sos" target_so_ops method.  */
30f2069
+/* Read the list of loaded libraries from the dynamic linker's base
30f2069
+   structure.  */
30f2069
 
30f2069
 static struct so_list *
30f2069
-svr4_current_sos (void)
30f2069
+svr4_current_sos_from_debug_base (void)
30f2069
 {
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
   CORE_ADDR lm;
30f2069
   struct so_list *head = NULL;
30f2069
   struct so_list **link_ptr = &head;
30f2069
-  struct svr4_info *info;
30f2069
   struct cleanup *back_to;
30f2069
   int ignore_first;
30f2069
+
30f2069
+  gdb_assert (info->debug_base);
30f2069
+
30f2069
+  /* Assume that everything is a library if the dynamic loader was loaded
30f2069
+     late by a static executable.  */
30f2069
+  if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
30f2069
+    ignore_first = 0;
30f2069
+  else
30f2069
+    ignore_first = 1;
30f2069
+
30f2069
+  back_to = make_cleanup (svr4_free_library_list, &head;;
30f2069
+
30f2069
+  /* Walk the inferior's link map list, and build our list of
30f2069
+     `struct so_list' nodes.  */
30f2069
+  lm = solib_svr4_r_map (info);
30f2069
+  if (lm)
30f2069
+    svr4_read_so_list (lm, 0, &link_ptr, ignore_first);
30f2069
+
30f2069
+  /* On Solaris, the dynamic linker is not in the normal list of
30f2069
+     shared objects, so make sure we pick it up too.  Having
30f2069
+     symbol information for the dynamic linker is quite crucial
30f2069
+     for skipping dynamic linker resolver code.  */
30f2069
+  lm = solib_svr4_r_ldsomap (info);
30f2069
+  if (lm)
30f2069
+    svr4_read_so_list (lm, 0, &link_ptr, 0);
30f2069
+
30f2069
+  discard_cleanups (back_to);
30f2069
+
30f2069
+  return head;
30f2069
+}
30f2069
+
30f2069
+/* Implement the "current_sos" target_so_ops method.  */
30f2069
+
30f2069
+static struct so_list *
30f2069
+svr4_current_sos (void)
30f2069
+{
30f2069
+  struct svr4_info *info;
30f2069
   struct svr4_library_list library_list;
30f2069
+  struct so_list *result;
30f2069
 
30f2069
   /* Fall back to manual examination of the target if the packet is not
30f2069
      supported or gdbserver failed to find DT_DEBUG.  gdb.server/solib-list.exp
556378e
@@ -1330,6 +1500,10 @@ svr4_current_sos (void)
30f2069
 
30f2069
   info = get_svr4_info ();
30f2069
 
30f2069
+  /* If we have a namespace table then return a flattened copy.  */
30f2069
+  if (info->namespace_table != NULL)
30f2069
+    return namespace_table_flatten (info->namespace_table);
30f2069
+
30f2069
   /* Always locate the debug struct, in case it has moved.  */
30f2069
   info->debug_base = 0;
30f2069
   locate_base (info);
556378e
@@ -1339,35 +1513,12 @@ svr4_current_sos (void)
30f2069
   if (! info->debug_base)
30f2069
     return svr4_default_sos ();
30f2069
 
30f2069
-  /* Assume that everything is a library if the dynamic loader was loaded
30f2069
-     late by a static executable.  */
30f2069
-  if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
30f2069
-    ignore_first = 0;
30f2069
-  else
30f2069
-    ignore_first = 1;
30f2069
-
30f2069
-  back_to = make_cleanup (svr4_free_library_list, &head;;
30f2069
-
30f2069
-  /* Walk the inferior's link map list, and build our list of
30f2069
-     `struct so_list' nodes.  */
30f2069
-  lm = solib_svr4_r_map (info);
30f2069
-  if (lm)
30f2069
-    svr4_read_so_list (lm, &link_ptr, ignore_first);
30f2069
-
30f2069
-  /* On Solaris, the dynamic linker is not in the normal list of
30f2069
-     shared objects, so make sure we pick it up too.  Having
30f2069
-     symbol information for the dynamic linker is quite crucial
30f2069
-     for skipping dynamic linker resolver code.  */
30f2069
-  lm = solib_svr4_r_ldsomap (info);
30f2069
-  if (lm)
30f2069
-    svr4_read_so_list (lm, &link_ptr, 0);
30f2069
-
30f2069
-  discard_cleanups (back_to);
30f2069
+  result = svr4_current_sos_from_debug_base ();
30f2069
 
30f2069
-  if (head == NULL)
30f2069
+  if (result == NULL)
30f2069
     return svr4_default_sos ();
30f2069
 
30f2069
-  return head;
30f2069
+  return result;
30f2069
 }
30f2069
 
30f2069
 /* Get the address of the link_map for a given OBJFILE.  */
556378e
@@ -1452,6 +1603,498 @@ exec_entry_point (struct bfd *abfd, stru
556378e
   return gdbarch_addr_bits_remove (target_gdbarch (), addr);
30f2069
 }
30f2069
 
30f2069
+/* A probe and its associated information structure.  */
30f2069
+
30f2069
+struct probe_and_info
30f2069
+{
30f2069
+  /* The probe.  */
30f2069
+  struct probe *probe;
30f2069
+
30f2069
+  /* The probe_info from which the probe was created.  */
30f2069
+  const struct probe_info *info;
30f2069
+};
30f2069
+
30f2069
+/* Get the solib event probe at the specified location, and the
30f2069
+   probe_info the probe was created with.  Fills in RESULT and
30f2069
+   returns nonzero if a solib event probe was found at the
30f2069
+   specified location.  Returns zero if no solib event probe
30f2069
+   was found.  */
30f2069
+
30f2069
+static int
30f2069
+solib_event_probe_at (struct svr4_info *info, struct bp_location *loc,
30f2069
+		      struct probe_and_info *result)
30f2069
+{
30f2069
+  int i;
30f2069
+
30f2069
+  for (i = 0; i < NUM_PROBES; i++)
30f2069
+    {
30f2069
+      struct probe *probe;
30f2069
+      int ix;
30f2069
+
30f2069
+      for (ix = 0; VEC_iterate (probe_p, info->probes[i], ix, probe); ++ix)
30f2069
+	{
30f2069
+	  if (loc->pspace == current_program_space
30f2069
+	      && loc->address == probe->address)
30f2069
+	    {
30f2069
+	      result->info = &probe_info[i];
30f2069
+	      result->probe = probe;
30f2069
+
30f2069
+	      return 1;
30f2069
+	    }
30f2069
+	}
30f2069
+    }
30f2069
+
30f2069
+  return 0;
30f2069
+}
30f2069
+
30f2069
+/* Decide what action to take when the specified solib event probe is
30f2069
+   hit.  */
30f2069
+
30f2069
+static enum probe_action
30f2069
+solib_event_probe_action (struct probe_and_info *pi)
30f2069
+{
30f2069
+  enum probe_action action;
30f2069
+  unsigned probe_argc;
30f2069
+
30f2069
+  action = pi->info->action;
30f2069
+  if (action == NAMESPACE_NO_ACTION || action == NAMESPACE_TABLE_INVALIDATE)
30f2069
+    return action;
30f2069
+
30f2069
+  gdb_assert (action == NAMESPACE_RELOAD
30f2069
+	      || action == NAMESPACE_UPDATE_OR_RELOAD);
30f2069
+
30f2069
+  /* Check that an appropriate number of arguments has been supplied.
30f2069
+     We expect:
30f2069
+       arg0: Lmid_t lmid (mandatory)
30f2069
+       arg1: struct r_debug *debug_base (mandatory)
30f2069
+       arg2: struct link_map *new (optional, for incremental updates)  */
30f2069
+  probe_argc = get_probe_argument_count (pi->probe);
30f2069
+  if (probe_argc == 2)
30f2069
+    action = NAMESPACE_RELOAD;
30f2069
+  else if (probe_argc < 2)
30f2069
+    action = NAMESPACE_TABLE_INVALIDATE;
30f2069
+
30f2069
+  return action;
30f2069
+}
30f2069
+
30f2069
+/* A namespace in the dynamic linker.  */
30f2069
+
30f2069
+struct namespace
30f2069
+{
30f2069
+  /* Numeric link-map ID of the namespace.  */
30f2069
+  LONGEST lmid;
30f2069
+
30f2069
+  /* List of objects loaded into the namespace.  */
30f2069
+  struct so_list *solist;
30f2069
+};
30f2069
+
30f2069
+/* Returns a hash code for the namespace referenced by p.  */
30f2069
+
30f2069
+static hashval_t
30f2069
+hash_namespace (const void *p)
30f2069
+{
30f2069
+  const struct namespace *ns = p;
30f2069
+
30f2069
+  return (hashval_t) ns->lmid;
30f2069
+}
30f2069
+
30f2069
+/* Returns non-zero if the namespaces referenced by p1 and p2
30f2069
+   are equal.  */
30f2069
+
30f2069
+static int
30f2069
+equal_namespace (const void *p1, const void *p2)
30f2069
+{
30f2069
+  const struct namespace *ns1 = p1;
30f2069
+  const struct namespace *ns2 = p2;
30f2069
+
30f2069
+  return ns1->lmid == ns2->lmid;
30f2069
+}
30f2069
+
30f2069
+/* Free a namespace.  */
30f2069
+
30f2069
+static void
30f2069
+free_namespace (void *p)
30f2069
+{
30f2069
+  struct namespace *ns = p;
30f2069
+
30f2069
+  svr4_free_library_list (ns->solist);
30f2069
+  xfree (ns);
30f2069
+}
30f2069
+
30f2069
+/* Populate this namespace by reading the entire list of shared
30f2069
+   objects from the inferior.  Returns nonzero on success.  */
30f2069
+
30f2069
+static int
30f2069
+namespace_update_full (struct svr4_info *info, LONGEST lmid,
30f2069
+		       CORE_ADDR debug_base, int is_initial_ns)
30f2069
+{
30f2069
+  struct so_list *result = NULL, *so;
30f2069
+  struct namespace lookup, *ns;
30f2069
+  void **slot;
30f2069
+
30f2069
+  /* Read the list of shared objects from the inferior.  The
30f2069
+     initial namespace requires extra processing and is handled
30f2069
+     separately.  */
30f2069
+  if (is_initial_ns)
30f2069
+    {
30f2069
+      result = svr4_current_sos_from_debug_base ();
30f2069
+    }
30f2069
+  else
30f2069
+    {
30f2069
+      CORE_ADDR lm = r_map_from_debug_base (debug_base);
30f2069
+      struct so_list **link_ptr = &result;
30f2069
+
30f2069
+      if (!svr4_read_so_list (lm, 0, &link_ptr, 0))
30f2069
+	return 0;
30f2069
+    }
30f2069
+
30f2069
+  /* If the namespace is empty then delete it from the table.  */
30f2069
+  if (result == NULL)
30f2069
+    {
30f2069
+      if (info->namespace_table != NULL)
30f2069
+	{
30f2069
+	  lookup.lmid = lmid;
30f2069
+	  htab_remove_elt (info->namespace_table, &lookup);
30f2069
+	}
30f2069
+
30f2069
+      return 1;
30f2069
+    }
30f2069
+
30f2069
+  /* Fill in the link-map IDs and initial namespace flags.  */
30f2069
+  for (so = result; so; so = so->next)
30f2069
+    {
30f2069
+      so->lm_info->lmid = lmid;
30f2069
+      so->lm_info->in_initial_ns = is_initial_ns;
30f2069
+    }
30f2069
+
30f2069
+  /* Create the namespace table, if necessary.  */
30f2069
+  if (info->namespace_table == NULL)
30f2069
+    {
30f2069
+      info->namespace_table = htab_create_alloc (1, hash_namespace,
30f2069
+						 equal_namespace,
30f2069
+						 free_namespace,
30f2069
+						 xcalloc, xfree);
30f2069
+    }
30f2069
+
30f2069
+  /* Update the namespace table with our new list.  */
30f2069
+  lookup.lmid = lmid;
30f2069
+  slot = htab_find_slot (info->namespace_table, &lookup, INSERT);
30f2069
+  if (*slot == HTAB_EMPTY_ENTRY)
30f2069
+    {
30f2069
+      ns = XCNEW (struct namespace);
30f2069
+      ns->lmid = lmid;
30f2069
+      *slot = ns;
30f2069
+    }
30f2069
+  else
30f2069
+    {
30f2069
+      ns = *slot;
30f2069
+      svr4_free_library_list (ns->solist);
30f2069
+    }
30f2069
+  ns->solist = result;
30f2069
+
30f2069
+  return 1;
30f2069
+}
30f2069
+
30f2069
+/* Update this namespace starting from the link-map entry passed by
30f2069
+   the linker in the probe's third argument.  Returns nonzero if the
30f2069
+   list was successfully updated, or zero to indicate failure.  */
30f2069
+
30f2069
+static int
30f2069
+namespace_update_incremental (struct svr4_info *info, LONGEST lmid,
30f2069
+			      CORE_ADDR lm, int is_initial_ns)
30f2069
+{
30f2069
+  struct namespace lookup, *ns;
30f2069
+  struct so_list *tail, **link, *so;
30f2069
+  struct value *val;
30f2069
+
30f2069
+  /* Find our namespace in the table.  */
30f2069
+  if (info->namespace_table == NULL)
30f2069
+    return 0;
30f2069
+
30f2069
+  lookup.lmid = lmid;
30f2069
+  ns = htab_find (info->namespace_table, &lookup);
30f2069
+  if (ns == NULL)
30f2069
+    return 0;
30f2069
+
30f2069
+  /* Walk to the end of the list.  */
30f2069
+  tail = ns->solist;
30f2069
+  if (tail == NULL)
30f2069
+    return 0;
30f2069
+
30f2069
+  while (tail->next)
30f2069
+    tail = tail->next;
30f2069
+  link = &tail->next;
30f2069
+
30f2069
+  /* Read the new objects.  */
30f2069
+  if (!svr4_read_so_list (lm, tail->lm_info->lm_addr, &link, 0))
30f2069
+    return 0;
30f2069
+
30f2069
+  /* Fill in the link-map IDs and initial namespace flags.  */
30f2069
+  for (so = tail; so; so = so->next)
30f2069
+    {
30f2069
+      so->lm_info->lmid = lmid;
30f2069
+      so->lm_info->in_initial_ns = is_initial_ns;
30f2069
+    }
30f2069
+
30f2069
+  return 1;
30f2069
+}
30f2069
+
30f2069
+/* Update the namespace table as appropriate when using the
30f2069
+   probes-based linker interface.  Do nothing if using the
30f2069
+   standard interface.  */
30f2069
+
30f2069
+static void
30f2069
+svr4_handle_solib_event (bpstat bs)
30f2069
+{
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
+  struct probe_and_info buf, *pi = &buf;
30f2069
+  enum probe_action action;
30f2069
+  struct value *val;
30f2069
+  LONGEST lmid;
30f2069
+  CORE_ADDR debug_base, lm = 0;
30f2069
+  int is_initial_ns;
30f2069
+
30f2069
+  /* It is possible that this function will be called incorrectly
30f2069
+     by the handle_solib_event in handle_inferior_event if GDB goes
30f2069
+     fully multi-target.  */
30f2069
+  gdb_assert (bs != NULL);
30f2069
+
30f2069
+  if (!info->using_probes)
30f2069
+    return;
30f2069
+
30f2069
+  if (!solib_event_probe_at (info, bs->bp_location_at, pi))
30f2069
+    goto error;
30f2069
+
30f2069
+  action = solib_event_probe_action (pi);
30f2069
+  if (action == NAMESPACE_TABLE_INVALIDATE)
30f2069
+    goto error;
30f2069
+
30f2069
+  if (action == NAMESPACE_NO_ACTION)
30f2069
+    return;
30f2069
+
30f2069
+  val = evaluate_probe_argument (pi->probe, 0);
30f2069
+  if (val == NULL)
30f2069
+    goto error;
30f2069
+
30f2069
+  lmid = value_as_long (val);
30f2069
+
30f2069
+  val = evaluate_probe_argument (pi->probe, 1);
30f2069
+  if (val == NULL)
30f2069
+    goto error;
30f2069
+
30f2069
+  debug_base = value_as_address (val);
30f2069
+  if (debug_base == 0)
30f2069
+    goto error;
30f2069
+
30f2069
+  /* Always locate the debug struct, in case it moved.  */
30f2069
+  info->debug_base = 0;
30f2069
+  if (locate_base (info) == 0)
30f2069
+    goto error;
30f2069
+
30f2069
+  is_initial_ns = (debug_base == info->debug_base);
30f2069
+
30f2069
+  if (action == NAMESPACE_UPDATE_OR_RELOAD)
30f2069
+    {
30f2069
+      val = evaluate_probe_argument (pi->probe, 2);
30f2069
+      if (val != NULL)
30f2069
+	lm = value_as_address (val);
30f2069
+
30f2069
+      if (lm == 0)
30f2069
+	action = NAMESPACE_RELOAD;
30f2069
+    }
30f2069
+
30f2069
+  if (action == NAMESPACE_UPDATE_OR_RELOAD)
30f2069
+    {
30f2069
+      if (namespace_update_incremental (info, lmid, lm, is_initial_ns))
30f2069
+	return;
30f2069
+
30f2069
+      action = NAMESPACE_RELOAD;
30f2069
+    }
30f2069
+
30f2069
+  gdb_assert (action == NAMESPACE_RELOAD);
30f2069
+
30f2069
+  if (namespace_update_full (info, lmid, debug_base, is_initial_ns))
30f2069
+    return;
30f2069
+
30f2069
+ error:
30f2069
+
30f2069
+  /* We should never reach here, but if we do we disable the
30f2069
+     probes interface and revert to the original interface.
30f2069
+     We don't reset the breakpoints as the ones we've set up
30f2069
+     are adequate.  */
30f2069
+  warning (_("Probes-based dynamic linker interface failed.\n"
30f2069
+	     "Reverting to original interface.\n"));
30f2069
+
30f2069
+  free_namespace_table (info);
30f2069
+  free_probes (info);
30f2069
+  info->using_probes = 0;
30f2069
+}
30f2069
+
30f2069
+/* Helper function for namespace_table_flatten.  */
30f2069
+
30f2069
+static int
30f2069
+namespace_table_flatten_helper (void **slot, void *arg)
30f2069
+{
30f2069
+  struct namespace *ns = (struct namespace *) *slot;
30f2069
+  struct so_list *src = ns->solist;
30f2069
+  struct so_list **link = (struct so_list **) arg;
30f2069
+
30f2069
+  while (*link)
30f2069
+    link = &(*link)->next;
30f2069
+
30f2069
+  while (src != NULL)
30f2069
+    {
30f2069
+      struct so_list *dst;
30f2069
+
30f2069
+      dst = xmalloc (sizeof (struct so_list));
30f2069
+      memcpy (dst, src, sizeof (struct so_list));
30f2069
+
30f2069
+      dst->lm_info = xmalloc (sizeof (struct lm_info));
30f2069
+      memcpy (dst->lm_info, src->lm_info, sizeof (struct lm_info));
30f2069
+
30f2069
+      *link = dst;
30f2069
+      link = &dst->next;
30f2069
+
30f2069
+      src = src->next;
30f2069
+    }
30f2069
+
30f2069
+  *link = NULL;
30f2069
+
30f2069
+  return 1; /* Continue traversal.  */
30f2069
+}
30f2069
+
30f2069
+/* Flatten the namespace table into a single list.  */
30f2069
+
30f2069
+static struct so_list *
30f2069
+namespace_table_flatten (htab_t namespace_table)
30f2069
+{
30f2069
+  struct so_list *dst = NULL;
30f2069
+
30f2069
+  htab_traverse (namespace_table, namespace_table_flatten_helper, &dst);
30f2069
+
30f2069
+  return dst;
30f2069
+}
30f2069
+
30f2069
+/* Helper function for svr4_update_solib_event_breakpoints.  */
30f2069
+
30f2069
+static int
30f2069
+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
30f2069
+{
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
+  struct bp_location *loc;
30f2069
+
30f2069
+  if (b->type != bp_shlib_event)
30f2069
+    return 0; /* Continue iterating.  */
30f2069
+
30f2069
+  for (loc = b->loc; loc; loc = loc->next)
30f2069
+    {
30f2069
+      struct probe_and_info buf, *pi = &buf;
30f2069
+
30f2069
+      if (solib_event_probe_at (info, loc, pi))
30f2069
+	{
30f2069
+	  if (pi->info->action == NAMESPACE_NO_ACTION)
30f2069
+	    b->enable_state = (stop_on_solib_events
30f2069
+			       ? bp_enabled : bp_disabled);
30f2069
+
30f2069
+	  return 0; /* Continue iterating.  */
30f2069
+	}
30f2069
+    }
30f2069
+
30f2069
+  return 0; /* Continue iterating.  */
30f2069
+}
30f2069
+
30f2069
+/* Enable or disable optional solib event breakpoints as appropriate.
30f2069
+   Called whenever stop_on_solib_events is changed.  */
30f2069
+
30f2069
+static void
30f2069
+svr4_update_solib_event_breakpoints (void)
30f2069
+{
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
+
30f2069
+  if (info->using_probes)
30f2069
+    iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
30f2069
+}
30f2069
+
30f2069
+/* Both the SunOS and the SVR4 dynamic linkers call a marker function
30f2069
+   before and after mapping and unmapping shared libraries.  The sole
30f2069
+   purpose of this method is to allow debuggers to set a breakpoint so
30f2069
+   they can track these changes.
30f2069
+
30f2069
+   Some versions of the glibc dynamic linker contain named probes
30f2069
+   to allow more fine grained stopping.  Given the address of the
30f2069
+   original marker function, this function attempts to find these
30f2069
+   probes, and if found, sets breakpoints on those instead.  If the
30f2069
+   probes aren't found, a single breakpoint is set on the original
30f2069
+   marker function.  */
30f2069
+
30f2069
+static void
30f2069
+svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch,
30f2069
+				     CORE_ADDR address)
30f2069
+{
30f2069
+  struct svr4_info *info = get_svr4_info ();
30f2069
+  struct obj_section *os;
30f2069
+
30f2069
+  os = find_pc_section (address);
30f2069
+  if (os != NULL)
30f2069
+    {
30f2069
+      int with_prefix;
30f2069
+
30f2069
+      for (with_prefix = 0; with_prefix <= 1; with_prefix++)
30f2069
+	{
30f2069
+	  int all_probes_found = 1;
30f2069
+	  int i;
30f2069
+
30f2069
+	  for (i = 0; i < NUM_PROBES; i++)
30f2069
+	    {
30f2069
+	      char name[32] = { '\0' };
30f2069
+
30f2069
+	      /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an
30f2069
+		 early version of the probes code in which the probes'
30f2069
+		 names were prefixed with "rtld_".  The locations and
30f2069
+		 arguments of the probes are otherwise the same, so we
30f2069
+		 check for the prefixed version if the unprefixed
30f2069
+		 probes are not found.  */
30f2069
+
30f2069
+	      if (with_prefix)
30f2069
+		strncat (name, "rtld_", sizeof (name));
30f2069
+
30f2069
+	      strncat (name, probe_info[i].name, sizeof (name) - sizeof ("rtld_"));
30f2069
+
30f2069
+	      info->probes[i] = find_probes_in_objfile (os->objfile, "rtld",
30f2069
+							name);
30f2069
+
30f2069
+	      if (!VEC_length (probe_p, info->probes[i]))
30f2069
+		{
30f2069
+		  free_probes (info);
30f2069
+		  all_probes_found = 0;
30f2069
+		  break;
30f2069
+		}
30f2069
+	    }
30f2069
+
30f2069
+	  if (all_probes_found)
30f2069
+	    {
30f2069
+	      info->using_probes = 1;
30f2069
+
30f2069
+	      for (i = 0; i < NUM_PROBES; i++)
30f2069
+		{
30f2069
+		  struct probe *probe;
30f2069
+		  int ix;
30f2069
+
30f2069
+		  for (ix = 0;
30f2069
+		       VEC_iterate (probe_p, info->probes[i], ix, probe);
30f2069
+		       ++ix)
30f2069
+		    create_solib_event_breakpoint (gdbarch, probe->address);
30f2069
+		}
30f2069
+
30f2069
+	      svr4_update_solib_event_breakpoints ();
30f2069
+	      return;
30f2069
+	    }
30f2069
+	}
30f2069
+    }
30f2069
+
30f2069
+  create_solib_event_breakpoint (gdbarch, address);
30f2069
+}
30f2069
+
30f2069
 /* Helper function for gdb_bfd_lookup_symbol.  */
30f2069
 
30f2069
 static int
556378e
@@ -1504,6 +2147,9 @@ enable_break (struct svr4_info *info, in
30f2069
   info->interp_text_sect_low = info->interp_text_sect_high = 0;
30f2069
   info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
30f2069
 
30f2069
+  free_probes (info);
30f2069
+  info->using_probes = 0;
30f2069
+
30f2069
   /* If we already have a shared library list in the target, and
30f2069
      r_debug contains r_brk, set the breakpoint there - this should
30f2069
      mean r_brk has already been relocated.  Assume the dynamic linker
556378e
@@ -1535,7 +2181,7 @@ enable_break (struct svr4_info *info, in
30f2069
 	 That knowledge is encoded in the address, if it's Thumb the low bit
30f2069
 	 is 1.  However, we've stripped that info above and it's not clear
30f2069
 	 what all the consequences are of passing a non-addr_bits_remove'd
30f2069
-	 address to create_solib_event_breakpoint.  The call to
30f2069
+	 address to svr4_create_solib_event_breakpoints.  The call to
30f2069
 	 find_pc_section verifies we know about the address and have some
30f2069
 	 hope of computing the right kind of breakpoint to use (via
30f2069
 	 symbol info).  It does mean that GDB needs to be pointed at a
556378e
@@ -1573,7 +2219,7 @@ enable_break (struct svr4_info *info, in
30f2069
 		+ bfd_section_size (tmp_bfd, interp_sect);
30f2069
 	    }
30f2069
 
556378e
-	  create_solib_event_breakpoint (target_gdbarch (), sym_addr);
556378e
+	  svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
30f2069
 	  return 1;
30f2069
 	}
30f2069
     }
556378e
@@ -1731,7 +2377,8 @@ enable_break (struct svr4_info *info, in
30f2069
 
30f2069
       if (sym_addr != 0)
30f2069
 	{
556378e
-	  create_solib_event_breakpoint (target_gdbarch (), load_addr + sym_addr);
556378e
+	  svr4_create_solib_event_breakpoints (target_gdbarch (),
30f2069
+					       load_addr + sym_addr);
30f2069
 	  xfree (interp_name);
30f2069
 	  return 1;
30f2069
 	}
556378e
@@ -1757,7 +2404,7 @@ enable_break (struct svr4_info *info, in
556378e
 	  sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
30f2069
 							 sym_addr,
30f2069
 							 &current_target);
556378e
-	  create_solib_event_breakpoint (target_gdbarch (), sym_addr);
556378e
+	  svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
30f2069
 	  return 1;
30f2069
 	}
30f2069
     }
556378e
@@ -1773,7 +2420,7 @@ enable_break (struct svr4_info *info, in
556378e
 	      sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
30f2069
 							     sym_addr,
30f2069
 							     &current_target);
556378e
-	      create_solib_event_breakpoint (target_gdbarch (), sym_addr);
556378e
+	      svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
30f2069
 	      return 1;
30f2069
 	    }
30f2069
 	}
556378e
@@ -2269,6 +2916,9 @@ svr4_solib_create_inferior_hook (int fro
30f2069
 
30f2069
   info = get_svr4_info ();
30f2069
 
30f2069
+  /* Free the probes-based interface's namespace table.  */
30f2069
+  free_namespace_table (info);
30f2069
+
30f2069
   /* Relocate the main executable if necessary.  */
30f2069
   svr4_relocate_main_executable ();
30f2069
 
556378e
@@ -2510,4 +3160,6 @@ _initialize_svr4_solib (void)
30f2069
   svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
30f2069
   svr4_so_ops.same = svr4_same;
30f2069
   svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
30f2069
+  svr4_so_ops.handle_solib_event = svr4_handle_solib_event;
30f2069
+  svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
30f2069
 }
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen-solib.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen-solib.c	2013-01-18 23:57:50.519792858 +0100
30f2069
@@ -0,0 +1,24 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <stdio.h>
30f2069
+
30f2069
+int
30f2069
+foo (int n)
30f2069
+{
30f2069
+  printf ("foo %d\n", n);
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen.c	2013-01-18 23:57:50.519792858 +0100
30f2069
@@ -0,0 +1,58 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#define _GNU_SOURCE
30f2069
+#include <dlfcn.h>
30f2069
+
30f2069
+void
30f2069
+stop ()
30f2069
+{
30f2069
+}
30f2069
+
30f2069
+int
30f2069
+main ()
30f2069
+{
30f2069
+  void *handle1, *handle2, *handle3;
30f2069
+  void (*func)(int);
30f2069
+
30f2069
+  handle1 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
30f2069
+  stop ();
30f2069
+
30f2069
+  func = (void (*)(int)) dlsym (handle1, "foo");
30f2069
+  func (1);
30f2069
+
30f2069
+  handle2 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
30f2069
+  stop ();
30f2069
+
30f2069
+  func = (void (*)(int)) dlsym (handle2, "foo");
30f2069
+  func (2);
30f2069
+
30f2069
+  handle3 = dlopen (SHLIB_NAME, RTLD_LAZY);
30f2069
+  stop ();
30f2069
+
30f2069
+  func = (void (*)(int)) dlsym (handle3, "foo");
30f2069
+  func (3);
30f2069
+
30f2069
+  dlclose (handle1);
30f2069
+  stop ();
30f2069
+
30f2069
+  dlclose (handle2);
30f2069
+  stop ();
30f2069
+
30f2069
+  dlclose (handle3);
30f2069
+  stop ();
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen.exp
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-dlmopen.exp	2013-01-18 23:57:50.519792858 +0100
30f2069
@@ -0,0 +1,125 @@
30f2069
+# Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+# This program is free software; you can redistribute it and/or modify
30f2069
+# it under the terms of the GNU General Public License as published by
30f2069
+# the Free Software Foundation; either version 3 of the License, or
30f2069
+# (at your option) any later version.
30f2069
+#
30f2069
+# This program is distributed in the hope that it will be useful,
30f2069
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+# GNU General Public License for more details.
30f2069
+#
30f2069
+# You should have received a copy of the GNU General Public License
30f2069
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30f2069
+
30f2069
+if { [skip_shlib_tests] || [is_remote target] } {
30f2069
+    return 0
30f2069
+}
30f2069
+
30f2069
+standard_testfile
30f2069
+
30f2069
+set libname $testfile-solib
30f2069
+set srcfile_lib $srcdir/$subdir/$libname.c
30f2069
+set binfile_lib [standard_output_file $libname.so]
30f2069
+
30f2069
+set normal_bp "_dl_debug_state"
30f2069
+set probes_bp "dl_main"
30f2069
+
30f2069
+if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
30f2069
+	  [list additional_flags=-fPIC]] != "" } {
30f2069
+    untested "Could not compile $binfile_lib."
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+if { [prepare_for_testing $testfile.exp $testfile $srcfile \
30f2069
+	  [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+# Run "info sharedlibrary" and check our library is shown the expected
30f2069
+# number of times.
30f2069
+proc check_info_shared { test expect } {
30f2069
+    global libname
30f2069
+    global gdb_prompt
30f2069
+
30f2069
+    set actual 0
30f2069
+
30f2069
+    gdb_test_multiple "info sharedlibrary" $test {
30f2069
+	-re $libname {
30f2069
+	    incr actual 1
30f2069
+	    exp_continue
30f2069
+	}
30f2069
+	-re "\r\n$gdb_prompt $" {
30f2069
+	    if { $actual == $expect } {
30f2069
+		pass $test
30f2069
+	    } else {
30f2069
+		fail $test
30f2069
+	    }
30f2069
+	}
30f2069
+    }
30f2069
+}
30f2069
+
30f2069
+# Enable stop-on-solib-events
30f2069
+gdb_test_no_output "set stop-on-solib-events 1"
30f2069
+
30f2069
+# Run to the first stop
30f2069
+gdb_test "run" ".*Stopped due to shared library event.*"
30f2069
+
30f2069
+# XFAIL if we are not using probes
30f2069
+set test "ensure using probes"
30f2069
+set using_probes 0
30f2069
+gdb_test_multiple "bt" $test {
30f2069
+    -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
30f2069
+	xfail $test
30f2069
+    }
30f2069
+    -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
30f2069
+	pass $test
30f2069
+	set using_probes 1
30f2069
+    }
30f2069
+}
30f2069
+
30f2069
+if { $using_probes } {
30f2069
+    # Set up breakpoints.
30f2069
+    gdb_test_no_output "set stop-on-solib-events 0"
30f2069
+    gdb_test "break stop" {Breakpoint [0-9]+ at .*}
30f2069
+    gdb_test_no_output "set breakpoint pending on"
30f2069
+    gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
30f2069
+
30f2069
+    # Check our library isn't loaded.
30f2069
+    check_info_shared "info sharedlibrary #1" 0
30f2069
+
30f2069
+    # Run to the first stop and check our library loaded.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #2" 1
30f2069
+
30f2069
+    # The next stop should be the function in the library.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
30f2069
+
30f2069
+    # Run to the next stop and check our library is now loaded twice.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #3" 2
30f2069
+
30f2069
+    # The next stop should be the function in the library.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
30f2069
+
30f2069
+    # Run to the next stop and check our library is now loaded three
30f2069
+    # times.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #4" 3
30f2069
+
30f2069
+    # The next stop should be the function in the library.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
30f2069
+
30f2069
+    # Run to the next stop and check our library is now loaded twice.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #5" 2
30f2069
+
30f2069
+    # Run to the next stop and check our library is now loaded once.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #6" 1
30f2069
+
30f2069
+    # Run to the next stop and check our library is not loaded.
30f2069
+    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+    check_info_shared "info sharedlibrary #7" 0
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-interp.exp
30f2069
===================================================================
556378e
--- gdb-7.5.50.20130118.orig/gdb/testsuite/gdb.base/break-interp.exp	2013-01-18 23:57:14.782978485 +0100
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-interp.exp	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -109,12 +109,19 @@ proc strip_debug {dest} {
30f2069
     }
30f2069
 }
30f2069
 
30f2069
+# The marker function for the standard runtime linker interface is
30f2069
+# _dl_debug_state.  The probes-based interface has no specific marker
30f2069
+# function; the probe we will stop on (init_start) is in dl_main so we
30f2069
+# check for that.
30f2069
+
30f2069
+set solib_bp {(_dl_debug_state|dl_main)}
30f2069
+
30f2069
 # Implementation of reach.
30f2069
 
30f2069
 proc reach_1 {func command displacement} {
30f2069
-    global gdb_prompt expect_out
30f2069
+    global gdb_prompt expect_out solib_bp
30f2069
 
30f2069
-    if {$func == "_dl_debug_state"} {
30f2069
+    if {$func == $solib_bp} {
30f2069
 	# Breakpoint on _dl_debug_state can have problems due to its overlap
30f2069
 	# with the existing internal breakpoint from GDB.
30f2069
 	gdb_test_no_output "set stop-on-solib-events 1"
30f2069
@@ -142,21 +149,21 @@ proc reach_1 {func command displacement}
30f2069
 	    exp_continue
30f2069
 	}
30f2069
 	-re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
30f2069
-	    if {$func == "_dl_debug_state"} {
30f2069
+	    if {$func == $solib_bp} {
30f2069
 		fail $test
30f2069
 	    } else {
30f2069
 		pass $test
30f2069
 	    }
30f2069
 	}
30f2069
 	-re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" {
30f2069
-	    if {$func == "_dl_debug_state"} {
30f2069
+	    if {$func == $solib_bp} {
30f2069
 		fail $test
30f2069
 	    } else {
30f2069
 		pass $test
30f2069
 	    }
30f2069
 	}
30f2069
 	-re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" {
30f2069
-	    if {$func == "_dl_debug_state"} {
30f2069
+	    if {$func == $solib_bp} {
30f2069
 		if {$debug_state_count == 0} {
30f2069
 		    # First stop does not yet relocate the _start function
30f2069
 		    # descriptor on ppc64.
30f2069
@@ -175,7 +182,7 @@ proc reach_1 {func command displacement}
30f2069
 	fail $test_displacement
30f2069
     }
30f2069
 
30f2069
-    if {$func == "_dl_debug_state"} {
30f2069
+    if {$func == $solib_bp} {
30f2069
 	gdb_test_no_output "set stop-on-solib-events 0"
30f2069
     }
30f2069
 }
30f2069
@@ -357,7 +364,7 @@ proc test_attach {file displacement {rel
30f2069
 }
30f2069
 
30f2069
 proc test_ld {file ifmain trynosym displacement} {
30f2069
-    global srcdir subdir gdb_prompt expect_out inferior_exited_re
30f2069
+    global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp
30f2069
 
30f2069
     # First test normal `file'-command loaded $FILE with symbols.
30f2069
 
30f2069
@@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ
30f2069
 	gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test"
30f2069
     }
30f2069
 
30f2069
-    reach "_dl_debug_state" "run" $displacement
30f2069
+    reach $solib_bp "run" $displacement
30f2069
 
30f2069
-    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt"
30f2069
+    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt"
30f2069
 
30f2069
     if $ifmain {
30f2069
 	reach "main" continue "NONE"
30f2069
@@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ
30f2069
 
30f2069
     # Try re-run if the new PIE displacement takes effect.
30f2069
     gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y"
30f2069
-    reach "_dl_debug_state" "run" $displacement
30f2069
+    reach $solib_bp "run" $displacement
30f2069
 
30f2069
     if $ifmain {
30f2069
 	test_core $file $displacement
30f2069
@@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ
30f2069
 	gdb_test "exec-file $file" "exec-file $escapedfile" "load"
30f2069
 
30f2069
 	if $ifmain {
30f2069
-	    reach "_dl_debug_state" run $displacement
30f2069
+	    reach $solib_bp run $displacement
30f2069
 
30f2069
 	    # Use two separate gdb_test_multiple statements to avoid timeouts due
30f2069
 	    # to slow processing of wildcard capturing long output
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes-solib.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes-solib.c	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,24 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <stdio.h>
30f2069
+
30f2069
+int
30f2069
+foo (int n)
30f2069
+{
30f2069
+  printf ("foo %d\n", n);
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes.c	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,26 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <dlfcn.h>
30f2069
+
30f2069
+int
30f2069
+main ()
30f2069
+{
30f2069
+  void *handle = dlopen (SHLIB_NAME, RTLD_LAZY);
30f2069
+
30f2069
+  dlclose (handle);
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes.exp
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/break-probes.exp	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,76 @@
30f2069
+# Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+# This program is free software; you can redistribute it and/or modify
30f2069
+# it under the terms of the GNU General Public License as published by
30f2069
+# the Free Software Foundation; either version 3 of the License, or
30f2069
+# (at your option) any later version.
30f2069
+#
30f2069
+# This program is distributed in the hope that it will be useful,
30f2069
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+# GNU General Public License for more details.
30f2069
+#
30f2069
+# You should have received a copy of the GNU General Public License
30f2069
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30f2069
+
30f2069
+if { [skip_shlib_tests] || [is_remote target] } {
30f2069
+    return 0
30f2069
+}
30f2069
+
30f2069
+standard_testfile
30f2069
+
30f2069
+set libname $testfile-solib
30f2069
+set srcfile_lib $srcdir/$subdir/$libname.c
30f2069
+set binfile_lib [standard_output_file $libname.so]
30f2069
+
30f2069
+set normal_bp "_dl_debug_state"
30f2069
+set probes_bp "dl_main"
30f2069
+
30f2069
+if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
30f2069
+	  [list additional_flags=-fPIC]] != "" } {
30f2069
+    untested "Could not compile $binfile_lib."
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+if { [prepare_for_testing $testfile.exp $testfile $srcfile \
30f2069
+	  [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+# Enable stop-on-solib-events
30f2069
+gdb_test_no_output "set stop-on-solib-events 1"
30f2069
+
30f2069
+# Run to the first stop
30f2069
+gdb_test "run" ".*Stopped due to shared library event.*"
30f2069
+
30f2069
+# XFAIL if we are not using probes
30f2069
+set test "ensure using probes"
30f2069
+set using_probes 0
30f2069
+gdb_test_multiple "bt" $test {
30f2069
+    -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
30f2069
+	xfail $test
30f2069
+    }
30f2069
+    -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
30f2069
+	pass $test
30f2069
+	set using_probes 1
30f2069
+    }
30f2069
+}
30f2069
+
30f2069
+if { $using_probes } {
30f2069
+    # Run til it loads our library
30f2069
+    set test "run til our library loads"
30f2069
+    set loaded_library 0
30f2069
+    while { !$loaded_library } {
30f2069
+	gdb_test_multiple "c" $test {
30f2069
+	    -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" {
30f2069
+		pass $test
30f2069
+		set loaded_library 1
30f2069
+	    }
30f2069
+	    -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
30f2069
+	    }
30f2069
+	}
30f2069
+    }
30f2069
+
30f2069
+    # Call something to ensure that relocation occurred
30f2069
+    gdb_test "call foo(23)" "foo 23.*\\\$.* = .*"
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared-solib1.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared-solib1.c	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,24 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <stdio.h>
30f2069
+
30f2069
+int
30f2069
+foo (int n)
30f2069
+{
30f2069
+  printf ("foo %d\n", n);
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared-solib2.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared-solib2.c	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,24 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <stdio.h>
30f2069
+
30f2069
+int
30f2069
+bar (int n)
30f2069
+{
30f2069
+  printf ("bar %d\n", n);
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared.c
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared.c	2013-01-18 23:57:50.520792854 +0100
30f2069
@@ -0,0 +1,48 @@
30f2069
+/* Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+   This program is free software; you can redistribute it and/or modify
30f2069
+   it under the terms of the GNU General Public License as published by
30f2069
+   the Free Software Foundation; either version 3 of the License, or
30f2069
+   (at your option) any later version.
30f2069
+
30f2069
+   This program is distributed in the hope that it will be useful,
30f2069
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+   GNU General Public License for more details.
30f2069
+
30f2069
+   You should have received a copy of the GNU General Public License
30f2069
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
30f2069
+
30f2069
+#include <dlfcn.h>
30f2069
+
30f2069
+void
30f2069
+stop ()
30f2069
+{
30f2069
+}
30f2069
+
30f2069
+int
30f2069
+main ()
30f2069
+{
30f2069
+  void *handle1, *handle2;
30f2069
+  void (*func)(int);
30f2069
+
30f2069
+  handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY);
30f2069
+  stop ();
30f2069
+
30f2069
+  handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY);
30f2069
+  stop ();
30f2069
+
30f2069
+  func = (void (*)(int)) dlsym (handle1, "foo");
30f2069
+  func (1);
30f2069
+
30f2069
+  func = (void (*)(int)) dlsym (handle2, "bar");
30f2069
+  func (2);
30f2069
+
30f2069
+  dlclose (handle1);
30f2069
+  stop ();
30f2069
+
30f2069
+  dlclose (handle2);
30f2069
+  stop ();
30f2069
+
30f2069
+  return 0;
30f2069
+}
556378e
Index: gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared.exp
30f2069
===================================================================
30f2069
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
556378e
+++ gdb-7.5.50.20130118/gdb/testsuite/gdb.base/info-shared.exp	2013-01-18 23:57:50.521792850 +0100
30f2069
@@ -0,0 +1,139 @@
30f2069
+# Copyright 2012 Free Software Foundation, Inc.
30f2069
+
30f2069
+# This program is free software; you can redistribute it and/or modify
30f2069
+# it under the terms of the GNU General Public License as published by
30f2069
+# the Free Software Foundation; either version 3 of the License, or
30f2069
+# (at your option) any later version.
30f2069
+#
30f2069
+# This program is distributed in the hope that it will be useful,
30f2069
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30f2069
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30f2069
+# GNU General Public License for more details.
30f2069
+#
30f2069
+# You should have received a copy of the GNU General Public License
30f2069
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30f2069
+
30f2069
+if { [skip_shlib_tests] || [is_remote target] } {
30f2069
+    return 0
30f2069
+}
30f2069
+
30f2069
+standard_testfile
30f2069
+
30f2069
+set lib1name $testfile-solib1
30f2069
+set srcfile_lib1 $srcdir/$subdir/$lib1name.c
30f2069
+set binfile_lib1 [standard_output_file $lib1name.so]
30f2069
+set define1 -DSHLIB1_NAME\=\"$binfile_lib1\"
30f2069
+
30f2069
+set lib2name $testfile-solib2
30f2069
+set srcfile_lib2 $srcdir/$subdir/$lib2name.c
30f2069
+set binfile_lib2 [standard_output_file $lib2name.so]
30f2069
+set define2 -DSHLIB2_NAME\=\"$binfile_lib2\"
30f2069
+
30f2069
+if { [gdb_compile_shlib $srcfile_lib1 $binfile_lib1 \
30f2069
+	  [list additional_flags=-fPIC]] != "" } {
30f2069
+    untested "Could not compile $binfile_lib1."
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+if { [gdb_compile_shlib $srcfile_lib2 $binfile_lib2 \
30f2069
+	  [list additional_flags=-fPIC]] != "" } {
30f2069
+    untested "Could not compile $binfile_lib2."
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+set cflags "$define1 $define2"
30f2069
+if { [prepare_for_testing $testfile.exp $testfile $srcfile \
30f2069
+	  [list additional_flags=$cflags libs=-ldl]] } {
30f2069
+    return -1
30f2069
+}
30f2069
+
30f2069
+# Run "info sharedlibrary" and check for the presence or absence of
30f2069
+# our libraries.
30f2069
+proc check_info_shared { test expect1 expect2 } {
30f2069
+    global lib1name
30f2069
+    global lib2name
30f2069
+    global gdb_prompt
30f2069
+
30f2069
+    set actual1 0
30f2069
+    set actual2 0
30f2069
+
30f2069
+    gdb_test_multiple "info sharedlibrary" $test {
30f2069
+	-re $lib1name {
30f2069
+	    set actual1 1
30f2069
+	    exp_continue
30f2069
+	}
30f2069
+	-re $lib2name {
30f2069
+	    set actual2 1
30f2069
+	    exp_continue
30f2069
+	}
30f2069
+	-re "\r\n$gdb_prompt $" {
30f2069
+	    if { $actual1 == $expect1 && $actual2 == $expect2 } {
30f2069
+		pass $test
30f2069
+	    } else {
30f2069
+		fail $test
30f2069
+	    }
30f2069
+	}
30f2069
+    }
30f2069
+}
30f2069
+
30f2069
+# Set up breakpoints.
30f2069
+gdb_test "break stop" {Breakpoint [0-9]+ at .*}
30f2069
+gdb_test_no_output "set breakpoint pending on"
30f2069
+gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
30f2069
+gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.}
30f2069
+
30f2069
+# Check neither of the libraries are loaded at the start.
30f2069
+gdb_test "start" {Temporary breakpoint [0-9]+, .* in main \(\)}
30f2069
+check_info_shared "info sharedlibrary #1" 0 0
30f2069
+
30f2069
+# Run to the first stop and check that only the first library is loaded.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+check_info_shared "info sharedlibrary #2" 1 0
30f2069
+
30f2069
+# Run to the second stop and check that both libraries are loaded.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+check_info_shared "info sharedlibrary #3" 1 1
30f2069
+
30f2069
+# Check that the next stop is in foo.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
30f2069
+
30f2069
+# Check that the next stop is in bar.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
30f2069
+
30f2069
+# Restart the inferior and make sure there are no breakpoint reset
30f2069
+# errors.  These can happen with the probes-based runtime linker
30f2069
+# interface if the cache is not cleared correctly.
30f2069
+set test "restart"
30f2069
+gdb_test_multiple "run" $test {
30f2069
+    -re {Start it from the beginning\? \(y or n\) } {
30f2069
+	send_gdb "y\n"
30f2069
+	exp_continue
30f2069
+    }
30f2069
+    -re {Error in re-setting breakpoint} {
30f2069
+	fail $test
30f2069
+    }
30f2069
+    -re "\r\n$gdb_prompt $" {
30f2069
+	pass $test
30f2069
+    }
30f2069
+}
30f2069
+
30f2069
+# We're at the first stop.  Check that only the first library is loaded.
30f2069
+check_info_shared "info sharedlibrary #4" 1 0
30f2069
+
30f2069
+# Run to the second stop and check that both libraries are loaded.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+check_info_shared "info sharedlibrary #5" 1 1
30f2069
+
30f2069
+# Check that the next stop is in foo.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
30f2069
+
30f2069
+# Check that the next stop is in bar.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
30f2069
+
30f2069
+# Run to the next stop and check that the first library has been unloaded.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+check_info_shared "info sharedlibrary #6" 0 1
30f2069
+
30f2069
+# Run to the last stop and check that both libraries are gone.
30f2069
+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
30f2069
+check_info_shared "info sharedlibrary #7" 0 0