Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Gary Benson <gbenson@redhat.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tromey@redhat.com>,
	Jan Kratochvil <jan.kratochvil@redhat.com>,
	Pedro Alves <palves@redhat.com>
Subject: [commit] Improved linker-debugger interface
Date: Tue, 04 Jun 2013 13:38:00 -0000	[thread overview]
Message-ID: <20130604133819.GA25892@blade.nx> (raw)
In-Reply-To: <20130516144340.GA2105@blade.nx>

[-- Attachment #1: Type: text/plain, Size: 500 bytes --]

Hi all,

I just committed the improved linker-debugger interface patch series
as attached.  For those of you using the patches in distributions,
some of the attached files have different filenames than previously
posted:

 a) what was rtld-probes-3-gdbserver.patch was split into
    rtld-probes-3.1-gdbserver.patch and rtld-probes-3.3-news.patch.

 b) rtld-probes-8-docs.patch is attached here as
    rtld-probes-3.2-docs.patch.

Thank you everyone who reviewed this.

Gary

-- 
http://gbenson.net/

[-- Attachment #2: rtld-probes-1-convenience.patch --]
[-- Type: text/plain, Size: 3463 bytes --]

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.15680
diff -u -r1.15680 ChangeLog
--- gdb/ChangeLog	4 Jun 2013 02:44:34 -0000	1.15680
+++ gdb/ChangeLog	4 Jun 2013 12:49:04 -0000
@@ -1,3 +1,11 @@
+2013-06-04  Gary Benson  <gbenson@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.
+
 2013-06-04  Alan Modra  <amodra@gmail.com>
 
 	* ppc-tdep.h (ppc_insns_match_pattern): Update prototype.
Index: gdb/probe.h
===================================================================
RCS file: /cvs/src/src/gdb/probe.h,v
retrieving revision 1.4
diff -u -r1.4 probe.h
--- gdb/probe.h	1 Jan 2013 06:32:49 -0000	1.4
+++ gdb/probe.h	4 Jun 2013 12:49:06 -0000
@@ -214,6 +214,16 @@
 
 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,
Index: gdb/probe.c
===================================================================
RCS file: /cvs/src/src/gdb/probe.c,v
retrieving revision 1.8
diff -u -r1.8 probe.c
--- gdb/probe.c	30 May 2013 17:39:34 -0000	1.8
+++ gdb/probe.c	4 Jun 2013 12:49:06 -0000
@@ -611,28 +611,55 @@
 
 /* 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.  */

[-- Attachment #3: rtld-probes-2-inhibit-sm-updates.patch --]
[-- Type: text/plain, Size: 6403 bytes --]

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.15681
diff -u -r1.15681 ChangeLog
--- gdb/ChangeLog	4 Jun 2013 12:50:20 -0000	1.15681
+++ gdb/ChangeLog	4 Jun 2013 12:51:30 -0000
@@ -1,3 +1,22 @@
+2013-06-04  Gary Benson  <gbenson@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): Removed field
+	"objfiles_changed_p".  New fields "new_objfiles_available",
+	"section_map_dirty" and "inhibit_updates".
+	(allocate_objfile): Set new_objfiles_available.
+	(free_objfile): Set section_map_dirty.
+	(objfile_relocate1): Likewise.
+	(in_plt_section): Likewise.
+	(find_pc_section): Update the conditions under which the
+	section map will be updated.
+	(inhibit_section_map_updates): New function.
+	(resume_section_map_updates): Likewise.
+	(resume_section_map_updates_cleanup): Likewise.
+
 2013-06-04  Gary Benson  <gbenson@redhat.com>
 
 	* probe.h (get_probe_argument_count): New declaration.
Index: gdb/objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.106
diff -u -r1.106 objfiles.h
--- gdb/objfiles.h	6 May 2013 19:15:17 -0000	1.106
+++ gdb/objfiles.h	4 Jun 2013 12:51:32 -0000
@@ -501,6 +501,22 @@
    modules.  */
 DECLARE_REGISTRY(objfile);
 
+/* 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 (struct program_space *pspace);
+
+/* Resume automatically rebuilding the section map as required.  */
+extern void resume_section_map_updates (struct program_space *pspace);
+
+/* 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/objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.160
diff -u -r1.160 objfiles.c
--- gdb/objfiles.c	6 May 2013 19:15:17 -0000	1.160
+++ gdb/objfiles.c	4 Jun 2013 12:51:32 -0000
@@ -67,9 +67,18 @@
 
 struct objfile_pspace_info
 {
-  int objfiles_changed_p;
   struct obj_section **sections;
   int num_sections;
+
+  /* Nonzero if object files have been added since the section map
+     was last updated.  */
+  int new_objfiles_available;
+
+  /* Nonzero if the section map MUST be updated before use.  */
+  int section_map_dirty;
+
+  /* Nonzero if section map updates should be inhibited if possible.  */
+  int inhibit_updates;
 };
 
 /* Per-program-space data key.  */
@@ -317,7 +326,7 @@
   objfile->flags |= flags;
 
   /* Rebuild section map next time we need it.  */
-  get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
+  get_objfile_pspace_data (objfile->pspace)->new_objfiles_available = 1;
 
   return objfile;
 }
@@ -646,7 +655,7 @@
   obstack_free (&objfile->objfile_obstack, 0);
 
   /* Rebuild section map next time we need it.  */
-  get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
+  get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1;
 
   xfree (objfile);
 }
@@ -826,7 +835,7 @@
   }
 
   /* Rebuild section map next time we need it.  */
-  get_objfile_pspace_data (objfile->pspace)->objfiles_changed_p = 1;
+  get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1;
 
   /* Update the table in exec_ops, used to read memory.  */
   ALL_OBJFILE_OSECTIONS (objfile, s)
@@ -1291,11 +1300,14 @@
 update_section_map (struct program_space *pspace,
 		    struct obj_section ***pmap, int *pmap_size)
 {
+  struct objfile_pspace_info *pspace_info;
   int alloc_size, map_size, i;
   struct obj_section *s, **map;
   struct objfile *objfile;
 
-  gdb_assert (get_objfile_pspace_data (pspace)->objfiles_changed_p != 0);
+  pspace_info = get_objfile_pspace_data (pspace);
+  gdb_assert (pspace_info->section_map_dirty != 0
+	      || pspace_info->new_objfiles_available != 0);
 
   map = *pmap;
   xfree (map);
@@ -1365,7 +1377,9 @@
     return s;
 
   pspace_info = get_objfile_pspace_data (current_program_space);
-  if (pspace_info->objfiles_changed_p != 0)
+  if (pspace_info->section_map_dirty
+      || (pspace_info->new_objfiles_available
+	  && !pspace_info->inhibit_updates))
     {
       update_section_map (current_program_space,
 			  &pspace_info->sections,
@@ -1373,7 +1387,8 @@
 
       /* Don't need updates to section map until objfiles are added,
          removed or relocated.  */
-      pspace_info->objfiles_changed_p = 0;
+      pspace_info->new_objfiles_available = 0;
+      pspace_info->section_map_dirty = 0;
     }
 
   /* The C standard (ISO/IEC 9899:TC2) requires the BASE argument to
@@ -1414,14 +1429,38 @@
 }
 \f
 
-/* Set objfiles_changed_p so section map will be rebuilt next time it
+/* Set section_map_dirty so section map will be rebuilt next time it
    is used.  Called by reread_symbols.  */
 
 void
 objfiles_changed (void)
 {
   /* Rebuild section map next time we need it.  */
-  get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
+  get_objfile_pspace_data (current_program_space)->section_map_dirty = 1;
+}
+
+/* See comments in objfiles.h.  */
+
+void
+inhibit_section_map_updates (struct program_space *pspace)
+{
+  get_objfile_pspace_data (pspace)->inhibit_updates = 1;
+}
+
+/* See comments in objfiles.h.  */
+
+void
+resume_section_map_updates (struct program_space *pspace)
+{
+  get_objfile_pspace_data (pspace)->inhibit_updates = 0;
+}
+
+/* See comments in objfiles.h.  */
+
+void
+resume_section_map_updates_cleanup (void *arg)
+{
+  resume_section_map_updates (arg);
 }
 
 /* The default implementation for the "iterate_over_objfiles_in_search_order"

[-- Attachment #4: rtld-probes-3.1-gdbserver.patch --]
[-- Type: text/plain, Size: 9682 bytes --]

Index: gdb/gdbserver/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/ChangeLog,v
retrieving revision 1.720
diff -u -r1.720 ChangeLog
--- gdb/gdbserver/ChangeLog	31 May 2013 19:14:33 -0000	1.720
+++ gdb/gdbserver/ChangeLog	4 Jun 2013 12:58:04 -0000
@@ -1,3 +1,12 @@
+2013-06-04  Gary Benson  <gbenson@redhat.com>
+
+	* server.c (handle_query): Add "augmented-libraries-svr4-read+"
+	to qSupported response when appropriate.
+	(handle_qxfer_libraries_svr4): Allow qXfer:libraries-svr4:read
+	with nonzero-length annex.
+	* linux-low.c (linux_qxfer_libraries_svr4): Parse and handle
+	arguments supplied in annex.
+
 2013-05-31  Doug Evans  <dje@google.com>
 
 	* linux-x86-low.c (ps_get_thread_area): Properly extend address to
Index: gdb/gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.191
diff -u -r1.191 server.c
--- gdb/gdbserver/server.c	24 May 2013 11:28:06 -0000	1.191
+++ gdb/gdbserver/server.c	4 Jun 2013 12:58:08 -0000
@@ -1115,8 +1115,7 @@
   if (writebuf != NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running ()
-      || the_target->qxfer_libraries_svr4 == NULL)
+  if (!target_running () || the_target->qxfer_libraries_svr4 == NULL)
     return -1;
 
   return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, offset, len);
@@ -1743,7 +1742,8 @@
 	       PBUFSIZ - 1);
 
       if (the_target->qxfer_libraries_svr4 != NULL)
-	strcat (own_buf, ";qXfer:libraries-svr4:read+");
+	strcat (own_buf, ";qXfer:libraries-svr4:read+"
+		";augmented-libraries-svr4-read+");
       else
 	{
 	  /* We do not have any hook to indicate whether the non-SVR4 target
Index: gdb/gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.237
diff -u -r1.237 linux-low.c
--- gdb/gdbserver/linux-low.c	23 May 2013 17:17:50 -0000	1.237
+++ gdb/gdbserver/linux-low.c	4 Jun 2013 12:58:06 -0000
@@ -5728,6 +5728,12 @@
     };
   const struct link_map_offsets *lmo;
   unsigned int machine;
+  int ptr_size;
+  CORE_ADDR lm_addr = 0, lm_prev = 0;
+  int allocated = 1024;
+  char *p;
+  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
+  int header_done = 0;
 
   if (writebuf != NULL)
     return -2;
@@ -5738,128 +5744,144 @@
   xsnprintf (filename, sizeof filename, "/proc/%d/exe", pid);
   is_elf64 = elf_64_file_p (filename, &machine);
   lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
+  ptr_size = is_elf64 ? 8 : 4;
 
-  if (priv->r_debug == 0)
-    priv->r_debug = get_r_debug (pid, is_elf64);
-
-  /* We failed to find DT_DEBUG.  Such situation will not change for this
-     inferior - do not retry it.  Report it to GDB as E01, see for the reasons
-     at the GDB solib-svr4.c side.  */
-  if (priv->r_debug == (CORE_ADDR) -1)
-    return -1;
-
-  if (priv->r_debug == 0)
+  while (annex[0] != '\0')
     {
-      document = xstrdup ("<library-list-svr4 version=\"1.0\"/>\n");
+      const char *sep;
+      CORE_ADDR *addrp;
+      int len;
+
+      sep = strchr (annex, '=');
+      if (sep == NULL)
+	break;
+
+      len = sep - annex;
+      if (len == 5 && strncmp (annex, "start", 5) == 0)
+	addrp = &lm_addr;
+      else if (len == 4 && strncmp (annex, "prev", 4) == 0)
+	addrp = &lm_prev;
+      else
+	{
+	  annex = strchr (sep, ';');
+	  if (annex == NULL)
+	    break;
+	  annex++;
+	  continue;
+	}
+
+      annex = decode_address_to_semicolon (addrp, sep + 1);
     }
-  else
+
+  if (lm_addr == 0)
     {
-      int allocated = 1024;
-      char *p;
-      const int ptr_size = is_elf64 ? 8 : 4;
-      CORE_ADDR lm_addr, lm_prev, l_name, l_addr, l_ld, l_next, l_prev;
-      int r_version, header_done = 0;
-
-      document = xmalloc (allocated);
-      strcpy (document, "<library-list-svr4 version=\"1.0\"");
-      p = document + strlen (document);
-
-      r_version = 0;
-      if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
-			     (unsigned char *) &r_version,
-			     sizeof (r_version)) != 0
-	  || r_version != 1)
+      int r_version = 0;
+
+      if (priv->r_debug == 0)
+	priv->r_debug = get_r_debug (pid, is_elf64);
+
+      /* We failed to find DT_DEBUG.  Such situation will not change
+	 for this inferior - do not retry it.  Report it to GDB as
+	 E01, see for the reasons at the GDB solib-svr4.c side.  */
+      if (priv->r_debug == (CORE_ADDR) -1)
+	return -1;
+
+      if (priv->r_debug != 0)
 	{
-	  warning ("unexpected r_debug version %d", r_version);
-	  goto done;
+	  if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
+				 (unsigned char *) &r_version,
+				 sizeof (r_version)) != 0
+	      || r_version != 1)
+	    {
+	      warning ("unexpected r_debug version %d", r_version);
+	    }
+	  else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
+				 &lm_addr, ptr_size) != 0)
+	    {
+	      warning ("unable to read r_map from 0x%lx",
+		       (long) priv->r_debug + lmo->r_map_offset);
+	    }
 	}
