[gdb/f18] Rebase to FSF GDB 7.5.

Jan Kratochvil jankratochvil at fedoraproject.org
Sat Aug 18 07:41:18 UTC 2012


commit 30f2069f6eae88d7672db5d92a457dce007d578e
Author: Jan Kratochvil <jan.kratochvil at redhat.com>
Date:   Sat Aug 18 09:41:09 2012 +0200

    Rebase to FSF GDB 7.5.
    
    - Update dlopen to support two variants of glibc (Gary Benson, BZ 669432).

 .gitignore                        |    2 +-
 gdb-dlopen-stap-probe-1of7.patch  |  795 +++++++++++++++
 gdb-dlopen-stap-probe-2of7.patch  |   74 ++
 gdb-dlopen-stap-probe-3of7.patch  |   98 ++
 gdb-dlopen-stap-probe-4of7.patch  |  131 +++
 gdb-dlopen-stap-probe-5of7.patch  |   17 +
 gdb-dlopen-stap-probe-6of7.patch  | 1989 +++++++++++++++++++++++++++++++++++++
 gdb-dlopen-stap-probe-7of7.patch  |  147 +++
 gdb-dlopen-stap-probe-test.patch  |  101 --
 gdb-dlopen-stap-probe-test2.patch |   69 ++
 gdb-dlopen-stap-probe.patch       |  357 -------
 gdb.spec                          |   36 +-
 sources                           |    2 +-
 13 files changed, 3349 insertions(+), 469 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 5b72433..66e0ded 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
 /gdb-libstdc++-v3-python-r155978.tar.bz2
