[gdb/f19] Fix performance regression when inferior opens many libraries (Gary Benson).
Jan Kratochvil
jankratochvil at fedoraproject.org
Sun May 19 16:44:15 UTC 2013
commit 6d620330a43ca2fbe902365bf3456e4a705d7299
Author: Jan Kratochvil <jan.kratochvil at redhat.com>
Date: Sun May 19 18:44:05 2013 +0200
Fix performance regression when inferior opens many libraries (Gary Benson).
gdb-dlopen-stap-probe-1of7.patch | 119 ++
gdb-dlopen-stap-probe-2of7.patch | 198 ++++
gdb-dlopen-stap-probe-3of7.patch | 376 +++++--
gdb-dlopen-stap-probe-4of7.patch | 243 ++--
gdb-dlopen-stap-probe-5of7.patch | 1098 +++++++++++++++++-
gdb-dlopen-stap-probe-6of7.patch | 2055 +++++----------------------------
gdb-dlopen-stap-probe-7of7.patch | 556 +++++++---
gdb-dlopen-stap-probe-fixup.patch | 62 +
gdb-dlopen-stap-probe-inhibit.patch | 60 -
gdb-dlopen-stap-probe-mapfailed.patch | 30 -
gdb-dlopen-stap-probe-test.patch | 307 -----
gdb-dlopen-stap-probe-test2.patch | 69 --
gdb.spec | 24 +-
13 files changed, 2592 insertions(+), 2605 deletions(-)
---
diff --git a/gdb-dlopen-stap-probe-1of7.patch b/gdb-dlopen-stap-probe-1of7.patch
new file mode 100644
index 0000000..cb74802
--- /dev/null
+++ b/gdb-dlopen-stap-probe-1of7.patch
@@ -0,0 +1,119 @@
+http://sourceware.org/ml/gdb-patches/2013-05/msg00625.html
+Subject: [RFA 1/7] Probes API convenience patch
+
+
+--uuKVzAmB+c+zQlhu
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch exposes part of the probes API in a more convenient
+way. I've included it for completeness, but it has previously
+been approved:
+
+ http://www.cygwin.com/ml/gdb-patches/2012-07/msg00340.html
+
+--uuKVzAmB+c+zQlhu
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-1-convenience.patch"
+
+2013-05-16 Gary Benson <gbenson at redhat.com>
+
+ * probe.h (get_probe_argument_count): New declaration.
+ (evaluate_probe_argument): Likewise.
+ * probe.c (get_probe_argument_count): New function.
+ (evaluate_probe_argument): Likewise.
+ (probe_safe_evaluate_at_pc): Use the above new functions.
+
+diff --git a/gdb/probe.h b/gdb/probe.h
+index 8d44ca2..1d29b87 100644
+--- a/gdb/probe.h
++++ b/gdb/probe.h
+@@ -214,6 +214,16 @@ extern void info_probes_for_ops (char *arg, int from_tty,
+
+ extern struct cmd_list_element **info_probes_cmdlist_get (void);
+
++/* Return the argument count of the specified probe. */
++
++extern unsigned get_probe_argument_count (struct probe *probe);
++
++/* Evaluate argument N of the specified probe. N must be between 0
++ inclusive and get_probe_argument_count exclusive. */
++
++extern struct value *evaluate_probe_argument (struct probe *probe,
++ unsigned n);
++
+ /* A convenience function that finds a probe at the PC in FRAME and
+ evaluates argument N, with 0 <= N < number_of_args. If there is no
+ probe at that location, or if the probe does not have enough arguments,
+diff --git a/gdb/probe.c b/gdb/probe.c
+index 77f3b13..a61f4ea 100644
+--- a/gdb/probe.c
++++ b/gdb/probe.c
+@@ -608,28 +608,55 @@ info_probes_command (char *arg, int from_tty)
+
+ /* See comments in probe.h. */
+
++unsigned
++get_probe_argument_count (struct probe *probe)
++{
++ const struct sym_probe_fns *probe_fns;
++
++ gdb_assert (probe->objfile != NULL);
++ gdb_assert (probe->objfile->sf != NULL);
++
++ probe_fns = probe->objfile->sf->sym_probe_fns;
++
++ gdb_assert (probe_fns != NULL);
++
++ return probe_fns->sym_get_probe_argument_count (probe);
++}
++
++/* See comments in probe.h. */
++
++struct value *
++evaluate_probe_argument (struct probe *probe, unsigned n)
++{
++ const struct sym_probe_fns *probe_fns;
++
++ gdb_assert (probe->objfile != NULL);
++ gdb_assert (probe->objfile->sf != NULL);
++
++ probe_fns = probe->objfile->sf->sym_probe_fns;
++
++ gdb_assert (probe_fns != NULL);
++
++ return probe_fns->sym_evaluate_probe_argument (probe, n);
++}
++
++/* See comments in probe.h. */
++
+ struct value *
+ probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n)
+ {
+ struct probe *probe;
+- const struct sym_probe_fns *probe_fns;
+ unsigned n_args;
+
+ probe = find_probe_by_pc (get_frame_pc (frame));
+ if (!probe)
+ return NULL;
+
+- gdb_assert (probe->objfile != NULL);
+- gdb_assert (probe->objfile->sf != NULL);
+- gdb_assert (probe->objfile->sf->sym_probe_fns != NULL);
+-
+- probe_fns = probe->objfile->sf->sym_probe_fns;
+- n_args = probe_fns->sym_get_probe_argument_count (probe);
+-
++ n_args = get_probe_argument_count (probe);
+ if (n >= n_args)
+ return NULL;
+
+- return probe_fns->sym_evaluate_probe_argument (probe, n);
++ return evaluate_probe_argument (probe, n);
+ }
+
+ /* See comment in probe.h. */
+
+--uuKVzAmB+c+zQlhu--
+
diff --git a/gdb-dlopen-stap-probe-2of7.patch b/gdb-dlopen-stap-probe-2of7.patch
new file mode 100644
index 0000000..3606cec
--- /dev/null
+++ b/gdb-dlopen-stap-probe-2of7.patch
@@ -0,0 +1,198 @@
+http://sourceware.org/ml/gdb-patches/2013-05/msg00627.html
+Subject: [RFA 2/7] API for inhibiting section map updates
+
+
+--bPg9NdpM9EETxvqt
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch adds a couple of functions to allow section map updates
+to be temporarily inhibited. Without this ability, the calls to
+evaluate_probe_argument in svr4_handle_solib_event trigger a section
+map update every time a group of shared objects are mapped, which
+significantly affects performance. The updates are unnecessary in
+this case as the sections in question are in the runtime linker and
+so already in the section map.
+
+--bPg9NdpM9EETxvqt
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-2-inhibit-sm-updates.patch"
+
+2013-05-16 Gary Benson <gbenson at redhat.com>
+
+ * objfiles.h (inhibit_section_map_updates): New function
+ declaration.
+ (resume_section_map_updates): Likewise.
+ (resume_section_map_updates_cleanup): Likewise.
+ * objfiles.c (objfile_pspace_info): 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.
+
+diff --git a/gdb/objfiles.h b/gdb/objfiles.h
+index 93149e2..0b7eea9 100644
+--- a/gdb/objfiles.h
++++ b/gdb/objfiles.h
+@@ -501,6 +501,22 @@ extern int in_plt_section (CORE_ADDR, char *);
+ 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 (void);
++
++/* Resume automatically rebuilding the section map as required. */
++extern void resume_section_map_updates (void);
++
++/* Version of the above suitable for use as a cleanup. */
++extern void resume_section_map_updates_cleanup (void *arg);
++
+ extern void default_iterate_over_objfiles_in_search_order
+ (struct gdbarch *gdbarch,
+ iterate_over_objfiles_in_search_order_cb_ftype *cb,
+diff --git a/gdb/objfiles.c b/gdb/objfiles.c
+index 3e49ea2..3af1064 100644
+--- a/gdb/objfiles.c
++++ b/gdb/objfiles.c
+@@ -67,9 +67,18 @@ struct objfile *rt_common_objfile; /* For runtime common symbols */
+
+ 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 @@ allocate_objfile (bfd *abfd, int flags)
+ 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 @@ free_objfile (struct objfile *objfile)
+ 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 @@ objfile_relocate1 (struct objfile *objfile,
+ }
+
+ /* 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 @@ static void
+ 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 (current_program_space);
++ gdb_assert (pspace_info->section_map_dirty != 0
++ || pspace_info->new_objfiles_available != 0);
+
+ map = *pmap;
+ xfree (map);
+@@ -1365,7 +1377,9 @@ find_pc_section (CORE_ADDR pc)
+ return s;
+
+ pspace_info = get_objfile_pspace_data (current_program_space);
+- if (pspace_info->objfiles_changed_p != 0)
++ if (pspace_info->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 @@ find_pc_section (CORE_ADDR pc)
+
+ /* 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 @@ in_plt_section (CORE_ADDR pc, char *name)
+ }
+
+
+-/* 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 (void)
++{
++ get_objfile_pspace_data (current_program_space)->inhibit_updates = 1;
++}
++
++/* See comments in objfiles.h. */
++
++void
++resume_section_map_updates (void)
++{
++ get_objfile_pspace_data (current_program_space)->inhibit_updates = 0;
++}
++
++/* See comments in objfiles.h. */
++
++void
++resume_section_map_updates_cleanup (void *arg)
++{
++ resume_section_map_updates ();
+ }
+
+ /* The default implementation for the "iterate_over_objfiles_in_search_order"
+
+--bPg9NdpM9EETxvqt--
+
diff --git a/gdb-dlopen-stap-probe-3of7.patch b/gdb-dlopen-stap-probe-3of7.patch
index 2337ded..93251ca 100644
--- a/gdb-dlopen-stap-probe-3of7.patch
+++ b/gdb-dlopen-stap-probe-3of7.patch
@@ -1,98 +1,314 @@
-2012-07-19 Gary Benson <gbenson at redhat.com>
+http://sourceware.org/ml/gdb-patches/2013-05/msg00626.html
+Subject: [RFA 3/7] New gdbserver functionality
- * probe.h (get_probe_argument_count): New declaration.
- (evaluate_probe_argument): Likewise.
- * probe.c (get_probe_argument_count): New function.
- (evaluate_probe_argument): Likewise.
- (probe_safe_evaluate_at_pc): Use the above new functions.
-diff --git a/gdb/probe.h b/gdb/probe.h
-index 8d44ca2..1d29b87 100644
---- a/gdb/probe.h
-+++ b/gdb/probe.h
-@@ -214,6 +214,16 @@ extern void info_probes_for_ops (char *arg, int from_tty,
+--Kc9HNjpzOXVc7FFU
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch updates gdbserver to allow arguments to be passed in the
+annex of qXfer:libraries-svr4:read to allow that function to transfer
+partial lists of libraries. The ability of gdbserver to support
+these arguments is indicated by a qSupported response containing
+"augmented-libraries-svr4-read+".
+
+--Kc9HNjpzOXVc7FFU
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-3-gdbserver.patch"
+
+2013-05-16 Gary Benson <gbenson at 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.
+
+diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
+index 6bb36d8..0a8f68b 100644
+--- a/gdb/gdbserver/server.c
++++ b/gdb/gdbserver/server.c
+@@ -1115,8 +1115,7 @@ handle_qxfer_libraries_svr4 (const char *annex,
+ if (writebuf != NULL)
+ return -2;
- extern struct cmd_list_element **info_probes_cmdlist_get (void);
+- 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 argument count of the specified probe. */
-+
-+extern unsigned get_probe_argument_count (struct probe *probe);
-+
-+/* Evaluate argument N of the specified probe. N must be between 0
-+ inclusive and get_probe_argument_count exclusive. */
-+
-+extern struct value *evaluate_probe_argument (struct probe *probe,
-+ unsigned n);
-+
- /* A convenience function that finds a probe at the PC in FRAME and
- evaluates argument N, with 0 <= N < number_of_args. If there is no
- probe at that location, or if the probe does not have enough arguments,
-diff --git a/gdb/probe.c b/gdb/probe.c
-index 77f3b13..a61f4ea 100644
---- a/gdb/probe.c
-+++ b/gdb/probe.c
-@@ -632,28 +632,55 @@ info_probes_command (char *arg, int from_tty)
+ return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, offset, len);
+@@ -1743,7 +1742,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
+ PBUFSIZ - 1);
- /* See comments in probe.h. */
+ 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
+diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
+index 72c51e0..beb3b8f 100644
+--- a/gdb/gdbserver/linux-low.c
++++ b/gdb/gdbserver/linux-low.c
+@@ -5677,6 +5677,12 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
+ };
+ 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;
-+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;
+ if (writebuf != NULL)
+ return -2;
+@@ -5687,128 +5693,146 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
+ 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);
++ if (annex[0] == '\0')
++ {
++ int r_version = 0;
+
+- /* 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)
++ priv->r_debug = get_r_debug (pid, is_elf64);
+
+- if (priv->r_debug == 0)
+- {
+- document = xstrdup ("<library-list-svr4 version=\"1.0\"/>\n");
++ /* 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;
+
-+ gdb_assert (probe->objfile != NULL);
-+ gdb_assert (probe->objfile->sf != NULL);
++ if (priv->r_debug != 0)
++ {
++ 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);
++ }
++ }
+ }
+ else
+ {
+- 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)
++ while (annex[0] != '\0')
+ {
+- warning ("unexpected r_debug version %d", r_version);
+- goto done;
++ const char *sep;
++ CORE_ADDR *addrp;
++ int len;
+
-+ probe_fns = probe->objfile->sf->sym_probe_fns;
++ sep = strchr (annex, '=');
++ if (!sep)
++ break;
+
-+ gdb_assert (probe_fns != NULL);
++ len = sep - annex;
++ if (len == 5 && !strncmp (annex, "start", 5))
++ addrp = &lm_addr;
++ else if (len == 4 && !strncmp (annex, "prev", 4))
++ addrp = &lm_prev;
++ else
++ {
++ annex = strchr (sep, ';');
++ if (!annex)
++ break;
++ annex++;
++ continue;
++ }
+
-+ return probe_fns->sym_evaluate_probe_argument (probe, n);
-+}
++ annex = decode_address_to_semicolon (addrp, sep + 1);
+ }
++ }
+
+- if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
+- &lm_addr, ptr_size) != 0)
++ document = xmalloc (allocated);
++ strcpy (document, "<library-list-svr4 version=\"1.0\"");
++ p = document + strlen (document);
+
-+/* See comments in probe.h. */
++ 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];
+
- 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;
++ 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;
- probe = find_probe_by_pc (get_frame_pc (frame));
- if (!probe)
- return NULL;
+- 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;
+ }
-- gdb_assert (probe->objfile != NULL);
-- gdb_assert (probe->objfile->sf != NULL);
-- gdb_assert (probe->objfile->sf->sym_probe_fns != NULL);
+- /* 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;
-
-- probe_fns = probe->objfile->sf->sym_probe_fns;
-- n_args = probe_fns->sym_get_probe_argument_count (probe);
+- if (!header_done)
+- {
+- /* Terminate `<library-list-svr4'. */
+- *p++ = '>';
+- header_done = 1;
+- }
-
-+ n_args = get_probe_argument_count (probe);
- if (n >= n_args)
- return NULL;
+- 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;
+- }
++ /* Expand to guarantee sufficient storage. */
++ uintptr_t document_len = p - document;
+
+- 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);
++ document = xrealloc (document, 2 * allocated);
++ allocated *= 2;
++ p = document + document_len;
+ }
-- return probe_fns->sym_evaluate_probe_argument (probe, n);
-+ return evaluate_probe_argument (probe, n);
- }
+- if (l_next == 0)
+- break;
+-
+- 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;
+ }
- /* See comment in probe.h. */
++ 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;
+
+--Kc9HNjpzOXVc7FFU--
+
diff --git a/gdb-dlopen-stap-probe-4of7.patch b/gdb-dlopen-stap-probe-4of7.patch
index 299931a..224c366 100644
--- a/gdb-dlopen-stap-probe-4of7.patch
+++ b/gdb-dlopen-stap-probe-4of7.patch
@@ -1,131 +1,146 @@
-2012-07-19 Gary Benson <gbenson at redhat.com>
+http://sourceware.org/ml/gdb-patches/2013-05/msg00628.html
+Subject: [RFA 4/7] GDB support for new gdbserver functionality
- * solib-svr4.c (svr4_info): Move earlier.
- (solib_svr4_pspace_data): Likewise.
- (svr4_pspace_data_cleanup): Likewise.
- (get_svr4_info): Likewise.
-diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
-index 307e483..c88b9cb 100644
---- a/gdb/solib-svr4.c
-+++ b/gdb/solib-svr4.c
-@@ -106,6 +106,59 @@ static const char * const main_name_list[] =
- NULL
- };
+--CaPKgh3XHpq3rEUV
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch adds client support for the new gdbserver functionality
+provided by patch 3 of this series.
+
+--CaPKgh3XHpq3rEUV
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-4-remote.patch"
+
+2013-05-16 Gary Benson <gbenson at 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.
+
+diff --git a/gdb/target.h b/gdb/target.h
+index e937d39..a8587e8 100644
+--- a/gdb/target.h
++++ b/gdb/target.h
+@@ -941,6 +941,10 @@ struct target_ops
+ (inclusive) to function END (exclusive). */
+ void (*to_call_history_range) (ULONGEST begin, ULONGEST end, int flags);
-+/* Per pspace SVR4 specific data. */
-+
-+struct svr4_info
-+{
-+ CORE_ADDR debug_base; /* Base of dynamic linker structures. */
++ /* Nonzero if TARGET_OBJECT_LIBRARIES_SVR4 may be read with a
++ non-empty annex. */
++ int (*to_augmented_libraries_svr4_read) (void);
+
-+ /* Validity flag for debug_loader_offset. */
-+ int debug_loader_offset_p;
-+
-+ /* Load address for the dynamic linker, inferred. */
-+ CORE_ADDR debug_loader_offset;
-+
-+ /* Name of the dynamic linker, valid if debug_loader_offset_p. */
-+ char *debug_loader_name;
-+
-+ /* Load map address for the main executable. */
-+ CORE_ADDR main_lm_addr;
-+
-+ CORE_ADDR interp_text_sect_low;
-+ CORE_ADDR interp_text_sect_high;
-+ CORE_ADDR interp_plt_sect_low;
-+ CORE_ADDR interp_plt_sect_high;
-+};
+ int to_magic;
+ /* Need sub-structure for target machine related rather than comm related?
+ */
+@@ -1809,6 +1813,9 @@ extern char *target_fileio_read_stralloc (const char *filename);
+ #define target_can_use_agent() \
+ (*current_target.to_can_use_agent) ()
+
++#define target_augmented_libraries_svr4_read() \
++ (*current_target.to_augmented_libraries_svr4_read) ()
+
-+/* Per-program-space data key. */
-+static const struct program_space_data *solib_svr4_pspace_data;
+ /* Command logging facility. */
+
+ #define target_log_command(p) \
+diff --git a/gdb/target.c b/gdb/target.c
+index 8653dac..519b97f 100644
+--- a/gdb/target.c
++++ b/gdb/target.c
+@@ -731,6 +731,7 @@ update_current_target (void)
+ 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 @@ update_current_target (void)
+ 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
+diff --git a/gdb/remote.c b/gdb/remote.c
+index 51bf025..e1cf8a4 100644
+--- a/gdb/remote.c
++++ b/gdb/remote.c
+@@ -343,6 +343,10 @@ struct remote_state
+ /* 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;
+@@ -3931,6 +3935,16 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
+ rs->string_tracing = (support == PACKET_ENABLE);
+ }
+
+static void
-+svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
++remote_augmented_libraries_svr4_read_feature
++ (const struct protocol_feature *feature,
++ enum packet_support support, const char *value)
+{
-+ struct svr4_info *info;
++ struct remote_state *rs = get_remote_state ();
+
-+ info = program_space_data (pspace, solib_svr4_pspace_data);
-+ xfree (info);
++ rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
+}
+
-+/* Get the current svr4 data. If none is found yet, add it now. This
-+ function always returns a valid object. */
-+
-+static struct svr4_info *
-+get_svr4_info (void)
+ static struct protocol_feature remote_protocol_features[] = {
+ { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
+ { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
+@@ -3941,6 +3955,8 @@ static struct protocol_feature remote_protocol_features[] = {
+ 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,
+@@ -11343,6 +11359,14 @@ remote_read_btrace (struct btrace_target_info *tinfo,
+ return btrace;
+ }
+
++static int
++remote_augmented_libraries_svr4_read (void)
+{
-+ struct svr4_info *info;
-+
-+ info = program_space_data (current_program_space, solib_svr4_pspace_data);
-+ if (info != NULL)
-+ return info;
++ struct remote_state *rs = get_remote_state ();
+
-+ info = XZALLOC (struct svr4_info);
-+ set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
-+ return info;
++ return rs->augmented_libraries_svr4_read;
+}
+
- /* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent
- the same shared library. */
-
-@@ -291,59 +344,6 @@ lm_addr_check (struct so_list *so, bfd *abfd)
- return so->lm_info->l_addr;
+ static void
+ init_remote_ops (void)
+ {
+@@ -11465,6 +11489,8 @@ Specify the serial device it is connected to\n\
+ 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;
}
--/* Per pspace SVR4 specific data. */
--
--struct svr4_info
--{
-- CORE_ADDR debug_base; /* Base of dynamic linker structures. */
--
-- /* Validity flag for debug_loader_offset. */
-- int debug_loader_offset_p;
--
-- /* Load address for the dynamic linker, inferred. */
-- CORE_ADDR debug_loader_offset;
--
-- /* Name of the dynamic linker, valid if debug_loader_offset_p. */
-- char *debug_loader_name;
--
-- /* Load map address for the main executable. */
-- CORE_ADDR main_lm_addr;
--
-- CORE_ADDR interp_text_sect_low;
-- CORE_ADDR interp_text_sect_high;
-- CORE_ADDR interp_plt_sect_low;
-- CORE_ADDR interp_plt_sect_high;
--};
--
--/* Per-program-space data key. */
--static const struct program_space_data *solib_svr4_pspace_data;
--
--static void
--svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
--{
-- struct svr4_info *info;
--
-- info = program_space_data (pspace, solib_svr4_pspace_data);
-- xfree (info);
--}
--
--/* Get the current svr4 data. If none is found yet, add it now. This
-- function always returns a valid object. */
--
--static struct svr4_info *
--get_svr4_info (void)
--{
-- struct svr4_info *info;
--
-- info = program_space_data (current_program_space, solib_svr4_pspace_data);
-- if (info != NULL)
-- return info;
--
-- info = XZALLOC (struct svr4_info);
-- set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
-- return info;
--}
--
- /* Local function prototypes */
-
- static int match_main (const char *);
+ /* Set up the extended remote vector by making a copy of the standard
+
+--CaPKgh3XHpq3rEUV--
+
diff --git a/gdb-dlopen-stap-probe-5of7.patch b/gdb-dlopen-stap-probe-5of7.patch
index cb18cd6..2ea873d 100644
--- a/gdb-dlopen-stap-probe-5of7.patch
+++ b/gdb-dlopen-stap-probe-5of7.patch
@@ -1,17 +1,1089 @@
-2012-07-19 Gary Benson <gbenson at redhat.com>
+http://sourceware.org/ml/gdb-patches/2013-05/msg00632.html
+Subject: [RFA 5/7] Improved linker-debugger interface
- * solib-svr4.c (svr4_info): Made debug_loader_offset_p a bitfield.
-diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
-index c88b9cb..8e41f19 100644
---- a/gdb/solib-svr4.c
-+++ b/gdb/solib-svr4.c
-@@ -113,7 +113,7 @@ struct svr4_info
- CORE_ADDR debug_base; /* Base of dynamic linker structures. */
+--qse+WBH4guesipZ+
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch implements the probes-based runtime linker interface.
+It works as follows:
+
+ - On inferior startup, GDB searches the dynamic linker for a
+ number of named probes.
+
+ - If all probes are found, GDB sets a breakpoint on each one.
+ Otherwise, the standard function _dl_debug_state is used.
+
+ - When using probes, a per-pspace list is maintained of all
+ libraries currently loaded by the inferior. It's updated
+ as necessary every time a solib event stop occurs.
+
+ - When using probes, svr4_current_sos will return a copy of
+ the cached list. When not using probes the entire list
+ will be fetched from the inferior as before.
+
+ - If any error occurs, GDB will print a warning and revert to
+ the standard interface.
+
+--qse+WBH4guesipZ+
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-5-main-changes.patch"
+
+2013-05-16 Gary Benson <gbenson at 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.
+
+Index: gdb-7.6/gdb/breakpoint.h
+===================================================================
+--- gdb-7.6.orig/gdb/breakpoint.h 2013-05-19 16:16:20.551087270 +0200
++++ gdb-7.6/gdb/breakpoint.h 2013-05-19 16:16:20.837086948 +0200
+@@ -1552,8 +1552,6 @@ extern int user_breakpoint_p (struct bre
+ /* Attempt to determine architecture of location identified by SAL. */
+ extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
+
+-extern void handle_solib_event (void);
+-
+ extern void breakpoint_free_objfile (struct objfile *objfile);
+
+ extern void breakpoints_relocate (struct objfile *objfile,
+Index: gdb-7.6/gdb/solib.h
+===================================================================
+--- gdb-7.6.orig/gdb/solib.h 2013-01-01 07:32:51.000000000 +0100
++++ gdb-7.6/gdb/solib.h 2013-05-19 16:16:20.838086946 +0200
+@@ -90,4 +90,12 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f
+ 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-7.6/gdb/solib.c
+===================================================================
+--- gdb-7.6.orig/gdb/solib.c 2013-05-19 16:16:20.468087363 +0200
++++ gdb-7.6/gdb/solib.c 2013-05-19 16:16:20.838086946 +0200
+@@ -1221,6 +1221,38 @@ no_shared_libraries (char *ignored, int
+ objfile_purge_solibs ();
+ }
+
++/* See solib.h. */
++
++void
++update_solib_breakpoints (void)
++{
++ struct target_so_ops *ops = solib_ops (target_gdbarch ());
++
++ if (ops->update_breakpoints != NULL)
++ ops->update_breakpoints ();
++}
++
++/* See solib.h. */
++
++void
++handle_solib_event (void)
++{
++ 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, ¤t_target, auto_solib_add);
++ target_terminal_inferior ();
++}
++
++
+ /* Reload shared libraries, but avoid reloading the same symbol file
+ we already have loaded. */
+
+Index: gdb-7.6/gdb/solist.h
+===================================================================
+--- gdb-7.6.orig/gdb/solist.h 2013-01-01 07:32:51.000000000 +0100
++++ gdb-7.6/gdb/solist.h 2013-05-19 16:16:20.838086946 +0200
+@@ -148,6 +148,19 @@ struct target_so_ops
+ 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-7.6/gdb/infrun.c
+===================================================================
+--- gdb-7.6.orig/gdb/infrun.c 2013-05-19 16:16:20.508087318 +0200
++++ gdb-7.6/gdb/infrun.c 2013-05-19 16:16:20.840086944 +0200
+@@ -370,6 +370,16 @@ static struct symbol *step_start_functio
+ /* Nonzero if we want to give control to the user when we're notified
+ of shared library events by the dynamic linker. */
+ int stop_on_solib_events;
++
++/* Enable or disable optional shared library event breakpoints
++ as appropriate when the above flag is changed. */
++
++static void
++set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
++{
++ update_solib_breakpoints ();
++}
++
+ static void
+ show_stop_on_solib_events (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+@@ -7335,7 +7345,7 @@ Show stopping for shared library events.
+ If nonzero, gdb will give control to the user when the dynamic linker\n\
+ notifies gdb of shared library events. The most common event of interest\n\
+ to the user would be loading/unloading of a new library."),
+- NULL,
++ set_stop_on_solib_events,
+ show_stop_on_solib_events,
+ &setlist, &showlist);
+
+Index: gdb-7.6/gdb/solib-svr4.c
+===================================================================
+--- gdb-7.6.orig/gdb/solib-svr4.c 2013-05-19 16:16:20.468087363 +0200
++++ gdb-7.6/gdb/solib-svr4.c 2013-05-19 16:21:40.285816084 +0200
+@@ -47,9 +47,12 @@
+ #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 +109,55 @@ static const char * const main_name_lis
+ 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 +365,56 @@ struct svr4_info
+ 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 mapping breakpoint addresses to probes and actions, used
++ by the probes-based interface. */
++ 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);
+ }
+
+@@ -982,6 +1073,36 @@ svr4_free_library_list (void *p_list)
+ }
+ }
+
++/* Copy library list. */
++
++static struct so_list *
++svr4_copy_library_list (struct so_list *src)
++{
++ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
++ struct so_list *dst = NULL;
++ struct so_list **link = &dst;
++
++ while (src != NULL)
++ {
++ struct so_list *new;
++
++ new = XZALLOC (struct so_list);
++
++ memcpy (new, src, sizeof (struct so_list));
++
++ new->lm_info = xmalloc (lmo->link_map_size);
++ memcpy (new->lm_info, src->lm_info, lmo->link_map_size);
++
++ new->next = NULL;
++ *link = new;
++ link = &new->next;
++
++ src = src->next;
++ }
++
++ return dst;
++}
++
+ #ifdef HAVE_LIBEXPAT
+
+ #include "xml-support.h"
+@@ -1097,14 +1218,19 @@ svr4_parse_libraries (const char *docume
+ 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;
+@@ -1113,7 +1239,7 @@ svr4_current_sos_via_xfer_libraries (str
+ /* Fetch the list of shared libraries. */
+ svr4_library_document = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_LIBRARIES_SVR4,
+- NULL);
++ annex);
+ if (svr4_library_document == NULL)
+ return 0;
+
+@@ -1127,7 +1253,8 @@ svr4_current_sos_via_xfer_libraries (str
+ #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;
+ }
+@@ -1161,15 +1288,17 @@ svr4_default_sos (void)
+ return new;
+ }
+
+-/* Read the whole inferior libraries chain starting at address LM. Add the
+- entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if
+- IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */
++/* Read the whole inferior libraries chain starting at address LM.
++ Expect the first entry in the chain's previous entry to be PREV_LM.
++ Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the
++ first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according
++ to it. Returns nonzero upon success. */
+
+-static void
+-svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr,
+- int ignore_first)
++static int
++svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
++ struct so_list ***link_ptr_ptr, int ignore_first)
+ {
+- CORE_ADDR prev_lm = 0, next_lm;
++ CORE_ADDR next_lm;
+
+ for (; lm != 0; prev_lm = lm, lm = next_lm)
+ {
+@@ -1185,7 +1314,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
+ if (new->lm_info == NULL)
+ {
+ do_cleanups (old_chain);
+- break;
++ return 0;
+ }
+
+ next_lm = new->lm_info->l_next;
+@@ -1196,7 +1325,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
+ paddress (target_gdbarch (), prev_lm),
+ paddress (target_gdbarch (), new->lm_info->l_prev));
+ do_cleanups (old_chain);
+- break;
++ return 0;
+ }
+
+ /* For SVR4 versions, the first entry in the link map is for the
+@@ -1291,17 +1420,19 @@ svr4_read_so_list (CORE_ADDR lm, struct
+ **link_ptr_ptr = new;
+ *link_ptr_ptr = &new->next;
+ }
++
++ return 1;
+ }
+
+-/* Implement the "current_sos" target_so_ops method. */
++/* Read the full list of currently loaded shared objects directly from
++ the inferior. */
+
+ 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;
+@@ -1314,19 +1445,16 @@ svr4_current_sos (void)
+ 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);
+@@ -1349,7 +1477,7 @@ svr4_current_sos (void)
+ `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
+@@ -1357,7 +1485,7 @@ svr4_current_sos (void)
+ 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);
+
+@@ -1367,6 +1495,22 @@ svr4_current_sos (void)
+ 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 we are using the probes interface and the solib list has
++ been cached then we simply return that. */
++ 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
+@@ -1449,6 +1593,434 @@ exec_entry_point (struct bfd *abfd, stru
+ 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. Returns nonzero on success. */
++
++static int
++solist_update_full (struct svr4_info *info)
++{
++ svr4_free_library_list (&info->solib_list);
++ 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;
++
++ /* Fall back to a full update if we haven't read anything yet. */
++ 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; tail = tail->next);
++ 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=%lx;prev=%lx", lm, 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;
++
++ 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)
++ goto error;
++
++ action = solib_event_probe_action (pa);
++ if (action == PROBES_INTERFACE_FAILED)
++ goto error;
++
++ if (action == DO_NOTHING)
++ 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 ();
++ usm_chain = make_cleanup (resume_section_map_updates_cleanup, NULL);
++
++ val = evaluate_probe_argument (pa->probe, 1);
++ if (val == NULL)
++ goto error;
++
++ debug_base = value_as_address (val);
++ if (debug_base == 0)
++ goto error;
++
++ /* Always locate the debug struct, in case it moved. */
++ info->debug_base = 0;
++ if (locate_base (info) == 0)
++ goto error;
++
++ /* Do not process namespaces other than the initial one. */
++ 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))
++ goto error;
++ }
++
++ discard_cleanups (old_chain);
++ return;
++
++ error:
++ /* We should never reach here, but if we do we disable the
++ probes interface and revert to the original interface. */
++
++ do_cleanups (old_chain);
++}
++
++/* Helper function for svr4_update_solib_event_breakpoints. */
++
++static int
++svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
++{
++ struct svr4_info *info = get_svr4_info ();
++ struct bp_location *loc;
++
++ if (b->type != bp_shlib_event)
++ return 0; /* Continue iterating. */
++
++ for (loc = b->loc; loc; loc = loc->next)
++ {
++ struct probe_and_action *pa = solib_event_probe_at (info, loc->address);
++
++ if (pa != NULL)
++ {
++ if (pa->action == DO_NOTHING)
++ b->enable_state = (stop_on_solib_events
++ ? bp_enabled : bp_disabled);
++
++ return 0; /* Continue iterating. */
++ }
++ }
++
++ return 0; /* Continue iterating. */
++}
++
++/* Enable or disable optional solib event breakpoints as appropriate.
++ Called whenever stop_on_solib_events is changed. */
++
++static void
++svr4_update_solib_event_breakpoints (void)
++{
++ struct svr4_info *info = get_svr4_info ();
++
++ if (info->probes_table)
++ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
++}
++
++/* Create and register solib event breakpoints. */
++
++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 svr4_info *info = get_svr4_info ();
++ struct obj_section *os;
++
++ os = find_pc_section (address);
++ if (os != NULL)
++ {
++ int with_prefix;
++
++ for (with_prefix = 0; with_prefix <= 1; with_prefix++)
++ {
++ 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++)
++ {
++ char name[32] = { '\0' };
++
++ /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an
++ early version of the probes code in which the probes'
++ names were prefixed with "rtld_" 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)
++ strncat (name, "rtld_", sizeof (name) - strlen (name) - 1);
++
++ strncat (name, probe_info[i].name,
++ sizeof (name) - strlen (name) - 1);
++
++ probes[i] = find_probes_in_objfile (os->objfile, "rtld", name);
++
++ if (!strcmp (name, "rtld_map_failed"))
++ continue;
++
++ if (!VEC_length (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
+@@ -1501,6 +2073,8 @@ enable_break (struct svr4_info *info, in
+ info->interp_text_sect_low = info->interp_text_sect_high = 0;
+ info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
+
++ free_probes_table (info);
++
+ /* If we already have a shared library list in the target, and
+ r_debug contains r_brk, set the breakpoint there - this should
+ mean r_brk has already been relocated. Assume the dynamic linker
+@@ -1532,7 +2106,7 @@ enable_break (struct svr4_info *info, in
+ That knowledge is encoded in the address, if it's Thumb the low bit
+ is 1. However, we've stripped that info above and it's not clear
+ what all the consequences are of passing a non-addr_bits_remove'd
+- address to create_solib_event_breakpoint. The call to
++ address to svr4_create_solib_event_breakpoints. The call to
+ find_pc_section verifies we know about the address and have some
+ hope of computing the right kind of breakpoint to use (via
+ symbol info). It does mean that GDB needs to be pointed at a
+@@ -1570,7 +2144,7 @@ enable_break (struct svr4_info *info, in
+ + bfd_section_size (tmp_bfd, interp_sect);
+ }
+
+- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
++ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ return 1;
+ }
+ }
+@@ -1728,7 +2302,8 @@ enable_break (struct svr4_info *info, in
+
+ if (sym_addr != 0)
+ {
+- create_solib_event_breakpoint (target_gdbarch (), load_addr + sym_addr);
++ svr4_create_solib_event_breakpoints (target_gdbarch (),
++ load_addr + sym_addr);
+ xfree (interp_name);
+ return 1;
+ }
+@@ -1754,7 +2329,7 @@ enable_break (struct svr4_info *info, in
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
+ sym_addr,
+ ¤t_target);
+- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
++ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ return 1;
+ }
+ }
+@@ -1770,7 +2345,7 @@ enable_break (struct svr4_info *info, in
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
+ sym_addr,
+ ¤t_target);
+- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
++ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ return 1;
+ }
+ }
+@@ -2266,6 +2841,9 @@ svr4_solib_create_inferior_hook (int fro
+
+ info = get_svr4_info ();
+
++ /* Free the probes-based interface's solib list. */
++ free_solib_list (info);
++
+ /* Relocate the main executable if necessary. */
+ svr4_relocate_main_executable ();
+
+@@ -2507,4 +3085,6 @@ _initialize_svr4_solib (void)
+ svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
+ svr4_so_ops.same = svr4_same;
+ svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
++ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
++ svr4_so_ops.handle_event = svr4_handle_solib_event;
+ }
+Index: gdb-7.6/gdb/breakpoint.c
+===================================================================
+--- gdb-7.6.orig/gdb/breakpoint.c 2013-05-19 16:16:20.606087208 +0200
++++ gdb-7.6/gdb/breakpoint.c 2013-05-19 16:21:55.288805269 +0200
+@@ -5361,25 +5361,6 @@ handle_jit_event (void)
+ target_terminal_inferior ();
+ }
- /* Validity flag for debug_loader_offset. */
-- int debug_loader_offset_p;
-+ unsigned int debug_loader_offset_p : 1;
+-/* Handle an solib event by calling solib_add. */
+-
+-void
+-handle_solib_event (void)
+-{
+- clear_program_space_solib_cache (current_inferior ()->pspace);
+-
+- /* Check for any newly added shared libraries if we're supposed to
+- be adding them automatically. Switch terminal for any messages
+- produced by breakpoint_re_set. */
+- target_terminal_ours_for_output ();
+-#ifdef SOLIB_ADD
+- SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
+-#else
+- solib_add (NULL, 0, ¤t_target, auto_solib_add);
+-#endif
+- target_terminal_inferior ();
+-}
+-
+ /* Prepare WHAT final decision for infrun. */
- /* Load address for the dynamic linker, inferred. */
- CORE_ADDR debug_loader_offset;
+ /* Decide what infrun needs to do with this bpstat. */
diff --git a/gdb-dlopen-stap-probe-6of7.patch b/gdb-dlopen-stap-probe-6of7.patch
index aca4bfd..500ab34 100644
--- a/gdb-dlopen-stap-probe-6of7.patch
+++ b/gdb-dlopen-stap-probe-6of7.patch
@@ -1,1501 +1,165 @@
-gdb/
-2012-07-30 Gary Benson <gbenson at redhat.com>
+http://sourceware.org/ml/gdb-patches/2013-05/msg00631.html
+Subject: [RFA 6/7] Linker-debugger interface tests by Jan
- * breakpoint.h (handle_solib_event): Moved function definition
- to solib.h, and added a new parameter.
- * breakpoint.c (handle_solib_event): Moved function to solib.c
- and added a new parameter.
- (bpstat_stop_status): Pass new argument to handle_solib_event.
- * solib.h (breakpoint.h): New include.
- (handle_solib_event): Moved function definition from breakpoint.h
- and added a new parameter.
- (update_solib_breakpoints): New function definition.
- * solib.c (handle_solib_event): Moved function from breakpoint.c
- and added a new parameter.
- (update_solib_breakpoints): New function.
- * solist.h (breakpoint.h): New include.
- (target_so_ops): New fields "handle_solib_event" and
- "update_breakpoints".
- * infrun.c (set_stop_on_solib_events): New function.
- (_initialize_infrun): Use the above for "set stop-on-solib-events".
- (handle_inferior_event): Pass new argument to handle_solib_event.
- * solib-svr4.c (probe.h): New include.
- (namespace_table_flatten): New forward declaration.
- (lm_info): New fields "lmid" and "in_initial_ns".
- (probe_action): New enum.
- (probe_info): New struct.
- (probe_info): New static variable.
- (NUM_PROBES): New definition.
- (svr4_info): New fields "using_probes", "probes" and
- "namespace_table".
- (free_probes): New function.
- (free_namespace_table): Likewise.
- (svr4_pspace_data_cleanup): Free probes and namespace table.
- (svr4_same): Also compare namespaces if using probes.
- (lm_addr_check): Only print .dynamic section at wrong address
- warning for initial namespace if using probes.
- (r_map_from_debug_base): New function.
- (solib_svr4_r_map): Call the above.
- (svr4_read_so_list): New parameter "prev_lm".
- Changed return type from void to int.
- Return nonzero on success, zero on error.
- (svr4_current_sos_from_debug_base): New function.
- (svr4_current_sos): Create result from namespace table if available.
- Use svr4_current_sos_from_debug_base to generate list otherwise.
- (probe_and_info): New struct.
- (solib_event_probe_at): New function.
- (solib_event_probe_action): Likewise.
- (namespace): New struct.
- (hash_namespace): New function.
- (equal_namespace): Likewise.
- (free_namespace): Likewise.
- (namespace_update_full): Likewise.
- (namespace_update_incremental): Likewise.
- (svr4_handle_solib_event): Likewise.
- (namespace_table_flatten_helper): Likewise.
- (namespace_table_flatten): Likewise.
- (svr4_update_solib_event_breakpoint): Likewise.
- (svr4_update_solib_event_breakpoints): Likewise.
- (svr4_create_solib_event_breakpoints): Likewise.
- (enable_break): Free probes before creating breakpoints.
- Use svr4_create_solib_event_breakpoints to create breakpoints.
- (svr4_solib_create_inferior_hook): Free the namespace table.
- (_initialize_svr4_solib): Initialise svr4_so_ops.handle_solib_event
- and svr4_so_ops.update_breakpoints.
-gdb/testsuite
-2012-07-30 Gary Benson <gbenson at redhat.com>
+--IYV9cRr2u6rjcP4B
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
- * gdb.base/break-interp.exp (solib_bp): New constant.
- (reach_1): Use the above instead of "_dl_debug_state".
- (test_attach): Likewise.
- (test_ld): Likewise.
- * gdb.base/break-probes.exp: New file.
- * gdb.base/break-probes.c: Likewise.
- * gdb.base/break-probes-solib.c: Likewise.
- * gdb.base/info-shared.exp: New file.
- * gdb.base/info-shared.c: Likewise.
- * gdb.base/info-shared-solib1.c: Likewise.
- * gdb.base/info-shared-solib2.c: Likewise.
- * gdb.base/break-dlmopen.exp: Likewise.
- * gdb.base/break-dlmopen.c: Likewise.
- * gdb.base/break-dlmopen-solib.c: Likewise.
-
-Index: gdb-7.5.50.20130215/gdb/breakpoint.h
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/breakpoint.h 2013-02-15 22:37:19.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/breakpoint.h 2013-02-15 22:37:47.185432296 +0100
-@@ -1552,8 +1552,6 @@ extern int user_breakpoint_p (struct bre
- /* Attempt to determine architecture of location identified by SAL. */
- extern struct gdbarch *get_sal_arch (struct symtab_and_line sal);
-
--extern void handle_solib_event (void);
--
- extern void breakpoint_free_objfile (struct objfile *objfile);
-
- extern void breakpoints_relocate (struct objfile *objfile,
-Index: gdb-7.5.50.20130215/gdb/breakpoint.c
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/breakpoint.c 2013-02-15 22:37:30.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/breakpoint.c 2013-02-15 22:37:35.755417584 +0100
-@@ -5250,7 +5250,7 @@ bpstat_stop_status (struct address_space
- {
- if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event)
- {
-- handle_solib_event ();
-+ handle_solib_event (bs);
- break;
- }
- }
-@@ -5346,25 +5346,6 @@ handle_jit_event (void)
- target_terminal_inferior ();
- }
-
--/* Handle an solib event by calling solib_add. */
--
--void
--handle_solib_event (void)
--{
-- clear_program_space_solib_cache (current_inferior ()->pspace);
--
-- /* Check for any newly added shared libraries if we're supposed to
-- be adding them automatically. Switch terminal for any messages
-- produced by breakpoint_re_set. */
-- target_terminal_ours_for_output ();
--#ifdef SOLIB_ADD
-- SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
--#else
-- solib_add (NULL, 0, ¤t_target, auto_solib_add);
--#endif
-- target_terminal_inferior ();
--}
--
- /* Prepare WHAT final decision for infrun. */
-
- /* Decide what infrun needs to do with this bpstat. */
-Index: gdb-7.5.50.20130215/gdb/solib.h
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/solib.h 2013-01-01 07:32:51.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/solib.h 2013-02-15 22:37:35.757417588 +0100
-@@ -20,6 +20,9 @@
- #ifndef SOLIB_H
- #define SOLIB_H
-
-+/* For bpstat. */
-+#include "breakpoint.h"
-+
- /* Forward decl's for prototypes */
- struct so_list;
- struct target_ops;
-@@ -90,4 +93,15 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f
- void *),
- void *data);
-
-+/* Handle an solib event by calling solib_add. Targets which handle
-+ solib events using breakpoints must pass a valid bpstat. Targets
-+ which handle solib events using some other mechanism should pass
-+ NULL. */
-+
-+extern void handle_solib_event (bpstat bs);
-+
-+/* Enable or disable optional solib event breakpoints as appropriate. */
-+
-+extern void update_solib_breakpoints (void);
-+
- #endif /* SOLIB_H */
-Index: gdb-7.5.50.20130215/gdb/solib.c
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/solib.c 2013-02-15 22:37:04.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/solib.c 2013-02-15 22:37:35.757417588 +0100
-@@ -1221,6 +1221,42 @@ no_shared_libraries (char *ignored, int
- objfile_purge_solibs ();
- }
-
-+/* See solib.h. */
-+
-+void
-+handle_solib_event (bpstat bs)
-+{
-+ struct target_so_ops *ops = solib_ops (target_gdbarch ());
-+
-+ if (ops->handle_solib_event != NULL)
-+ ops->handle_solib_event (bs);
-+
-+ clear_program_space_solib_cache (current_inferior ()->pspace);
-+
-+ /* Check for any newly added shared libraries if we're supposed to
-+ be adding them automatically. Switch terminal for any messages
-+ produced by breakpoint_re_set. */
-+ target_terminal_ours_for_output ();
-+#ifdef SOLIB_ADD
-+ SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
-+#else
-+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
-+#endif
-+ target_terminal_inferior ();
-+}
-+
-+/* See solib.h. */
-+
-+void
-+update_solib_breakpoints (void)
-+{
-+ struct target_so_ops *ops = solib_ops (target_gdbarch ());
-+
-+ if (ops->update_breakpoints != NULL)
-+ ops->update_breakpoints ();
-+}
-+
-+
- /* Reload shared libraries, but avoid reloading the same symbol file
- we already have loaded. */
-
-Index: gdb-7.5.50.20130215/gdb/solist.h
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/solist.h 2013-01-01 07:32:51.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/solist.h 2013-02-15 22:37:35.758417590 +0100
-@@ -22,6 +22,8 @@
- #define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
- /* For domain_enum domain. */
- #include "symtab.h"
-+/* For bpstat. */
-+#include "breakpoint.h"
-
- /* Forward declaration for target specific link map information. This
- struct is opaque to all but the target specific file. */
-@@ -148,6 +150,20 @@ struct target_so_ops
- core file (in particular, for readonly sections). */
- int (*keep_data_in_core) (CORE_ADDR vaddr,
- unsigned long size);
-+
-+ /* Target-specific handling of solib events. For targets which
-+ handle solib events using breakpoints a valid bpstat must be
-+ passed. Targets which handle solib events using some other
-+ mechanism should pass NULL. This pointer can be NULL, in which
-+ case no specific handling is necessary for this target. */
-+ void (*handle_solib_event) (bpstat bs);
-+
-+ /* Enable or disable optional solib event breakpoints as
-+ appropriate. This should be called whenever
-+ stop_on_solib_events is changed. This pointer can be
-+ NULL, in which case no enabling or disabling is necessary
-+ for this target. */
-+ void (*update_breakpoints) (void);
- };
-
- /* Free the memory associated with a (so_list *). */
-Index: gdb-7.5.50.20130215/gdb/infrun.c
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/infrun.c 2013-02-15 22:37:04.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/infrun.c 2013-02-15 22:37:35.760417594 +0100
-@@ -369,6 +369,16 @@ static struct symbol *step_start_functio
- /* Nonzero if we want to give control to the user when we're notified
- of shared library events by the dynamic linker. */
- int stop_on_solib_events;
-+
-+/* Enable or disable optional shared library event breakpoints
-+ as appropriate when the above flag is changed. */
-+
-+static void
-+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
-+{
-+ update_solib_breakpoints ();
-+}
-+
- static void
- show_stop_on_solib_events (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
-@@ -3346,7 +3356,7 @@ handle_inferior_event (struct execution_
- context_switch (ecs->ptid);
- regcache = get_thread_regcache (ecs->ptid);
-
-- handle_solib_event ();
-+ handle_solib_event (NULL);
-
- ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (regcache),
-@@ -7334,7 +7344,7 @@ Show stopping for shared library events.
- If nonzero, gdb will give control to the user when the dynamic linker\n\
- notifies gdb of shared library events. The most common event of interest\n\
- to the user would be loading/unloading of a new library."),
-- NULL,
-+ set_stop_on_solib_events,
- show_stop_on_solib_events,
- &setlist, &showlist);
-
-Index: gdb-7.5.50.20130215/gdb/solib-svr4.c
-===================================================================
---- gdb-7.5.50.20130215.orig/gdb/solib-svr4.c 2013-02-15 22:37:30.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/solib-svr4.c 2013-02-15 22:37:35.761417596 +0100
-@@ -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 struct so_list *namespace_table_flatten (htab_t namespace_table);
-
- /* Link map info to include in an allocated so_list entry. */
-
-@@ -70,6 +72,16 @@ struct lm_info
-
- /* Values read in from inferior's fields of the same name. */
- CORE_ADDR l_ld, l_next, l_prev, l_name;
-+
-+ /* Numeric link-map ID of the namespace this object is loaded
-+ into. This value is only valid when using the probes-based
-+ interface. */
-+ LONGEST lmid;
-+
-+ /* Nonzero if the namespace list this object is loaded into is the
-+ application's initial namespace (LM_ID_BASE). This value is
-+ only valid when using the probes-based interface. */
-+ unsigned int in_initial_ns : 1;
- };
-
- /* On SVR4 systems, a list of symbols in the dynamic linker where
-@@ -106,6 +118,53 @@ static const char * const main_name_lis
- NULL
- };
-
-+/* What to do with the namespace table when a probe stop occurs. */
-+
-+enum probe_action
-+ {
-+ /* Something went seriously wrong. Stop using probes and
-+ revert to using the older interface. */
-+ NAMESPACE_TABLE_INVALIDATE,
-+
-+ /* No action is required. This namespace is still valid. */
-+ NAMESPACE_NO_ACTION,
-+
-+ /* This namespace should be reloaded entirely. */
-+ NAMESPACE_RELOAD,
-+
-+ /* Attempt to incrementally update this namespace. If the
-+ update fails or is not possible, fall back to reloading
-+ the namespace in full. */
-+ NAMESPACE_UPDATE_OR_RELOAD,
-+ };
-+
-+/* A probe's name and its associated action. */
-+
-+struct probe_info
-+{
-+ /* The name of the probe. */
-+ const char *name;
-+
-+ /* What to do with the namespace table when a probe stop occurs. */
-+ enum probe_action action;
-+};
-+
-+/* A list of named probes and their associated actions. If all
-+ probes are present in the dynamic linker then the probes-based
-+ interface will be used. */
-+
-+static const struct probe_info probe_info[] =
-+{
-+ { "init_start", NAMESPACE_NO_ACTION },
-+ { "init_complete", NAMESPACE_RELOAD },
-+ { "map_start", NAMESPACE_NO_ACTION },
-+ { "reloc_complete", NAMESPACE_UPDATE_OR_RELOAD },
-+ { "unmap_start", NAMESPACE_NO_ACTION },
-+ { "unmap_complete", NAMESPACE_RELOAD },
-+};
-+
-+#define NUM_PROBES ARRAY_SIZE (probe_info)
-+
- /* Per pspace SVR4 specific data. */
-
- struct svr4_info
-@@ -128,17 +187,58 @@ struct svr4_info
- CORE_ADDR interp_text_sect_high;
- CORE_ADDR interp_plt_sect_low;
- CORE_ADDR interp_plt_sect_high;
-+
-+ /* Nonzero if we are using the probes-based interface. */
-+ unsigned int using_probes : 1;
-+
-+ /* Named probes in the dynamic linker. */
-+ VEC (probe_p) *probes[NUM_PROBES];
-+
-+ /* Table of dynamic linker namespaces, used by the probes-based
-+ interface. */
-+ htab_t namespace_table;
- };
-
- /* Per-program-space data key. */
- static const struct program_space_data *solib_svr4_pspace_data;
-
-+/* Free any allocated probe vectors. */
-+
-+static void
-+free_probes (struct svr4_info *info)
-+{
-+ int i;
-+
-+ for (i = 0; i < NUM_PROBES; i++)
-+ VEC_free (probe_p, info->probes[i]);
-+
-+ memset (info->probes, 0, sizeof (info->probes));
-+}
-+
-+/* Free the namespace table. */
-+
-+static void
-+free_namespace_table (struct svr4_info *info)
-+{
-+ if (info->namespace_table == NULL)
-+ return;
-+
-+ htab_delete (info->namespace_table);
-+ info->namespace_table = NULL;
-+}
-+
- static void
- svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
- {
- struct svr4_info *info;
-
- info = program_space_data (pspace, solib_svr4_pspace_data);
-+ if (info == NULL)
-+ return;
-+
-+ free_probes (info);
-+ free_namespace_table (info);
-+
- xfree (info);
- }
-
-@@ -187,10 +287,21 @@ svr4_same_1 (const char *gdb_so_name, co
- return 0;
- }
-
-+/* Return non-zero if GDB and INFERIOR represent the same shared
-+ library. */
-+
- static int
- svr4_same (struct so_list *gdb, struct so_list *inferior)
- {
-- return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
-+ struct svr4_info *info = get_svr4_info ();
-+
-+ if (info->using_probes)
-+ {
-+ if (gdb->lm_info->lmid != inferior->lm_info->lmid)
-+ return 0;
-+ }
-+
-+ return svr4_same_1 (gdb->so_original_name, inferior->so_original_name);
- }
-
- static struct lm_info *
-@@ -321,18 +432,26 @@ lm_addr_check (struct so_list *so, bfd *
- }
- else
- {
-- /* There is no way to verify the library file matches. prelink
-- can during prelinking of an unprelinked file (or unprelinking
-- of a prelinked file) shift the DYNAMIC segment by arbitrary
-- offset without any page size alignment. There is no way to
-- find out the ELF header and/or Program Headers for a limited
-- verification if it they match. One could do a verification
-- of the DYNAMIC segment. Still the found address is the best
-- one GDB could find. */
--
-- warning (_(".dynamic section for \"%s\" "
-- "is not at the expected address "
-- "(wrong library or version mismatch?)"), so->so_name);
-+ struct svr4_info *info = get_svr4_info ();
-+
-+ if (!info->using_probes || so->lm_info->in_initial_ns)
-+ {
-+ /* There is no way to verify the library file
-+ matches. prelink can during prelinking of an
-+ unprelinked file (or unprelinking of a prelinked
-+ file) shift the DYNAMIC segment by arbitrary
-+ offset without any page size alignment. There is
-+ no way to find out the ELF header and/or Program
-+ Headers for a limited verification if it they
-+ match. One could do a verification of the
-+ DYNAMIC segment. Still the found address is the
-+ best one GDB could find. */
-+
-+ warning (_(".dynamic section for \"%s\" "
-+ "is not at the expected address "
-+ "(wrong library or version mismatch?)"),
-+ so->so_name);
-+ }
- }
- }
-
-@@ -774,16 +893,10 @@ locate_base (struct svr4_info *info)
- return info->debug_base;
- }
-
--/* Find the first element in the inferior's dynamic link map, and
-- return its address in the inferior. Return zero if the address
-- could not be determined.
--
-- FIXME: Perhaps we should validate the info somehow, perhaps by
-- checking r_version for a known version number, or r_state for
-- RT_CONSISTENT. */
-+/* Read the r_map field from the supplied r_debug structure. */
-
- static CORE_ADDR
--solib_svr4_r_map (struct svr4_info *info)
-+r_map_from_debug_base (CORE_ADDR debug_base)
- {
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
-@@ -792,13 +905,27 @@ solib_svr4_r_map (struct svr4_info *info
-
- TRY_CATCH (ex, RETURN_MASK_ERROR)
- {
-- addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
-+ addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
- ptr_type);
- }
- exception_print (gdb_stderr, ex);
- return addr;
- }
-
-+/* Find the first element in the inferior's dynamic link map, and
-+ return its address in the inferior. Return zero if the address
-+ could not be determined.
-+
-+ FIXME: Perhaps we should validate the info somehow, perhaps by
-+ checking r_version for a known version number, or r_state for
-+ RT_CONSISTENT. */
-+
-+static CORE_ADDR
-+solib_svr4_r_map (struct svr4_info *info)
-+{
-+ return r_map_from_debug_base (info->debug_base);
-+}
-+
- /* Find r_brk from the inferior's debug base. */
-
- static CORE_ADDR
-@@ -1161,15 +1288,17 @@ svr4_default_sos (void)
- return new;
- }
-
--/* Read the whole inferior libraries chain starting at address LM. Add the
-- entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if
-- IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */
-+/* Read the whole inferior libraries chain starting at address LM.
-+ Expect the first entry in the chain's previous entry to be PREV_LM.
-+ Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the
-+ first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according
-+ to it. Returns nonzero upon success. */
-
--static void
--svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr,
-- int ignore_first)
-+static int
-+svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
-+ struct so_list ***link_ptr_ptr, int ignore_first)
- {
-- CORE_ADDR prev_lm = 0, next_lm;
-+ CORE_ADDR next_lm;
-
- for (; lm != 0; prev_lm = lm, lm = next_lm)
- {
-@@ -1185,7 +1314,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
- if (new->lm_info == NULL)
- {
- do_cleanups (old_chain);
-- break;
-+ return 0;
- }
-
- next_lm = new->lm_info->l_next;
-@@ -1196,7 +1325,7 @@ svr4_read_so_list (CORE_ADDR lm, struct
- paddress (target_gdbarch (), prev_lm),
- paddress (target_gdbarch (), new->lm_info->l_prev));
- do_cleanups (old_chain);
-- break;
-+ return 0;
- }
-
- /* For SVR4 versions, the first entry in the link map is for the
-@@ -1291,20 +1420,61 @@ svr4_read_so_list (CORE_ADDR lm, struct
- **link_ptr_ptr = new;
- *link_ptr_ptr = &new->next;
- }
-+
-+ return 1;
- }
-
--/* Implement the "current_sos" target_so_ops method. */
-+/* Read the list of loaded libraries from the dynamic linker's base
-+ structure. */
-
- static struct so_list *
--svr4_current_sos (void)
-+svr4_current_sos_from_debug_base (void)
- {
-+ struct svr4_info *info = get_svr4_info ();
- CORE_ADDR lm;
- struct so_list *head = NULL;
- struct so_list **link_ptr = &head;
-- struct svr4_info *info;
- struct cleanup *back_to;
- int ignore_first;
-+
-+ gdb_assert (info->debug_base);
-+
-+ /* Assume that everything is a library if the dynamic loader was loaded
-+ late by a static executable. */
-+ if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
-+ ignore_first = 0;
-+ else
-+ ignore_first = 1;
-+
-+ back_to = make_cleanup (svr4_free_library_list, &head);
-+
-+ /* Walk the inferior's link map list, and build our list of
-+ `struct so_list' nodes. */
-+ lm = solib_svr4_r_map (info);
-+ if (lm)
-+ svr4_read_so_list (lm, 0, &link_ptr, ignore_first);
-+
-+ /* On Solaris, the dynamic linker is not in the normal list of
-+ shared objects, so make sure we pick it up too. Having
-+ symbol information for the dynamic linker is quite crucial
-+ for skipping dynamic linker resolver code. */
-+ lm = solib_svr4_r_ldsomap (info);
-+ if (lm)
-+ svr4_read_so_list (lm, 0, &link_ptr, 0);
-+
-+ discard_cleanups (back_to);
-+
-+ return head;
-+}
-+
-+/* Implement the "current_sos" target_so_ops method. */
-+
-+static struct so_list *
-+svr4_current_sos (void)
-+{
-+ struct svr4_info *info;
- struct svr4_library_list library_list;
-+ struct so_list *result;
-
- /* Fall back to manual examination of the target if the packet is not
- supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp
-@@ -1327,6 +1497,10 @@ svr4_current_sos (void)
-
- info = get_svr4_info ();
-
-+ /* If we have a namespace table then return a flattened copy. */
-+ if (info->namespace_table != NULL)
-+ return namespace_table_flatten (info->namespace_table);
-+
- /* Always locate the debug struct, in case it has moved. */
- info->debug_base = 0;
- locate_base (info);
-@@ -1336,35 +1510,12 @@ svr4_current_sos (void)
- if (! info->debug_base)
- return svr4_default_sos ();
-
-- /* Assume that everything is a library if the dynamic loader was loaded
-- late by a static executable. */
-- if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
-- ignore_first = 0;
-- else
-- ignore_first = 1;
--
-- back_to = make_cleanup (svr4_free_library_list, &head);
--
-- /* Walk the inferior's link map list, and build our list of
-- `struct so_list' nodes. */
-- lm = solib_svr4_r_map (info);
-- if (lm)
-- svr4_read_so_list (lm, &link_ptr, ignore_first);
--
-- /* On Solaris, the dynamic linker is not in the normal list of
-- shared objects, so make sure we pick it up too. Having
-- symbol information for the dynamic linker is quite crucial
-- for skipping dynamic linker resolver code. */
-- lm = solib_svr4_r_ldsomap (info);
-- if (lm)
-- svr4_read_so_list (lm, &link_ptr, 0);
--
-- discard_cleanups (back_to);
-+ result = svr4_current_sos_from_debug_base ();
-
-- if (head == NULL)
-+ if (result == NULL)
- return svr4_default_sos ();
-
-- return head;
-+ return result;
- }
-
- /* Get the address of the link_map for a given OBJFILE. */
-@@ -1449,6 +1600,498 @@ exec_entry_point (struct bfd *abfd, stru
- return gdbarch_addr_bits_remove (target_gdbarch (), addr);
- }
-
-+/* A probe and its associated information structure. */
-+
-+struct probe_and_info
-+{
-+ /* The probe. */
-+ struct probe *probe;
-+
-+ /* The probe_info from which the probe was created. */
-+ const struct probe_info *info;
-+};
-+
-+/* Get the solib event probe at the specified location, and the
-+ probe_info the probe was created with. Fills in RESULT and
-+ returns nonzero if a solib event probe was found at the
-+ specified location. Returns zero if no solib event probe
-+ was found. */
-+
-+static int
-+solib_event_probe_at (struct svr4_info *info, struct bp_location *loc,
-+ struct probe_and_info *result)
-+{
-+ int i;
-+
-+ for (i = 0; i < NUM_PROBES; i++)
-+ {
-+ struct probe *probe;
-+ int ix;
-+
-+ for (ix = 0; VEC_iterate (probe_p, info->probes[i], ix, probe); ++ix)
-+ {
-+ if (loc->pspace == current_program_space
-+ && loc->address == probe->address)
-+ {
-+ result->info = &probe_info[i];
-+ result->probe = probe;
-+
-+ return 1;
-+ }
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/* Decide what action to take when the specified solib event probe is
-+ hit. */
-+
-+static enum probe_action
-+solib_event_probe_action (struct probe_and_info *pi)
-+{
-+ enum probe_action action;
-+ unsigned probe_argc;
-+
-+ action = pi->info->action;
-+ if (action == NAMESPACE_NO_ACTION || action == NAMESPACE_TABLE_INVALIDATE)
-+ return action;
-+
-+ gdb_assert (action == NAMESPACE_RELOAD
-+ || action == NAMESPACE_UPDATE_OR_RELOAD);
-+
-+ /* Check that an appropriate number of arguments has been supplied.
-+ We expect:
-+ arg0: Lmid_t lmid (mandatory)
-+ arg1: struct r_debug *debug_base (mandatory)
-+ arg2: struct link_map *new (optional, for incremental updates) */
-+ probe_argc = get_probe_argument_count (pi->probe);
-+ if (probe_argc == 2)
-+ action = NAMESPACE_RELOAD;
-+ else if (probe_argc < 2)
-+ action = NAMESPACE_TABLE_INVALIDATE;
-+
-+ return action;
-+}
-+
-+/* A namespace in the dynamic linker. */
-+
-+struct namespace
-+{
-+ /* Numeric link-map ID of the namespace. */
-+ LONGEST lmid;
-+
-+ /* List of objects loaded into the namespace. */
-+ struct so_list *solist;
-+};
-+
-+/* Returns a hash code for the namespace referenced by p. */
-+
-+static hashval_t
-+hash_namespace (const void *p)
-+{
-+ const struct namespace *ns = p;
-+
-+ return (hashval_t) ns->lmid;
-+}
-+
-+/* Returns non-zero if the namespaces referenced by p1 and p2
-+ are equal. */
-+
-+static int
-+equal_namespace (const void *p1, const void *p2)
-+{
-+ const struct namespace *ns1 = p1;
-+ const struct namespace *ns2 = p2;
-+
-+ return ns1->lmid == ns2->lmid;
-+}
-+
-+/* Free a namespace. */
-+
-+static void
-+free_namespace (void *p)
-+{
-+ struct namespace *ns = p;
-+
-+ svr4_free_library_list (ns->solist);
-+ xfree (ns);
-+}
-+
-+/* Populate this namespace by reading the entire list of shared
-+ objects from the inferior. Returns nonzero on success. */
-+
-+static int
-+namespace_update_full (struct svr4_info *info, LONGEST lmid,
-+ CORE_ADDR debug_base, int is_initial_ns)
-+{
-+ struct so_list *result = NULL, *so;
-+ struct namespace lookup, *ns;
-+ void **slot;
-+
-+ /* Read the list of shared objects from the inferior. The
-+ initial namespace requires extra processing and is handled
-+ separately. */
-+ if (is_initial_ns)
-+ {
-+ result = svr4_current_sos_from_debug_base ();
-+ }
-+ else
-+ {
-+ CORE_ADDR lm = r_map_from_debug_base (debug_base);
-+ struct so_list **link_ptr = &result;
-+
-+ if (!svr4_read_so_list (lm, 0, &link_ptr, 0))
-+ return 0;
-+ }
-+
-+ /* If the namespace is empty then delete it from the table. */
-+ if (result == NULL)
-+ {
-+ if (info->namespace_table != NULL)
-+ {
-+ lookup.lmid = lmid;
-+ htab_remove_elt (info->namespace_table, &lookup);
-+ }
-+
-+ return 1;
-+ }
-+
-+ /* Fill in the link-map IDs and initial namespace flags. */
-+ for (so = result; so; so = so->next)
-+ {
-+ so->lm_info->lmid = lmid;
-+ so->lm_info->in_initial_ns = is_initial_ns;
-+ }
-+
-+ /* Create the namespace table, if necessary. */
-+ if (info->namespace_table == NULL)
-+ {
-+ info->namespace_table = htab_create_alloc (1, hash_namespace,
-+ equal_namespace,
-+ free_namespace,
-+ xcalloc, xfree);
-+ }
-+
-+ /* Update the namespace table with our new list. */
-+ lookup.lmid = lmid;
-+ slot = htab_find_slot (info->namespace_table, &lookup, INSERT);
-+ if (*slot == HTAB_EMPTY_ENTRY)
-+ {
-+ ns = XCNEW (struct namespace);
-+ ns->lmid = lmid;
-+ *slot = ns;
-+ }
-+ else
-+ {
-+ ns = *slot;
-+ svr4_free_library_list (ns->solist);
-+ }
-+ ns->solist = result;
-+
-+ return 1;
-+}
-+
-+/* Update this namespace starting from the link-map entry passed by
-+ the linker in the probe's third argument. Returns nonzero if the
-+ list was successfully updated, or zero to indicate failure. */
-+
-+static int
-+namespace_update_incremental (struct svr4_info *info, LONGEST lmid,
-+ CORE_ADDR lm, int is_initial_ns)
-+{
-+ struct namespace lookup, *ns;
-+ struct so_list *tail, **link, *so;
-+ struct value *val;
-+
-+ /* Find our namespace in the table. */
-+ if (info->namespace_table == NULL)
-+ return 0;
-+
-+ lookup.lmid = lmid;
-+ ns = htab_find (info->namespace_table, &lookup);
-+ if (ns == NULL)
-+ return 0;
-+
-+ /* Walk to the end of the list. */
-+ tail = ns->solist;
-+ if (tail == NULL)
-+ return 0;
-+
-+ while (tail->next)
-+ tail = tail->next;
-+ link = &tail->next;
-+
-+ /* Read the new objects. */
-+ if (!svr4_read_so_list (lm, tail->lm_info->lm_addr, &link, 0))
-+ return 0;
-+
-+ /* Fill in the link-map IDs and initial namespace flags. */
-+ for (so = tail; so; so = so->next)
-+ {
-+ so->lm_info->lmid = lmid;
-+ so->lm_info->in_initial_ns = is_initial_ns;
-+ }
-+
-+ return 1;
-+}
-+
-+/* Update the namespace table as appropriate when using the
-+ probes-based linker interface. Do nothing if using the
-+ standard interface. */
-+
-+static void
-+svr4_handle_solib_event (bpstat bs)
-+{
-+ struct svr4_info *info = get_svr4_info ();
-+ struct probe_and_info buf, *pi = &buf;
-+ enum probe_action action;
-+ struct value *val;
-+ LONGEST lmid;
-+ CORE_ADDR debug_base, lm = 0;
-+ int is_initial_ns;
-+
-+ /* It is possible that this function will be called incorrectly
-+ by the handle_solib_event in handle_inferior_event if GDB goes
-+ fully multi-target. */
-+ gdb_assert (bs != NULL);
-+
-+ if (!info->using_probes)
-+ return;
-+
-+ if (!solib_event_probe_at (info, bs->bp_location_at, pi))
-+ goto error;
-+
-+ action = solib_event_probe_action (pi);
-+ if (action == NAMESPACE_TABLE_INVALIDATE)
-+ goto error;
-+
-+ if (action == NAMESPACE_NO_ACTION)
-+ return;
-+
-+ val = evaluate_probe_argument (pi->probe, 0);
-+ if (val == NULL)
-+ goto error;
-+
-+ lmid = value_as_long (val);
-+
-+ val = evaluate_probe_argument (pi->probe, 1);
-+ if (val == NULL)
-+ goto error;
-+
-+ debug_base = value_as_address (val);
-+ if (debug_base == 0)
-+ goto error;
-+
-+ /* Always locate the debug struct, in case it moved. */
-+ info->debug_base = 0;
-+ if (locate_base (info) == 0)
-+ goto error;
-+
-+ is_initial_ns = (debug_base == info->debug_base);
-+
-+ if (action == NAMESPACE_UPDATE_OR_RELOAD)
-+ {
-+ val = evaluate_probe_argument (pi->probe, 2);
-+ if (val != NULL)
-+ lm = value_as_address (val);
-+
-+ if (lm == 0)
-+ action = NAMESPACE_RELOAD;
-+ }
-+
-+ if (action == NAMESPACE_UPDATE_OR_RELOAD)
-+ {
-+ if (namespace_update_incremental (info, lmid, lm, is_initial_ns))
-+ return;
-+
-+ action = NAMESPACE_RELOAD;
-+ }
-+
-+ gdb_assert (action == NAMESPACE_RELOAD);
-+
-+ if (namespace_update_full (info, lmid, debug_base, is_initial_ns))
-+ return;
-+
-+ error:
-+
-+ /* We should never reach here, but if we do we disable the
-+ probes interface and revert to the original interface.
-+ We don't reset the breakpoints as the ones we've set up
-+ are adequate. */
-+ warning (_("Probes-based dynamic linker interface failed.\n"
-+ "Reverting to original interface.\n"));
-+
-+ free_namespace_table (info);
-+ free_probes (info);
-+ info->using_probes = 0;
-+}
-+
-+/* Helper function for namespace_table_flatten. */
-+
-+static int
-+namespace_table_flatten_helper (void **slot, void *arg)
-+{
-+ struct namespace *ns = (struct namespace *) *slot;
-+ struct so_list *src = ns->solist;
-+ struct so_list **link = (struct so_list **) arg;
-+
-+ while (*link)
-+ link = &(*link)->next;
-+
-+ while (src != NULL)
-+ {
-+ struct so_list *dst;
-+
-+ dst = xmalloc (sizeof (struct so_list));
-+ memcpy (dst, src, sizeof (struct so_list));
-+
-+ dst->lm_info = xmalloc (sizeof (struct lm_info));
-+ memcpy (dst->lm_info, src->lm_info, sizeof (struct lm_info));
-+
-+ *link = dst;
-+ link = &dst->next;
-+
-+ src = src->next;
-+ }
-+
-+ *link = NULL;
-+
-+ return 1; /* Continue traversal. */
-+}
-+
-+/* Flatten the namespace table into a single list. */
-+
-+static struct so_list *
-+namespace_table_flatten (htab_t namespace_table)
-+{
-+ struct so_list *dst = NULL;
-+
-+ htab_traverse (namespace_table, namespace_table_flatten_helper, &dst);
-+
-+ return dst;
-+}
-+
-+/* Helper function for svr4_update_solib_event_breakpoints. */
-+
-+static int
-+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
-+{
-+ struct svr4_info *info = get_svr4_info ();
-+ struct bp_location *loc;
-+
-+ if (b->type != bp_shlib_event)
-+ return 0; /* Continue iterating. */
-+
-+ for (loc = b->loc; loc; loc = loc->next)
-+ {
-+ struct probe_and_info buf, *pi = &buf;
-+
-+ if (solib_event_probe_at (info, loc, pi))
-+ {
-+ if (pi->info->action == NAMESPACE_NO_ACTION)
-+ b->enable_state = (stop_on_solib_events
-+ ? bp_enabled : bp_disabled);
-+
-+ return 0; /* Continue iterating. */
-+ }
-+ }
-+
-+ return 0; /* Continue iterating. */
-+}
-+
-+/* Enable or disable optional solib event breakpoints as appropriate.
-+ Called whenever stop_on_solib_events is changed. */
-+
-+static void
-+svr4_update_solib_event_breakpoints (void)
-+{
-+ struct svr4_info *info = get_svr4_info ();
-+
-+ if (info->using_probes)
-+ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
-+}
-+
-+/* Both the SunOS and the SVR4 dynamic linkers call a marker function
-+ before and after mapping and unmapping shared libraries. The sole
-+ purpose of this method is to allow debuggers to set a breakpoint so
-+ they can track these changes.
-+
-+ Some versions of the glibc dynamic linker contain named probes
-+ to allow more fine grained stopping. Given the address of the
-+ original marker function, this function attempts to find these
-+ probes, and if found, sets breakpoints on those instead. If the
-+ probes aren't found, a single breakpoint is set on the original
-+ marker function. */
-+
-+static void
-+svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch,
-+ CORE_ADDR address)
-+{
-+ struct svr4_info *info = get_svr4_info ();
-+ struct obj_section *os;
-+
-+ os = find_pc_section (address);
-+ if (os != NULL)
-+ {
-+ int with_prefix;
-+
-+ for (with_prefix = 0; with_prefix <= 1; with_prefix++)
-+ {
-+ int all_probes_found = 1;
-+ int i;
-+
-+ for (i = 0; i < NUM_PROBES; i++)
-+ {
-+ char name[32] = { '\0' };
-+
-+ /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an
-+ early version of the probes code in which the probes'
-+ names were prefixed with "rtld_". The locations and
-+ arguments of the probes are otherwise the same, so we
-+ check for the prefixed version if the unprefixed
-+ probes are not found. */
-+
-+ if (with_prefix)
-+ strncat (name, "rtld_", sizeof (name));
-+
-+ strncat (name, probe_info[i].name, sizeof (name) - sizeof ("rtld_"));
-+
-+ info->probes[i] = find_probes_in_objfile (os->objfile, "rtld",
-+ name);
-+
-+ if (!VEC_length (probe_p, info->probes[i]))
-+ {
-+ free_probes (info);
-+ all_probes_found = 0;
-+ break;
-+ }
-+ }
-+
-+ if (all_probes_found)
-+ {
-+ info->using_probes = 1;
-+
-+ for (i = 0; i < NUM_PROBES; i++)
-+ {
-+ struct probe *probe;
-+ int ix;
-+
-+ for (ix = 0;
-+ VEC_iterate (probe_p, info->probes[i], ix, probe);
-+ ++ix)
-+ create_solib_event_breakpoint (gdbarch, probe->address);
-+ }
-+
-+ svr4_update_solib_event_breakpoints ();
-+ return;
-+ }
-+ }
-+ }
-+
-+ create_solib_event_breakpoint (gdbarch, address);
-+}
-+
- /* Helper function for gdb_bfd_lookup_symbol. */
-
- static int
-@@ -1501,6 +2144,9 @@ enable_break (struct svr4_info *info, in
- info->interp_text_sect_low = info->interp_text_sect_high = 0;
- info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
-
-+ free_probes (info);
-+ info->using_probes = 0;
-+
- /* If we already have a shared library list in the target, and
- r_debug contains r_brk, set the breakpoint there - this should
- mean r_brk has already been relocated. Assume the dynamic linker
-@@ -1532,7 +2178,7 @@ enable_break (struct svr4_info *info, in
- That knowledge is encoded in the address, if it's Thumb the low bit
- is 1. However, we've stripped that info above and it's not clear
- what all the consequences are of passing a non-addr_bits_remove'd
-- address to create_solib_event_breakpoint. The call to
-+ address to svr4_create_solib_event_breakpoints. The call to
- find_pc_section verifies we know about the address and have some
- hope of computing the right kind of breakpoint to use (via
- symbol info). It does mean that GDB needs to be pointed at a
-@@ -1570,7 +2216,7 @@ enable_break (struct svr4_info *info, in
- + bfd_section_size (tmp_bfd, interp_sect);
- }
-
-- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
-+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
- return 1;
- }
- }
-@@ -1728,7 +2374,8 @@ enable_break (struct svr4_info *info, in
-
- if (sym_addr != 0)
- {
-- create_solib_event_breakpoint (target_gdbarch (), load_addr + sym_addr);
-+ svr4_create_solib_event_breakpoints (target_gdbarch (),
-+ load_addr + sym_addr);
- xfree (interp_name);
- return 1;
- }
-@@ -1754,7 +2401,7 @@ enable_break (struct svr4_info *info, in
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
- sym_addr,
- ¤t_target);
-- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
-+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
- return 1;
- }
- }
-@@ -1770,7 +2417,7 @@ enable_break (struct svr4_info *info, in
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
- sym_addr,
- ¤t_target);
-- create_solib_event_breakpoint (target_gdbarch (), sym_addr);
-+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
- return 1;
- }
- }
-@@ -2266,6 +2913,9 @@ svr4_solib_create_inferior_hook (int fro
-
- info = get_svr4_info ();
-
-+ /* Free the probes-based interface's namespace table. */
-+ free_namespace_table (info);
-+
- /* Relocate the main executable if necessary. */
- svr4_relocate_main_executable ();
-
-@@ -2507,4 +3157,6 @@ _initialize_svr4_solib (void)
- svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
- svr4_so_ops.same = svr4_same;
- svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
-+ svr4_so_ops.handle_solib_event = svr4_handle_solib_event;
-+ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
- }
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen-solib.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen-solib.c 2013-02-15 22:37:35.761417596 +0100
-@@ -0,0 +1,24 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+
-+int
-+foo (int n)
-+{
-+ printf ("foo %d\n", n);
-+
-+ return 0;
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen.c 2013-02-15 22:37:35.762417598 +0100
-@@ -0,0 +1,58 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
-+
-+#define _GNU_SOURCE
-+#include <dlfcn.h>
-+
-+void
-+stop ()
-+{
-+}
-+
-+int
-+main ()
-+{
-+ void *handle1, *handle2, *handle3;
-+ void (*func)(int);
-+
-+ handle1 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
-+ stop ();
-+
-+ func = (void (*)(int)) dlsym (handle1, "foo");
-+ func (1);
-+
-+ handle2 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY);
-+ stop ();
-+
-+ func = (void (*)(int)) dlsym (handle2, "foo");
-+ func (2);
-+
-+ handle3 = dlopen (SHLIB_NAME, RTLD_LAZY);
-+ stop ();
-+
-+ func = (void (*)(int)) dlsym (handle3, "foo");
-+ func (3);
-+
-+ dlclose (handle1);
-+ stop ();
-+
-+ dlclose (handle2);
-+ stop ();
-+
-+ dlclose (handle3);
-+ stop ();
-+
-+ return 0;
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen.exp
+This patch updates the testsuite to cope with some changes resulting
+from the probes-based interface, and adds a new test. This patch is
+principally the work of Jan Kratochvil.
+
+--IYV9cRr2u6rjcP4B
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-6-tests-jk.patch"
+
+2013-05-16 Jan Kratochvil <jan.kratochvil at redhat.com>
+ Gary Benson <gbenson at 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.
+
+Index: gdb-7.6/gdb/testsuite/lib/gdb.exp
===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-dlmopen.exp 2013-02-15 22:37:35.762417598 +0100
-@@ -0,0 +1,125 @@
-+# Copyright 2012 Free Software Foundation, Inc.
-+
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 3 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program. If not, see <http://www.gnu.org/licenses/>.
-+
-+if { [skip_shlib_tests] || [is_remote target] } {
-+ return 0
-+}
-+
-+standard_testfile
-+
-+set libname $testfile-solib
-+set srcfile_lib $srcdir/$subdir/$libname.c
-+set binfile_lib [standard_output_file $libname.so]
-+
-+set normal_bp "_dl_debug_state"
-+set probes_bp "dl_main"
-+
-+if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
-+ [list additional_flags=-fPIC]] != "" } {
-+ untested "Could not compile $binfile_lib."
-+ return -1
-+}
-+
-+if { [prepare_for_testing $testfile.exp $testfile $srcfile \
-+ [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
-+ return -1
-+}
+--- gdb-7.6.orig/gdb/testsuite/lib/gdb.exp 2013-05-19 16:05:37.881840646 +0200
++++ gdb-7.6/gdb/testsuite/lib/gdb.exp 2013-05-19 16:06:10.436822964 +0200
+@@ -4011,22 +4011,6 @@ proc build_executable_from_specs {testna
+
+ 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
+- }
+-
+- if { [gdb_compile $objects "${binfile}" executable $options] != "" } {
+- untested $testname
+- return -1
+- }
+-
+ set info_options ""
+ if { [lsearch -exact $options "c++"] >= 0 } {
+ set info_options "c++"
+@@ -4034,6 +4018,42 @@ proc build_executable_from_specs {testna
+ if [get_compiler_info ${info_options}] {
+ return -1
+ }
+
-+# Run "info sharedlibrary" and check our library is shown the expected
-+# number of times.
-+proc check_info_shared { test expect } {
-+ global libname
-+ global gdb_prompt
++ set binfile [standard_output_file $executable]
+
-+ set actual 0
++ 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_test_multiple "info sharedlibrary" $test {
-+ -re $libname {
-+ incr actual 1
-+ exp_continue
++ # 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}"
+ }
-+ -re "\r\n$gdb_prompt $" {
-+ if { $actual == $expect } {
-+ pass $test
-+ } else {
-+ fail $test
++ 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
+ }
-+}
-+
-+# Enable stop-on-solib-events
-+gdb_test_no_output "set stop-on-solib-events 1"
-+
-+# Run to the first stop
-+gdb_test "run" ".*Stopped due to shared library event.*"
+
-+# XFAIL if we are not using probes
-+set test "ensure using probes"
-+set using_probes 0
-+gdb_test_multiple "bt" $test {
-+ -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
-+ xfail $test
+ return 0
+ }
+
+Index: gdb-7.6/gdb/testsuite/lib/prelink-support.exp
+===================================================================
+--- gdb-7.6.orig/gdb/testsuite/lib/prelink-support.exp 2013-05-19 16:05:37.881840646 +0200
++++ gdb-7.6/gdb/testsuite/lib/prelink-support.exp 2013-05-19 16:05:39.100839980 +0200
+@@ -95,8 +95,9 @@ proc file_copy {src dest} {
+ # 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 @@ proc build_executable_own_libs {testname
+
+ 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
++ }
+ }
-+ -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
-+ pass $test
-+ set using_probes 1
++ if {$interp == "no"} {
++ set interp ""
+ }
+
+ set dests {}
+@@ -164,13 +172,19 @@ proc build_executable_own_libs {testname
+
+ # 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 { $using_probes } {
-+ # Set up breakpoints.
-+ gdb_test_no_output "set stop-on-solib-events 0"
-+ gdb_test "break stop" {Breakpoint [0-9]+ at .*}
-+ gdb_test_no_output "set breakpoint pending on"
-+ gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
-+
-+ # Check our library isn't loaded.
-+ check_info_shared "info sharedlibrary #1" 0
-+
-+ # Run to the first stop and check our library loaded.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #2" 1
-+
-+ # The next stop should be the function in the library.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
-+
-+ # Run to the next stop and check our library is now loaded twice.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #3" 2
-+
-+ # The next stop should be the function in the library.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
-+
-+ # Run to the next stop and check our library is now loaded three
-+ # times.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #4" 3
-+
-+ # The next stop should be the function in the library.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
-+
-+ # Run to the next stop and check our library is now loaded twice.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #5" 2
-+
-+ # Run to the next stop and check our library is now loaded once.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #6" 1
-+
-+ # Run to the next stop and check our library is not loaded.
-+ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+ check_info_shared "info sharedlibrary #7" 0
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-interp.exp
+
+ 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-7.6/gdb/testsuite/gdb.base/break-interp.exp
===================================================================
---- gdb-7.5.50.20130215.orig/gdb/testsuite/gdb.base/break-interp.exp 2013-01-01 07:33:25.000000000 +0100
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-interp.exp 2013-02-15 22:37:35.762417598 +0100
+--- gdb-7.6.orig/gdb/testsuite/gdb.base/break-interp.exp 2013-05-19 16:05:37.882840646 +0200
++++ gdb-7.6/gdb/testsuite/gdb.base/break-interp.exp 2013-05-19 16:05:39.101839979 +0200
@@ -109,12 +109,19 @@ proc strip_debug {dest} {
}
}
@@ -1591,73 +255,13 @@ Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-interp.exp
# Use two separate gdb_test_multiple statements to avoid timeouts due
# to slow processing of wildcard capturing long output
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes-solib.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes-solib.c 2013-02-15 22:37:35.762417598 +0100
-@@ -0,0 +1,24 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+
-+int
-+foo (int n)
-+{
-+ printf ("foo %d\n", n);
-+
-+ return 0;
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes.c 2013-02-15 22:37:35.763417600 +0100
-@@ -0,0 +1,26 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
-+
-+#include <dlfcn.h>
-+
-+int
-+main ()
-+{
-+ void *handle = dlopen (SHLIB_NAME, RTLD_LAZY);
-+
-+ dlclose (handle);
-+
-+ return 0;
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes.exp
+Index: gdb-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes.exp 2013-02-15 22:37:35.763417600 +0100
-@@ -0,0 +1,76 @@
-+# Copyright 2012 Free Software Foundation, Inc.
-+
++++ gdb-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread.exp 2013-05-19 16:05:39.101839979 +0200
+@@ -0,0 +1,74 @@
++# Copyright 2011 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
@@ -1671,73 +275,73 @@ Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/break-probes.exp
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
-+if { [skip_shlib_tests] || [is_remote target] } {
++if {![istarget *-linux*] || [skip_shlib_tests]} {
+ return 0
+}
+
-+standard_testfile
++load_lib prelink-support.exp
+
-+set libname $testfile-solib
-+set srcfile_lib $srcdir/$subdir/$libname.c
-+set binfile_lib [standard_output_file $libname.so]
++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]
+
-+set normal_bp "_dl_debug_state"
-+set probes_bp "dl_main"
++# Use build_executable_own_libs as prelinked libpthread.so can produce false
++# PASS - it is OK if GDB processes it still before relocation.
+
-+if { [gdb_compile_shlib $srcfile_lib $binfile_lib \
-+ [list additional_flags=-fPIC]] != "" } {
-+ untested "Could not compile $binfile_lib."
++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 { [prepare_for_testing $testfile.exp $testfile $srcfile \
-+ [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } {
++if { ![runto_main] } {
+ return -1
+}
+
-+# Enable stop-on-solib-events
-+gdb_test_no_output "set stop-on-solib-events 1"
-+
-+# Run to the first stop
-+gdb_test "run" ".*Stopped due to shared library event.*"
-+
-+# XFAIL if we are not using probes
-+set test "ensure using probes"
-+set using_probes 0
-+gdb_test_multiple "bt" $test {
-+ -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" {
++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
+ }
-+ -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
++}
++
++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
-+ set using_probes 1
+ }
+}
+
-+if { $using_probes } {
-+ # Run til it loads our library
-+ set test "run til our library loads"
-+ set loaded_library 0
-+ while { !$loaded_library } {
-+ gdb_test_multiple "c" $test {
-+ -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" {
-+ pass $test
-+ set loaded_library 1
-+ }
-+ -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
-+ }
-+ }
-+ }
++gdb_test "set variable filename=\"$lib_dlopen\""
+
-+ # Call something to ensure that relocation occurred
-+ gdb_test "call foo(23)" "foo 23.*\\\$.* = .*"
-+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared-solib1.c
++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-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared-solib1.c 2013-02-15 22:37:35.763417600 +0100
-@@ -0,0 +1,24 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
++++ gdb-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread.c 2013-05-19 16:05:39.101839979 +0200
+@@ -0,0 +1,46 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++ Copyright 2011 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
@@ -1752,50 +356,43 @@ Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared-solib1.c
+ 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>
++#include <dlfcn.h>
++#include <stddef.h>
++#include <assert.h>
+
-+int
-+foo (int n)
-+{
-+ printf ("foo %d\n", n);
++static const char *volatile filename;
+
-+ return 0;
++static void
++notify (void)
++{
++ filename = NULL; /* notify-here */
+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared-solib2.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared-solib2.c 2013-02-15 22:37:35.763417600 +0100
-@@ -0,0 +1,24 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++int
++main (void)
++{
++ void *h;
++ void (*fp) (void (*) (void));
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
++ assert (filename != NULL);
++ h = dlopen (filename, RTLD_LAZY);
++ assert (h != NULL);
+
-+#include <stdio.h>
++ fp = dlsym (h, "f");
++ assert (fp != NULL);
+
-+int
-+bar (int n)
-+{
-+ printf ("bar %d\n", n);
++ fp (notify);
+
+ return 0;
+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared.c
+Index: gdb-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared.c 2013-02-15 22:37:35.763417600 +0100
-@@ -0,0 +1,48 @@
-+/* Copyright 2012 Free Software Foundation, Inc.
++++ gdb-7.6/gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c 2013-05-19 16:05:39.101839979 +0200
+@@ -0,0 +1,40 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++ Copyright 2011 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
@@ -1810,180 +407,64 @@ Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared.c
+ 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 <pthread.h>
++#include <assert.h>
+
-+void
-+stop ()
++static void *
++tfunc (void *arg)
+{
++ void (*notifyp) (void) = arg;
++
++ notifyp ();
+}
+
-+int
-+main ()
++void
++f (void (*notifyp) (void))
+{
-+ void *handle1, *handle2;
-+ void (*func)(int);
-+
-+ handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY);
-+ stop ();
-+
-+ handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY);
-+ stop ();
-+
-+ func = (void (*)(int)) dlsym (handle1, "foo");
-+ func (1);
-+
-+ func = (void (*)(int)) dlsym (handle2, "bar");
-+ func (2);
-+
-+ dlclose (handle1);
-+ stop ();
++ pthread_t t;
++ int i;
+
-+ dlclose (handle2);
-+ stop ();
++ i = pthread_create (&t, NULL, tfunc, notifyp);
++ assert (i == 0);
+
-+ return 0;
++ i = pthread_join (t, NULL);
++ assert (i == 0);
+}
-Index: gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared.exp
+Index: gdb-7.6/gdb/testsuite/gdb.base/solib-corrupted.exp
===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.50.20130215/gdb/testsuite/gdb.base/info-shared.exp 2013-02-15 22:37:35.764417602 +0100
-@@ -0,0 +1,139 @@
-+# Copyright 2012 Free Software Foundation, Inc.
-+
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 3 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program. If not, see <http://www.gnu.org/licenses/>.
-+
-+if { [skip_shlib_tests] || [is_remote target] } {
-+ return 0
-+}
-+
-+standard_testfile
-+
-+set lib1name $testfile-solib1
-+set srcfile_lib1 $srcdir/$subdir/$lib1name.c
-+set binfile_lib1 [standard_output_file $lib1name.so]
-+set define1 -DSHLIB1_NAME\=\"$binfile_lib1\"
-+
-+set lib2name $testfile-solib2
-+set srcfile_lib2 $srcdir/$subdir/$lib2name.c
-+set binfile_lib2 [standard_output_file $lib2name.so]
-+set define2 -DSHLIB2_NAME\=\"$binfile_lib2\"
-+
-+if { [gdb_compile_shlib $srcfile_lib1 $binfile_lib1 \
-+ [list additional_flags=-fPIC]] != "" } {
-+ untested "Could not compile $binfile_lib1."
-+ return -1
-+}
-+
-+if { [gdb_compile_shlib $srcfile_lib2 $binfile_lib2 \
-+ [list additional_flags=-fPIC]] != "" } {
-+ untested "Could not compile $binfile_lib2."
-+ return -1
-+}
-+
-+set cflags "$define1 $define2"
-+if { [prepare_for_testing $testfile.exp $testfile $srcfile \
-+ [list additional_flags=$cflags libs=-ldl]] } {
-+ return -1
-+}
-+
-+# Run "info sharedlibrary" and check for the presence or absence of
-+# our libraries.
-+proc check_info_shared { test expect1 expect2 } {
-+ global lib1name
-+ global lib2name
-+ global gdb_prompt
-+
-+ set actual1 0
-+ set actual2 0
-+
-+ gdb_test_multiple "info sharedlibrary" $test {
-+ -re $lib1name {
-+ set actual1 1
-+ exp_continue
-+ }
-+ -re $lib2name {
-+ set actual2 1
-+ exp_continue
-+ }
-+ -re "\r\n$gdb_prompt $" {
-+ if { $actual1 == $expect1 && $actual2 == $expect2 } {
-+ pass $test
-+ } else {
-+ fail $test
-+ }
+--- gdb-7.6.orig/gdb/testsuite/gdb.base/solib-corrupted.exp 2013-05-19 16:05:37.883840645 +0200
++++ gdb-7.6/gdb/testsuite/gdb.base/solib-corrupted.exp 2013-05-19 16:05:39.102839978 +0200
+@@ -36,6 +36,33 @@ if ![runto_main] {
+ return
+ }
+
++# With probes interface GDB no longer scans the inferior library list so its
++# corruption cannot be tested. There is no way to disable the probes
++# interface.
++
++set probes { init_start init_complete map_start reloc_complete unmap_start
++ unmap_complete }
++set test "info probes"
++gdb_test_multiple $test $test {
++ -re "^rtld\[ \t\]+(?:rtld_)?(\[a-z_\]+)\[ \t\]" {
++ set idx [lsearch -exact $probes $expect_out(1,string)]
++ if { $idx >= 0 } {
++ set probes [lreplace $probes $idx $idx]
+ }
-+ }
-+}
-+
-+# Set up breakpoints.
-+gdb_test "break stop" {Breakpoint [0-9]+ at .*}
-+gdb_test_no_output "set breakpoint pending on"
-+gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
-+gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.}
-+
-+# Check neither of the libraries are loaded at the start.
-+gdb_test "start" {Temporary breakpoint [0-9]+, .* in main \(\)}
-+check_info_shared "info sharedlibrary #1" 0 0
-+
-+# Run to the first stop and check that only the first library is loaded.
-+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+check_info_shared "info sharedlibrary #2" 1 0
-+
-+# Run to the second stop and check that both libraries are loaded.
-+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+check_info_shared "info sharedlibrary #3" 1 1
-+
-+# Check that the next stop is in foo.
-+gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
-+
-+# Check that the next stop is in bar.
-+gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
-+
-+# Restart the inferior and make sure there are no breakpoint reset
-+# errors. These can happen with the probes-based runtime linker
-+# interface if the cache is not cleared correctly.
-+set test "restart"
-+gdb_test_multiple "run" $test {
-+ -re {Start it from the beginning\? \(y or n\) } {
-+ send_gdb "y\n"
+ exp_continue
+ }
-+ -re {Error in re-setting breakpoint} {
-+ fail $test
++ -re "^\[^\r\n\]*\r\n" {
++ exp_continue
+ }
-+ -re "\r\n$gdb_prompt $" {
-+ pass $test
++ -re "^$gdb_prompt $" {
+ }
+}
++if { [llength $probes] == 0 } {
++ xfail $test
++ untested "GDB is using probes"
++ return
++}
+
-+# We're at the first stop. Check that only the first library is loaded.
-+check_info_shared "info sharedlibrary #4" 1 0
-+
-+# Run to the second stop and check that both libraries are loaded.
-+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+check_info_shared "info sharedlibrary #5" 1 1
-+
-+# Check that the next stop is in foo.
-+gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
-+
-+# Check that the next stop is in bar.
-+gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
-+
-+# Run to the next stop and check that the first library has been unloaded.
-+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+check_info_shared "info sharedlibrary #6" 0 1
-+
-+# Run to the last stop and check that both libraries are gone.
-+gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
-+check_info_shared "info sharedlibrary #7" 0 0
+ gdb_test "info sharedlibrary" "From * To .*" "normal list"
+
+ # GDB checks there for matching L_PREV.
diff --git a/gdb-dlopen-stap-probe-7of7.patch b/gdb-dlopen-stap-probe-7of7.patch
index 8f2b419..30357e9 100644
--- a/gdb-dlopen-stap-probe-7of7.patch
+++ b/gdb-dlopen-stap-probe-7of7.patch
@@ -1,147 +1,435 @@
-2012-07-30 Gary Benson <gbenson at redhat.com>
+http://sourceware.org/ml/gdb-patches/2013-05/msg00630.html
+Subject: [RFA 7/7] Linker-debugger interface tests
- * objfiles.h (inhibit_section_map_updates): New function
- declaration.
- (resume_section_map_updates): Likewise.
- (resume_section_map_updates_cleanup): Likewise.
- * objfiles.c (objfile_pspace_info): New field "inhibit_updates".
- (find_pc_section): Do not update the section map if
- inhibit_updates is set.
- (inhibit_section_map_updates): New function.
- (resume_section_map_updates): Likewise.
- (resume_section_map_updates_cleanup): Likewise.
- * solib-svr4.c (svr4_handle_solib_event): Inhibit section map
- updates for calls to evaluate_probe_argument.
-Index: gdb-7.5.50.20130118/gdb/objfiles.h
-===================================================================
---- gdb-7.5.50.20130118.orig/gdb/objfiles.h 2013-01-18 23:18:16.862315673 +0100
-+++ gdb-7.5.50.20130118/gdb/objfiles.h 2013-01-18 23:18:36.702343482 +0100
-@@ -508,6 +508,22 @@ extern int in_plt_section (CORE_ADDR, ch
- 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 (void);
-+
-+/* Resume automatically rebuilding the section map as required. */
-+extern void resume_section_map_updates (void);
-+
-+/* Version of the above suitable for use as a cleanup. */
-+extern void resume_section_map_updates_cleanup (void *arg);
-+
- extern void default_iterate_over_objfiles_in_search_order
- (struct gdbarch *gdbarch,
- iterate_over_objfiles_in_search_order_cb_ftype *cb,
-Index: gdb-7.5.50.20130118/gdb/objfiles.c
-===================================================================
---- gdb-7.5.50.20130118.orig/gdb/objfiles.c 2013-01-18 23:18:13.647311006 +0100
-+++ gdb-7.5.50.20130118/gdb/objfiles.c 2013-01-18 23:18:16.862315673 +0100
-@@ -69,6 +69,9 @@ struct objfile_pspace_info
- int objfiles_changed_p;
- struct obj_section **sections;
- int num_sections;
-+
-+ /* Nonzero if section map updates should be inhibited. */
-+ int inhibit_updates;
- };
-
- /* Per-program-space data key. */
-@@ -1356,7 +1359,7 @@ find_pc_section (CORE_ADDR pc)
- return s;
-
- pspace_info = get_objfile_pspace_data (current_program_space);
-- if (pspace_info->objfiles_changed_p != 0)
-+ if (pspace_info->objfiles_changed_p && !pspace_info->inhibit_updates)
- {
- update_section_map (current_program_space,
- &pspace_info->sections,
-@@ -1415,6 +1418,30 @@ objfiles_changed (void)
- get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1;
- }
-
-+/* See comments in objfiles.h. */
+--DCA/C9WSnDtl50zu
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+
+This patch adds some testcases for the linker-debugger interface.
+
+--DCA/C9WSnDtl50zu
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: attachment; filename="rtld-probes-7-tests-gb.patch"
+
+2013-05-16 Gary Benson <gbenson at 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.
+
+diff --git a/gdb/testsuite/gdb.base/break-probes.exp b/gdb/testsuite/gdb.base/break-probes.exp
+new file mode 100644
+index 0000000..8372636
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/break-probes.exp
+@@ -0,0 +1,77 @@
++# Copyright 2013 Free Software Foundation, Inc.
+
-+void
-+inhibit_section_map_updates (void)
++# 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 $" {
++ xfail $test
++ }
++ -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" {
++ pass $test
++ set using_probes 1
++ }
++}
++
++if { $using_probes } {
++ # Run til it loads our library
++ set test "run til our library loads"
++ set loaded_library 0
++ while { !$loaded_library } {
++ gdb_test_multiple "c" $test {
++ -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" {
++ pass $test
++ set loaded_library 1
++ }
++ -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
++ }
++ }
++ }
++
++ # Call something to ensure that relocation occurred
++ gdb_test "call foo(23)" "\\\$.* = 31.*\\\M.*"
++}
+diff --git a/gdb/testsuite/gdb.base/break-probes.c b/gdb/testsuite/gdb.base/break-probes.c
+new file mode 100644
+index 0000000..a778099
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/break-probes.c
+@@ -0,0 +1,26 @@
++/* Copyright 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>
++
++int
++main ()
+{
-+ get_objfile_pspace_data (current_program_space)->inhibit_updates = 1;
++ void *handle = dlopen (SHLIB_NAME, RTLD_LAZY);
++
++ dlclose (handle);
++
++ return 0;
+}
+diff --git a/gdb/testsuite/gdb.base/break-probes-solib.c b/gdb/testsuite/gdb.base/break-probes-solib.c
+new file mode 100644
+index 0000000..bdde2db
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/break-probes-solib.c
+@@ -0,0 +1,22 @@
++/* Copyright 2013 Free Software Foundation, Inc.
+
-+/* See comments in objfiles.h. */
++ 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.
+
-+void
-+resume_section_map_updates (void)
++ 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)
+{
-+ get_objfile_pspace_data (current_program_space)->inhibit_updates = 0;
++ return n * n / 17;
++}
+diff --git a/gdb/testsuite/gdb.base/info-shared.exp b/gdb/testsuite/gdb.base/info-shared.exp
+new file mode 100644
+index 0000000..1dabb9f
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/info-shared.exp
+@@ -0,0 +1,145 @@
++# Copyright 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.
++runto_main
++check_info_shared "info sharedlibrary #1" 0 0
++
++# Set up breakpoints.
++gdb_test "break stop" {Breakpoint [0-9]+ at .*}
++gdb_test_no_output "set breakpoint pending on"
++gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.}
++gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.}
++
++# Run to the first stop and check that only the first library is loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #2" 1 0
++
++# Run to the second stop and check that both libraries are loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #3" 1 1
++
++# Check that the next stop is in foo.
++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++# Check that the next stop is in bar.
++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
++
++# Restart the inferior and make sure there are no breakpoint reset
++# errors. These can happen with the probes-based runtime linker
++# interface if the cache is not cleared correctly.
++set test "restart"
++gdb_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
++ }
+}
+
-+/* See comments in objfiles.h. */
++# 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_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #5" 1 0
++
++# Run to the second stop and check that both libraries are loaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #6" 1 1
++
++# Check that the next stop is in foo.
++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*}
++
++# Check that the next stop is in bar.
++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*}
++
++# Run to the next stop and check that the first library has been unloaded.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #7" 0 1
++
++# Run to the last stop and check that both libraries are gone.
++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)}
++check_info_shared "info sharedlibrary #8" 0 0
+diff --git a/gdb/testsuite/gdb.base/info-shared.c b/gdb/testsuite/gdb.base/info-shared.c
+new file mode 100644
+index 0000000..d699a11
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/info-shared.c
+@@ -0,0 +1,48 @@
++/* Copyright 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>
+
+void
-+resume_section_map_updates_cleanup (void *arg)
++stop ()
++{
++}
++
++int
++main ()
++{
++ void *handle1, *handle2;
++ void (*func)(int);
++
++ handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY);
++ stop ();
++
++ handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY);
++ stop ();
++
++ func = (void (*)(int)) dlsym (handle1, "foo");
++ func (1);
++
++ func = (void (*)(int)) dlsym (handle2, "bar");
++ func (2);
++
++ dlclose (handle1);
++ stop ();
++
++ dlclose (handle2);
++ stop ();
++
++ return 0;
++}
+diff --git a/gdb/testsuite/gdb.base/info-shared-solib1.c b/gdb/testsuite/gdb.base/info-shared-solib1.c
+new file mode 100644
+index 0000000..9979ee7
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/info-shared-solib1.c
+@@ -0,0 +1,24 @@
++/* Copyright 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)
+{
-+ resume_section_map_updates ();
-+}
-+
- /* The default implementation for the "iterate_over_objfiles_in_search_order"
- gdbarch method. It is equivalent to use the ALL_OBJFILES macro,
- searching the objfiles in the order they are stored internally,
-Index: gdb-7.5.50.20130118/gdb/solib-svr4.c
-===================================================================
---- gdb-7.5.50.20130118.orig/gdb/solib-svr4.c 2013-01-18 23:18:13.649311010 +0100
-+++ gdb-7.5.50.20130118/gdb/solib-svr4.c 2013-01-18 23:18:16.863315675 +0100
-@@ -1849,6 +1849,7 @@ svr4_handle_solib_event (bpstat bs)
- struct svr4_info *info = get_svr4_info ();
- struct probe_and_info buf, *pi = &buf;
- enum probe_action action;
-+ struct cleanup *cleanups = NULL;
- struct value *val;
- LONGEST lmid;
- CORE_ADDR debug_base, lm = 0;
-@@ -1872,6 +1873,19 @@ svr4_handle_solib_event (bpstat bs)
- if (action == NAMESPACE_NO_ACTION)
- return;
-
-+ /* EVALUATE_PROBE_ARGUMENT looks up symbols in the dynamic linker
-+ using FIND_PC_SECTION. FIND_PC_SECTION is accelerated by a cache
-+ called the section map. The section map is invalidated every
-+ time a shared library is loaded or unloaded, and if the inferior
-+ is generating a lot of shared library events then the section map
-+ will be updated every time SVR4_HANDLE_SOLIB_EVENT is called.
-+ We called FIND_PC_SECTION in SVR4_CREATE_SOLIB_EVENT_BREAKPOINTS,
-+ so we can guarantee that the dynamic linker's sections are in the
-+ section map. We can therefore inhibit section map updates across
-+ these calls to EVALUATE_PROBE_ARGUMENT and save a lot of time. */
-+ inhibit_section_map_updates ();
-+ cleanups = make_cleanup (resume_section_map_updates_cleanup, NULL);
-+
- val = evaluate_probe_argument (pi->probe, 0);
- if (val == NULL)
- goto error;
-@@ -1903,6 +1917,9 @@ svr4_handle_solib_event (bpstat bs)
- action = NAMESPACE_RELOAD;
- }
-
-+ do_cleanups (cleanups);
-+ cleanups = NULL;
-+
- if (action == NAMESPACE_UPDATE_OR_RELOAD)
- {
- if (namespace_update_incremental (info, lmid, lm, is_initial_ns))
-@@ -1925,6 +1942,8 @@ svr4_handle_solib_event (bpstat bs)
- warning (_("Probes-based dynamic linker interface failed.\n"
- "Reverting to original interface.\n"));
-
-+ if (cleanups != NULL)
-+ do_cleanups (cleanups);
- free_namespace_table (info);
- free_probes (info);
- info->using_probes = 0;
++ printf ("foo %d\n", n);
++
++ return 0;
++}
+diff --git a/gdb/testsuite/gdb.base/info-shared-solib2.c b/gdb/testsuite/gdb.base/info-shared-solib2.c
+new file mode 100644
+index 0000000..d4ed1e6
+--- /dev/null
++++ b/gdb/testsuite/gdb.base/info-shared-solib2.c
+@@ -0,0 +1,24 @@
++/* Copyright 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;
++}
+
+--DCA/C9WSnDtl50zu--
+
diff --git a/gdb-dlopen-stap-probe-fixup.patch b/gdb-dlopen-stap-probe-fixup.patch
new file mode 100644
index 0000000..30e18c1
--- /dev/null
+++ b/gdb-dlopen-stap-probe-fixup.patch
@@ -0,0 +1,62 @@
+--- gdb-7.6-x/gdb/solib-svr4.c 2013-05-19 16:04:36.838874595 +0200
++++ gdb-7.6/gdb/solib-svr4.c 2013-05-19 16:12:35.112514978 +0200
+@@ -1078,7 +1078,6 @@ svr4_free_library_list (void *p_list)
+ static struct so_list *
+ svr4_copy_library_list (struct so_list *src)
+ {
+- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+ struct so_list *dst = NULL;
+ struct so_list **link = &dst;
+
+@@ -1090,8 +1089,8 @@ svr4_copy_library_list (struct so_list *
+
+ memcpy (new, src, sizeof (struct so_list));
+
+- new->lm_info = xmalloc (lmo->link_map_size);
+- memcpy (new->lm_info, src->lm_info, lmo->link_map_size);
++ new->lm_info = xmalloc (sizeof (*new->lm_info));
++ memcpy (new->lm_info, src->lm_info, sizeof (*new->lm_info));
+
+ new->next = NULL;
+ *link = new;
+@@ -1747,7 +1746,7 @@ solist_update_incremental (struct svr4_i
+ struct svr4_library_list library_list;
+ char annex[64];
+
+- xsnprintf (annex, sizeof (annex), "start=%lx;prev=%lx", lm, prev_lm);
++ xsnprintf (annex, sizeof (annex), "start=%lx;prev=%lx", (unsigned long) lm, (unsigned long) prev_lm);
+ if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
+ return 0;
+
+@@ -1813,7 +1812,10 @@ svr4_handle_solib_event (void)
+ goto error;
+
+ if (action == DO_NOTHING)
++{
++do_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
+--- gdb-7.6-x/gdb/testsuite/gdb.base/break-probes.exp 2013-05-19 16:06:19.452818090 +0200
++++ gdb-7.6/gdb/testsuite/gdb.base/break-probes.exp 2013-05-19 16:07:49.730770135 +0200
+@@ -60,14 +60,15 @@ gdb_test_multiple "bt" $test {
+ if { $using_probes } {
+ # Run til it loads our library
+ set test "run til our library loads"
+- set loaded_library 0
+- while { !$loaded_library } {
++ 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
+- set loaded_library 1
+ }
+ -re "Stopped due to shared library event\\M.*$gdb_prompt $" {
++ set not_loaded_library 1
+ }
+ }
+ }
diff --git a/gdb.spec b/gdb.spec
index 89c2d83..16bc3f0 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -36,7 +36,7 @@ Version: 7.6
# The release always contains a leading reserved number, start it at 1.
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 28%{?dist}
+Release: 29%{?dist}
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain
Group: Development/Debuggers
@@ -504,16 +504,16 @@ Patch579: gdb-7.2.50-sparc-add-workaround-to-broken-debug-files.patch
# Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).
# Fix crash regression from the dlopen of libpthread.so fix (BZ 911712).
+# Fix performance regression when inferior opens many libraries (Gary Benson).
#=push
-Patch718: gdb-dlopen-stap-probe-3of7.patch
-Patch719: gdb-dlopen-stap-probe-4of7.patch
-Patch720: gdb-dlopen-stap-probe-5of7.patch
-Patch721: gdb-dlopen-stap-probe-6of7.patch
-Patch722: gdb-dlopen-stap-probe-7of7.patch
-Patch619: gdb-dlopen-stap-probe-test.patch
-Patch723: gdb-dlopen-stap-probe-test2.patch
-Patch822: gdb-dlopen-stap-probe-mapfailed.patch
-Patch827: gdb-dlopen-stap-probe-inhibit.patch
+Patch718: gdb-dlopen-stap-probe-1of7.patch
+Patch719: gdb-dlopen-stap-probe-2of7.patch
+Patch720: gdb-dlopen-stap-probe-3of7.patch
+Patch721: gdb-dlopen-stap-probe-4of7.patch
+Patch722: gdb-dlopen-stap-probe-5of7.patch
+Patch723: gdb-dlopen-stap-probe-6of7.patch
+Patch822: gdb-dlopen-stap-probe-7of7.patch
+Patch827: gdb-dlopen-stap-probe-fixup.patch
# Work around PR libc/13097 "linux-vdso.so.1" warning message.
#=push
@@ -876,7 +876,6 @@ find -name "*.info*"|xargs rm -f
%patch723 -p1
%patch822 -p1
%patch827 -p1
-%patch619 -p1
%patch627 -p1
%patch634 -p1
%patch653 -p1
@@ -1398,6 +1397,9 @@ fi
%endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch"
%changelog
+* Sun May 19 2013 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.6-29.fc19
+- Fix performance regression when inferior opens many libraries (Gary Benson).
+
* Thu May 9 2013 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.6-28.fc19
- Fix needless expansion of non-gdbindex symtabs (Doug Evans).
More information about the scm-commits
mailing list