+    }
+
+  document = xmalloc (allocated);
+  strcpy (document, "<library-list-svr4 version=\"1.0\"");
+  p = document + strlen (document);
+
+  while (lm_addr
+	 && read_one_ptr (lm_addr + lmo->l_name_offset,
+			  &l_name, ptr_size) == 0
+	 && read_one_ptr (lm_addr + lmo->l_addr_offset,
+			  &l_addr, ptr_size) == 0
+	 && read_one_ptr (lm_addr + lmo->l_ld_offset,
+			  &l_ld, ptr_size) == 0
+	 && read_one_ptr (lm_addr + lmo->l_prev_offset,
+			  &l_prev, ptr_size) == 0
+	 && read_one_ptr (lm_addr + lmo->l_next_offset,
+			  &l_next, ptr_size) == 0)
+    {
+      unsigned char libname[PATH_MAX];
 
-      if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
-			&lm_addr, ptr_size) != 0)
+      if (lm_prev != l_prev)
 	{
-	  warning ("unable to read r_map from 0x%lx",
-		   (long) priv->r_debug + lmo->r_map_offset);
-	  goto done;
+	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
+		   (long) lm_prev, (long) l_prev);
+	  break;
 	}
 
-      lm_prev = 0;
-      while (read_one_ptr (lm_addr + lmo->l_name_offset,
-			   &l_name, ptr_size) == 0
-	     && read_one_ptr (lm_addr + lmo->l_addr_offset,
-			      &l_addr, ptr_size) == 0
-	     && read_one_ptr (lm_addr + lmo->l_ld_offset,
-			      &l_ld, ptr_size) == 0
-	     && read_one_ptr (lm_addr + lmo->l_prev_offset,
-			      &l_prev, ptr_size) == 0
-	     && read_one_ptr (lm_addr + lmo->l_next_offset,
-			      &l_next, ptr_size) == 0)
+      /* Not checking for error because reading may stop before
+	 we've got PATH_MAX worth of characters.  */
+      libname[0] = '\0';
+      linux_read_memory (l_name, libname, sizeof (libname) - 1);
+      libname[sizeof (libname) - 1] = '\0';
+      if (libname[0] != '\0')
 	{
-	  unsigned char libname[PATH_MAX];
+	  /* 6x the size for xml_escape_text below.  */
+	  size_t len = 6 * strlen ((char *) libname);
+	  char *name;
 
-	  if (lm_prev != l_prev)
+	  if (!header_done)
 	    {
-	      warning ("Corrupted shared library list: 0x%lx != 0x%lx",
-		       (long) lm_prev, (long) l_prev);
-	      break;
+	      /* Terminate `<library-list-svr4'.  */
+	      *p++ = '>';
+	      header_done = 1;
 	    }
 
-	  /* Not checking for error because reading may stop before
-	     we've got PATH_MAX worth of characters.  */
-	  libname[0] = '\0';
-	  linux_read_memory (l_name, libname, sizeof (libname) - 1);
-	  libname[sizeof (libname) - 1] = '\0';
-	  if (libname[0] != '\0')
+	  while (allocated < p - document + len + 200)
 	    {
-	      /* 6x the size for xml_escape_text below.  */
-	      size_t len = 6 * strlen ((char *) libname);
-	      char *name;
-
-	      if (!header_done)
-		{
-		  /* Terminate `<library-list-svr4'.  */
-		  *p++ = '>';
-		  header_done = 1;
-		}
-
-	      while (allocated < p - document + len + 200)
-		{
-		  /* Expand to guarantee sufficient storage.  */
-		  uintptr_t document_len = p - document;
-
-		  document = xrealloc (document, 2 * allocated);
-		  allocated *= 2;
-		  p = document + document_len;
-		}
-
-	      name = xml_escape_text ((char *) libname);
-	      p += sprintf (p, "<library name=\"%s\" lm=\"0x%lx\" "
-			       "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
-			    name, (unsigned long) lm_addr,
-			    (unsigned long) l_addr, (unsigned long) l_ld);
-	      free (name);
-	    }
-	  else if (lm_prev == 0)
-	    {
-	      sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr);
-	      p = p + strlen (p);
-	    }
+	      /* Expand to guarantee sufficient storage.  */
+	      uintptr_t document_len = p - document;
 
-	  if (l_next == 0)
-	    break;
+	      document = xrealloc (document, 2 * allocated);
+	      allocated *= 2;
+	      p = document + document_len;
+	    }
 
-	  lm_prev = lm_addr;
-	  lm_addr = l_next;
+	  name = xml_escape_text ((char *) libname);
+	  p += sprintf (p, "<library name=\"%s\" lm=\"0x%lx\" "
+			"l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
+			name, (unsigned long) lm_addr,
+			(unsigned long) l_addr, (unsigned long) l_ld);
+	  free (name);
 	}
-    done:
-      if (!header_done)
+      else if (lm_prev == 0)
 	{
-	  /* Empty list; terminate `<library-list-svr4'.  */
-	  strcpy (p, "/>");
+	  sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr);
+	  p = p + strlen (p);
 	}
-      else
-	strcpy (p, "</library-list-svr4>");
+
+      lm_prev = lm_addr;
+      lm_addr = l_next;
     }
 
+  if (!header_done)
+    {
+      /* Empty list; terminate `<library-list-svr4'.  */
+      strcpy (p, "/>");
+    }
+  else
+    strcpy (p, "</library-list-svr4>");
+
   document_len = strlen (document);
   if (offset < document_len)
     document_len -= offset;