-/gdb-7.4.91.20120801.tar.bz2
+/gdb-7.5.tar.bz2
diff --git a/gdb-dlopen-stap-probe-1of7.patch b/gdb-dlopen-stap-probe-1of7.patch
new file mode 100644
index 0000000..1891fb3
--- /dev/null
+++ b/gdb-dlopen-stap-probe-1of7.patch
@@ -0,0 +1,795 @@
+http://sourceware.org/ml/gdb-cvs/2012-07/msg00123.html
+
+### src/gdb/ChangeLog	2012/07/18 04:36:15	1.14473
+### src/gdb/ChangeLog	2012/07/18 16:12:15	1.14474
+## -1,3 +1,37 @@
++2012-07-18  Sergio Durigan Junior  <sergiodj at redhat.com>
++
++	* elfread.c (elf_get_probe_argument_count): Remove `objfile' argument.
++	(elf_compile_to_ax): Likewise.
++	* infrun.c (insert_exception_resume_from_probe): Likewise.
++	(check_exception_resume): Remove `objfile' variable.
++	* probe.c (find_probe_by_pc): Remove `objfile' argument.
++	(struct probe_and_objfile, probe_and_objfile_s): Delete.
++	(collect_probes): Adjust return value to `VEC (probe_p) *'.
++	(compare_entries): Rename to...
++	(compare_probes): ...this.  Adjust function to work with
++	`struct probe *'.  Rename variables `ea' and `eb' to `pa' and `pb'
++	respectively.
++	(gen_ui_out_table_header_info): Adjust `probes' argument to be
++	`VEC (probe_p) *'.
++	(print_ui_out_info): Adjust argument to be `struct probe *'.
++	(info_probes_for_ops): Adjust internal computations to use
++	`VEC (probe_p) *'.
++	(probe_safe_evaluate_at_pc): Refactor to not pass `objfile' anymore.
++	* probe.h (struct probe_ops) <get_probe_argument_count, compile_to_ax,
++	gen_info_probes_table_values>: Remove `objfile' argument.
++	(struct probe) <objfile>: New field.
++	(find_probe_by_pc): Remove `objfile' argument.
++	* stap-probe.c (stap_parse_probe_arguments): Likewise.
++	(stap_get_probe_argument_count): Likewise.
++	(stap_get_arg): Likewise.
++	(stap_evaluate_probe_argument): Likewise.
++	(stap_compile_to_ax): Likewise.
++	(compile_probe_arg): Refactor not to pass `objfile' anymore.
++	(handle_stap_probe): Fill `objfile' field from `struct probe'.
++	(stap_gen_info_probes_table_header): Remove `objfile' argument.
++	* symfile.h (struct sym_probe_fns) <sym_evaluate_probe_argument,
++	sym_compile_to_ax>: Likewise.
++
+ 2012-07-18  Terry Guo  <terry.guo at arm.com>
+ 
+ 	PR 14329
+--- src/gdb/elfread.c	2012/06/26 20:14:01	1.133
++++ src/gdb/elfread.c	2012/07/18 16:12:15	1.134
+@@ -1635,33 +1635,29 @@
+    symfile.h.  */
+ 
+ static unsigned
+-elf_get_probe_argument_count (struct objfile *objfile,
+-			      struct probe *probe)
++elf_get_probe_argument_count (struct probe *probe)
+ {
+-  return probe->pops->get_probe_argument_count (probe, objfile);
++  return probe->pops->get_probe_argument_count (probe);
+ }
+ 
+ /* Implementation of `sym_evaluate_probe_argument', as documented in
+    symfile.h.  */
+ 
+ static struct value *
+-elf_evaluate_probe_argument (struct objfile *objfile,
+-			     struct probe *probe,
+-			     unsigned n)
++elf_evaluate_probe_argument (struct probe *probe, unsigned n)
+ {
+-  return probe->pops->evaluate_probe_argument (probe, objfile, n);
++  return probe->pops->evaluate_probe_argument (probe, n);
+ }
+ 
+ /* Implementation of `sym_compile_to_ax', as documented in symfile.h.  */
+ 
+ static void
+-elf_compile_to_ax (struct objfile *objfile,
+-		   struct probe *probe,
++elf_compile_to_ax (struct probe *probe,
+ 		   struct agent_expr *expr,
+ 		   struct axs_value *value,
+ 		   unsigned n)
+ {
+-  probe->pops->compile_to_ax (probe, objfile, expr, value, n);
++  probe->pops->compile_to_ax (probe, expr, value, n);
+ }
+ 
+ /* Implementation of `sym_relocate_probe', as documented in symfile.h.  */
+--- src/gdb/infrun.c	2012/07/01 10:37:04	1.549
++++ src/gdb/infrun.c	2012/07/18 16:12:16	1.550
+@@ -5518,7 +5518,6 @@
+ static void
+ insert_exception_resume_from_probe (struct thread_info *tp,
+ 				    const struct probe *probe,
+-				    struct objfile *objfile,
+ 				    struct frame_info *frame)
+ {
+   struct value *arg_value;
+@@ -5534,7 +5533,7 @@
+   if (debug_infrun)
+     fprintf_unfiltered (gdb_stdlog,
+ 			"infrun: exception resume at %s\n",
+-			paddress (get_objfile_arch (objfile),
++			paddress (get_objfile_arch (probe->objfile),
+ 				  handler));
+ 
+   bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
+@@ -5552,7 +5551,6 @@
+ 			struct frame_info *frame)
+ {
+   volatile struct gdb_exception e;
+-  struct objfile *objfile;
+   const struct probe *probe;
+   struct symbol *func;
+ 
+@@ -5560,11 +5558,10 @@
+      SystemTap probe point.  If so, the probe has two arguments: the
+      CFA and the HANDLER.  We ignore the CFA, extract the handler, and
+      set a breakpoint there.  */
+-  probe = find_probe_by_pc (get_frame_pc (frame), &objfile);
++  probe = find_probe_by_pc (get_frame_pc (frame));
+   if (probe)
+     {
+-      insert_exception_resume_from_probe (ecs->event_thread, probe,
+-					  objfile, frame);
++      insert_exception_resume_from_probe (ecs->event_thread, probe, frame);
+       return;
+     }
+ 
+--- src/gdb/probe.c	2012/05/08 01:35:34	1.3
++++ src/gdb/probe.c	2012/07/18 16:12:17	1.4
+@@ -204,7 +204,7 @@
+ /* See definition in probe.h.  */
+ 
+ struct probe *
+-find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out)
++find_probe_by_pc (CORE_ADDR pc)
+ {
+   struct objfile *objfile;
+ 
+@@ -221,10 +221,7 @@
+     probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile);
+     for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
+       if (probe->address == pc)
+-	{
+-	  *objfile_out = objfile;
+-	  return probe;
+-	}
++	return probe;
+   }
+ 
+   return NULL;
+@@ -232,21 +229,6 @@
+ 
+ 
+ 
+-/* A utility structure.  A VEC of these is built when handling "info
+-   probes".  */
+-
+-struct probe_and_objfile
+-{
+-  /* The probe.  */
+-  struct probe *probe;
+-
+-  /* The probe's objfile.  */
+-  struct objfile *objfile;
+-};
+-
+-typedef struct probe_and_objfile probe_and_objfile_s;
+-DEF_VEC_O (probe_and_objfile_s);
+-
+ /* A helper function for collect_probes that compiles a regexp and
+    throws an exception on error.  This installs a cleanup to free the
+    resulting pattern on success.  If RX is NULL, this does nothing.  */
+@@ -275,16 +257,16 @@
+    If POPS is not NULL, only probes of this certain probe_ops will match.
+    Each argument is a regexp, or NULL, which matches anything.  */
+ 
+-static VEC (probe_and_objfile_s) *
++static VEC (probe_p) *
+ collect_probes (char *objname, char *provider, char *probe_name,
+ 		const struct probe_ops *pops)
+ {
+   struct objfile *objfile;
+-  VEC (probe_and_objfile_s) *result = NULL;
++  VEC (probe_p) *result = NULL;
+   struct cleanup *cleanup, *cleanup_temps;
+   regex_t obj_pat, prov_pat, probe_pat;
+ 
+-  cleanup = make_cleanup (VEC_cleanup (probe_and_objfile_s), &result);
++  cleanup = make_cleanup (VEC_cleanup (probe_p), &result);
+ 
+   cleanup_temps = make_cleanup (null_cleanup, NULL);
+   compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp"));
+@@ -310,8 +292,6 @@
+ 
+       for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++)
+ 	{
+-	  probe_and_objfile_s entry;
+-
+ 	  if (pops != NULL && probe->pops != pops)
+ 	    continue;
+ 
+@@ -323,9 +303,7 @@
+ 	      && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0)
+ 	    continue;
+ 
+-	  entry.probe = probe;
+-	  entry.objfile = objfile;
+-	  VEC_safe_push (probe_and_objfile_s, result, &entry);
++	  VEC_safe_push (probe_p, result, probe);
+ 	}
+     }
+ 
+@@ -334,36 +312,36 @@
+   return result;
+ }
+ 
+-/* A qsort comparison function for probe_and_objfile_s objects.  */
++/* A qsort comparison function for probe_p objects.  */
+ 
+ static int
+-compare_entries (const void *a, const void *b)
++compare_probes (const void *a, const void *b)
+ {
+-  const probe_and_objfile_s *ea = a;
+-  const probe_and_objfile_s *eb = b;
++  const struct probe *pa = *((const struct probe **) a);
++  const struct probe *pb = *((const struct probe **) b);
+   int v;
+ 
+-  v = strcmp (ea->probe->provider, eb->probe->provider);
++  v = strcmp (pa->provider, pb->provider);
+   if (v)
+     return v;
+ 
+-  v = strcmp (ea->probe->name, eb->probe->name);
++  v = strcmp (pa->name, pb->name);
+   if (v)
+     return v;
+ 
+-  if (ea->probe->address < eb->probe->address)
++  if (pa->address < pb->address)
+     return -1;
+-  if (ea->probe->address > eb->probe->address)
++  if (pa->address > pb->address)
+     return 1;
+ 
+-  return strcmp (ea->objfile->name, eb->objfile->name);
++  return strcmp (pa->objfile->name, pb->objfile->name);
+ }
+ 
+ /* Helper function that generate entries in the ui_out table being
+    crafted by `info_probes_for_ops'.  */
+ 
+ static void
+-gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes,
++gen_ui_out_table_header_info (VEC (probe_p) *probes,
+ 			      const struct probe_ops *p)
+ {
+   /* `headings' refers to the names of the columns when printing `info
+@@ -392,11 +370,11 @@
+        VEC_iterate (info_probe_column_s, headings, ix, column);
+        ++ix)
+     {
+-      probe_and_objfile_s *entry;
++      struct probe *probe;
+       int jx;
+       size_t size_max = strlen (column->print_name);
+ 
+-      for (jx = 0; VEC_iterate (probe_and_objfile_s, probes, jx, entry); ++jx)
++      for (jx = 0; VEC_iterate (probe_p, probes, jx, probe); ++jx)
+ 	{
+ 	  /* `probe_fields' refers to the values of each new field that this
+ 	     probe will display.  */
+@@ -405,12 +383,11 @@
+ 	  const char *val;
+ 	  int kx;
+ 
+-	  if (entry->probe->pops != p)
++	  if (probe->pops != p)
+ 	    continue;
+ 
+ 	  c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields);
+-	  p->gen_info_probes_table_values (entry->probe, entry->objfile,
+-					   &probe_fields);
++	  p->gen_info_probes_table_values (probe, &probe_fields);
+ 
+ 	  gdb_assert (VEC_length (const_char_ptr, probe_fields)
+ 		      == headings_size);
+@@ -437,10 +414,10 @@
+ }
+ 
+ /* Helper function to print extra information about a probe and an objfile
+-   represented by ENTRY.  */
++   represented by PROBE.  */
+ 
+ static void
+-print_ui_out_info (probe_and_objfile_s *entry)
++print_ui_out_info (struct probe *probe)
+ {
+   int ix;
+   int j = 0;
+@@ -451,23 +428,21 @@
+   info_probe_column_s *column;
+   struct cleanup *c;
+ 
+-  gdb_assert (entry != NULL);
+-  gdb_assert (entry->probe != NULL);
+-  gdb_assert (entry->probe->pops != NULL);
++  gdb_assert (probe != NULL);
++  gdb_assert (probe->pops != NULL);
+ 
+-  if (entry->probe->pops->gen_info_probes_table_header == NULL
+-      && entry->probe->pops->gen_info_probes_table_values == NULL)
++  if (probe->pops->gen_info_probes_table_header == NULL
++      && probe->pops->gen_info_probes_table_values == NULL)
+     return;
+ 
+-  gdb_assert (entry->probe->pops->gen_info_probes_table_header != NULL
+-	      && entry->probe->pops->gen_info_probes_table_values != NULL);
++  gdb_assert (probe->pops->gen_info_probes_table_header != NULL
++	      && probe->pops->gen_info_probes_table_values != NULL);
+ 
+   c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings);
+   make_cleanup (VEC_cleanup (const_char_ptr), &values);
+ 
+-  entry->probe->pops->gen_info_probes_table_header (&headings);
+-  entry->probe->pops->gen_info_probes_table_values (entry->probe,
+-						    entry->objfile, &values);
++  probe->pops->gen_info_probes_table_header (&headings);
++  probe->pops->gen_info_probes_table_values (probe, &values);
+ 
+   gdb_assert (VEC_length (info_probe_column_s, headings)
+ 	      == VEC_length (const_char_ptr, values));
+@@ -515,16 +490,16 @@
+ void
+ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops)
+ {
+-  char *provider, *probe = NULL, *objname = NULL;
++  char *provider, *probe_name = NULL, *objname = NULL;
+   struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+-  VEC (probe_and_objfile_s) *items;
++  VEC (probe_p) *probes;
+   int i, any_found;
+   int ui_out_extra_fields = 0;
+   size_t size_addr;
+   size_t size_name = strlen ("Name");
+   size_t size_objname = strlen ("Object");
+   size_t size_provider = strlen ("Provider");
+-  probe_and_objfile_s *entry;
++  struct probe *probe;
+   struct gdbarch *gdbarch = get_current_arch ();
+ 
+   /* Do we have a `provider:probe:objfile' style of linespec?  */
+@@ -533,10 +508,10 @@
+     {
+       make_cleanup (xfree, provider);
+ 
+-      probe = extract_arg (&arg);
+-      if (probe)
++      probe_name = extract_arg (&arg);
++      if (probe_name)
+ 	{
+-	  make_cleanup (xfree, probe);
++	  make_cleanup (xfree, probe_name);
+ 
+ 	  objname = extract_arg (&arg);
+ 	  if (objname)
+@@ -564,28 +539,27 @@
+   else
+     ui_out_extra_fields = get_number_extra_fields (pops);
+ 
+-  items = collect_probes (objname, provider, probe, pops);
+-  make_cleanup (VEC_cleanup (probe_and_objfile_s), &items);
++  probes = collect_probes (objname, provider, probe_name, pops);
++  make_cleanup (VEC_cleanup (probe_p), &probes);
+   make_cleanup_ui_out_table_begin_end (current_uiout,
+ 				       4 + ui_out_extra_fields,
+-				       VEC_length (probe_and_objfile_s, items),
++				       VEC_length (probe_p, probes),
+ 				       "StaticProbes");
+ 
+-  if (!VEC_empty (probe_and_objfile_s, items))
+-    qsort (VEC_address (probe_and_objfile_s, items),
+-	   VEC_length (probe_and_objfile_s, items),
+-	   sizeof (probe_and_objfile_s), compare_entries);
++  if (!VEC_empty (probe_p, probes))
++    qsort (VEC_address (probe_p, probes), VEC_length (probe_p, probes),
++	   sizeof (probe_p), compare_probes);
+ 
+   /* What's the size of an address in our architecture?  */
+   size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10;
+ 
+   /* Determining the maximum size of each field (`provider', `name' and
+      `objname').  */
+-  for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i)
++  for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i)
+     {
+-      size_name = max (strlen (entry->probe->name), size_name);
+-      size_provider = max (strlen (entry->probe->provider), size_provider);
+-      size_objname = max (strlen (entry->objfile->name), size_objname);
++      size_name = max (strlen (probe->name), size_name);
++      size_provider = max (strlen (probe->provider), size_provider);
++      size_objname = max (strlen (probe->objfile->name), size_objname);
+     }
+ 
+   ui_out_table_header (current_uiout, size_provider, ui_left, "provider",
+@@ -601,26 +575,26 @@
+       /* We have to generate the table header for each new probe type that we
+ 	 will print.  */
+       for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix)
+-	gen_ui_out_table_header_info (items, po);
++	gen_ui_out_table_header_info (probes, po);
+     }
+   else
+-    gen_ui_out_table_header_info (items, pops);
++    gen_ui_out_table_header_info (probes, pops);
+ 
+   ui_out_table_header (current_uiout, size_objname, ui_left, "object",
+ 		       _("Object"));
+   ui_out_table_body (current_uiout);
+ 
+-  for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i)
++  for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i)
+     {
+       struct cleanup *inner;
+ 
+       inner = make_cleanup_ui_out_tuple_begin_end (current_uiout, "probe");
+ 
+-      ui_out_field_string (current_uiout, "provider", entry->probe->provider);
+-      ui_out_field_string (current_uiout, "name", entry->probe->name);
++      ui_out_field_string (current_uiout, "provider", probe->provider);
++      ui_out_field_string (current_uiout, "name", probe->name);
+       ui_out_field_core_addr (current_uiout, "addr",
+-			      get_objfile_arch (entry->objfile),
+-			      entry->probe->address);
++			      get_objfile_arch (probe->objfile),
++			      probe->address);
+ 
+       if (pops == NULL)
+ 	{
+@@ -629,19 +603,19 @@
+ 
+ 	  for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po);
+ 	       ++ix)
+-	    if (entry->probe->pops == po)
+-	      print_ui_out_info (entry);
++	    if (probe->pops == po)
++	      print_ui_out_info (probe);
+ 	}
+       else
+-	print_ui_out_info (entry);
++	print_ui_out_info (probe);
+ 
+-      ui_out_field_string (current_uiout, "object", entry->objfile->name);
++      ui_out_field_string (current_uiout, "object", probe->objfile->name);
+       ui_out_text (current_uiout, "\n");
+ 
+       do_cleanups (inner);
+     }
+ 
+-  any_found = !VEC_empty (probe_and_objfile_s, items);
++  any_found = !VEC_empty (probe_p, probes);
+   do_cleanups (cleanup);
+ 
+   if (!any_found)
+@@ -662,23 +636,24 @@
+ probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n)
+ {
+   struct probe *probe;
+-  struct objfile *objfile;
++  const struct sym_probe_fns *probe_fns;
+   unsigned n_probes;
+ 
+-  probe = find_probe_by_pc (get_frame_pc (frame), &objfile);
++  probe = find_probe_by_pc (get_frame_pc (frame));
+   if (!probe)
+     return NULL;
+-  gdb_assert (objfile->sf && objfile->sf->sym_probe_fns);
+ 
+-  n_probes
+-    = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
+-								probe);
++  gdb_assert (probe->objfile != NULL);
++  gdb_assert (probe->objfile->sf != NULL);
++  gdb_assert (probe->objfile->sf->sym_probe_fns != NULL);
++
++  probe_fns = probe->objfile->sf->sym_probe_fns;
++  n_probes = probe_fns->sym_get_probe_argument_count (probe);
++
+   if (n >= n_probes)
+     return NULL;
+ 
+-  return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile,
+-								  probe,
+-								  n);
++  return probe_fns->sym_evaluate_probe_argument (probe, n);
+ }
+ 
+ /* See comment in probe.h.  */
+--- src/gdb/probe.h	2012/04/27 20:47:55	1.1
++++ src/gdb/probe.h	2012/07/18 16:12:17	1.2
+@@ -66,21 +66,18 @@
+ 
+     /* Return the number of arguments of PROBE.  */
+ 
+-    unsigned (*get_probe_argument_count) (struct probe *probe,
+-					  struct objfile *objfile);
++    unsigned (*get_probe_argument_count) (struct probe *probe);
+ 
+     /* Evaluate the Nth argument from the PROBE, returning a value
+        corresponding to it.  The argument number is represented N.  */
+ 
+     struct value *(*evaluate_probe_argument) (struct probe *probe,
+-					      struct objfile *objfile,
+ 					      unsigned n);
+ 
+     /* Compile the Nth argument of the PROBE to an agent expression.
+        The argument number is represented by N.  */
+ 
+-    void (*compile_to_ax) (struct probe *probe, struct objfile *objfile,
+-			   struct agent_expr *aexpr,
++    void (*compile_to_ax) (struct probe *probe, struct agent_expr *aexpr,
+ 			   struct axs_value *axs_value, unsigned n);
+ 
+     /* Set the semaphore associated with the PROBE.  This function only makes
+@@ -108,8 +105,8 @@
+     void (*gen_info_probes_table_header) (VEC (info_probe_column_s) **heads);
+ 
+     /* Function that will fill VALUES with the values of the extra fields
+-       to be printed for PROBE  and OBJFILE.  If the backend implements
+-       the `gen_ui_out_table_header' method, then it should implement
++       to be printed for PROBE.  If the backend implements the
++       `gen_ui_out_table_header' method, then it should implement
+        this method as well.  The backend should also guarantee that the
+        order and the number of values in the vector is exactly the same
+        as the order of the extra fields provided in the method
+@@ -118,7 +115,6 @@
+        position in the vector.  */
+ 
+     void (*gen_info_probes_table_values) (struct probe *probe,
+-					  struct objfile *objfile,
+ 					  VEC (const_char_ptr) **values);
+   };
+ 
+@@ -157,6 +153,11 @@
+     /* The operations associated with this probe.  */
+     const struct probe_ops *pops;
+ 
++    /* The objfile which contains this probe.  Even if the probe is also
++       present in a separate debug objfile, this variable always points to
++       the non-separate debug objfile.  */
++    struct objfile *objfile;
++
+     /* The name of the probe.  */
+     const char *name;
+ 
+@@ -181,11 +182,9 @@
+ extern void register_probe_ops (struct probe *probe);
+ 
+ /* Given a PC, find an associated probe with type PTYPE.  If a probe is
+-   found, set *OBJFILE_OUT to the probe's objfile, and return the
+-   probe.  If no probe is found, return NULL.  */
++   found, return it.  If no probe is found, return NULL.  */
+ 
+-extern struct probe *find_probe_by_pc (CORE_ADDR pc,
+-				       struct objfile **objfile_out);
++extern struct probe *find_probe_by_pc (CORE_ADDR pc);
+ 
+ /* Search OBJFILE for a probe with the given PROVIDER, NAME and PTYPE.
+    Return a VEC of all probes that were found.  If no matching probe
+--- src/gdb/stap-probe.c	2012/05/08 01:35:35	1.4
++++ src/gdb/stap-probe.c	2012/07/18 16:12:17	1.5
+@@ -903,10 +903,10 @@
+    this information.  */
+ 
+ static void
+-stap_parse_probe_arguments (struct stap_probe *probe, struct objfile *objfile)
++stap_parse_probe_arguments (struct stap_probe *probe)
+ {
+   const char *cur;
+-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
++  struct gdbarch *gdbarch = get_objfile_arch (probe->p.objfile);
+ 
+   gdb_assert (!probe->args_parsed);
+   cur = probe->args_u.text;
+@@ -991,15 +991,14 @@
+    argument string.  */
+ 
+ static unsigned
+-stap_get_probe_argument_count (struct probe *probe_generic,
+-			       struct objfile *objfile)
++stap_get_probe_argument_count (struct probe *probe_generic)
+ {
+   struct stap_probe *probe = (struct stap_probe *) probe_generic;
+ 
+   gdb_assert (probe_generic->pops == &stap_probe_ops);
+ 
+   if (!probe->args_parsed)
+-    stap_parse_probe_arguments (probe, objfile);
++    stap_parse_probe_arguments (probe);
+ 
+   gdb_assert (probe->args_parsed);
+   return VEC_length (stap_probe_arg_s, probe->args_u.vec);
+@@ -1042,10 +1041,10 @@
+ }
+ 
+ static struct stap_probe_arg *
+-stap_get_arg (struct stap_probe *probe, struct objfile *objfile, unsigned n)
++stap_get_arg (struct stap_probe *probe, unsigned n)
+ {
+   if (!probe->args_parsed)
+-    stap_parse_probe_arguments (probe, objfile);
++    stap_parse_probe_arguments (probe);
+ 
+   return VEC_index (stap_probe_arg_s, probe->args_u.vec, n);
+ }
+@@ -1054,8 +1053,7 @@
+    corresponding to it.  Assertion is thrown if N does not exist.  */
+ 
+ static struct value *
+-stap_evaluate_probe_argument (struct probe *probe_generic,
+-			      struct objfile *objfile, unsigned n)
++stap_evaluate_probe_argument (struct probe *probe_generic, unsigned n)
+ {
+   struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
+   struct stap_probe_arg *arg;
+@@ -1063,7 +1061,7 @@
+ 
+   gdb_assert (probe_generic->pops == &stap_probe_ops);
+ 
+-  arg = stap_get_arg (stap_probe, objfile, n);
++  arg = stap_get_arg (stap_probe, n);
+   return evaluate_subexp_standard (arg->atype, arg->aexpr, &pos, EVAL_NORMAL);
+ }
+ 
+@@ -1071,9 +1069,8 @@
+    Assertion is thrown if N does not exist.  */
+ 
+ static void
+-stap_compile_to_ax (struct probe *probe_generic, struct objfile *objfile,
+-		    struct agent_expr *expr, struct axs_value *value,
+-		    unsigned n)
++stap_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr,
++		    struct axs_value *value, unsigned n)
+ {
+   struct stap_probe *stap_probe = (struct stap_probe *) probe_generic;
+   struct stap_probe_arg *arg;
+@@ -1081,7 +1078,7 @@
+ 
+   gdb_assert (probe_generic->pops == &stap_probe_ops);
+ 
+-  arg = stap_get_arg (stap_probe, objfile, n);
++  arg = stap_get_arg (stap_probe, n);
+ 
+   pc = arg->aexpr->elts;
+   gen_expr (arg->aexpr, &pc, expr, value);
+@@ -1124,20 +1121,24 @@
+   struct frame_info *frame = get_selected_frame (_("No frame selected"));
+   CORE_ADDR pc = get_frame_pc (frame);
+   int sel = (int) (uintptr_t) data;
+-  struct objfile *objfile;
+   struct probe *pc_probe;
++  const struct sym_probe_fns *pc_probe_fns;
+   unsigned n_args;
+ 
+   /* SEL == -1 means "_probe_argc".  */
+   gdb_assert (sel >= -1);
+ 
+-  pc_probe = find_probe_by_pc (pc, &objfile);
++  pc_probe = find_probe_by_pc (pc);
+   if (pc_probe == NULL)
+     error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
+ 
+-  n_args
+-    = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
+-								pc_probe);
++  gdb_assert (pc_probe->objfile != NULL);
++  gdb_assert (pc_probe->objfile->sf != NULL);
++  gdb_assert (pc_probe->objfile->sf->sym_probe_fns != NULL);
++
++  pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns;
++
++  n_args = pc_probe_fns->sym_get_probe_argument_count (pc_probe);
+   if (sel == -1)
+     return value_from_longest (builtin_type (arch)->builtin_int, n_args);
+ 
+@@ -1145,9 +1146,7 @@
+     error (_("Invalid probe argument %d -- probe has %u arguments available"),
+ 	   sel, n_args);
+ 
+-  return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile,
+-								  pc_probe,
+-								  sel);
++  return pc_probe_fns->sym_evaluate_probe_argument (pc_probe, sel);
+ }
+ 
+ /* This is called to compile one of the $_probe_arg* convenience
+@@ -1159,20 +1158,25 @@
+ {
+   CORE_ADDR pc = expr->scope;
+   int sel = (int) (uintptr_t) data;
+-  struct objfile *objfile;
+   struct probe *pc_probe;
++  const struct sym_probe_fns *pc_probe_fns;
+   int n_probes;
+ 
+   /* SEL == -1 means "_probe_argc".  */
+   gdb_assert (sel >= -1);
+ 
+-  pc_probe = find_probe_by_pc (pc, &objfile);
++  pc_probe = find_probe_by_pc (pc);
+   if (pc_probe == NULL)
+     error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc));
+ 
+-  n_probes
+-    = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile,
+-								pc_probe);
++  gdb_assert (pc_probe->objfile != NULL);
++  gdb_assert (pc_probe->objfile->sf != NULL);
++  gdb_assert (pc_probe->objfile->sf->sym_probe_fns != NULL);
++
++  pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns;
++
++  n_probes = pc_probe_fns->sym_get_probe_argument_count (pc_probe);
++
+   if (sel == -1)
+     {
+       value->kind = axs_rvalue;
+@@ -1186,8 +1190,7 @@
+     error (_("Invalid probe argument %d -- probe has %d arguments available"),
+ 	   sel, n_probes);
+ 
+-  objfile->sf->sym_probe_fns->sym_compile_to_ax (objfile, pc_probe,
+-						 expr, value, sel);
++  pc_probe_fns->sym_compile_to_ax (pc_probe, expr, value, sel);
+ }
+ 
+ 
+@@ -1297,6 +1300,7 @@
+ 
+   ret = obstack_alloc (&objfile->objfile_obstack, sizeof (*ret));
+   ret->p.pops = &stap_probe_ops;
++  ret->p.objfile = objfile;
+ 
+   /* Provider and the name of the probe.  */
+   ret->p.provider = &el->data[3 * size];
+@@ -1481,15 +1485,16 @@
+ 
+ static void
+ stap_gen_info_probes_table_values (struct probe *probe_generic,
+-				   struct objfile *objfile,
+ 				   VEC (const_char_ptr) **ret)
+ {
+   struct stap_probe *probe = (struct stap_probe *) probe_generic;
+-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
++  struct gdbarch *gdbarch;
+   const char *val = NULL;
+ 
+   gdb_assert (probe_generic->pops == &stap_probe_ops);
+ 
++  gdbarch = get_objfile_arch (probe->p.objfile);
++
+   if (probe->sem_addr)
+     val = print_core_address (gdbarch, probe->sem_addr);
+ 
+--- src/gdb/symfile.h	2012/05/24 22:14:35	1.109
++++ src/gdb/symfile.h	2012/07/18 16:12:17	1.110
+@@ -320,8 +320,7 @@
+      have come from a call to this objfile's sym_get_probes method.
+      If you provide an implementation of sym_get_probes, you must
+      implement this method as well.  */
+-  unsigned (*sym_get_probe_argument_count) (struct objfile *objfile,
+-					    struct probe *probe);
++  unsigned (*sym_get_probe_argument_count) (struct probe *probe);
+ 
+   /* Evaluate the Nth argument available to PROBE.  PROBE will have
+      come from a call to this objfile's sym_get_probes method.  N will
+@@ -330,8 +329,7 @@
+      PC will match the address of the probe.  If you provide an
+      implementation of sym_get_probes, you must implement this method
+      as well.  */
+-  struct value *(*sym_evaluate_probe_argument) (struct objfile *objfile,
+-						struct probe *probe,
++  struct value *(*sym_evaluate_probe_argument) (struct probe *probe,
+ 						unsigned n);
+ 
+   /* Compile the Nth probe argument to an agent expression.  PROBE
+@@ -339,8 +337,7 @@
+      method.  N will be between 0 and the number of arguments
+      available to this probe.  EXPR and VALUE are the agent expression
+      that is being updated.  */
+-  void (*sym_compile_to_ax) (struct objfile *objfile,
+-			     struct probe *probe,
++  void (*sym_compile_to_ax) (struct probe *probe,
+ 			     struct agent_expr *expr,
+ 			     struct axs_value *value,
+ 			     unsigned n);
diff --git a/gdb-dlopen-stap-probe-2of7.patch b/gdb-dlopen-stap-probe-2of7.patch
new file mode 100644
index 0000000..81b35e9
--- /dev/null
+++ b/gdb-dlopen-stap-probe-2of7.patch
@@ -0,0 +1,74 @@
+http://sourceware.org/ml/gdb-cvs/2012-07/msg00124.html
+
+### src/gdb/ChangeLog	2012/07/18 16:12:15	1.14474
+### src/gdb/ChangeLog	2012/07/18 16:20:36	1.14475
+## -1,5 +1,10 @@
+ 2012-07-18  Sergio Durigan Junior  <sergiodj at redhat.com>
+ 
++	* probe.c (probe_safe_evaluate_at_pc): Rename variable `n_probes'.
++	* stap-probe.c (compile_probe_arg): Likewise.
++
++2012-07-18  Sergio Durigan Junior  <sergiodj at redhat.com>
++
+ 	* elfread.c (elf_get_probe_argument_count): Remove `objfile' argument.
+ 	(elf_compile_to_ax): Likewise.
+ 	* infrun.c (insert_exception_resume_from_probe): Likewise.
+--- src/gdb/probe.c	2012/07/18 16:12:17	1.4
++++ src/gdb/probe.c	2012/07/18 16:20:43	1.5
+@@ -637,7 +637,7 @@
+ {
+   struct probe *probe;
+   const struct sym_probe_fns *probe_fns;
+-  unsigned n_probes;
++  unsigned n_args;
+ 
+   probe = find_probe_by_pc (get_frame_pc (frame));
+   if (!probe)
+@@ -648,9 +648,9 @@
+   gdb_assert (probe->objfile->sf->sym_probe_fns != NULL);
+ 
+   probe_fns = probe->objfile->sf->sym_probe_fns;
+-  n_probes = probe_fns->sym_get_probe_argument_count (probe);
++  n_args = probe_fns->sym_get_probe_argument_count (probe);
+ 
+-  if (n >= n_probes)
++  if (n >= n_args)
+     return NULL;
+ 
+   return probe_fns->sym_evaluate_probe_argument (probe, n);
+--- src/gdb/stap-probe.c	2012/07/18 16:12:17	1.5
++++ src/gdb/stap-probe.c	2012/07/18 16:20:43	1.6
+@@ -1160,7 +1160,7 @@
+   int sel = (int) (uintptr_t) data;
+   struct probe *pc_probe;
+   const struct sym_probe_fns *pc_probe_fns;
+-  int n_probes;
++  int n_args;
+ 
+   /* SEL == -1 means "_probe_argc".  */
+   gdb_assert (sel >= -1);
+@@ -1175,20 +1175,20 @@
+ 
+   pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns;
+ 
+-  n_probes = pc_probe_fns->sym_get_probe_argument_count (pc_probe);
++  n_args = pc_probe_fns->sym_get_probe_argument_count (pc_probe);
+ 
+   if (sel == -1)
+     {
+       value->kind = axs_rvalue;
+       value->type = builtin_type (expr->gdbarch)->builtin_int;
+-      ax_const_l (expr, n_probes);
++      ax_const_l (expr, n_args);
+       return;
+     }
+ 
+   gdb_assert (sel >= 0);
+-  if (sel >= n_probes)
++  if (sel >= n_args)
+     error (_("Invalid probe argument %d -- probe has %d arguments available"),
+-	   sel, n_probes);
++	   sel, n_args);
+ 
+   pc_probe_fns->sym_compile_to_ax (pc_probe, expr, value, sel);
+ }
diff --git a/gdb-dlopen-stap-probe-3of7.patch b/gdb-dlopen-stap-probe-3of7.patch
new file mode 100644
index 0000000..2337ded
--- /dev/null
+++ b/gdb-dlopen-stap-probe-3of7.patch
@@ -0,0 +1,98 @@
+2012-07-19  Gary Benson  <gbenson at redhat.com>
+
+	* probe.h (get_probe_argument_count): New declaration.
+	(evaluate_probe_argument): Likewise.
+	* probe.c (get_probe_argument_count): New function.
+	(evaluate_probe_argument): Likewise.
+	(probe_safe_evaluate_at_pc): Use the above new functions.
+
+diff --git a/gdb/probe.h b/gdb/probe.h
+index 8d44ca2..1d29b87 100644
+--- a/gdb/probe.h
++++ b/gdb/probe.h
+@@ -214,6 +214,16 @@ extern void info_probes_for_ops (char *arg, int from_tty,
+ 
+ extern struct cmd_list_element **info_probes_cmdlist_get (void);
+ 
++/* Return the argument count of the specified probe.  */
++
++extern unsigned get_probe_argument_count (struct probe *probe);
++
++/* Evaluate argument N of the specified probe.  N must be between 0
++   inclusive and get_probe_argument_count exclusive.  */
++
++extern struct value *evaluate_probe_argument (struct probe *probe,
++					      unsigned n);
++
+ /* A convenience function that finds a probe at the PC in FRAME and
+    evaluates argument N, with 0 <= N < number_of_args.  If there is no
+    probe at that location, or if the probe does not have enough arguments,
+diff --git a/gdb/probe.c b/gdb/probe.c
+index 77f3b13..a61f4ea 100644
+--- a/gdb/probe.c
++++ b/gdb/probe.c
+@@ -632,28 +632,55 @@ info_probes_command (char *arg, int from_tty)
+ 
+ /* See comments in probe.h.  */
+ 
++unsigned
++get_probe_argument_count (struct probe *probe)
++{
++  const struct sym_probe_fns *probe_fns;
++
++  gdb_assert (probe->objfile != NULL);
++  gdb_assert (probe->objfile->sf != NULL);
++
++  probe_fns = probe->objfile->sf->sym_probe_fns;
++
++  gdb_assert (probe_fns != NULL);
++
++  return probe_fns->sym_get_probe_argument_count (probe);
++}
++
++/* See comments in probe.h.  */
++
++struct value *
++evaluate_probe_argument (struct probe *probe, unsigned n)
++{
++  const struct sym_probe_fns *probe_fns;
++
++  gdb_assert (probe->objfile != NULL);
++  gdb_assert (probe->objfile->sf != NULL);
++
++  probe_fns = probe->objfile->sf->sym_probe_fns;
++
++  gdb_assert (probe_fns != NULL);
++
++  return probe_fns->sym_evaluate_probe_argument (probe, n);
++}
++
++/* See comments in probe.h.  */
++
+ struct value *
+ probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n)
+ {
+   struct probe *probe;
+-  const struct sym_probe_fns *probe_fns;
+   unsigned n_args;
+ 
+   probe = find_probe_by_pc (get_frame_pc (frame));
+   if (!probe)
+     return NULL;
+ 
+-  gdb_assert (probe->objfile != NULL);
+-  gdb_assert (probe->objfile->sf != NULL);
+-  gdb_assert (probe->objfile->sf->sym_probe_fns != NULL);
+-
+-  probe_fns = probe->objfile->sf->sym_probe_fns;
+-  n_args = probe_fns->sym_get_probe_argument_count (probe);
+-
++  n_args = get_probe_argument_count (probe);
+   if (n >= n_args)
+     return NULL;
+ 
+-  return probe_fns->sym_evaluate_probe_argument (probe, n);
++  return evaluate_probe_argument (probe, n);
+ }
+ 
+ /* See comment in probe.h.  */
diff --git a/gdb-dlopen-stap-probe-4of7.patch b/gdb-dlopen-stap-probe-4of7.patch
new file mode 100644
index 0000000..299931a
--- /dev/null
+++ b/gdb-dlopen-stap-probe-4of7.patch
@@ -0,0 +1,131 @@
+2012-07-19  Gary Benson  <gbenson at redhat.com>
+
+	* solib-svr4.c (svr4_info): Move earlier.
+	(solib_svr4_pspace_data): Likewise.
+	(svr4_pspace_data_cleanup): Likewise.
+	(get_svr4_info): Likewise.
+
+diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
+index 307e483..c88b9cb 100644
+--- a/gdb/solib-svr4.c
++++ b/gdb/solib-svr4.c
+@@ -106,6 +106,59 @@ static const  char * const main_name_list[] =
+   NULL
+ };
+ 
++/* Per pspace SVR4 specific data.  */
++
++struct svr4_info
++{
++  CORE_ADDR debug_base;	/* Base of dynamic linker structures.  */
++
++  /* Validity flag for debug_loader_offset.  */
++  int debug_loader_offset_p;
++
++  /* Load address for the dynamic linker, inferred.  */
++  CORE_ADDR debug_loader_offset;
++
++  /* Name of the dynamic linker, valid if debug_loader_offset_p.  */
++  char *debug_loader_name;
++
++  /* Load map address for the main executable.  */
++  CORE_ADDR main_lm_addr;
++
++  CORE_ADDR interp_text_sect_low;
++  CORE_ADDR interp_text_sect_high;
++  CORE_ADDR interp_plt_sect_low;
++  CORE_ADDR interp_plt_sect_high;
++};
++
++/* Per-program-space data key.  */
++static const struct program_space_data *solib_svr4_pspace_data;
++
++static void
++svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
++{
++  struct svr4_info *info;
++
++  info = program_space_data (pspace, solib_svr4_pspace_data);
++  xfree (info);
++}
++
++/* Get the current svr4 data.  If none is found yet, add it now.  This
++   function always returns a valid object.  */
++
++static struct svr4_info *
++get_svr4_info (void)
++{
++  struct svr4_info *info;
++
++  info = program_space_data (current_program_space, solib_svr4_pspace_data);
++  if (info != NULL)
++    return info;
++
++  info = XZALLOC (struct svr4_info);
++  set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
++  return info;
++}
++
+ /* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent
+    the same shared library.  */
+ 
+@@ -291,59 +344,6 @@ lm_addr_check (struct so_list *so, bfd *abfd)
+   return so->lm_info->l_addr;
+ }
+ 
+-/* Per pspace SVR4 specific data.  */
+-
+-struct svr4_info
+-{
+-  CORE_ADDR debug_base;	/* Base of dynamic linker structures.  */
+-
+-  /* Validity flag for debug_loader_offset.  */
+-  int debug_loader_offset_p;
+-
+-  /* Load address for the dynamic linker, inferred.  */
+-  CORE_ADDR debug_loader_offset;
+-
+-  /* Name of the dynamic linker, valid if debug_loader_offset_p.  */
+-  char *debug_loader_name;
+-
+-  /* Load map address for the main executable.  */
+-  CORE_ADDR main_lm_addr;
+-
+-  CORE_ADDR interp_text_sect_low;
+-  CORE_ADDR interp_text_sect_high;
+-  CORE_ADDR interp_plt_sect_low;
+-  CORE_ADDR interp_plt_sect_high;
+-};
+-
+-/* Per-program-space data key.  */
+-static const struct program_space_data *solib_svr4_pspace_data;
+-
+-static void
+-svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
+-{
+-  struct svr4_info *info;
+-
+-  info = program_space_data (pspace, solib_svr4_pspace_data);
+-  xfree (info);
+-}
+-
+-/* Get the current svr4 data.  If none is found yet, add it now.  This
+-   function always returns a valid object.  */
+-
+-static struct svr4_info *
+-get_svr4_info (void)
+-{
+-  struct svr4_info *info;
+-
+-  info = program_space_data (current_program_space, solib_svr4_pspace_data);
+-  if (info != NULL)
+-    return info;
+-
+-  info = XZALLOC (struct svr4_info);
+-  set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
+-  return info;
+-}
+-
+ /* Local function prototypes */
+ 
+ static int match_main (const char *);
diff --git a/gdb-dlopen-stap-probe-5of7.patch b/gdb-dlopen-stap-probe-5of7.patch
new file mode 100644
index 0000000..cb18cd6
--- /dev/null
+++ b/gdb-dlopen-stap-probe-5of7.patch
@@ -0,0 +1,17 @@
+2012-07-19  Gary Benson  <gbenson at redhat.com>
+
+	* solib-svr4.c (svr4_info): Made debug_loader_offset_p a bitfield.
+
+diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
+index c88b9cb..8e41f19 100644
+--- a/gdb/solib-svr4.c
++++ b/gdb/solib-svr4.c
+@@ -113,7 +113,7 @@ struct svr4_info
+   CORE_ADDR debug_base;	/* Base of dynamic linker structures.  */
+ 
+   /* Validity flag for debug_loader_offset.  */
+-  int debug_loader_offset_p;
++  unsigned int debug_loader_offset_p : 1;
+ 
+   /* Load address for the dynamic linker, inferred.  */
+   CORE_ADDR debug_loader_offset;
diff --git a/gdb-dlopen-stap-probe-6of7.patch b/gdb-dlopen-stap-probe-6of7.patch
new file mode 100644
index 0000000..574150e
--- /dev/null
+++ b/gdb-dlopen-stap-probe-6of7.patch
@@ -0,0 +1,1989 @@
+gdb/
+2012-07-30  Gary Benson  <gbenson at redhat.com>
+
+	* breakpoint.h (handle_solib_event): Moved function definition
+	to solib.h, and added a new parameter.
+	* breakpoint.c (handle_solib_event): Moved function to solib.c
+	and added a new parameter.
+	(bpstat_stop_status): Pass new argument to handle_solib_event.
+	* solib.h (breakpoint.h): New include.
+	(handle_solib_event): Moved function definition from breakpoint.h
+	and added a new parameter.
+	(update_solib_breakpoints): New function definition.
+	* solib.c (handle_solib_event): Moved function from breakpoint.c
+	and added a new parameter.
+	(update_solib_breakpoints): New function.
+	* solist.h (breakpoint.h): New include.
+	(target_so_ops): New fields "handle_solib_event" and
+	"update_breakpoints".
+	* infrun.c (set_stop_on_solib_events): New function.
+	(_initialize_infrun): Use the above for "set stop-on-solib-events".
+	(handle_inferior_event): Pass new argument to handle_solib_event.
+	* solib-svr4.c (probe.h): New include.
+	(namespace_table_flatten): New forward declaration.
+	(lm_info): New fields "lmid" and "in_initial_ns".
+	(probe_action): New enum.
+	(probe_info): New struct.
+	(probe_info): New static variable.
+	(NUM_PROBES): New definition.
+	(svr4_info): New fields  "using_probes", "probes" and
+	"namespace_table".
+	(free_probes): New function.
+	(free_namespace_table): Likewise.
+	(svr4_pspace_data_cleanup): Free probes and namespace table.
+	(svr4_same): Also compare namespaces if using probes.
+	(lm_addr_check): Only print .dynamic section at wrong address
+	warning for initial namespace if using probes.
+	(r_map_from_debug_base): New function.
+	(solib_svr4_r_map): Call the above.
+	(svr4_read_so_list): New parameter "prev_lm".
+	Changed	return type from void to int.
+	Return nonzero on success, zero on error.
+	(svr4_current_sos_from_debug_base): New function.
+	(svr4_current_sos): Create result from namespace table if available.
+	Use svr4_current_sos_from_debug_base to generate list otherwise.
+	(probe_and_info): New struct.
+	(solib_event_probe_at): New function.
+	(solib_event_probe_action): Likewise.
+	(namespace): New struct.
+	(hash_namespace): New function.
+	(equal_namespace): Likewise.
+	(free_namespace): Likewise.
+	(namespace_update_full): Likewise.
+	(namespace_update_incremental): Likewise.
+	(svr4_handle_solib_event): Likewise.
+	(namespace_table_flatten_helper): Likewise.
+	(namespace_table_flatten): Likewise.
+	(svr4_update_solib_event_breakpoint): Likewise.
+	(svr4_update_solib_event_breakpoints): Likewise.
+	(svr4_create_solib_event_breakpoints): Likewise.
+	(enable_break): Free probes before creating breakpoints.
+	Use svr4_create_solib_event_breakpoints to create breakpoints.
+	(svr4_solib_create_inferior_hook): Free the namespace table.
+	(_initialize_svr4_solib): Initialise svr4_so_ops.handle_solib_event
+	and svr4_so_ops.update_breakpoints.
+
+gdb/testsuite
+2012-07-30  Gary Benson  <gbenson at redhat.com>
+
+	* gdb.base/break-interp.exp (solib_bp): New constant.
+	(reach_1): Use the above instead of "_dl_debug_state".
+	(test_attach): Likewise.
+	(test_ld): Likewise.
+	* gdb.base/break-probes.exp: New file.
+	* gdb.base/break-probes.c: Likewise.
+	* gdb.base/break-probes-solib.c: Likewise.
+	* gdb.base/info-shared.exp: New file.
+	* gdb.base/info-shared.c: Likewise.
+	* gdb.base/info-shared-solib1.c: Likewise.
+	* gdb.base/info-shared-solib2.c: Likewise.
+	* gdb.base/break-dlmopen.exp: Likewise.
+	* gdb.base/break-dlmopen.c: Likewise.
+	* gdb.base/break-dlmopen-solib.c: Likewise.
+
+Index: gdb-7.4.91.20120814/gdb/breakpoint.h
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/breakpoint.h	2012-08-14 17:31:37.050984427 +0200
++++ gdb-7.4.91.20120814/gdb/breakpoint.h	2012-08-14 17:34:44.203746601 +0200
+@@ -1515,8 +1515,6 @@ extern int user_breakpoint_p (struct bre
+ /* Attempt to determine architecture of location identified by SAL.  */
+ extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
+ 
+-extern void handle_solib_event (void);
+-
+ extern void breakpoints_relocate (struct objfile *objfile,
+ 				  struct section_offsets *delta);
+ 
+Index: gdb-7.4.91.20120814/gdb/breakpoint.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/breakpoint.c	2012-08-14 17:31:37.128984404 +0200
++++ gdb-7.4.91.20120814/gdb/breakpoint.c	2012-08-14 17:34:44.211746597 +0200
+@@ -5205,7 +5205,7 @@ bpstat_stop_status (struct address_space
+     {
+       if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event)
+ 	{
+-	  handle_solib_event ();
++	  handle_solib_event (bs);
+ 	  break;
+ 	}
+     }
+@@ -5301,25 +5301,6 @@ handle_jit_event (void)
+   target_terminal_inferior ();
+ }
+ 
+-/* Handle an solib event by calling solib_add.  */
+-
+-void
+-handle_solib_event (void)
+-{
+-  clear_program_space_solib_cache (current_inferior ()->pspace);
+-
+-  /* Check for any newly added shared libraries if we're supposed to
+-     be adding them automatically.  Switch terminal for any messages
+-     produced by breakpoint_re_set.  */
+-  target_terminal_ours_for_output ();
+-#ifdef SOLIB_ADD
+-  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+-#else
+-  solib_add (NULL, 0, &current_target, auto_solib_add);
+-#endif
+-  target_terminal_inferior ();
+-}
+-
+ /* Prepare WHAT final decision for infrun.  */
+ 
+ /* Decide what infrun needs to do with this bpstat.  */
+Index: gdb-7.4.91.20120814/gdb/solib.h
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/solib.h	2012-02-03 16:19:37.000000000 +0100
++++ gdb-7.4.91.20120814/gdb/solib.h	2012-08-14 17:34:44.257746587 +0200
+@@ -21,6 +21,9 @@
+ #ifndef SOLIB_H
+ #define SOLIB_H
+ 
++/* For bpstat.  */
++#include "breakpoint.h"
++
+ /* Forward decl's for prototypes */
+ struct so_list;
+ struct target_ops;
+@@ -91,4 +94,15 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f
+ 								      void *),
+ 						    void *data);
+ 
++/* Handle an solib event by calling solib_add.  Targets which handle
++   solib events using breakpoints must pass a valid bpstat.  Targets
++   which handle solib events using some other mechanism should pass
++   NULL.  */
++
++extern void handle_solib_event (bpstat bs);
++
++/* Enable or disable optional solib event breakpoints as appropriate.  */
++
++extern void update_solib_breakpoints (void);
++
+ #endif /* SOLIB_H */
+Index: gdb-7.4.91.20120814/gdb/solib.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/solib.c	2012-08-14 17:31:36.832984492 +0200
++++ gdb-7.4.91.20120814/gdb/solib.c	2012-08-14 17:34:44.272746583 +0200
+@@ -1226,6 +1226,42 @@ no_shared_libraries (char *ignored, int
+   objfile_purge_solibs ();
+ }
+ 
++/* See solib.h.  */
++
++void
++handle_solib_event (bpstat bs)
++{
++  struct target_so_ops *ops = solib_ops (target_gdbarch);
++
++  if (ops->handle_solib_event != NULL)
++    ops->handle_solib_event (bs);
++
++  clear_program_space_solib_cache (current_inferior ()->pspace);
++
++  /* Check for any newly added shared libraries if we're supposed to
++     be adding them automatically.  Switch terminal for any messages
++     produced by breakpoint_re_set.  */
++  target_terminal_ours_for_output ();
++#ifdef SOLIB_ADD
++  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
++#else
++  solib_add (NULL, 0, &current_target, auto_solib_add);
++#endif
++  target_terminal_inferior ();
++}
++
++/* See solib.h.  */
++
++void
++update_solib_breakpoints (void)
++{
++  struct target_so_ops *ops = solib_ops (target_gdbarch);
++
++  if (ops->update_breakpoints != NULL)
++    ops->update_breakpoints ();
++}
++
++
+ /* Reload shared libraries, but avoid reloading the same symbol file
+    we already have loaded.  */
+ 
+Index: gdb-7.4.91.20120814/gdb/solist.h
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/solist.h	2012-01-04 09:17:11.000000000 +0100
++++ gdb-7.4.91.20120814/gdb/solist.h	2012-08-14 17:34:44.273746584 +0200
+@@ -23,6 +23,8 @@
+ #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
+ /* For domain_enum domain.  */
+ #include "symtab.h"
++/* For bpstat.  */
++#include "breakpoint.h"
+ 
+ /* Forward declaration for target specific link map information.  This
+    struct is opaque to all but the target specific file.  */
+@@ -149,6 +151,20 @@ struct target_so_ops
+        core file (in particular, for readonly sections).  */
+     int (*keep_data_in_core) (CORE_ADDR vaddr,
+ 			      unsigned long size);
++
++    /* Target-specific handling of solib events.  For targets which
++       handle solib events using breakpoints a valid bpstat must be
++       passed.  Targets which handle solib events using some other
++       mechanism should pass NULL.  This pointer can be NULL, in which
++       case no specific handling is necessary for this target.  */
++    void (*handle_solib_event) (bpstat bs);
++
++    /* Enable or disable optional solib event breakpoints as
++       appropriate.  This should be called whenever
++       stop_on_solib_events is changed.  This pointer can be
++       NULL, in which case no enabling or disabling is necessary
++       for this target.  */
++    void (*update_breakpoints) (void);
+   };
+ 
+ /* Free the memory associated with a (so_list *).  */
+Index: gdb-7.4.91.20120814/gdb/infrun.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/infrun.c	2012-08-14 17:33:16.249955007 +0200
++++ gdb-7.4.91.20120814/gdb/infrun.c	2012-08-14 17:34:44.276746583 +0200
+@@ -361,6 +361,16 @@ static struct symbol *step_start_functio
+ /* Nonzero if we want to give control to the user when we're notified
+    of shared library events by the dynamic linker.  */
+ int stop_on_solib_events;
++
++/* Enable or disable optional shared library event breakpoints
++   as appropriate when the above flag is changed.  */
++
++static void
++set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
++{
++  update_solib_breakpoints ();
++}
++
+ static void
+ show_stop_on_solib_events (struct ui_file *file, int from_tty,
+ 			   struct cmd_list_element *c, const char *value)
+@@ -3321,7 +3331,7 @@ handle_inferior_event (struct execution_
+ 	    context_switch (ecs->ptid);
+ 	  regcache = get_thread_regcache (ecs->ptid);
+ 
+-	  handle_solib_event ();
++	  handle_solib_event (NULL);
+ 
+ 	  ecs->event_thread->control.stop_bpstat
+ 	    = bpstat_stop_status (get_regcache_aspace (regcache),
+@@ -7226,7 +7236,7 @@ Show stopping for shared library events.
+ If nonzero, gdb will give control to the user when the dynamic linker\n\
+ notifies gdb of shared library events.  The most common event of interest\n\
+ to the user would be loading/unloading of a new library."),
+-			    NULL,
++			    set_stop_on_solib_events,
+ 			    show_stop_on_solib_events,
+ 			    &setlist, &showlist);
+ 
+Index: gdb-7.4.91.20120814/gdb/solib-svr4.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/solib-svr4.c	2012-08-14 17:34:39.346752840 +0200
++++ gdb-7.4.91.20120814/gdb/solib-svr4.c	2012-08-14 17:35:42.635732596 +0200
+@@ -47,10 +47,12 @@
+ #include "auxv.h"
+ #include "exceptions.h"
+ #include "gdb_bfd.h"
++#include "probe.h"
+ 
+ static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
+ static int svr4_have_link_map_offsets (void);
+ static void svr4_relocate_main_executable (void);
++static struct so_list *namespace_table_flatten (htab_t namespace_table);
+ 
+ /* Link map info to include in an allocated so_list entry.  */
+ 
+@@ -71,6 +73,16 @@ struct lm_info
+ 
+     /* Values read in from inferior's fields of the same name.  */
+     CORE_ADDR l_ld, l_next, l_prev, l_name;
++
++    /* Numeric link-map ID of the namespace this object is loaded
++       into.  This value is only valid when using the probes-based
++       interface.  */
++    LONGEST lmid;
++
++    /* Nonzero if the namespace list this object is loaded into is the
++       application's initial namespace (LM_ID_BASE).  This value is
++       only valid when using the probes-based interface.  */
++    unsigned int in_initial_ns : 1;
+   };
+ 
+ /* On SVR4 systems, a list of symbols in the dynamic linker where
+@@ -107,6 +119,53 @@ static const  char * const main_name_lis
+   NULL
+ };
+ 
++/* What to do with the namespace table when a probe stop occurs.  */
++
++enum probe_action
++  {
++    /* Something went seriously wrong.  Stop using probes and
++       revert to using the older interface.  */
++    NAMESPACE_TABLE_INVALIDATE,
++
++    /* No action is required.  This namespace is still valid.  */
++    NAMESPACE_NO_ACTION,
++
++    /* This namespace should be reloaded entirely.  */
++    NAMESPACE_RELOAD,
++
++    /* Attempt to incrementally update this namespace. If the
++       update fails or is not possible, fall back to reloading
++       the namespace in full.  */
++    NAMESPACE_UPDATE_OR_RELOAD,
++  };
++
++/* A probe's name and its associated action.  */
++
++struct probe_info
++{
++  /* The name of the probe.  */
++  const char *name;
++
++  /* What to do with the namespace table when a probe stop occurs.  */
++  enum probe_action action;
++};
++
++/* A list of named probes and their associated actions.  If all
++   probes are present in the dynamic linker then the probes-based
++   interface will be used.  */
++
++static const struct probe_info probe_info[] =
++{
++  { "init_start", NAMESPACE_NO_ACTION },
++  { "init_complete", NAMESPACE_RELOAD },
++  { "map_start", NAMESPACE_NO_ACTION },
++  { "reloc_complete", NAMESPACE_UPDATE_OR_RELOAD },
++  { "unmap_start", NAMESPACE_NO_ACTION },
++  { "unmap_complete", NAMESPACE_RELOAD },
++};
++
++#define NUM_PROBES ARRAY_SIZE (probe_info)
++
+ /* Per pspace SVR4 specific data.  */
+ 
+ struct svr4_info
+@@ -129,17 +188,58 @@ struct svr4_info
+   CORE_ADDR interp_text_sect_high;
+   CORE_ADDR interp_plt_sect_low;
+   CORE_ADDR interp_plt_sect_high;
++
++  /* Nonzero if we are using the probes-based interface.  */
++  unsigned int using_probes : 1;
++
++  /* Named probes in the dynamic linker.  */
++  VEC (probe_p) *probes[NUM_PROBES];
++
++  /* Table of dynamic linker namespaces, used by the probes-based
++     interface.  */
++  htab_t namespace_table;
+ };
+ 
+ /* Per-program-space data key.  */
+ static const struct program_space_data *solib_svr4_pspace_data;
+ 
++/* Free any allocated probe vectors.  */
++
++static void
++free_probes (struct svr4_info *info)
++{
++  int i;
++
++  for (i = 0; i < NUM_PROBES; i++)
++    VEC_free (probe_p, info->probes[i]);
++
++  memset (info->probes, 0, sizeof (info->probes));
++}
++
++/* Free the namespace table.  */
++
++static void
++free_namespace_table (struct svr4_info *info)
++{
++  if (info->namespace_table == NULL)
++    return;
++
++  htab_delete (info->namespace_table);
++  info->namespace_table = NULL;
++}
++
+ static void
+ svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
+ {
+   struct svr4_info *info;
+ 
+   info = program_space_data (pspace, solib_svr4_pspace_data);
++  if (info == NULL)
++    return;
++
++  free_probes (info);
++  free_namespace_table (info);
++
+   xfree (info);
+ }
+ 
+@@ -188,10 +288,21 @@ svr4_same_1 (const char *gdb_so_name, co
+   return 0;
+ }
+ 
++/* Return non-zero if GDB and INFERIOR represent the same shared
++   library.  */
++
+ static int
+ svr4_same (struct so_list *gdb, struct so_list *inferior)
+ {
+-  return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
++  struct svr4_info *info = get_svr4_info ();
++
++  if (info->using_probes)
++    {
++      if (gdb->lm_info->lmid != inferior->lm_info->lmid)
++	return 0;
++    }
++
++  return svr4_same_1 (gdb->so_original_name, inferior->so_original_name);
+ }
+ 
+ static struct lm_info *
+@@ -322,18 +433,26 @@ lm_addr_check (struct so_list *so, bfd *
+ 	    }
+ 	  else
+ 	    {
+-	      /* There is no way to verify the library file matches.  prelink
+-		 can during prelinking of an unprelinked file (or unprelinking
+-		 of a prelinked file) shift the DYNAMIC segment by arbitrary
+-		 offset without any page size alignment.  There is no way to
+-		 find out the ELF header and/or Program Headers for a limited
+-		 verification if it they match.  One could do a verification
+-		 of the DYNAMIC segment.  Still the found address is the best
+-		 one GDB could find.  */
+-
+-	      warning (_(".dynamic section for \"%s\" "
+-			 "is not at the expected address "
+-			 "(wrong library or version mismatch?)"), so->so_name);
++	      struct svr4_info *info = get_svr4_info ();
++
++	      if (!info->using_probes || so->lm_info->in_initial_ns)
++		{
++		  /* There is no way to verify the library file
++		     matches.  prelink can during prelinking of an
++		     unprelinked file (or unprelinking of a prelinked
++		     file) shift the DYNAMIC segment by arbitrary
++		     offset without any page size alignment.  There is
++		     no way to find out the ELF header and/or Program
++		     Headers for a limited verification if it they
++		     match.  One could do a verification of the
++		     DYNAMIC segment.  Still the found address is the
++		     best one GDB could find.  */
++
++		  warning (_(".dynamic section for \"%s\" "
++			     "is not at the expected address "
++			     "(wrong library or version mismatch?)"),
++			   so->so_name);
++		}
+ 	    }
+ 	}
+ 
+@@ -775,16 +894,10 @@ locate_base (struct svr4_info *info)
+   return info->debug_base;
+ }
+ 
+-/* Find the first element in the inferior's dynamic link map, and
+-   return its address in the inferior.  Return zero if the address
+-   could not be determined.
+-
+-   FIXME: Perhaps we should validate the info somehow, perhaps by
+-   checking r_version for a known version number, or r_state for
+-   RT_CONSISTENT.  */
++/* Read the r_map field from the supplied r_debug structure.  */
+ 
+ static CORE_ADDR
+-solib_svr4_r_map (struct svr4_info *info)
++r_map_from_debug_base (CORE_ADDR debug_base)
+ {
+   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+   struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+@@ -793,13 +906,27 @@ solib_svr4_r_map (struct svr4_info *info
+ 
+   TRY_CATCH (ex, RETURN_MASK_ERROR)
+     {
+-      addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
++      addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
+                                         ptr_type);
+     }
+   exception_print (gdb_stderr, ex);
+   return addr;
+ }
+ 
++/* Find the first element in the inferior's dynamic link map, and
++   return its address in the inferior.  Return zero if the address
++   could not be determined.
++
++   FIXME: Perhaps we should validate the info somehow, perhaps by
++   checking r_version for a known version number, or r_state for
++   RT_CONSISTENT.  */
++
++static CORE_ADDR
++solib_svr4_r_map (struct svr4_info *info)
++{
++  return r_map_from_debug_base (info->debug_base);
++}
++
+ /* Find r_brk from the inferior's debug base.  */
+ 
+ static CORE_ADDR
+@@ -1164,15 +1291,17 @@ svr4_default_sos (void)
+   return new;
+ }
+ 
+-/* Read the whole inferior libraries chain starting at address LM.  Add the
+-   entries to the tail referenced by LINK_PTR_PTR.  Ignore the first entry if
+-   IGNORE_FIRST and set global MAIN_LM_ADDR according to it.  */
++/* Read the whole inferior libraries chain starting at address LM.
++   Expect the first entry in the chain's previous entry to be PREV_LM.
++   Add the entries to the tail referenced by LINK_PTR_PTR.  Ignore the
++   first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according
++   to it.  Returns nonzero upon success.  */
+ 
+-static void
+-svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr,
+-		   int ignore_first)
++static int
++svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
++		   struct so_list ***link_ptr_ptr, int ignore_first)
+ {
+-  CORE_ADDR prev_lm = 0, next_lm;
++  CORE_ADDR next_lm;
+ 
+   for (; lm != 0; prev_lm = lm, lm = next_lm)
+     {
+@@ -1189,7 +1318,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
+       if (new->lm_info == NULL)
+ 	{
+ 	  do_cleanups (old_chain);
+-	  break;
++	  return 0;
+ 	}
+ 
+       next_lm = new->lm_info->l_next;
+@@ -1200,7 +1329,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
+ 		   paddress (target_gdbarch, prev_lm),
+ 		   paddress (target_gdbarch, new->lm_info->l_prev));
+ 	  do_cleanups (old_chain);
+-	  break;
++	  return 0;
+ 	}
+ 
+       /* For SVR4 versions, the first entry in the link map is for the
+@@ -1295,20 +1424,61 @@ svr4_read_so_list (CORE_ADDR lm, struct
+       **link_ptr_ptr = new;
+       *link_ptr_ptr = &new->next;
+     }
++
++  return 1;
+ }
+ 
+-/* Implement the "current_sos" target_so_ops method.  */
++/* Read the list of loaded libraries from the dynamic linker's base
++   structure.  */
+ 
+ static struct so_list *
+-svr4_current_sos (void)
++svr4_current_sos_from_debug_base (void)
+ {
++  struct svr4_info *info = get_svr4_info ();
+   CORE_ADDR lm;
+   struct so_list *head = NULL;
+   struct so_list **link_ptr = &head;
+-  struct svr4_info *info;
+   struct cleanup *back_to;
+   int ignore_first;
++
++  gdb_assert (info->debug_base);
++
++  /* Assume that everything is a library if the dynamic loader was loaded
++     late by a static executable.  */
++  if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
++    ignore_first = 0;
++  else
++    ignore_first = 1;
++
++  back_to = make_cleanup (svr4_free_library_list, &head);
++
++  /* Walk the inferior's link map list, and build our list of
++     `struct so_list' nodes.  */
++  lm = solib_svr4_r_map (info);
++  if (lm)
++    svr4_read_so_list (lm, 0, &link_ptr, ignore_first);
++
++  /* On Solaris, the dynamic linker is not in the normal list of
++     shared objects, so make sure we pick it up too.  Having
++     symbol information for the dynamic linker is quite crucial
++     for skipping dynamic linker resolver code.  */
++  lm = solib_svr4_r_ldsomap (info);
++  if (lm)
++    svr4_read_so_list (lm, 0, &link_ptr, 0);
++
++  discard_cleanups (back_to);
++
++  return head;
++}
++
++/* Implement the "current_sos" target_so_ops method.  */
++
++static struct so_list *
++svr4_current_sos (void)
++{
++  struct svr4_info *info;
+   struct svr4_library_list library_list;
++  struct so_list *result;
+ 
+   /* Fall back to manual examination of the target if the packet is not
+      supported or gdbserver failed to find DT_DEBUG.  gdb.server/solib-list.exp
+@@ -1331,6 +1501,10 @@ svr4_current_sos (void)
+ 
+   info = get_svr4_info ();
+ 
++  /* If we have a namespace table then return a flattened copy.  */
++  if (info->namespace_table != NULL)
++    return namespace_table_flatten (info->namespace_table);
++
+   /* Always locate the debug struct, in case it has moved.  */
+   info->debug_base = 0;
+   locate_base (info);
+@@ -1340,35 +1514,12 @@ svr4_current_sos (void)
+   if (! info->debug_base)
+     return svr4_default_sos ();
+ 
+-  /* Assume that everything is a library if the dynamic loader was loaded
+-     late by a static executable.  */
+-  if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
+-    ignore_first = 0;
+-  else
+-    ignore_first = 1;
+-
+-  back_to = make_cleanup (svr4_free_library_list, &head);
+-
+-  /* Walk the inferior's link map list, and build our list of
+-     `struct so_list' nodes.  */
+-  lm = solib_svr4_r_map (info);
+-  if (lm)
+-    svr4_read_so_list (lm, &link_ptr, ignore_first);
+-
+-  /* On Solaris, the dynamic linker is not in the normal list of
+-     shared objects, so make sure we pick it up too.  Having
+-     symbol information for the dynamic linker is quite crucial
+-     for skipping dynamic linker resolver code.  */
+-  lm = solib_svr4_r_ldsomap (info);
+-  if (lm)
+-    svr4_read_so_list (lm, &link_ptr, 0);
+-
+-  discard_cleanups (back_to);
++  result = svr4_current_sos_from_debug_base ();
+ 
+-  if (head == NULL)
++  if (result == NULL)
+     return svr4_default_sos ();
+ 
+-  return head;
++  return result;
+ }
+ 
+ /* Get the address of the link_map for a given OBJFILE.  */
+@@ -1450,6 +1601,498 @@ exec_entry_point (struct bfd *abfd, stru
+ 					     targ);
+ }
+ 
++/* A probe and its associated information structure.  */
++
++struct probe_and_info
++{
++  /* The probe.  */
++  struct probe *probe;
++
++  /* The probe_info from which the probe was created.  */
++  const struct probe_info *info;
++};
++
++/* Get the solib event probe at the specified location, and the
++   probe_info the probe was created with.  Fills in RESULT and
++   returns nonzero if a solib event probe was found at the
++   specified location.  Returns zero if no solib event probe
++   was found.  */
++
++static int
++solib_event_probe_at (struct svr4_info *info, struct bp_location *loc,
++		      struct probe_and_info *result)
++{
++  int i;
++
++  for (i = 0; i < NUM_PROBES; i++)
++    {
++      struct probe *probe;
++      int ix;
++
++      for (ix = 0; VEC_iterate (probe_p, info->probes[i], ix, probe); ++ix)
++	{
++	  if (loc->pspace == current_program_space
++	      && loc->address == probe->address)
++	    {
++	      result->info = &probe_info[i];
++	      result->probe = probe;
++
++	      return 1;
++	    }
++	}
++    }
++
++  return 0;
++}
++
++/* Decide what action to take when the specified solib event probe is
++   hit.  */
++
++static enum probe_action
++solib_event_probe_action (struct probe_and_info *pi)
++{
++  enum probe_action action;
++  unsigned probe_argc;
++
++  action = pi->info->action;
++  if (action == NAMESPACE_NO_ACTION || action == NAMESPACE_TABLE_INVALIDATE)
++    return action;
++
++  gdb_assert (action == NAMESPACE_RELOAD
++	      || action == NAMESPACE_UPDATE_OR_RELOAD);
++
++  /* Check that an appropriate number of arguments has been supplied.
++     We expect:
++       arg0: Lmid_t lmid (mandatory)
++       arg1: struct r_debug *debug_base (mandatory)
++       arg2: struct link_map *new (optional, for incremental updates)  */
++  probe_argc = get_probe_argument_count (pi->probe);
++  if (probe_argc == 2)
++    action = NAMESPACE_RELOAD;
++  else if (probe_argc < 2)
++    action = NAMESPACE_TABLE_INVALIDATE;
++
++  return action;
++}
++
++/* A namespace in the dynamic linker.  */
++
++struct namespace
++{
++  /* Numeric link-map ID of the namespace.  */
++  LONGEST lmid;
++
++  /* List of objects loaded into the namespace.  */
++  struct so_list *solist;
++};
++
++/* Returns a hash code for the namespace referenced by p.  */
++
++static hashval_t
++hash_namespace (const void *p)
++{
++  const struct namespace *ns = p;
++
++  return (hashval_t) ns->lmid;
++}
++
++/* Returns non-zero if the namespaces referenced by p1 and p2
++   are equal.  */
++
++static int
++equal_namespace (const void *p1, const void *p2)
++{
++  const struct namespace *ns1 = p1;
++  const struct namespace *ns2 = p2;
++
++  return ns1->lmid == ns2->lmid;
++}
++
++/* Free a namespace.  */
++
++static void
++free_namespace (void *p)
++{
++  struct namespace *ns = p;
++
++  svr4_free_library_list (ns->solist);
++  xfree (ns);
++}
++
++/* Populate this namespace by reading the entire list of shared
++   objects from the inferior.  Returns nonzero on success.  */
++
++static int
++namespace_update_full (struct svr4_info *info, LONGEST lmid,
++		       CORE_ADDR debug_base, int is_initial_ns)
++{
++  struct so_list *result = NULL, *so;
++  struct namespace lookup, *ns;
++  void **slot;
++
++  /* Read the list of shared objects from the inferior.  The
++     initial namespace requires extra processing and is handled
++     separately.  */
++  if (is_initial_ns)
++    {
++      result = svr4_current_sos_from_debug_base ();
++    }
++  else
++    {
++      CORE_ADDR lm = r_map_from_debug_base (debug_base);
++      struct so_list **link_ptr = &result;
++
++      if (!svr4_read_so_list (lm, 0, &link_ptr, 0))
++	return 0;
++    }
++
++  /* If the namespace is empty then delete it from the table.  */
++  if (result == NULL)
++    {
++      if (info->namespace_table != NULL)
++	{
++	  lookup.lmid = lmid;
++	  htab_remove_elt (info->namespace_table, &lookup);
++	}
++
++      return 1;
++    }
++
++  /* Fill in the link-map IDs and initial namespace flags.  */
++  for (so = result; so; so = so->next)
++    {
++      so->lm_info->lmid = lmid;
++      so->lm_info->in_initial_ns = is_initial_ns;
++    }
++
++  /* Create the namespace table, if necessary.  */
++  if (info->namespace_table == NULL)
++    {
++      info->namespace_table = htab_create_alloc (1, hash_namespace,
++						 equal_namespace,
++						 free_namespace,
++						 xcalloc, xfree);
++    }
++
++  /* Update the namespace table with our new list.  */
++  lookup.lmid = lmid;
++  slot = htab_find_slot (info->namespace_table, &lookup, INSERT);
++  if (*slot == HTAB_EMPTY_ENTRY)
++    {
++      ns = XCNEW (struct namespace);
++      ns->lmid = lmid;
++      *slot = ns;
++    }
++  else
++    {
++      ns = *slot;
++      svr4_free_library_list (ns->solist);
++    }
++  ns->solist = result;
++
++  return 1;
++}
++
++/* Update this namespace starting from the link-map entry passed by
++   the linker in the probe's third argument.  Returns nonzero if the
++   list was successfully updated, or zero to indicate failure.  */
++
++static int
++namespace_update_incremental (struct svr4_info *info, LONGEST lmid,
++			      CORE_ADDR lm, int is_initial_ns)
++{
++  struct namespace lookup, *ns;
++  struct so_list *tail, **link, *so;
++  struct value *val;
++
++  /* Find our namespace in the table.  */
++  if (info->namespace_table == NULL)
++    return 0;
++
++  lookup.lmid = lmid;
++  ns = htab_find (info->namespace_table, &lookup);
++  if (ns == NULL)
++    return 0;
++
++  /* Walk to the end of the list.  */
++  tail = ns->solist;
++  if (tail == NULL)
++    return 0;
++
++  while (tail->next)
++    tail = tail->next;
++  link = &tail->next;
++
++  /* Read the new objects.  */
++  if (!svr4_read_so_list (lm, tail->lm_info->lm_addr, &link, 0))
++    return 0;
++
++  /* Fill in the link-map IDs and initial namespace flags.  */
++  for (so = tail; so; so = so->next)
++    {
++      so->lm_info->lmid = lmid;
++      so->lm_info->in_initial_ns = is_initial_ns;
++    }
++
++  return 1;
++}
++
++/* Update the namespace table as appropriate when using the
++   probes-based linker interface.  Do nothing if using the
++   standard interface.  */
++
++static void
++svr4_handle_solib_event (bpstat bs)
++{
++  struct svr4_info *info = get_svr4_info ();
++  struct probe_and_info buf, *pi = &buf;
++  enum probe_action action;
++  struct value *val;
++  LONGEST lmid;
++  CORE_ADDR debug_base, lm = 0;
++  int is_initial_ns;
++
++  /* It is possible that this function will be called incorrectly
++     by the handle_solib_event in handle_inferior_event if GDB goes
++     fully multi-target.  */
++  gdb_assert (bs != NULL);
++
++  if (!info->using_probes)
++    return;
++
++  if (!solib_event_probe_at (info, bs->bp_location_at, pi))
++    goto error;
++
++  action = solib_event_probe_action (pi);
++  if (action == NAMESPACE_TABLE_INVALIDATE)
++    goto error;
++
++  if (action == NAMESPACE_NO_ACTION)
++    return;
++
++  val = evaluate_probe_argument (pi->probe, 0);
++  if (val == NULL)
++    goto error;
++
++  lmid = value_as_long (val);
++
++  val = evaluate_probe_argument (pi->probe, 1);
++  if (val == NULL)
++    goto error;
++
++  debug_base = value_as_address (val);
++  if (debug_base == 0)
++    goto error;
++
++  /* Always locate the debug struct, in case it moved.  */
++  info->debug_base = 0;
++  if (locate_base (info) == 0)
++    goto error;
++
++  is_initial_ns = (debug_base == info->debug_base);
++
++  if (action == NAMESPACE_UPDATE_OR_RELOAD)
++    {
++      val = evaluate_probe_argument (pi->probe, 2);
++      if (val != NULL)
++	lm = value_as_address (val);
++
++      if (lm == 0)
++	action = NAMESPACE_RELOAD;
++    }
++
++  if (action == NAMESPACE_UPDATE_OR_RELOAD)
++    {
++      if (namespace_update_incremental (info, lmid, lm, is_initial_ns))
++	return;
++
++      action = NAMESPACE_RELOAD;
++    }
++
++  gdb_assert (action == NAMESPACE_RELOAD);
++
++  if (namespace_update_full (info, lmid, debug_base, is_initial_ns))
++    return;
++
++ error:
++
++  /* We should never reach here, but if we do we disable the
++     probes interface and revert to the original interface.
++     We don't reset the breakpoints as the ones we've set up
++     are adequate.  */
++  warning (_("Probes-based dynamic linker interface failed.\n"
++	     "Reverting to original interface.\n"));
++
++  free_namespace_table (info);
++  free_probes (info);
++  info->using_probes = 0;
++}
++
++/* Helper function for namespace_table_flatten.  */
++
++static int
++namespace_table_flatten_helper (void **slot, void *arg)
++{
++  struct namespace *ns = (struct namespace *) *slot;
++  struct so_list *src = ns->solist;
++  struct so_list **link = (struct so_list **) arg;
++
++  while (*link)
++    link = &(*link)->next;
++
++  while (src != NULL)
++    {
++      struct so_list *dst;
++
++      dst = xmalloc (sizeof (struct so_list));
++      memcpy (dst, src, sizeof (struct so_list));
++
++      dst->lm_info = xmalloc (sizeof (struct lm_info));
++      memcpy (dst->lm_info, src->lm_info, sizeof (struct lm_info));
++
++      *link = dst;
++      link = &dst->next;
++
++      src = src->next;
++    }
++
++  *link = NULL;
++
++  return 1; /* Continue traversal.  */
++}
++
++/* Flatten the namespace table into a single list.  */
++
++static struct so_list *
++namespace_table_flatten (htab_t namespace_table)
++{
++  struct so_list *dst = NULL;
++
++  htab_traverse (namespace_table, namespace_table_flatten_helper, &dst);
++
++  return dst;
++}
++
++/* Helper function for svr4_update_solib_event_breakpoints.  */
++
++static int
++svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
++{
++  struct svr4_info *info = get_svr4_info ();
++  struct bp_location *loc;
++
++  if (b->type != bp_shlib_event)
++    return 0; /* Continue iterating.  */
++
++  for (loc = b->loc; loc; loc = loc->next)
++    {
++      struct probe_and_info buf, *pi = &buf;
++
++      if (solib_event_probe_at (info, loc, pi))
++	{
++	  if (pi->info->action == NAMESPACE_NO_ACTION)
++	    b->enable_state = (stop_on_solib_events
++			       ? bp_enabled : bp_disabled);
++
++	  return 0; /* Continue iterating.  */
++	}
++    }
++
++  return 0; /* Continue iterating.  */
++}
++
++/* Enable or disable optional solib event breakpoints as appropriate.
++   Called whenever stop_on_solib_events is changed.  */
++
++static void
++svr4_update_solib_event_breakpoints (void)
++{
++  struct svr4_info *info = get_svr4_info ();
++
++  if (info->using_probes)
++    iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
++}
++
++/* Both the SunOS and the SVR4 dynamic linkers call a marker function
++   before and after mapping and unmapping shared libraries.  The sole
++   purpose of this method is to allow debuggers to set a breakpoint so
++   they can track these changes.
++
++   Some versions of the glibc dynamic linker contain named probes
++   to allow more fine grained stopping.  Given the address of the
++   original marker function, this function attempts to find these
++   probes, and if found, sets breakpoints on those instead.  If the
++   probes aren't found, a single breakpoint is set on the original
++   marker function.  */
++
++static void
++svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch,
++				     CORE_ADDR address)
++{
++  struct svr4_info *info = get_svr4_info ();
++  struct obj_section *os;
++
++  os = find_pc_section (address);
++  if (os != NULL)
++    {
++      int with_prefix;
++
++      for (with_prefix = 0; with_prefix <= 1; with_prefix++)
++	{
++	  int all_probes_found = 1;
++	  int i;
++
++	  for (i = 0; i < NUM_PROBES; i++)
++	    {
++	      char name[32] = { '\0' };
++
++	      /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an
++		 early version of the probes code in which the probes'
++		 names were prefixed with "rtld_".  The locations and
++		 arguments of the probes are otherwise the same, so we
++		 check for the prefixed version if the unprefixed
++		 probes are not found.  */
++
++	      if (with_prefix)
++		strncat (name, "rtld_", sizeof (name));
++
++	      strncat (name, probe_info[i].name, sizeof (name) - sizeof ("rtld_"));
++
++	      info->probes[i] = find_probes_in_objfile (os->objfile, "rtld",
++							name);
++
++	      if (!VEC_length (probe_p, info->probes[i]))
++		{
++		  free_probes (info);
++		  all_probes_found = 0;
++		  break;
++		}
++	    }
++
++	  if (all_probes_found)
++	    {
++	      info->using_probes = 1;
++
++	      for (i = 0; i < NUM_PROBES; i++)
++		{
++		  struct probe *probe;
++		  int ix;
++
++		  for (ix = 0;
++		       VEC_iterate (probe_p, info->probes[i], ix, probe);
++		       ++ix)
++		    create_solib_event_breakpoint (gdbarch, probe->address);
++		}
++
++	      svr4_update_solib_event_breakpoints ();
++	      return;
++	    }
++	}
++    }
++
++  create_solib_event_breakpoint (gdbarch, address);
++}
++
+ /* Helper function for gdb_bfd_lookup_symbol.  */
+ 
+ static int
+@@ -1502,6 +2145,9 @@ enable_break (struct svr4_info *info, in
+   info->interp_text_sect_low = info->interp_text_sect_high = 0;
+   info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
+ 
++  free_probes (info);
++  info->using_probes = 0;
++
+   /* If we already have a shared library list in the target, and
+      r_debug contains r_brk, set the breakpoint there - this should
+      mean r_brk has already been relocated.  Assume the dynamic linker
+@@ -1533,7 +2179,7 @@ enable_break (struct svr4_info *info, in
+ 	 That knowledge is encoded in the address, if it's Thumb the low bit
+ 	 is 1.  However, we've stripped that info above and it's not clear
+ 	 what all the consequences are of passing a non-addr_bits_remove'd
+-	 address to create_solib_event_breakpoint.  The call to
++	 address to svr4_create_solib_event_breakpoints.  The call to
+ 	 find_pc_section verifies we know about the address and have some
+ 	 hope of computing the right kind of breakpoint to use (via
+ 	 symbol info).  It does mean that GDB needs to be pointed at a
+@@ -1571,7 +2217,7 @@ enable_break (struct svr4_info *info, in
+ 		+ bfd_section_size (tmp_bfd, interp_sect);
+ 	    }
+ 
+-	  create_solib_event_breakpoint (target_gdbarch, sym_addr);
++	  svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
+ 	  return 1;
+ 	}
+     }
+@@ -1729,7 +2375,8 @@ enable_break (struct svr4_info *info, in
+ 
+       if (sym_addr != 0)
+ 	{
+-	  create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr);
++	  svr4_create_solib_event_breakpoints (target_gdbarch,
++					       load_addr + sym_addr);
+ 	  xfree (interp_name);
+ 	  return 1;
+ 	}
+@@ -1755,7 +2402,7 @@ enable_break (struct svr4_info *info, in
+ 	  sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+ 							 sym_addr,
+ 							 &current_target);
+-	  create_solib_event_breakpoint (target_gdbarch, sym_addr);
++	  svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
+ 	  return 1;
+ 	}
+     }
+@@ -1771,7 +2418,7 @@ enable_break (struct svr4_info *info, in
+ 	      sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+ 							     sym_addr,
+ 							     &current_target);
+-	      create_solib_event_breakpoint (target_gdbarch, sym_addr);
++	      svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
+ 	      return 1;
+ 	    }
+ 	}
+@@ -2281,6 +2928,9 @@ svr4_solib_create_inferior_hook (int fro
+ 
+   info = get_svr4_info ();
+ 
++  /* Free the probes-based interface's namespace table.  */
++  free_namespace_table (info);
++
+   /* Relocate the main executable if necessary.  */
+   svr4_relocate_main_executable ();
+ 
+@@ -2547,4 +3197,6 @@ _initialize_svr4_solib (void)
+   svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
+   svr4_so_ops.same = svr4_same;
+   svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
++  svr4_so_ops.handle_solib_event = svr4_handle_solib_event;
++  svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
+ }
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c	2012-08-14 17:34:44.330746591 +0200
+@@ -0,0 +1,24 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++
++int
++foo (int n)
++{
++  printf ("foo %d\n", n);
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c	2012-08-14 17:34:44.339746576 +0200
+@@ -0,0 +1,58 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#define _GNU_SOURCE
++#include <dlfcn.h>
++
++void
++stop ()
++{
++}
++
++int
++main ()
++{
++  void *handle1, *handle2, *handle3;
++  void (*func)(int);
++
++  handle1 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
++  stop ();
++
++  func = (void (*)(int)) dlsym (handle1, "foo");
++  func (1);
++
++  handle2 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
++  stop ();
++
++  func = (void (*)(int)) dlsym (handle2, "foo");
++  func (2);
++
++  handle3 = dlopen (SHLIB_NAME, RTLD_LAZY);
++  stop ();
++
++  func = (void (*)(int)) dlsym (handle3, "foo");
++  func (3);
++
++  dlclose (handle1);
++  stop ();
++
++  dlclose (handle2);
++  stop ();
++
++  dlclose (handle3);
++  stop ();
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp	2012-08-14 17:34:44.343746563 +0200
+@@ -0,0 +1,125 @@
++# Copyright 2012 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++if { [skip_shlib_tests] || [is_remote target] } {
++    return 0
++}
++
++standard_testfile
++
++set libname $testfile-solib
++set srcfile_lib $srcdir/$subdir/$libname.c
++set binfile_lib [standard_output_file $libname.so]
++
++set normal_bp "_dl_debug_state"
++set probes_bp "dl_main"
++
++if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
++	  [list additional_flags=-fPIC]] != "" } {
++    untested "Could not compile $binfile_lib."
++    return -1
++}
++
++if { [prepare_for_testing $testfile.exp $testfile $srcfile \
++	  [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
++    return -1
++}
++
++# Run "info sharedlibrary" and check our library is shown the expected
++# number of times.
++proc check_info_shared { test expect } {
++    global libname
++    global gdb_prompt
++
++    set actual 0
++
++    gdb_test_multiple "info sharedlibrary" $test {
++	-re $libname {
++	    incr actual 1
++	    exp_continue
++	}
++	-re "\r\n$gdb_prompt $" {
++	    if { $actual == $expect } {
++		pass $test
++	    } else {
++		fail $test
++	    }
++	}
++    }
++}
++
++# Enable stop-on-solib-events
++gdb_test_no_output "set stop-on-solib-events 1"
++
++# Run to the first stop
++gdb_test "run" ".*Stopped due to shared library event.*"
++
++# XFAIL if we are not using probes
++set test "ensure using probes"
++set using_probes 0
++gdb_test_multiple "bt" $test {
++    -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
++	xfail $test
++    }
++    -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
++	pass $test
++	set using_probes 1
++    }
++}
++
++if { $using_probes } {
++    # Set up breakpoints.
++    gdb_test_no_output "set stop-on-solib-events 0"
++    gdb_test "break stop" {Breakpoint [0-9]+ at .*}
++    gdb_test_no_output "set breakpoint pending on"
++    gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
++
++    # Check our library isn't loaded.
++    check_info_shared "info sharedlibrary #1" 0
++
++    # Run to the first stop and check our library loaded.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #2" 1
++
++    # The next stop should be the function in the library.
++    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++    # Run to the next stop and check our library is now loaded twice.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #3" 2
++
++    # The next stop should be the function in the library.
++    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++    # Run to the next stop and check our library is now loaded three
++    # times.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #4" 3
++
++    # The next stop should be the function in the library.
++    gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++    # Run to the next stop and check our library is now loaded twice.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #5" 2
++
++    # Run to the next stop and check our library is now loaded once.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #6" 1
++
++    # Run to the next stop and check our library is not loaded.
++    gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++    check_info_shared "info sharedlibrary #7" 0
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/testsuite/gdb.base/break-interp.exp	2012-06-21 22:46:21.000000000 +0200
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp	2012-08-14 17:34:44.344746565 +0200
+@@ -109,12 +109,19 @@ proc strip_debug {dest} {
+     }
+ }
+ 
++# The marker function for the standard runtime linker interface is
++# _dl_debug_state.  The probes-based interface has no specific marker
++# function; the probe we will stop on (init_start) is in dl_main so we
++# check for that.
++
++set solib_bp {(_dl_debug_state|dl_main)}
++
+ # Implementation of reach.
+ 
+ proc reach_1 {func command displacement} {
+-    global gdb_prompt expect_out
++    global gdb_prompt expect_out solib_bp
+ 
+-    if {$func == "_dl_debug_state"} {
++    if {$func == $solib_bp} {
+ 	# Breakpoint on _dl_debug_state can have problems due to its overlap
+ 	# with the existing internal breakpoint from GDB.
+ 	gdb_test_no_output "set stop-on-solib-events 1"
+@@ -142,21 +149,21 @@ proc reach_1 {func command displacement}
+ 	    exp_continue
+ 	}
+ 	-re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		fail $test
+ 	    } else {
+ 		pass $test
+ 	    }
+ 	}
+ 	-re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		fail $test
+ 	    } else {
+ 		pass $test
+ 	    }
+ 	}
+ 	-re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		if {$debug_state_count == 0} {
+ 		    # First stop does not yet relocate the _start function
+ 		    # descriptor on ppc64.
+@@ -175,7 +182,7 @@ proc reach_1 {func command displacement}
+ 	fail $test_displacement
+     }
+ 
+-    if {$func == "_dl_debug_state"} {
++    if {$func == $solib_bp} {
+ 	gdb_test_no_output "set stop-on-solib-events 0"
+     }
+ }
+@@ -357,7 +364,7 @@ proc test_attach {file displacement {rel
+ }
+ 
+ proc test_ld {file ifmain trynosym displacement} {
+-    global srcdir subdir gdb_prompt expect_out inferior_exited_re
++    global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp
+ 
+     # First test normal `file'-command loaded $FILE with symbols.
+ 
+@@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ
+ 	gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test"
+     }
+ 
+-    reach "_dl_debug_state" "run" $displacement
++    reach $solib_bp "run" $displacement
+ 
+-    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt"
++    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt"
+ 
+     if $ifmain {
+ 	reach "main" continue "NONE"
+@@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ
+ 
+     # Try re-run if the new PIE displacement takes effect.
+     gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y"
+-    reach "_dl_debug_state" "run" $displacement
++    reach $solib_bp "run" $displacement
+ 
+     if $ifmain {
+ 	test_core $file $displacement
+@@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ
+ 	gdb_test "exec-file $file" "exec-file $escapedfile" "load"
+ 
+ 	if $ifmain {
+-	    reach "_dl_debug_state" run $displacement
++	    reach $solib_bp run $displacement
+ 
+ 	    # Use two separate gdb_test_multiple statements to avoid timeouts due
+ 	    # to slow processing of wildcard capturing long output
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c	2012-08-14 17:34:44.355746561 +0200
+@@ -0,0 +1,24 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++
++int
++foo (int n)
++{
++  printf ("foo %d\n", n);
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c	2012-08-14 17:34:44.362746561 +0200
+@@ -0,0 +1,26 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <dlfcn.h>
++
++int
++main ()
++{
++  void *handle = dlopen (SHLIB_NAME, RTLD_LAZY);
++
++  dlclose (handle);
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp	2012-08-14 17:34:44.363746561 +0200
+@@ -0,0 +1,76 @@
++# Copyright 2012 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++if { [skip_shlib_tests] || [is_remote target] } {
++    return 0
++}
++
++standard_testfile
++
++set libname $testfile-solib
++set srcfile_lib $srcdir/$subdir/$libname.c
++set binfile_lib [standard_output_file $libname.so]
++
++set normal_bp "_dl_debug_state"
++set probes_bp "dl_main"
++
++if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
++	  [list additional_flags=-fPIC]] != "" } {
++    untested "Could not compile $binfile_lib."
++    return -1
++}
++
++if { [prepare_for_testing $testfile.exp $testfile $srcfile \
++	  [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
++    return -1
++}
++
++# Enable stop-on-solib-events
++gdb_test_no_output "set stop-on-solib-events 1"
++
++# Run to the first stop
++gdb_test "run" ".*Stopped due to shared library event.*"
++
++# XFAIL if we are not using probes
++set test "ensure using probes"
++set using_probes 0
++gdb_test_multiple "bt" $test {
++    -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
++	xfail $test
++    }
++    -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
++	pass $test
++	set using_probes 1
++    }
++}
++
++if { $using_probes } {
++    # Run til it loads our library
++    set test "run til our library loads"
++    set loaded_library 0
++    while { !$loaded_library } {
++	gdb_test_multiple "c" $test {
++	    -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" {
++		pass $test
++		set loaded_library 1
++	    }
++	    -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
++	    }
++	}
++    }
++
++    # Call something to ensure that relocation occurred
++    gdb_test "call foo(23)" "foo 23.*\\\$.* = .*"
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c	2012-08-14 17:34:44.365746561 +0200
+@@ -0,0 +1,24 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++
++int
++foo (int n)
++{
++  printf ("foo %d\n", n);
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c	2012-08-14 17:34:44.365746561 +0200
+@@ -0,0 +1,24 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++
++int
++bar (int n)
++{
++  printf ("bar %d\n", n);
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c	2012-08-14 17:34:44.366746561 +0200
+@@ -0,0 +1,48 @@
++/* Copyright 2012 Free Software Foundation, Inc.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <dlfcn.h>
++
++void
++stop ()
++{
++}
++
++int
++main ()
++{
++  void *handle1, *handle2;
++  void (*func)(int);
++
++  handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY);
++  stop ();
++
++  handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY);
++  stop ();
++
++  func = (void (*)(int)) dlsym (handle1, "foo");
++  func (1);
++
++  func = (void (*)(int)) dlsym (handle2, "bar");
++  func (2);
++
++  dlclose (handle1);
++  stop ();
++
++  dlclose (handle2);
++  stop ();
++
++  return 0;
++}
+Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp	2012-08-14 17:34:44.367746561 +0200
+@@ -0,0 +1,139 @@
++# Copyright 2012 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++if { [skip_shlib_tests] || [is_remote target] } {
++    return 0
++}
++
++standard_testfile
++
++set lib1name $testfile-solib1
++set srcfile_lib1 $srcdir/$subdir/$lib1name.c
++set binfile_lib1 [standard_output_file $lib1name.so]
++set define1 -DSHLIB1_NAME\=\"$binfile_lib1\"
++
++set lib2name $testfile-solib2
++set srcfile_lib2 $srcdir/$subdir/$lib2name.c
++set binfile_lib2 [standard_output_file $lib2name.so]
++set define2 -DSHLIB2_NAME\=\"$binfile_lib2\"
++
++if { [gdb_compile_shlib $srcfile_lib1 $binfile_lib1 \
++	  [list additional_flags=-fPIC]] != "" } {
++    untested "Could not compile $binfile_lib1."
++    return -1
++}
++
++if { [gdb_compile_shlib $srcfile_lib2 $binfile_lib2 \
++	  [list additional_flags=-fPIC]] != "" } {
++    untested "Could not compile $binfile_lib2."
++    return -1
++}
++
++set cflags "$define1 $define2"
++if { [prepare_for_testing $testfile.exp $testfile $srcfile \
++	  [list additional_flags=$cflags libs=-ldl]] } {
++    return -1
++}
++
++# Run "info sharedlibrary" and check for the presence or absence of
++# our libraries.
++proc check_info_shared { test expect1 expect2 } {
++    global lib1name
++    global lib2name
++    global gdb_prompt
++
++    set actual1 0
++    set actual2 0
++
++    gdb_test_multiple "info sharedlibrary" $test {
++	-re $lib1name {
++	    set actual1 1
++	    exp_continue
++	}
++	-re $lib2name {
++	    set actual2 1
++	    exp_continue
++	}
++	-re "\r\n$gdb_prompt $" {
++	    if { $actual1 == $expect1 && $actual2 == $expect2 } {
++		pass $test
++	    } else {
++		fail $test
++	    }
++	}
++    }
++}
++
++# Set up breakpoints.
++gdb_test "break stop" {Breakpoint [0-9]+ at .*}
++gdb_test_no_output "set breakpoint pending on"
++gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
++gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.}
++
++# Check neither of the libraries are loaded at the start.
++gdb_test "start" {Temporary breakpoint [0-9]+, .* in main \(\)}
++check_info_shared "info sharedlibrary #1" 0 0
++
++# Run to the first stop and check that only the first library is loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #2" 1 0
++
++# Run to the second stop and check that both libraries are loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #3" 1 1
++
++# Check that the next stop is in foo.
++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++# Check that the next stop is in bar.
++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
++
++# Restart the inferior and make sure there are no breakpoint reset
++# errors.  These can happen with the probes-based runtime linker
++# interface if the cache is not cleared correctly.
++set test "restart"
++gdb_test_multiple "run" $test {
++    -re {Start it from the beginning\? \(y or n\) } {
++	send_gdb "y\n"
++	exp_continue
++    }
++    -re {Error in re-setting breakpoint} {
++	fail $test
++    }
++    -re "\r\n$gdb_prompt $" {
++	pass $test
++    }
++}
++
++# We're at the first stop.  Check that only the first library is loaded.
++check_info_shared "info sharedlibrary #4" 1 0
++
++# Run to the second stop and check that both libraries are loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #5" 1 1
++
++# Check that the next stop is in foo.
++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++# Check that the next stop is in bar.
++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
++
++# Run to the next stop and check that the first library has been unloaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #6" 0 1
++
++# Run to the last stop and check that both libraries are gone.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #7" 0 0
diff --git a/gdb-dlopen-stap-probe-7of7.patch b/gdb-dlopen-stap-probe-7of7.patch
new file mode 100644
index 0000000..074db24
--- /dev/null
+++ b/gdb-dlopen-stap-probe-7of7.patch
@@ -0,0 +1,147 @@
+2012-07-30  Gary Benson  <gbenson at redhat.com>
+
+	* objfiles.h (inhibit_section_map_updates): New function
+	declaration.
+	(resume_section_map_updates): Likewise.
+	(resume_section_map_updates_cleanup): Likewise.
+	* objfiles.c (objfile_pspace_info): New field "inhibit_updates".
+	(find_pc_section): Do not update the section map if
+	inhibit_updates is set.
+	(inhibit_section_map_updates): New function.
+	(resume_section_map_updates): Likewise.
+	(resume_section_map_updates_cleanup): Likewise.
+	* solib-svr4.c (svr4_handle_solib_event): Inhibit section map
+	updates for calls to evaluate_probe_argument.
+
+Index: gdb-7.4.91.20120814/gdb/objfiles.h
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/objfiles.h	2012-08-14 17:16:54.000000000 +0200
++++ gdb-7.4.91.20120814/gdb/objfiles.h	2012-08-14 17:20:55.913174609 +0200
+@@ -526,6 +526,22 @@ extern void set_objfile_data (struct obj
+ extern void *objfile_data (struct objfile *objfile,
+ 			   const struct objfile_data *data);
+ 
++/* In normal use, the section map will be rebuilt by FIND_PC_SECTION
++   if objfiles have been added, removed or relocated since it was last
++   called.  Calling INHIBIT_SECTION_MAP_UPDATES will inhibit this
++   behavior until RESUME_SECTION_MAP_UPDATES is called.  If you call
++   INHIBIT_SECTION_MAP_UPDATES you must ensure that every call to
++   FIND_PC_SECTION in the inhibited region relates to a section that
++   is already in the section map and has not since been removed or
++   relocated.  */
++extern void inhibit_section_map_updates (void);
++
++/* Resume automatically rebuilding the section map as required.  */
++extern void resume_section_map_updates (void);
++
++/* Version of the above suitable for use as a cleanup.  */
++extern void resume_section_map_updates_cleanup (void *arg);
++
+ extern void default_iterate_over_objfiles_in_search_order
+   (struct gdbarch *gdbarch,
+    iterate_over_objfiles_in_search_order_cb_ftype *cb,
+Index: gdb-7.4.91.20120814/gdb/objfiles.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/objfiles.c	2012-08-14 17:16:55.000000000 +0200
++++ gdb-7.4.91.20120814/gdb/objfiles.c	2012-08-14 17:20:55.915174609 +0200
+@@ -70,6 +70,9 @@ struct objfile_pspace_info
+   int objfiles_changed_p;
+   struct obj_section **sections;
+   int num_sections;
++
++  /* Nonzero if section map updates should be inhibited.  */
++  int inhibit_updates;
+ };
+ 
+ /* Per-program-space data key.  */
+@@ -1295,7 +1298,7 @@ find_pc_section (CORE_ADDR pc)
+     return s;
+ 
+   pspace_info = get_objfile_pspace_data (current_program_space);
+-  if (pspace_info->objfiles_changed_p != 0)
++  if (pspace_info->objfiles_changed_p && !pspace_info->inhibit_updates)
+     {
+       update_section_map (current_program_space,
+ 			  &pspace_info->sections,
+@@ -1463,6 +1466,30 @@ objfiles_changed (void)
+   get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
+ }
+ 
++/* See comments in objfiles.h.  */
++
++void
++inhibit_section_map_updates (void)
++{
++  get_objfile_pspace_data (current_program_space)->inhibit_updates = 1;
++}
++
++/* See comments in objfiles.h.  */
++
++void
++resume_section_map_updates (void)
++{
++  get_objfile_pspace_data (current_program_space)->inhibit_updates = 0;
++}
++
++/* See comments in objfiles.h.  */
++
++void
++resume_section_map_updates_cleanup (void *arg)
++{
++  resume_section_map_updates ();
++}
++
+ /* The default implementation for the "iterate_over_objfiles_in_search_order"
+    gdbarch method.  It is equivalent to use the ALL_OBJFILES macro,
+    searching the objfiles in the order they are stored internally,
+Index: gdb-7.4.91.20120814/gdb/solib-svr4.c
+===================================================================
+--- gdb-7.4.91.20120814.orig/gdb/solib-svr4.c	2012-08-14 17:20:42.000000000 +0200
++++ gdb-7.4.91.20120814/gdb/solib-svr4.c	2012-08-14 17:21:14.090169216 +0200
+@@ -1847,6 +1847,7 @@ svr4_handle_solib_event (bpstat bs)
+   struct svr4_info *info = get_svr4_info ();
+   struct probe_and_info buf, *pi = &buf;
+   enum probe_action action;
++  struct cleanup *cleanups = NULL;
+   struct value *val;
+   LONGEST lmid;
+   CORE_ADDR debug_base, lm = 0;
+@@ -1870,6 +1871,19 @@ svr4_handle_solib_event (bpstat bs)
+   if (action == NAMESPACE_NO_ACTION)
+     return;
+ 
++  /* EVALUATE_PROBE_ARGUMENT looks up symbols in the dynamic linker
++     using FIND_PC_SECTION.  FIND_PC_SECTION is accelerated by a cache
++     called the section map.  The section map is invalidated every
++     time a shared library is loaded or unloaded, and if the inferior
++     is generating a lot of shared library events then the section map
++     will be updated every time SVR4_HANDLE_SOLIB_EVENT is called.
++     We called FIND_PC_SECTION in SVR4_CREATE_SOLIB_EVENT_BREAKPOINTS,
++     so we can guarantee that the dynamic linker's sections are in the
++     section map.  We can therefore inhibit section map updates across
++     these calls to EVALUATE_PROBE_ARGUMENT and save a lot of time.  */
++  inhibit_section_map_updates ();
++  cleanups = make_cleanup (resume_section_map_updates_cleanup, NULL);
++
+   val = evaluate_probe_argument (pi->probe, 0);
+   if (val == NULL)
+     goto error;
+@@ -1901,6 +1915,9 @@ svr4_handle_solib_event (bpstat bs)
+ 	action = NAMESPACE_RELOAD;
+     }
+ 
++  do_cleanups (cleanups);
++  cleanups = NULL;
++
+   if (action == NAMESPACE_UPDATE_OR_RELOAD)
+     {
+       if (namespace_update_incremental (info, lmid, lm, is_initial_ns))
+@@ -1923,6 +1940,8 @@ svr4_handle_solib_event (bpstat bs)
+   warning (_("Probes-based dynamic linker interface failed.\n"
+ 	     "Reverting to original interface.\n"));
+ 
++  if (cleanups != NULL)
++    do_cleanups (cleanups);
+   free_namespace_table (info);
+   free_probes (info);
+   info->using_probes = 0;
diff --git a/gdb-dlopen-stap-probe-test.patch b/gdb-dlopen-stap-probe-test.patch
index efd3683..fb2ebd1 100644
--- a/gdb-dlopen-stap-probe-test.patch
+++ b/gdb-dlopen-stap-probe-test.patch
@@ -305,104 +305,3 @@ Index: gdb-7.4.50.20120714/gdb/testsuite/lib/prelink-support.exp
      return $prelink_args
  }
  
-Index: gdb-7.4.50.20120714/gdb/testsuite/gdb.base/break-interp.exp
-===================================================================
---- gdb-7.4.50.20120714.orig/gdb/testsuite/gdb.base/break-interp.exp	2012-06-21 22:46:21.000000000 +0200
-+++ gdb-7.4.50.20120714/gdb/testsuite/gdb.base/break-interp.exp	2012-07-15 08:51:38.244701248 +0200
-@@ -109,14 +109,21 @@ proc strip_debug {dest} {
-     }
- }
- 
-+# Former symbol for solib changes notifications was _dl_debug_state, newer one
-+# is dl_main (in fact _dl_debug_notify but it is inlined without any extra
-+# debug info), the right one one traps by `set stop-on-solib-events 1'.
-+
-+set solib_bp {(_dl_debug_state|dl_main)}
-+
- # Implementation of reach.
- 
- proc reach_1 {func command displacement} {
--    global gdb_prompt expect_out
-+    global gdb_prompt expect_out solib_bp
- 
--    if {$func == "_dl_debug_state"} {
-+    if {$func == $solib_bp} {
- 	# Breakpoint on _dl_debug_state can have problems due to its overlap
- 	# with the existing internal breakpoint from GDB.
-+	# With also _dl_debug_notify we would need even two breakpoints.
- 	gdb_test_no_output "set stop-on-solib-events 1"
-     } elseif {! [gdb_breakpoint $func allow-pending]} {
- 	return
-@@ -142,21 +149,21 @@ proc reach_1 {func command displacement}
- 	    exp_continue
- 	}
- 	-re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
--	    if {$func == "_dl_debug_state"} {
-+	    if {$func == $solib_bp} {
- 		fail $test
- 	    } else {
- 		pass $test
- 	    }
- 	}
- 	-re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" {
--	    if {$func == "_dl_debug_state"} {
-+	    if {$func == $solib_bp} {
- 		fail $test
- 	    } else {
- 		pass $test
- 	    }
- 	}
- 	-re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" {
--	    if {$func == "_dl_debug_state"} {
-+	    if {$func == $solib_bp} {
- 		if {$debug_state_count == 0} {
- 		    # First stop does not yet relocate the _start function
- 		    # descriptor on ppc64.
-@@ -175,7 +182,7 @@ proc reach_1 {func command displacement}
- 	fail $test_displacement
-     }
- 
--    if {$func == "_dl_debug_state"} {
-+    if {$func == $solib_bp} {
- 	gdb_test_no_output "set stop-on-solib-events 0"
-     }
- }
-@@ -357,7 +364,7 @@ proc test_attach {file displacement {rel
- }
- 
- proc test_ld {file ifmain trynosym displacement} {
--    global srcdir subdir gdb_prompt expect_out inferior_exited_re
-+    global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp
- 
-     # First test normal `file'-command loaded $FILE with symbols.
- 
-@@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ
- 	gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test"
-     }
- 
--    reach "_dl_debug_state" "run" $displacement
-+    reach $solib_bp "run" $displacement
- 
--    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt"
-+    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt"
- 
-     if $ifmain {
- 	reach "main" continue "NONE"
-@@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ
- 
-     # Try re-run if the new PIE displacement takes effect.
-     gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y"
--    reach "_dl_debug_state" "run" $displacement
-+    reach $solib_bp "run" $displacement
- 
-     if $ifmain {
- 	test_core $file $displacement
-@@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ
- 	gdb_test "exec-file $file" "exec-file $escapedfile" "load"
- 
- 	if $ifmain {
--	    reach "_dl_debug_state" run $displacement
-+	    reach $solib_bp run $displacement
- 
- 	    # Use two separate gdb_test_multiple statements to avoid timeouts due
- 	    # to slow processing of wildcard capturing long output
diff --git a/gdb-dlopen-stap-probe-test2.patch b/gdb-dlopen-stap-probe-test2.patch
new file mode 100644
index 0000000..9ca4f6b
--- /dev/null
+++ b/gdb-dlopen-stap-probe-test2.patch
@@ -0,0 +1,69 @@
+http://sourceware.org/ml/gdb-patches/2012-08/msg00500.html
+Subject: [patch] testsuite: Make solib-corrupted.exp untested for probes  [Re: [RFA 0/4 take 2] Improved linker-debugger interface]
+
+On Fri, 17 Aug 2012 22:53:53 +0200, Jan Kratochvil wrote:
+> It regresses with glibc-debuginfo installed:
+> 
+> info sharedlibrary^M
+> From                To                  Syms Read   Shared Object Library^M
+> 0x00007ffff7ddcb20  0x00007ffff7df63d9  Yes         /lib64/ld-linux-x86-64.so.2^M
+> 0x00007ffff7ae05b0  0x00007ffff7b4ad78  Yes         /lib64/libm.so.6^M
+> 0x00007ffff77431a0  0x00007ffff7883cf0  Yes         /lib64/libc.so.6^M
+> (gdb) FAIL: gdb.base/solib-corrupted.exp: corrupted list
+> 
+> But I guess there is no longer a way to test it with probes so it should just
+> run some 'info probes' and make this test UNTESTED if rtld probes are
+> available.
+
+I had to implement it for Fedora already anyway.
+
+
+Regards,
+Jan
+
+
+gdb/testsuite/
+2012-08-18  Jan Kratochvil  <jan.kratochvil at redhat.com>
+
+	* gdb.base/solib-corrupted.exp: New variable probes.
+	(info probes): New test.
+
+diff --git a/gdb/testsuite/gdb.base/solib-corrupted.exp b/gdb/testsuite/gdb.base/solib-corrupted.exp
+index 84b3b0c..c9f55d6 100644
+--- a/gdb/testsuite/gdb.base/solib-corrupted.exp
++++ b/gdb/testsuite/gdb.base/solib-corrupted.exp
+@@ -36,6 +36,33 @@ if ![runto_main] {
+     return
+ }
+ 
++# With probes interface GDB no longer scans the inferior library list so its
++# corruption cannot be tested.  There is no way to disable the probes
++# interface.
++
++set probes { init_start init_complete map_start reloc_complete unmap_start
++	     unmap_complete }
++set test "info probes"
++gdb_test_multiple $test $test {
++    -re "^rtld\[ \t\]+(?:rtld_)?(\[a-z_\]+)\[ \t\]" {
++	set idx [lsearch -exact $probes $expect_out(1,string)]
++	if { $idx >= 0 } {
++	    set probes [lreplace $probes $idx $idx]
++	}
++	exp_continue
++    }
++    -re "^\[^\r\n\]*\r\n" {
++	exp_continue
++    }
++    -re "^$gdb_prompt $" {
++    }
++}
++if { [llength $probes] == 0 } {
++    xfail $test
++    untested "GDB is using probes"
++    return
++}
++
+ gdb_test "info sharedlibrary" "From * To .*" "normal list"
+ 
+ # GDB checks there for matching L_PREV.
+
diff --git a/gdb.spec b/gdb.spec
index 73df70e..a915c38 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -27,20 +27,20 @@
 Summary: A GNU source-level debugger for C, C++, Fortran, Go and other languages
 Name: %{?scl_prefix}gdb
 
-%global snap       20120801
-# See tempstamp of source gnulib installed into gdb/gnulib/ .
+%global snap       20120817
+# See timestamp of source gnulib installed into gdb/gnulib/ .
 %global snapgnulib 20120623
-Version: 7.4.91.%{snap}
+Version: 7.5
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 18%{?dist}
+Release: 19%{?dist}
 
 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain
 Group: Development/Debuggers
 # Do not provide URL for snapshots as the file lasts there only for 2 days.
 # ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.bz2
-Source: gdb-%{version}.tar.bz2
+Source: ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.bz2
 Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 URL: http://gnu.org/software/gdb/
 
@@ -512,8 +512,15 @@ Patch579: gdb-7.2.50-sparc-add-workaround-to-broken-debug-files.patch
 
 # Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).
 #=push
-Patch618: gdb-dlopen-stap-probe.patch
+Patch618: gdb-dlopen-stap-probe-1of7.patch
+Patch717: gdb-dlopen-stap-probe-2of7.patch
+Patch718: gdb-dlopen-stap-probe-3of7.patch
+Patch719: gdb-dlopen-stap-probe-4of7.patch
+Patch720: gdb-dlopen-stap-probe-5of7.patch
+Patch721: gdb-dlopen-stap-probe-6of7.patch
+Patch722: gdb-dlopen-stap-probe-7of7.patch
 Patch619: gdb-dlopen-stap-probe-test.patch
+Patch723: gdb-dlopen-stap-probe-test2.patch
 
 # Work around PR libc/13097 "linux-vdso.so.1" warning message.
 #=push
@@ -848,6 +855,13 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c gdb/go-exp.c
 %patch548 -p1
 %patch579 -p1
 %patch618 -p1
+%patch717 -p1
+%patch718 -p1
+%patch719 -p1
+%patch720 -p1
+%patch721 -p1
+%patch722 -p1
+%patch723 -p1
 %patch619 -p1
 %patch627 -p1
 %patch634 -p1
@@ -1355,7 +1369,11 @@ fi
 %endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch"
 
 %changelog
-* Fri Aug 17 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.4.91.20120801-18
+* Sat Aug 18 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.5-19.fc18
+- Rebase to FSF GDB 7.5.
+- Update dlopen to support two variants of glibc (Gary Benson, BZ 669432).
+
+* Fri Aug 17 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.4.91.20120801-18.fc18
 - Drop Source URL for snapshots.
 - Separate %%{snapgnulib} from %%{snap}.
 - Fix %%{libstdcxxpython} to be %%{name}-prefixed.
@@ -1363,11 +1381,11 @@ fi
 - Include RHEL-5 compatible %%{buildroot} cleanup.
 - Use %%__global_ldflags.
 
-* Wed Aug  1 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.4.91.20120801-17
+* Wed Aug  1 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.4.91.20120801-17.fc18
 - Rebase to FSF GDB 7.4.91.20120801.
 - [dwz] Rebase it from FSF GDB HEAD.
 
-* Thu Jul 19 2012 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 7.4.50.20120714-16
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 7.4.50.20120714-16.fc18
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
 
 * Mon Jul 16 2012 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.4.50.20120714-15.fc18
diff --git a/sources b/sources
index 1e944af..45b960d 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
 4981307aa9619bbec5b73261e4e41c8d  gdb-libstdc++-v3-python-r155978.tar.bz2
-ed42ee95b7a114551094c84ee4192643  gdb-7.4.91.20120801.tar.bz2
+24a6779a9fe0260667710de1b082ef61  gdb-7.5.tar.bz2


More information about the scm-commits mailing list