[-- Attachment #5: rtld-probes-3.2-docs.patch --]
[-- Type: text/plain, Size: 3780 bytes --]

Index: gdb/doc/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/doc/ChangeLog,v
retrieving revision 1.1463
diff -u -r1.1463 ChangeLog
--- gdb/doc/ChangeLog	24 May 2013 04:50:26 -0000	1.1463
+++ gdb/doc/ChangeLog	4 Jun 2013 13:05:24 -0000
@@ -1,3 +1,12 @@
+2013-06-04 Gary Benson  <gbenson@redhat.com>
+
+	* gdb.texinfo (General Query Packets/qSupported): Added
+	"qXfer:libraries-svr4:read" and "augmented-libraries-svr4-read".
+	to the table of currently defined stub features.
+	Added a more detailed entry for "augmented-libraries-svr4-read".
+	(General Query Packets/qXfer:libraries-svr4:read): Documented
+	the augmented form of this packet.
+
 2013-05-23  Joel Brobecker  <brobecker@adacore.com>
 
 	* gdb.texinfo (System-wide Configuration Scripts): Renames
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.1093
diff -u -r1.1093 gdb.texinfo
--- gdb/doc/gdb.texinfo	24 May 2013 04:50:26 -0000	1.1093
+++ gdb/doc/gdb.texinfo	4 Jun 2013 13:05:58 -0000
@@ -38594,6 +38594,16 @@
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:libraries-svr4:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
+@item @samp{augmented-libraries-svr4-read}
+@tab No
+@tab @samp{-}
+@tab No
+
 @item @samp{qXfer:memory-map:read}
 @tab No
 @tab @samp{-}
@@ -38770,6 +38780,11 @@
 The remote stub understands the @samp{qXfer:libraries-svr4:read} packet
 (@pxref{qXfer svr4 library list read}).
 
+@item augmented-libraries-svr4-read
+The remote stub understands the augmented form of the
+@samp{qXfer:libraries-svr4:read} packet
+(@pxref{qXfer svr4 library list read}).
+
 @item qXfer:memory-map:read
 The remote stub understands the @samp{qXfer:memory-map:read} packet
 (@pxref{qXfer memory map read}).
@@ -39065,7 +39080,10 @@
 @anchor{qXfer svr4 library list read}
 Access the target's list of loaded libraries when the target is an SVR4
 platform.  @xref{Library List Format for SVR4 Targets}.  The annex part
-of the generic @samp{qXfer} packet must be empty (@pxref{qXfer read}).
+of the generic @samp{qXfer} packet must be empty unless the remote
+stub indicated it supports the augmented form of this packet
+by supplying an appropriate @samp{qSupported} response
+(@pxref{qXfer read}, @ref{qSupported}).
 
 This packet is optional for better performance on SVR4 targets.  
 @value{GDBN} uses memory read packets to read the SVR4 library list otherwise.
@@ -39073,6 +39091,30 @@
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+If the remote stub indicates it supports the augmented form of this
+packet then the annex part of the generic @samp{qXfer} packet may
+contain a semicolon-separated list of @samp{@var{name}=@var{value}}
+arguments.  The currently supported arguments are:
+
+@table @code
+@item start=@var{address}
+A hexadecimal number specifying the address of the @samp{struct
+link_map} to start reading the library list from.  If unset or zero
+then the first @samp{struct link_map} in the library list will be
+chosen as the starting point.
+
+@item prev=@var{address}
+A hexadecimal number specifying the address of the @samp{struct
+link_map} immediately preceding the @samp{struct link_map}
+specified by the @samp{start} argument.  If unset or zero then
+the remote stub will expect that no @samp{struct link_map}
+exists prior to the starting point.
+
+@end table
+
+Arguments that are not understood by the remote stub will be silently
+ignored.
+
 @item qXfer:memory-map:read::@var{offset},@var{length}
 @anchor{qXfer memory map read}
 Access the target's @dfn{memory-map}.  @xref{Memory Map Format}.  The

[-- Attachment #6: rtld-probes-3.3-news.patch --]
[-- Type: text/plain, Size: 1359 bytes --]

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.15682
diff -u -r1.15682 ChangeLog
--- gdb/ChangeLog	4 Jun 2013 12:53:33 -0000	1.15682
+++ gdb/ChangeLog	4 Jun 2013 13:00:08 -0000
@@ -1,3 +1,7 @@
+2013-06-04  Gary Benson  <gbenson@redhat.com>
+
+	* NEWS: Update.
+
 2013-06-04  Gary Benson  <gbenson@redhat.com>
 
 	* objfiles.h (inhibit_section_map_updates): New function
Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.600
diff -u -r1.600 NEWS
--- gdb/NEWS	23 May 2013 17:17:50 -0000	1.600
+++ gdb/NEWS	4 Jun 2013 13:00:12 -0000
@@ -95,6 +95,14 @@
   stub to step through an address range itself, without GDB
   involvemement at each single-step.
 
+qXfer:libraries-svr4:read's annex
+  The previously unused annex of the qXfer:libraries-svr4:read packet
+  is now used to support passing an argument list.  The remote stub
+  reports support for this argument list to GDB's qSupported query.
+  The defined arguments are "start" and "prev", used to reduce work
+  necessary for library list updating, resulting in significant
+  speedup.
+
 * New features in the GDB remote stub, GDBserver
 
   ** GDBserver now supports target-assisted range stepping.  Currently

[-- Attachment #7: rtld-probes-4-remote.patch --]
[-- Type: text/plain, Size: 5060 bytes --]

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.15683
diff -u -r1.15683 ChangeLog
--- gdb/ChangeLog	4 Jun 2013 13:02:15 -0000	1.15683
+++ gdb/ChangeLog	4 Jun 2013 13:08:43 -0000
@@ -1,3 +1,19 @@
+2013-06-04  Gary Benson  <gbenson@redhat.com>
+
+	* target.h (target_ops): New field
+	"to_augmented_libraries_svr4_read".
+	(target_augmented_libraries_svr4_read): New macro.
+	* target.c (update_current_target): Handle
+	to_augmented_libraries_svr4_read.
+	* remote.c (remote_state): New field
+	"augmented_libraries_svr4_read".
+	(remote_augmented_libraries_svr4_read_feature): New function.
+	(remote_protocol_features): Add entry for
+	"augmented-libraries-svr4-read".
+	(remote_augmented_libraries_svr4_read): New function.
+	(init_remote_ops): Initialize
+	remote_ops.to_augmented_libraries_svr4_read.
+
 2013-06-04  Gary Benson  <gbenson@redhat.com>
 
 	* NEWS: Update.
Index: gdb/target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.262
diff -u -r1.262 target.h
--- gdb/target.h	14 May 2013 20:33:36 -0000	1.262
+++ gdb/target.h	4 Jun 2013 13:08:55 -0000
@@ -941,6 +941,10 @@
        (inclusive) to function END (exclusive).  */
     void (*to_call_history_range) (ULONGEST begin, ULONGEST end, int flags);
 
+    /* Nonzero if TARGET_OBJECT_LIBRARIES_SVR4 may be read with a
+       non-empty annex.  */
+    int (*to_augmented_libraries_svr4_read) (void);
+
     int to_magic;
     /* Need sub-structure for target machine related rather than comm related?
      */
@@ -1809,6 +1813,9 @@
 #define target_can_use_agent() \
   (*current_target.to_can_use_agent) ()
 
+#define target_augmented_libraries_svr4_read() \
+  (*current_target.to_augmented_libraries_svr4_read) ()
+
 /* Command logging facility.  */
 
 #define target_log_command(p)						\
Index: gdb/target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.335
diff -u -r1.335 target.c
--- gdb/target.c	14 May 2013 20:33:36 -0000	1.335
+++ gdb/target.c	4 Jun 2013 13:08:54 -0000
@@ -731,6 +731,7 @@
       INHERIT (to_traceframe_info, t);
       INHERIT (to_use_agent, t);
       INHERIT (to_can_use_agent, t);
+      INHERIT (to_augmented_libraries_svr4_read, t);
       INHERIT (to_magic, t);
       INHERIT (to_supports_evaluation_of_breakpoint_conditions, t);
       INHERIT (to_can_run_breakpoint_commands, t);
@@ -975,6 +976,9 @@
   de_fault (to_can_use_agent,
 	    (int (*) (void))
 	    return_zero);
+  de_fault (to_augmented_libraries_svr4_read,
+	    (int (*) (void))
+	    return_zero);
   de_fault (to_execution_direction, default_execution_direction);
 
 #undef de_fault
Index: gdb/remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.552
diff -u -r1.552 remote.c
--- gdb/remote.c	30 May 2013 09:29:18 -0000	1.552
+++ gdb/remote.c	4 Jun 2013 13:08:50 -0000
@@ -361,6 +361,10 @@
   /* True if the stub can collect strings using tracenz bytecode.  */
   int string_tracing;
 
+  /* True if the stub supports qXfer:libraries-svr4:read with a
+     non-empty annex.  */
+  int augmented_libraries_svr4_read;
+
   /* Nonzero if the user has pressed Ctrl-C, but the target hasn't
      responded to that.  */
   int ctrlc_pending_p;
@@ -3949,6 +3953,16 @@
   rs->string_tracing = (support == PACKET_ENABLE);
 }
 
+static void
+remote_augmented_libraries_svr4_read_feature
+  (const struct protocol_feature *feature,
+   enum packet_support support, const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
+}
+
 static struct protocol_feature remote_protocol_features[] = {
   { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3959,6 +3973,8 @@
     PACKET_qXfer_libraries },
   { "qXfer:libraries-svr4:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_libraries_svr4 },
+  { "augmented-libraries-svr4-read", PACKET_DISABLE,
+    remote_augmented_libraries_svr4_read_feature, -1 },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_memory_map },
   { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
@@ -11439,6 +11455,14 @@
   return btrace;
 }
 
+static int
+remote_augmented_libraries_svr4_read (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return rs->augmented_libraries_svr4_read;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -11561,6 +11585,8 @@
   remote_ops.to_disable_btrace = remote_disable_btrace;
   remote_ops.to_teardown_btrace = remote_teardown_btrace;
   remote_ops.to_read_btrace = remote_read_btrace;
+  remote_ops.to_augmented_libraries_svr4_read =
+    remote_augmented_libraries_svr4_read;
 }
 
 /* Set up the extended remote vector by making a copy of the standard

[-- Attachment #8: rtld-probes-5-main-changes.patch --]
[-- Type: text/plain, Size: 33655 bytes --]

Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.15684
diff -u -r1.15684 ChangeLog
--- gdb/ChangeLog	4 Jun 2013 13:10:53 -0000	1.15684
+++ gdb/ChangeLog	4 Jun 2013 13:14:01 -0000
@@ -1,3 +1,56 @@
+2013-06-04  Gary Benson  <gbenson@redhat.com>
+
+	* breakpoint.h (handle_solib_event): Moved function declaration
+	to solib.h.
+	* breakpoint.c (handle_solib_event): Moved function to solib.c.
+	(bpstat_stop_status): Pass new argument to handle_solib_event.
+	* solib.h (update_solib_breakpoints): New function declaration.
+	(handle_solib_event): Moved function declaration from
+	breakpoint.h.
+	* solib.c (update_solib_breakpoints): New function.
+	(handle_solib_event): Moved function from breakpoint.c.
+	Updated to call solib_ops->handle_event if not NULL.
+	* solist.h (target_so_ops): New fields "update_breakpoints" and
+	"handle_event".
+	* 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.
+	(svr4_free_library_list): New forward declaration.
+	(probe_action): New enum.
+	(probe_info): New struct.
+	(probe_info): New static variable.
+	(NUM_PROBES): New definition.
+	(svr4_info): New fields "using_xfer", "probes_table" and
+	"solib_list".
+	(free_probes_table): New function.
+	(free_solib_list): New function.
+	(svr4_pspace_data_cleanup): Free probes table and solib list.
+	(svr4_copy_library_list): New function.
+	(svr4_current_sos_via_xfer_libraries): New parameter "annex".
+	(svr4_read_so_list): New parameter "prev_lm".
+	(svr4_current_sos_direct): Renamed from "svr4_current_sos".
+	(svr4_current_sos): New function.
+	(probe_and_action): New struct.
+	(hash_probe_and_action): New function.
+	(equal_probe_and_action): Likewise.
+	(register_solib_event_probe): Likewise.
+	(solib_event_probe_at): Likewise.
+	(solib_event_probe_action): Likewise.
+	(solist_update_full): Likewise.
+	(solist_update_incremental): Likewise.
+	(disable_probes_interface_cleanup): Likewise.
+	(svr4_handle_solib_event): Likewise.
+	(svr4_update_solib_event_breakpoint): Likewise.
+	(svr4_update_solib_event_breakpoints): Likewise.
+	(svr4_create_solib_event_breakpoints): Likewise.
+	(enable_break): Free probes table before creating breakpoints.
+	Use svr4_create_solib_event_breakpoints to create breakpoints.
+	(svr4_solib_create_inferior_hook): Free the solib list.
+	(_initialize_svr4_solib): Initialise
+	svr4_so_ops.handle_solib_event and svr4_so_ops.update_breakpoints.
+
 2013-06-04  Gary Benson  <gbenson@redhat.com>
 
 	* target.h (target_ops): New field
Index: gdb/breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.197
diff -u -r1.197 breakpoint.h
--- gdb/breakpoint.h	21 May 2013 04:18:54 -0000	1.197
+++ gdb/breakpoint.h	4 Jun 2013 13:14:13 -0000
@@ -1554,8 +1554,6 @@
 /* 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 breakpoint_free_objfile (struct objfile *objfile);
 
 extern char *ep_parse_optional_if_clause (char **arg);
Index: gdb/breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.764
diff -u -r1.764 breakpoint.c
--- gdb/breakpoint.c	30 May 2013 17:09:02 -0000	1.764
+++ gdb/breakpoint.c	4 Jun 2013 13:14:12 -0000
@@ -5352,21 +5352,6 @@
   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 ();
-  solib_add (NULL, 0, &current_target, auto_solib_add);
-  target_terminal_inferior ();
-}
-
 /* Prepare WHAT final decision for infrun.  */
 
 /* Decide what infrun needs to do with this bpstat.  */
Index: gdb/solib.h
===================================================================
RCS file: /cvs/src/src/gdb/solib.h,v
retrieving revision 1.35
diff -u -r1.35 solib.h
--- gdb/solib.h	21 May 2013 08:16:10 -0000	1.35
+++ gdb/solib.h	4 Jun 2013 13:14:22 -0000
@@ -90,4 +90,12 @@
 								      void *),
 						    void *data);
 
+/* Enable or disable optional solib event breakpoints as appropriate.  */
+
+extern void update_solib_breakpoints (void);
+
+/* Handle an solib event by calling solib_add.  */
+
+extern void handle_solib_event (void);
+
 #endif /* SOLIB_H */
Index: gdb/solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.175
diff -u -r1.175 solib.c
--- gdb/solib.c	4 Jun 2013 01:33:31 -0000	1.175
+++ gdb/solib.c	4 Jun 2013 13:14:22 -0000
@@ -1209,6 +1209,37 @@
   objfile_purge_solibs ();
 }
 
+/* See solib.h.  */
+
+void
+update_solib_breakpoints (void)
+{
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
+
+  if (ops->update_breakpoints != NULL)
+    ops->update_breakpoints ();
+}
+
+/* See solib.h.  */
+
+void
+handle_solib_event (void)
+{
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
+
+  if (ops->handle_event != NULL)
+    ops->handle_event ();
+
+  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 ();
+  solib_add (NULL, 0, &current_target, auto_solib_add);
+  target_terminal_inferior ();
+}
+
 /* Reload shared libraries, but avoid reloading the same symbol file
    we already have loaded.  */
 
Index: gdb/solist.h
===================================================================
RCS file: /cvs/src/src/gdb/solist.h,v
retrieving revision 1.39
diff -u -r1.39 solist.h
--- gdb/solist.h	6 May 2013 22:18:38 -0000	1.39
+++ gdb/solist.h	4 Jun 2013 13:14:22 -0000
@@ -153,6 +153,19 @@
        core file (in particular, for readonly sections).  */
     int (*keep_data_in_core) (CORE_ADDR vaddr,
 			      unsigned long size);
+
+    /* 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);
+
+    /* Target-specific processing of solib events that will be
+       performed before solib_add is called.  This pointer can be
+       NULL, in which case no specific preprocessing is necessary
+       for this target.  */
+    void (*handle_event) (void);
   };
 
 /* Free the memory associated with a (so_list *).  */
Index: gdb/infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.582
diff -u -r1.582 infrun.c
--- gdb/infrun.c	30 May 2013 17:37:50 -0000	1.582
+++ gdb/infrun.c	4 Jun 2013 13:14:18 -0000
@@ -370,6 +370,16 @@
 /* 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)
@@ -7333,7 +7343,7 @@
 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/solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.178
diff -u -r1.178 solib-svr4.c
--- gdb/solib-svr4.c	21 May 2013 23:41:29 -0000	1.178
+++ gdb/solib-svr4.c	4 Jun 2013 13:14:20 -0000
@@ -46,10 +46,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 void svr4_free_library_list (void *p_list);
 
 /* Link map info to include in an allocated so_list entry.  */
 
@@ -106,6 +108,55 @@
   NULL
 };
 
+/* What to do when a probe stop occurs.  */
+
+enum probe_action
+{
+  /* Something went seriously wrong.  Stop using probes and
+     revert to using the older interface.  */
+  PROBES_INTERFACE_FAILED,
+
+  /* No action is required.  The shared object list is still
+     valid.  */
+  DO_NOTHING,
+
+  /* The shared object list should be reloaded entirely.  */
+  FULL_RELOAD,
+
+  /* Attempt to incrementally update the shared object list. If
+     the update fails or is not possible, fall back to reloading
+     the list in full.  */
+  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 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", DO_NOTHING },
+  { "init_complete", FULL_RELOAD },
+  { "map_start", DO_NOTHING },
+  { "map_failed", DO_NOTHING },
+  { "reloc_complete", UPDATE_OR_RELOAD },
+  { "unmap_start", DO_NOTHING },
+  { "unmap_complete", FULL_RELOAD },
+};
+
+#define NUM_PROBES ARRAY_SIZE (probe_info)
+
 /* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent
    the same shared library.  */
 
@@ -313,17 +364,58 @@
   CORE_ADDR interp_text_sect_high;
   CORE_ADDR interp_plt_sect_low;
   CORE_ADDR interp_plt_sect_high;
+
+  /* Nonzero if the list of objects was last obtained from the target
+     via qXfer:libraries-svr4:read.  */
+  int using_xfer;
+
+  /* Table of struct probe_and_action instances, used by the
+     probes-based interface to map breakpoint addresses to probes
+     and their associated actions.  Lookup is performed using
+     probe_and_action->probe->address.  */
+  htab_t probes_table;
+
+  /* List of objects loaded into the inferior, used by the probes-
+     based interface.  */
+  struct so_list *solib_list;
 };
 
 /* Per-program-space data key.  */
 static const struct program_space_data *solib_svr4_pspace_data;
 
+/* Free the probes table.  */
+
+static void
+free_probes_table (struct svr4_info *info)
+{
+  if (info->probes_table == NULL)
+    return;
+
+  htab_delete (info->probes_table);
+  info->probes_table = NULL;
+}
+
+/* Free the solib list.  */
+
+static void
+free_solib_list (struct svr4_info *info)
+{
+  svr4_free_library_list (&info->solib_list);
+  info->solib_list = 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_table (info);
+  free_solib_list (info);
+
   xfree (info);
 }
 
@@ -991,6 +1083,34 @@
     }
 }
 
+/* Copy library list.  */
+
+static struct so_list *
+svr4_copy_library_list (struct so_list *src)
+{
+  struct so_list *dst = NULL;
+  struct so_list **link = &dst;
+
+  while (src != NULL)
+    {
+      struct so_list *new;
+
+      new = xmalloc (sizeof (struct so_list));
+      memcpy (new, src, sizeof (struct so_list));
+
+      new->lm_info = xmalloc (sizeof (struct lm_info));
+      memcpy (new->lm_info, src->lm_info, sizeof (struct lm_info));
+
+      new->next = NULL;
+      *link = new;
+      link = &new->next;
+
+      src = src->next;
+    }
+
+  return dst;
+}
+
 #ifdef HAVE_LIBEXPAT
 
 #include "xml-support.h"
@@ -1106,23 +1226,30 @@
   return 0;
 }
 
-/* Attempt to get so_list from target via qXfer:libraries:read packet.
+/* Attempt to get so_list from target via qXfer:libraries-svr4:read packet.
 
    Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such
    case.  Return 1 if *SO_LIST_RETURN contains the library list, it may be
-   empty, caller is responsible for freeing all its entries.  */
+   empty, caller is responsible for freeing all its entries.
+
+   Note that ANNEX must be NULL if the remote does not explicitly allow
+   qXfer:libraries-svr4:read packets with non-empty annexes.  Support for
+   this can be checked using target_augmented_libraries_svr4_read ().  */
 
 static int
-svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list)
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
+				     const char *annex)
 {
   char *svr4_library_document;
   int result;
   struct cleanup *back_to;
 
+  gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ());
+
   /* Fetch the list of shared libraries.  */
   svr4_library_document = target_read_stralloc (&current_target,
 						TARGET_OBJECT_LIBRARIES_SVR4,
-						NULL);
+						annex);
   if (svr4_library_document == NULL)
     return 0;
 
@@ -1136,7 +1263,8 @@
 #else
 
 static int
-svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list)
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
+				     const char *annex)
 {
   return 0;
 }
@@ -1170,15 +1298,19 @@
   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.  If zero is returned the
+   entries stored to LINK_PTR_PTR are still valid although they may
+   represent only part of the inferior library list.  */
 
-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)
     {
@@ -1194,7 +1326,7 @@
       if (new->lm_info == NULL)
 	{
 	  do_cleanups (old_chain);
-	  break;
+	  return 0;
 	}
 
       next_lm = new->lm_info->l_next;
@@ -1205,7 +1337,7 @@
 		   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
@@ -1251,17 +1383,21 @@
       **link_ptr_ptr = new;
       *link_ptr_ptr = &new->next;
     }
+
+  return 1;
 }
 
-/* Implement the "current_sos" target_so_ops method.  */
+/* Read the full list of currently loaded shared objects directly
+   from the inferior, without referring to any libraries read and
+   stored by the probes interface.  Handle special cases relating
+   to the first elements of the list.  */
 
 static struct so_list *
-svr4_current_sos (void)
+svr4_current_sos_direct (struct svr4_info *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;
   struct svr4_library_list library_list;
@@ -1274,19 +1410,16 @@
      Unfortunately statically linked inferiors will also fall back through this
      suboptimal code path.  */
 
-  if (svr4_current_sos_via_xfer_libraries (&library_list))
+  info->using_xfer = svr4_current_sos_via_xfer_libraries (&library_list,
+							  NULL);
+  if (info->using_xfer)
     {
       if (library_list.main_lm)
-	{
-	  info = get_svr4_info ();
-	  info->main_lm_addr = library_list.main_lm;
-	}
+	info->main_lm_addr = library_list.main_lm;
 
       return library_list.head ? library_list.head : svr4_default_sos ();
     }
 
-  info = get_svr4_info ();
-
   /* Always locate the debug struct, in case it has moved.  */
   info->debug_base = 0;
   locate_base (info);
@@ -1309,7 +1442,7 @@
      `struct so_list' nodes.  */
   lm = solib_svr4_r_map (info);
   if (lm)
-    svr4_read_so_list (lm, &link_ptr, ignore_first);
+    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
@@ -1317,7 +1450,7 @@
      for skipping dynamic linker resolver code.  */
   lm = solib_svr4_r_ldsomap (info);
   if (lm)
-    svr4_read_so_list (lm, &link_ptr, 0);
+    svr4_read_so_list (lm, 0, &link_ptr, 0);
 
   discard_cleanups (back_to);
 
@@ -1327,6 +1460,22 @@
   return head;
 }
 
+/* Implement the "current_sos" target_so_ops method.  */
+
+static struct so_list *
+svr4_current_sos (void)
+{
+  struct svr4_info *info = get_svr4_info ();
+
+  /* If the solib list has been read and stored by the probes
+     interface then we return a copy of the stored list.  */
+  if (info->solib_list != NULL)
+    return svr4_copy_library_list (info->solib_list);
+
+  /* Otherwise obtain the solib list directly from the inferior.  */
+  return svr4_current_sos_direct (info);
+}
+
 /* Get the address of the link_map for a given OBJFILE.  */
 
 CORE_ADDR
@@ -1409,6 +1558,476 @@
   return gdbarch_addr_bits_remove (target_gdbarch (), addr);
 }
 
+/* A probe and its associated action.  */
+
+struct probe_and_action
+{
+  /* The probe.  */
+  struct probe *probe;
+
+  /* The action.  */
+  enum probe_action action;
+};
+
+/* Returns a hash code for the probe_and_action referenced by p.  */
+
+static hashval_t
+hash_probe_and_action (const void *p)
+{
+  const struct probe_and_action *pa = p;
+
+  return (hashval_t) pa->probe->address;
+}
+
+/* Returns non-zero if the probe_and_actions referenced by p1 and p2
+   are equal.  */
+
+static int
+equal_probe_and_action (const void *p1, const void *p2)
+{
+  const struct probe_and_action *pa1 = p1;
+  const struct probe_and_action *pa2 = p2;
+
+  return pa1->probe->address == pa2->probe->address;
+}
+
+/* Register a solib event probe and its associated action in the
+   probes table.  */
+
+static void
+register_solib_event_probe (struct probe *probe, enum probe_action action)
+{
+  struct svr4_info *info = get_svr4_info ();
+  struct probe_and_action lookup, *pa;
+  void **slot;
+
+  /* Create the probes table, if necessary.  */
+  if (info->probes_table == NULL)
+    info->probes_table = htab_create_alloc (1, hash_probe_and_action,
+					    equal_probe_and_action,
+					    xfree, xcalloc, xfree);
+
+  lookup.probe = probe;
+  slot = htab_find_slot (info->probes_table, &lookup, INSERT);
+  gdb_assert (*slot == HTAB_EMPTY_ENTRY);
+
+  pa = XCNEW (struct probe_and_action);
+  pa->probe = probe;
+  pa->action = action;
+
+  *slot = pa;
+}
+
+/* Get the solib event probe at the specified location, and the
+   action associated with it.  Returns NULL if no solib event probe
+   was found.  */
+
+static struct probe_and_action *
+solib_event_probe_at (struct svr4_info *info, CORE_ADDR address)
+{
+  struct probe lookup_probe;
+  struct probe_and_action lookup;
+  void **slot;
+
+  lookup_probe.address = address;
+  lookup.probe = &lookup_probe;
+  slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT);
+
+  if (slot == NULL)
+    return NULL;
+
+  return (struct probe_and_action *) *slot;
+}
+
+/* Decide what action to take when the specified solib event probe is
+   hit.  */
+
+static enum probe_action
+solib_event_probe_action (struct probe_and_action *pa)
+{
+  enum probe_action action;
+  unsigned probe_argc;
+
+  action = pa->action;
+  if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED)
+    return action;
+
+  gdb_assert (action == FULL_RELOAD || action == 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 (pa->probe);
+  if (probe_argc == 2)
+    action = FULL_RELOAD;
+  else if (probe_argc < 2)
+    action = PROBES_INTERFACE_FAILED;
+
+  return action;
+}
+
+/* Populate the shared object list by reading the entire list of
+   shared objects from the inferior.  Handle special cases relating
+   to the first elements of the list.  Returns nonzero on success.  */
+
+static int
+solist_update_full (struct svr4_info *info)
+{
+  free_solib_list (info);
+  info->solib_list = svr4_current_sos_direct (info);
+
+  return 1;
+}
+
+/* Update the shared object list 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
+solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
+{
+  struct so_list *tail;
+  CORE_ADDR prev_lm;
+
+  /* svr4_current_sos_direct contains logic to handle a number of
+     special cases relating to the first elements of the list.  To
+     avoid duplicating this logic we defer to solist_update_full
+     if the list is empty.  */
+  if (info->solib_list == NULL)
+    return 0;
+
+  /* Fall back to a full update if we are using a remote target
+     that does not support incremental transfers.  */
+  if (info->using_xfer && !target_augmented_libraries_svr4_read ())
+    return 0;
+
+  /* Walk to the end of the list.  */
+  for (tail = info->solib_list; tail->next != NULL; tail = tail->next)
+    /* Nothing.  */;
+  prev_lm = tail->lm_info->lm_addr;
+
+  /* Read the new objects.  */
+  if (info->using_xfer)
+    {
+      struct svr4_library_list library_list;
+      char annex[64];
+
+      xsnprintf (annex, sizeof (annex), "start=%s;prev=%s",
+		 phex_nz (lm, sizeof (lm)),
+		 phex_nz (prev_lm, sizeof (prev_lm)));
+      if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
+	return 0;
+
+      tail->next = library_list.head;
+    }
+  else
+    {
+      struct so_list **link = &tail->next;
+
+      /* IGNORE_FIRST may safely be set to zero here because the
+	 above check and deferral to solist_update_full ensures
+	 that this call to svr4_read_so_list will never see the
+	 first element.  */
+      if (!svr4_read_so_list (lm, prev_lm, &link, 0))
+	return 0;
+    }
+
+  return 1;
+}
+
+/* Disable the probes-based linker interface and revert to the
+   original interface.  We don't reset the breakpoints as the
+   ones set up for the probes-based interface are adequate.  */
+
+static void
+disable_probes_interface_cleanup (void *arg)
+{
+  struct svr4_info *info = get_svr4_info ();
+
+  warning (_("Probes-based dynamic linker interface failed.\n"
+	     "Reverting to original interface.\n"));
+
+  free_probes_table (info);
+  free_solib_list (info);
+}
+
+/* Update the solib list as appropriate when using the
+   probes-based linker interface.  Do nothing if using the
+   standard interface.  */
+
+static void
+svr4_handle_solib_event (void)
+{
+  struct svr4_info *info = get_svr4_info ();
+  struct probe_and_action *pa;
+  enum probe_action action;
+  struct cleanup *old_chain, *usm_chain;
+  struct value *val;
+  CORE_ADDR pc, debug_base, lm = 0;
+  int is_initial_ns;
+
+  /* Do nothing if not using the probes interface.  */
+  if (info->probes_table == NULL)
+    return;
+
+  /* If anything goes wrong we revert to the original linker
+     interface.  */
+  old_chain = make_cleanup (disable_probes_interface_cleanup, NULL);
+
+  pc = regcache_read_pc (get_current_regcache ());
+  pa = solib_event_probe_at (info, pc);
+  if (pa == NULL)
+    {
+      do_cleanups (old_chain);
+      return;
+    }
+
+  action = solib_event_probe_action (pa);
+  if (action == PROBES_INTERFACE_FAILED)
+    {
+      do_cleanups (old_chain);
+      return;
+    }
+
+  if (action == DO_NOTHING)
+    {
+      discard_cleanups (old_chain);
+      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 (current_program_space);
+  usm_chain = make_cleanup (resume_section_map_updates_cleanup,
+			    current_program_space);
+
+  val = evaluate_probe_argument (pa->probe, 1);
+  if (val == NULL)
+    {
+      do_cleanups (old_chain);
+      return;
+    }
+
+  debug_base = value_as_address (val);
+  if (debug_base == 0)
+    {
+      do_cleanups (old_chain);
+      return;
+    }
+
+  /* Always locate the debug struct, in case it moved.  */
+  info->debug_base = 0;
+  if (locate_base (info) == 0)
+    {
+      do_cleanups (old_chain);
+      return;
+    }
+
+  /* GDB does not currently support libraries loaded via dlmopen
+     into namespaces other than the initial one.  We must ignore
+     any namespace other than the initial namespace here until
+     support for this is added to GDB.  */
+  if (debug_base != info->debug_base)
+    action = DO_NOTHING;
+
+  if (action == UPDATE_OR_RELOAD)
+    {
+      val = evaluate_probe_argument (pa->probe, 2);
+      if (val != NULL)
+	lm = value_as_address (val);
+
+      if (lm == 0)
+	action = FULL_RELOAD;
+    }
+
+  /* Resume section map updates.  */
+  do_cleanups (usm_chain);
+
+  if (action == UPDATE_OR_RELOAD)
+    {
+      if (!solist_update_incremental (info, lm))
+	action = FULL_RELOAD;
+    }
+
+  if (action == FULL_RELOAD)
+    {
+      if (!solist_update_full (info))
+	{
+	  do_cleanups (old_chain);
+	  return;
+	}
+    }
+
+  discard_cleanups (old_chain);
+}
+
+/* Helper function for svr4_update_solib_event_breakpoints.  */
+
+static int
+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
+{
+  struct bp_location *loc;
+
+  if (b->type != bp_shlib_event)
+    {
+      /* Continue iterating.  */
+      return 0;
+    }
+
+  for (loc = b->loc; loc != NULL; loc = loc->next)
+    {
+      struct svr4_info *info;
+      struct probe_and_action *pa;
+
+      info = program_space_data (loc->pspace, solib_svr4_pspace_data);
+      if (info == NULL || info->probes_table == NULL)
+	continue;
+
+      pa = solib_event_probe_at (info, loc->address);
+      if (pa == NULL)
+	continue;
+
+      if (pa->action == DO_NOTHING)
+	{
+	  if (b->enable_state == bp_disabled && stop_on_solib_events)
+	    enable_breakpoint (b);
+	  else if (b->enable_state == bp_enabled && !stop_on_solib_events)
+	    disable_breakpoint (b);
+	}
+
+      break;
+    }
+
+  /* Continue iterating.  */
+  return 0;
+}
+
+/* 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)
+{
+  iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
+}
+
+/* Create and register solib event breakpoints.  PROBES is an array
+   of NUM_PROBES elements, each of which is vector of probes.  A
+   solib event breakpoint will be created and registered for each
+   probe.  */
+
+static void
+svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
+			       VEC (probe_p) **probes)
+{
+  int i;
+
+  for (i = 0; i < NUM_PROBES; i++)
+    {
+      enum probe_action action = probe_info[i].action;
+      struct probe *probe;
+      int ix;
+
+      for (ix = 0;
+	   VEC_iterate (probe_p, probes[i], ix, probe);
+	   ++ix)
+	{
+	  create_solib_event_breakpoint (gdbarch, probe->address);
+	  register_solib_event_probe (probe, action);
+	}
+    }
+
+  svr4_update_solib_event_breakpoints ();
+}
+
+/* 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 obj_section *os;
+
+  os = find_pc_section (address);
+  if (os != NULL)
+    {
+      int with_prefix;
+
+      for (with_prefix = 0; with_prefix <= 1; with_prefix++)
+	{
+	  VEC (probe_p) *probes[NUM_PROBES];
+	  int all_probes_found = 1;
+	  int i;
+
+	  memset (probes, 0, sizeof (probes));
+	  for (i = 0; i < NUM_PROBES; i++)
+	    {
+	      const char *name = probe_info[i].name;
+	      char buf[32];
+
+	      /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4
+		 shipped with an early version of the probes code in
+		 which the probes' names were prefixed with "rtld_"
+		 and the "map_failed" probe did not exist.  The
+		 locations of the probes are otherwise the same, so
+		 we check for probes with prefixed names if probes
+		 with unprefixed names are not present.  */
+	      if (with_prefix)
+		{
+		  xsnprintf (buf, sizeof (buf), "rtld_%s", name);
+		  name = buf;
+		}
+
+	      probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
+
+	      /* The "map_failed" probe did not exist in early
+		 versions of the probes code in which the probes'
+		 names were prefixed with "rtld_".  */
+	      if (strcmp (name, "rtld_map_failed") == 0)
+		continue;
+
+	      if (VEC_empty (probe_p, probes[i]))
+		{
+		  all_probes_found = 0;
+		  break;
+		}
+	    }
+
+	  if (all_probes_found)
+	    svr4_create_probe_breakpoints (gdbarch, probes);
+
+	  for (i = 0; i < NUM_PROBES; i++)
+	    VEC_free (probe_p, probes[i]);
+
+	  if (all_probes_found)
+	    return;
+	}
+    }
+
+  create_solib_event_breakpoint (gdbarch, address);
+}
+
 /* Helper function for gdb_bfd_lookup_symbol.  */
 
 static int
@@ -1492,7 +2111,7 @@
 	 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
@@ -1530,7 +2149,7 @@
 		+ 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;
 	}
     }
@@ -1688,7 +2307,8 @@
 
       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;
 	}
@@ -1714,7 +2334,7 @@
 	  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;
 	}
     }
@@ -1730,7 +2350,7 @@
 	      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;
 	    }
 	}
@@ -2226,6 +2846,10 @@
 
   info = get_svr4_info ();
 
+  /* Clear the probes-based interface's state.  */
+  free_probes_table (info);
+  free_solib_list (info);
+
   /* Relocate the main executable if necessary.  */
   svr4_relocate_main_executable ();
 
@@ -2468,4 +3092,6 @@
   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.update_breakpoints = svr4_update_solib_event_breakpoints;
+  svr4_so_ops.handle_event = svr4_handle_solib_event;
 }

[-- Attachment #9: rtld-probes-6-tests-jk.patch --]
[-- Type: text/plain, Size: 16507 bytes --]

Index: gdb/testsuite/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/ChangeLog,v
retrieving revision 1.3682
diff -u -r1.3682 ChangeLog
--- gdb/testsuite/ChangeLog	30 May 2013 00:25:16 -0000	1.3682
+++ gdb/testsuite/ChangeLog	4 Jun 2013 13:20:02 -0000
@@ -1,3 +1,19 @@
+2013-06-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Gary Benson  <gbenson@redhat.com>
+
+	* lib/gdb.exp (build_executable_from_specs): Use gdb_compile_pthread,
+	gdb_compile_shlib or gdb_compile_shlib_pthreads where appropriate.
+	* lib/prelink-support.exp (build_executable_own_libs): Allow INTERP
+	to be set to "no" to indicate that no ld.so copy should be made.
+	* 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.threads/dlopen-libpthread.exp: New file.
+	* gdb.threads/dlopen-libpthread.c: Likewise.
+	* gdb.threads/dlopen-libpthread-lib.c: Likewise.
+	* gdb.base/solib-corrupted.exp: Disable test if GDB is using probes.
+
 2013-05-30  Yao Qi  <yao@codesourcery.com>
 
 	* gdb.mi/mi-cmd-param-changed.exp (test_command_param_changed):
Index: gdb/testsuite/lib/gdb.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb.exp,v
retrieving revision 1.231
diff -u -r1.231 gdb.exp
--- gdb/testsuite/lib/gdb.exp	6 May 2013 22:11:15 -0000	1.231
+++ gdb/testsuite/lib/gdb.exp	4 Jun 2013 13:20:08 -0000
@@ -4051,31 +4051,6 @@
 
     set binfile [standard_output_file $executable]
 
-    set objects {}
-    set i 0
-    foreach {s local_options} $args {
-        if  { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $local_options] != "" } {
-            untested $testname
-            return -1
-        }
-        lappend objects "${binfile}${i}.o"
-	incr i
-    }
-
-    set pthreads [lsearch -exact $options "pthreads"]
-    if { $pthreads >= 0 } {
-        set options [lreplace $options $pthreads $pthreads]
-        if  { [gdb_compile_pthreads $objects "${binfile}" executable $options] != "" } {
-            untested $testname
-            return -1
-        }
-    } else {
-        if  { [gdb_compile $objects "${binfile}" executable $options] != "" } {
-            untested $testname
-            return -1
-        }
-    }
-
     set info_options ""
     if { [lsearch -exact $options "c++"] >= 0 } {
 	set info_options "c++"
@@ -4083,6 +4058,42 @@
     if [get_compiler_info ${info_options}] {
         return -1
     }
+
+    set binfile [standard_output_file $executable]
+
+    set func gdb_compile
+    set func_index [lsearch -regexp $options {^(pthreads|shlib|shlib_pthreads)$}]
+    if {$func_index != -1} {
+	set func "${func}_[lindex $options $func_index]"
+    }
+
+    # gdb_compile_shlib and gdb_compile_shlib_pthreads do not use the 3rd
+    # parameter.  They also requires $sources while gdb_compile and
+    # gdb_compile_pthreads require $objects.  Moreover they ignore any options.
+    if [string match gdb_compile_shlib* $func] {
+	set sources_path {}
+	foreach {s local_options} $args {
+	    lappend sources_path "${srcdir}/${subdir}/${s}"
+	}
+	set ret [$func $sources_path "${binfile}" $options]
+    } else {
+	set objects {}
+	set i 0
+	foreach {s local_options} $args {
+	    if  { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $local_options] != "" } {
+		untested $testname
+		return -1
+	    }
+	    lappend objects "${binfile}${i}.o"
+	    incr i
+	}
+	set ret [$func $objects "${binfile}" executable $options]
+    }
+    if  { $ret != "" } {
+        untested $testname
+        return -1
+    }
+
     return 0
 }
 
Index: gdb/testsuite/lib/prelink-support.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/prelink-support.exp,v
retrieving revision 1.6
diff -u -r1.6 prelink-support.exp
--- gdb/testsuite/lib/prelink-support.exp	1 Jan 2013 06:41:28 -0000	1.6
+++ gdb/testsuite/lib/prelink-support.exp	4 Jun 2013 13:20:08 -0000
@@ -95,8 +95,9 @@
 # Wrap function build_executable so that the resulting executable is fully
 # self-sufficient (without dependencies on system libraries).  Parameter
 # INTERP may be used to specify a loader (ld.so) to be used that is
-# different from the default system one.  Libraries on which the executable
-# depends are copied into directory DIR.  Default DIR value to
+# different from the default system one.  INTERP can be set to "no" if no ld.so
+# copy should be made.  Libraries on which the executable depends are copied
+# into directory DIR.  Default DIR value to
 # `${objdir}/${subdir}/${EXECUTABLE}.d'.
 #
 # In case of success, return a string containing the arguments to be used
@@ -151,8 +152,15 @@
 
     if {$interp == ""} {
 	set interp_system [section_get $binfile .interp]
-	set interp ${dir}/[file tail $interp_system]
-	file_copy $interp_system $interp
+	if {$interp_system == ""} {
+	    fail "$test could not find .interp"
+	} else {
+	    set interp ${dir}/[file tail $interp_system]
+	    file_copy $interp_system $interp
+	}
+    }
+    if {$interp == "no"} {
+	set interp ""
     }
 
     set dests {}
@@ -164,13 +172,19 @@
 
     # Do not lappend it so that "-rpath $dir" overrides any possible "-rpath"s
     # specified by the caller to be able to link it for ldd" above.
-    set options [linsert $options 0 "ldflags=-Wl,--dynamic-linker,$interp,-rpath,$dir"]
+    set options [linsert $options 0 "ldflags=-Wl,-rpath,$dir"]
+    if {$interp != ""} {
+	set options [linsert $options 0 "ldflags=-Wl,--dynamic-linker,$interp"]
+    }
 
     if {[build_executable $testname $executable $sources $options] == -1} {
 	return ""
     }
 
-    set prelink_args "--dynamic-linker=$interp --ld-library-path=$dir $binfile $interp [concat $dests]"
+    set prelink_args "--ld-library-path=$dir $binfile [concat $dests]"
+    if {$interp != ""} {
+	set prelink_args "--dynamic-linker=$interp $prelink_args $interp"
+    }
     return $prelink_args
 }
 
Index: gdb/testsuite/gdb.base/break-interp.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/break-interp.exp,v
retrieving revision 1.40
diff -u -r1.40 break-interp.exp
--- gdb/testsuite/gdb.base/break-interp.exp	15 Mar 2013 01:41:28 -0000	1.40
+++ gdb/testsuite/gdb.base/break-interp.exp	4 Jun 2013 13:20:03 -0000
@@ -109,12 +109,19 @@
     }
 }
 
+# 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 @@
 	    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 @@
 	fail $test_displacement
     }
 
-    if {$func == "_dl_debug_state"} {
+    if {$func == $solib_bp} {
 	gdb_test_no_output "set stop-on-solib-events 0"
     }
 }
@@ -361,7 +368,7 @@
 }
 
 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.
 
@@ -389,9 +396,9 @@
 	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"
@@ -403,7 +410,7 @@
 
     # 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
@@ -435,7 +442,7 @@
 	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/testsuite/gdb.threads/dlopen-libpthread.exp
===================================================================
RCS file: gdb/testsuite/gdb.threads/dlopen-libpthread.exp
diff -N gdb/testsuite/gdb.threads/dlopen-libpthread.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.threads/dlopen-libpthread.exp	4 Jun 2013 13:20:05 -0000
@@ -0,0 +1,74 @@
+# Copyright 2011-2013 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 {![istarget *-linux*] || [skip_shlib_tests]} {
+    return 0
+}
+
+load_lib prelink-support.exp
+
+set testfile "dlopen-libpthread"
+set srcmainfile ${testfile}.c
+set srclibfile ${testfile}-lib.c
+set executable ${testfile}
+set binfile_lib ${objdir}/${subdir}/${executable}.so
+set binfile ${objdir}/${subdir}/${executable}
+set lib_dlopen [shlib_target_file ${executable}.so]
+
+# Use build_executable_own_libs as prelinked libpthread.so can produce false
+# PASS - it is OK if GDB processes it still before relocation.
+
+set relink_args [build_executable_own_libs ${testfile}.exp ${executable}.so $srclibfile {debug shlib_pthreads} no]
+if {$relink_args == "" || ![prelink_no $relink_args]
+    || [prepare_for_testing ${testfile}.exp ${executable} ${srcmainfile} {debug shlib_load}] } {
+    return -1
+}
+gdb_load_shlibs $binfile_lib
+
+if { ![runto_main] } {
+    return -1
+}
+
+set test "info probes all rtld rtld_map_complete"
+gdb_test_multiple $test $test {
+    -re "\[ \t\]rtld_map_complete\[ \t\]+0x\[0-9a-f\]+.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "No probes matched\\.\r\n$gdb_prompt $" {
+	xfail $test
+	untested ${testfile}.exp
+	return
+    }
+}
+
+set test "libpthread.so not found"
+gdb_test_multiple "info sharedlibrary" $test {
+    -re "/libpthread\\.so.*\r\n$gdb_prompt $" {
+	fail $test
+    }
+    -re "/libc\\.so.*\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+
+gdb_test "set variable filename=\"$lib_dlopen\""
+
+gdb_breakpoint "notify"
+
+# The error was:
+# Cannot find new threads: generic error
+gdb_continue_to_breakpoint "notify" ".* notify-here .*"
+
+gdb_test "info sharedlibrary" {/libpthread\.so.*} "libpthread.so found"
Index: gdb/testsuite/gdb.threads/dlopen-libpthread.c
===================================================================
RCS file: gdb/testsuite/gdb.threads/dlopen-libpthread.c
diff -N gdb/testsuite/gdb.threads/dlopen-libpthread.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.threads/dlopen-libpthread.c	4 Jun 2013 13:20:05 -0000
@@ -0,0 +1,46 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011-2013 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>
+#include <stddef.h>
+#include <assert.h>
+
+static const char *volatile filename;
+
+static void
+notify (void)
+{
+  filename = NULL; /* notify-here */
+}
+
+int
+main (void)
+{
+  void *h;
+  void (*fp) (void (*) (void));
+
+  assert (filename != NULL);
+  h = dlopen (filename, RTLD_LAZY);
+  assert (h != NULL);
+
+  fp = dlsym (h, "f");
+  assert (fp != NULL);
+
+  fp (notify);
+
+  return 0;
+}
Index: gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c
===================================================================
RCS file: gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c
diff -N gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c	4 Jun 2013 13:20:05 -0000
@@ -0,0 +1,40 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011-2013 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 <pthread.h>
+#include <assert.h>
+
+static void *
+tfunc (void *arg)
+{
+  void (*notifyp) (void) = arg;
+
+  notifyp ();
+}
+
+void
+f (void (*notifyp) (void))
+{
+  pthread_t t;
+  int i;
+
+  i = pthread_create (&t, NULL, tfunc, notifyp);
+  assert (i == 0);
+
+  i = pthread_join (t, NULL);
+  assert (i == 0);
+}
Index: gdb/testsuite/gdb.base/solib-corrupted.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/solib-corrupted.exp,v
retrieving revision 1.8
diff -u -r1.8 solib-corrupted.exp
--- gdb/testsuite/gdb.base/solib-corrupted.exp	1 Jan 2013 06:33:26 -0000	1.8
+++ gdb/testsuite/gdb.base/solib-corrupted.exp	4 Jun 2013 13:20:04 -0000
@@ -36,6 +36,33 @@
     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.

[-- Attachment #10: rtld-probes-7-tests-gb.patch --]
[-- Type: text/plain, Size: 14659 bytes --]

Index: gdb/testsuite/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/ChangeLog,v
retrieving revision 1.3683
diff -u -r1.3683 ChangeLog
--- gdb/testsuite/ChangeLog	4 Jun 2013 13:23:31 -0000	1.3683
+++ gdb/testsuite/ChangeLog	4 Jun 2013 13:28:03 -0000
@@ -1,3 +1,13 @@
+2013-06-04  Gary Benson  <gbenson@redhat.com>
+
+	* 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.
+
 2013-06-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
 	    Gary Benson  <gbenson@redhat.com>
 
Index: gdb/testsuite/gdb.base/break-probes.exp
===================================================================
RCS file: gdb/testsuite/gdb.base/break-probes.exp
diff -N gdb/testsuite/gdb.base/break-probes.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/break-probes.exp	4 Jun 2013 13:28:04 -0000
@@ -0,0 +1,78 @@
+# Copyright 2012-2013 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] } {
+    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"
+
+# Start the inferior and run to the first stop
+gdb_run_cmd
+gdb_test "" ".*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 $" {
+	untested "probes not present on this system"
+    }
+    -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 not_loaded_library 1
+    while { $not_loaded_library } {
+	set not_loaded_library 0
+	gdb_test_multiple "c" $test {
+	    -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" {
+		pass $test
+	    }
+	    -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
+		set not_loaded_library 1
+	    }
+	}
+    }
+
+    # Call something to ensure that relocation occurred
+    gdb_test "call foo(23)" "\\\$.* = 31.*\\\M.*"
+}
Index: gdb/testsuite/gdb.base/break-probes.c
===================================================================
RCS file: gdb/testsuite/gdb.base/break-probes.c
diff -N gdb/testsuite/gdb.base/break-probes.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/break-probes.c	4 Jun 2013 13:28:04 -0000
@@ -0,0 +1,30 @@
+/* Copyright 2012-2013 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>
+#include <assert.h>
+#include <stddef.h>
+
+int
+main (void)
+{
+  void *handle = dlopen (SHLIB_NAME, RTLD_LAZY);
+
+  assert (handle != NULL);
+
+  dlclose (handle);
+
+  return 0;
+}
Index: gdb/testsuite/gdb.base/break-probes-solib.c
===================================================================
RCS file: gdb/testsuite/gdb.base/break-probes-solib.c
diff -N gdb/testsuite/gdb.base/break-probes-solib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/break-probes-solib.c	4 Jun 2013 13:28:04 -0000
@@ -0,0 +1,22 @@
+/* Copyright 2012-2013 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)
+{
+  return n * n / 17;
+}
Index: gdb/testsuite/gdb.base/info-shared.exp
===================================================================
RCS file: gdb/testsuite/gdb.base/info-shared.exp
diff -N gdb/testsuite/gdb.base/info-shared.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/info-shared.exp	4 Jun 2013 13:28:05 -0000
@@ -0,0 +1,146 @@
+# Copyright 2012-2013 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] } {
+    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
+	    }
+	}
+    }
+}
+
+# Start the inferior, and check neither of the libraries are loaded at
+# the start.
+if ![runto_main] {
+    return 0
+}
+check_info_shared "info sharedlibrary #1" 0 0
+
+# Set up breakpoints.
+gdb_breakpoint "stop"
+gdb_breakpoint "foo" allow-pending
+gdb_breakpoint "bar" allow-pending
+
+# Run to the first stop and check that only the first library is loaded.
+gdb_continue_to_breakpoint "library load #1" "stop .*"
+check_info_shared "info sharedlibrary #2" 1 0
+
+# Run to the second stop and check that both libraries are loaded.
+gdb_continue_to_breakpoint "library load #2" "stop .*"
+check_info_shared "info sharedlibrary #3" 1 1
+
+# Check that the next stop is in foo.
+gdb_continue_to_breakpoint "library function #1" "foo .*"
+
+# Check that the next stop is in bar.
+gdb_continue_to_breakpoint "library function #2" "bar .*"
+
+# 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_run_cmd
+gdb_test_multiple "" $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
+    }
+}
+
+# Check that neither library is loaded.
+check_info_shared "info sharedlibrary #4" 0 0
+
+# Run to the first stop and check that only the first library is loaded.
+gdb_continue_to_breakpoint "library load #3" "stop .*"
+check_info_shared "info sharedlibrary #5" 1 0
+
+# Run to the second stop and check that both libraries are loaded.
+gdb_continue_to_breakpoint "library load #4" "stop .*"
+check_info_shared "info sharedlibrary #6" 1 1
+
+# Check that the next stop is in foo.
+gdb_continue_to_breakpoint "library function #3" "foo .*"
+
+# Check that the next stop is in bar.
+gdb_continue_to_breakpoint "library function #4" "bar .*"
+
+# Run to the next stop and check that the first library has been unloaded.
+gdb_continue_to_breakpoint "library unload #1" "stop .*"
+check_info_shared "info sharedlibrary #7" 0 1
+
+# Run to the last stop and check that both libraries are gone.
+gdb_continue_to_breakpoint "library unload #2" "stop .*"
+check_info_shared "info sharedlibrary #8" 0 0
Index: gdb/testsuite/gdb.base/info-shared.c
===================================================================
RCS file: gdb/testsuite/gdb.base/info-shared.c
diff -N gdb/testsuite/gdb.base/info-shared.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/info-shared.c	4 Jun 2013 13:28:05 -0000
@@ -0,0 +1,52 @@
+/* Copyright 2012-2013 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>
+#include <assert.h>
+#include <stddef.h>
+
+void
+stop (void)
+{
+}
+
+int
+main (void)
+{
+  void *handle1, *handle2;
+  void (*func)(int);
+
+  handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY);
+  assert (handle1 != NULL);
+  stop ();
+
+  handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY);
+  assert (handle2 != NULL);
+  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/testsuite/gdb.base/info-shared-solib1.c
===================================================================
RCS file: gdb/testsuite/gdb.base/info-shared-solib1.c
diff -N gdb/testsuite/gdb.base/info-shared-solib1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/info-shared-solib1.c	4 Jun 2013 13:28:05 -0000
@@ -0,0 +1,24 @@
+/* Copyright 2012-2013 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/testsuite/gdb.base/info-shared-solib2.c
===================================================================
RCS file: gdb/testsuite/gdb.base/info-shared-solib2.c
diff -N gdb/testsuite/gdb.base/info-shared-solib2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/info-shared-solib2.c	4 Jun 2013 13:28:05 -0000
@@ -0,0 +1,24 @@
+/* Copyright 2012-2013 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;
+}

  parent reply	other threads:[~2013-06-04 13:38 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-16 14:43 [RFA 0/7] " Gary Benson
2013-05-16 14:47 ` [RFA 1/7] Probes API convenience patch Gary Benson
2013-05-16 14:48 ` [RFA 2/7] API for inhibiting section map updates Gary Benson
2013-05-20 14:22   ` Tom Tromey
2013-05-24  7:47     ` [RFA 2/7 take 2] " Gary Benson
2013-05-24 14:18       ` Tom Tromey
2013-05-29 17:18       ` Pedro Alves
2013-05-30  9:12         ` Gary Benson
2013-05-16 14:48 ` [RFA 3/7] New gdbserver functionality Gary Benson
2013-05-16 18:18   ` Tom Tromey
2013-05-24  7:46     ` [RFA 3/7 take 2] " Gary Benson
2013-05-25 21:05       ` Jan Kratochvil
2013-05-26  2:45         ` Eli Zaretskii
2013-05-29 18:50       ` Pedro Alves
2013-05-30  9:38         ` Gary Benson
2013-05-30 10:40           ` Pedro Alves
2013-05-30 10:54             ` Gary Benson
2013-05-30 16:31               ` Eli Zaretskii
2013-05-30 17:22                 ` Gary Benson
2013-05-16 14:48 ` [RFA 4/7] GDB support for new " Gary Benson
2013-05-16 14:55 ` [RFA 6/7] Linker-debugger interface tests by Jan Gary Benson
2013-05-29 19:06   ` Pedro Alves
2013-05-30  9:19     ` Gary Benson
2013-05-16 14:55 ` [RFA 5/7] Improved linker-debugger interface Gary Benson
2013-05-17 19:05   ` Jan Kratochvil
2013-05-24  8:30     ` [RFA 5/7 take 2] " Gary Benson
2013-05-25 21:05       ` Jan Kratochvil
2013-05-29 18:51       ` Pedro Alves
2013-05-30 10:43         ` [RFA 5/7 take 3] " Gary Benson
2013-05-30 17:18           ` Pedro Alves
2013-05-31 13:22             ` [RFA 5/7 take 4] " Gary Benson
2013-05-31 13:27               ` Pedro Alves
2013-06-03 10:31               ` Pedro Alves
2013-06-03 16:37               ` Jan Kratochvil
2013-06-03 17:28                 ` Pedro Alves
2013-06-04 11:33                   ` Gary Benson
2013-05-16 14:55 ` [RFA 7/7] Linker-debugger interface tests Gary Benson
2013-05-19 13:45   ` Jan Kratochvil
2013-05-19 16:43     ` Jan Kratochvil
2013-05-24  8:38     ` [RFA 7/7 take 2] " Gary Benson
2013-05-24  8:58       ` Jan Kratochvil
2013-05-24 14:05         ` [obv] Fix excessive backslashes in testsuite Gary Benson
2013-05-25 21:06       ` [RFA 7/7 take 2] Linker-debugger interface tests Jan Kratochvil
2013-05-16 17:33 ` [RFA 0/7] Improved linker-debugger interface Tom Tromey
2013-05-16 18:53   ` Gary Benson
2013-06-06  9:00   ` Gary Benson
2013-05-19 13:46 ` Jan Kratochvil
2013-05-29 19:08 ` Pedro Alves
2013-06-04 13:38 ` Gary Benson [this message]
2013-06-25 21:04   ` [commit] " Joel Brobecker
2013-06-25 22:03     ` Sergio Durigan Junior
2013-06-26  0:49       ` Joel Brobecker
2013-07-09  8:41         ` Gary Benson
     [not found]         ` <20130708104719.GA11176@blade.nx>
2013-07-09 14:45           ` Joel Brobecker
2013-06-26 15:38       ` Tom Tromey
2013-06-26 17:23         ` Sergio Durigan Junior
2013-06-26 19:15           ` Joel Brobecker
2013-06-27 23:33           ` Tom Tromey
2013-06-30  3:12             ` Sergio Durigan Junior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130604133819.GA25892@blade.nx \
    --to=gbenson@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=jan.kratochvil@redhat.com \
    --cc=palves@redhat.com \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox