[gdb/f16] Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).

Jan Kratochvil jankratochvil at fedoraproject.org
Wed Aug 10 17:42:25 UTC 2011


commit 922e4a0796ed02d391ea64de0735185d12a52819
Author: Jan Kratochvil <jan.kratochvil at redhat.com>
Date:   Wed Aug 10 19:42:06 2011 +0200

    Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).

 gdb-dlopen-stap-probe-test.patch |  408 ++++++++++++++++++++++++++++++++++++++
 gdb-dlopen-stap-probe.patch      |  358 +++++++++++++++++++++++++++++++++
 gdb.spec                         |   11 +-
 3 files changed, 776 insertions(+), 1 deletions(-)
---
diff --git a/gdb-dlopen-stap-probe-test.patch b/gdb-dlopen-stap-probe-test.patch
new file mode 100644
index 0000000..55a6a92
--- /dev/null
+++ b/gdb-dlopen-stap-probe-test.patch
@@ -0,0 +1,408 @@
+commit 5bfdc32cd3bf373c3b02e1fd864ed8ceab0292b2
+Author: Jan Kratochvil <jan.kratochvil at redhat.com>
+Date:   Mon Aug 8 12:08:53 2011 +0200
+
+    +testcase
+
+Index: gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread-lib.c	2011-08-10 18:30:56.000000000 +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
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <pthread.h>
++#include <assert.h>
++
++static void *
++tfunc (void *arg)
++{
++  void (*notifyp) (void) = arg;
++
++  notifyp ();
++}
++
++void
++f (void (*notifyp) (void))
++{
++  pthread_t t;
++  int i;
++
++  i = pthread_create (&t, NULL, tfunc, notifyp);
++  assert (i == 0);
++
++  i = pthread_join (t, NULL);
++  assert (i == 0);
++}
+Index: gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread.c	2011-08-10 18:30:56.000000000 +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
++   the Free Software Foundation; either version 3 of the License, or
++   (at your option) any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
++
++#include <dlfcn.h>
++#include <stddef.h>
++#include <assert.h>
++
++static const char *volatile filename;
++
++static void
++notify (void)
++{
++  filename = NULL; /* notify-here */
++}
++
++int
++main (void)
++{
++  void *h;
++  void (*fp) (void (*) (void));
++
++  assert (filename != NULL);
++  h = dlopen (filename, RTLD_LAZY);
++  assert (h != NULL);
++
++  fp = dlsym (h, "f");
++  assert (fp != NULL);
++
++  fp (notify);
++
++  return 0;
++}
+Index: gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.3.50.20110722/gdb/testsuite/gdb.threads/dlopen-libpthread.exp	2011-08-10 18:30:56.000000000 +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
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++if {![istarget *-linux*] || [skip_shlib_tests]} {
++    return 0
++}
++
++load_lib prelink-support.exp
++
++set testfile "dlopen-libpthread"
++set srcmainfile ${testfile}.c
++set srclibfile ${testfile}-lib.c
++set executable ${testfile}
++set binfile_lib ${objdir}/${subdir}/${executable}.so
++set binfile ${objdir}/${subdir}/${executable}
++set lib_dlopen [shlib_target_file ${executable}.so]
++
++# Use build_executable_own_libs as prelinked libpthread.so can produce false
++# PASS - it is OK if GDB processes it still before relocation.
++
++set relink_args [build_executable_own_libs ${testfile}.exp ${executable}.so $srclibfile {debug shlib_pthreads} no]
++if {$relink_args == "" || ![prelink_no $relink_args]
++    || [prepare_for_testing ${testfile}.exp ${executable} ${srcmainfile} {debug shlib_load}] } {
++    return -1
++}
++gdb_load_shlibs $binfile_lib
++
++if { ![runto_main] } {
++    return -1
++}
++
++set test "print _dl_debug_notify"
++gdb_test_multiple $test $test {
++    -re " 0x\[0-9a-f\]+ <_dl_debug_notify>\r\n$gdb_prompt $" {
++	pass $test
++    }
++    -re "No symbol \"_dl_debug_notify\" in current context\\.\r\n$gdb_prompt $" {
++	xfail $test
++	untested ${testfile}.exp
++	return
++    }
++}
++
++set test "libpthread.so not found"
++gdb_test_multiple "info sharedlibrary" $test {
++    -re "/libpthread\\.so.*\r\n$gdb_prompt $" {
++	fail $test
++    }
++    -re "/libc\\.so.*\r\n$gdb_prompt $" {
++	pass $test
++    }
++}
++
++gdb_test "set variable filename=\"$lib_dlopen\""
++
++gdb_breakpoint "notify"
++
++# The error was:
++# Cannot find new threads: generic error
++gdb_continue_to_breakpoint "notify" ".* notify-here .*"
++
++gdb_test "info sharedlibrary" {/libpthread\.so.*} "libpthread.so found"
+Index: gdb-7.3.50.20110722/gdb/testsuite/lib/gdb.exp
+===================================================================
+--- gdb-7.3.50.20110722.orig/gdb/testsuite/lib/gdb.exp	2011-08-10 18:30:55.000000000 +0200
++++ gdb-7.3.50.20110722/gdb/testsuite/lib/gdb.exp	2011-08-10 18:30:56.000000000 +0200
+@@ -3563,30 +3563,49 @@ proc build_executable { testname executa
+         set sources ${executable}.c
+     }
+ 
+-    set binfile ${objdir}/${subdir}/${executable}
+-
+-    set objects {}
+-    for {set i 0} "\$i<[llength $sources]" {incr i} {
+-        set s [lindex $sources $i]
+-        if  { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $options] != "" } {
+-            untested $testname
+-            return -1
+-        }
+-        lappend objects "${binfile}${i}.o"
++    # get_compiler_info by gdb_compile_shlib and gdb_compile_shlib_pthreads.
++    set info_options ""
++    if { [lsearch -exact $options "c++"] >= 0 } {
++	set info_options "c++"
+     }
+-    
+-    if  { [gdb_compile $objects "${binfile}" executable $options] != "" } {
+-        untested $testname
++    if [get_compiler_info binfile_unused ${info_options}] {
+         return -1
+     }
+ 
+-    set info_options ""
+-    if { [lsearch -exact $options "c++"] >= 0 } {
+-	set info_options "c++"
++    set binfile ${objdir}/${subdir}/${executable}
++
++    set func gdb_compile
++    set func_index [lsearch -regexp $options {^(pthreads|shlib|shlib_pthreads)$}]
++    if {$func_index != -1} {
++	set func "${func}_[lindex $options $func_index]"
+     }
+-    if [get_compiler_info ${binfile} ${info_options}] {
++
++    # 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.
++    if [string match gdb_compile_shlib* $func] {
++	set sources_path {}
++	foreach s $sources {
++	    lappend sources_path "${srcdir}/${subdir}/${s}"
++	}
++	set ret [$func $sources_path "${binfile}" $options]
++    } else {
++	set objects {}
++	for {set i 0} "\$i<[llength $sources]" {incr i} {
++	    set s [lindex $sources $i]
++	    if  { [gdb_compile "${srcdir}/${subdir}/${s}" "${binfile}${i}.o" object $options] != "" } {
++		untested $testname
++		return -1
++	    }
++	    lappend objects "${binfile}${i}.o"
++	}
++	set ret [$func $objects "${binfile}" executable $options]
++    }
++    if  { $ret != "" } {
++        untested $testname
+         return -1
+     }
++
+     return 0
+ }
+ 
+Index: gdb-7.3.50.20110722/gdb/testsuite/lib/prelink-support.exp
+===================================================================
+--- gdb-7.3.50.20110722.orig/gdb/testsuite/lib/prelink-support.exp	2011-01-01 16:33:52.000000000 +0100
++++ gdb-7.3.50.20110722/gdb/testsuite/lib/prelink-support.exp	2011-08-10 19:25:41.000000000 +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
++	}
++    }
++    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 {[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.3.50.20110722/gdb/testsuite/gdb.base/break-interp.exp
+===================================================================
+--- gdb-7.3.50.20110722.orig/gdb/testsuite/gdb.base/break-interp.exp	2011-07-01 21:12:12.000000000 +0200
++++ gdb-7.3.50.20110722/gdb/testsuite/gdb.base/break-interp.exp	2011-08-10 18:32:21.000000000 +0200
+@@ -108,14 +108,20 @@ proc strip_debug {dest} {
+     }
+ }
+ 
++# Former symbol for solib changes notifications was _dl_debug_state, newer one
++# is _dl_debug_notify, the right one one traps by `set stop-on-solib-events 1'.
++
++set solib_bp {(_dl_debug_state|_dl_debug_notify)}
++
+ # Implementation of reach.
+ 
+ proc reach_1 {func command displacement} {
+-    global gdb_prompt expect_out
++    global gdb_prompt expect_out solib_bp
+ 
+-    if {$func == "_dl_debug_state"} {
++    if {$func == $solib_bp} {
+ 	# Breakpoint on _dl_debug_state can have problems due to its overlap
+ 	# with the existing internal breakpoint from GDB.
++	# With also _dl_debug_notify we would need even two breakpoints.
+ 	gdb_test_no_output "set stop-on-solib-events 1"
+     } elseif {! [gdb_breakpoint $func allow-pending]} {
+ 	return
+@@ -141,21 +147,21 @@ proc reach_1 {func command displacement}
+ 	    exp_continue
+ 	}
+ 	-re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		fail $test
+ 	    } else {
+ 		pass $test
+ 	    }
+ 	}
+ 	-re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		fail $test
+ 	    } else {
+ 		pass $test
+ 	    }
+ 	}
+ 	-re "Stopped due to shared library event\r\n$gdb_prompt $" {
+-	    if {$func == "_dl_debug_state"} {
++	    if {$func == $solib_bp} {
+ 		if {$debug_state_count == 0} {
+ 		    # First stop does not yet relocate the _start function
+ 		    # descriptor on ppc64.
+@@ -174,7 +180,7 @@ proc reach_1 {func command displacement}
+ 	fail $test_displacement
+     }
+ 
+-    if {$func == "_dl_debug_state"} {
++    if {$func == $solib_bp} {
+ 	gdb_test_no_output "set stop-on-solib-events 0"
+     }
+ }
+@@ -373,7 +379,7 @@ proc test_attach {file displacement {rel
+ }
+ 
+ proc test_ld {file ifmain trynosym displacement} {
+-    global srcdir subdir gdb_prompt expect_out inferior_exited_re
++    global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp
+ 
+     # First test normal `file'-command loaded $FILE with symbols.
+ 
+@@ -401,9 +407,9 @@ proc test_ld {file ifmain trynosym displ
+ 	gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test"
+     }
+ 
+-    reach "_dl_debug_state" "run" $displacement
++    reach $solib_bp "run" $displacement
+ 
+-    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt"
++    gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt"
+ 
+     if $ifmain {
+ 	reach "main" continue "NONE"
+@@ -415,7 +421,7 @@ proc test_ld {file ifmain trynosym displ
+ 
+     # Try re-run if the new PIE displacement takes effect.
+     gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y"
+-    reach "_dl_debug_state" "run" $displacement
++    reach $solib_bp "run" $displacement
+ 
+     if $ifmain {
+ 	test_core $file $displacement
+@@ -448,7 +454,7 @@ proc test_ld {file ifmain trynosym displ
+     gdb_test "exec-file $file" "exec-file $escapedfile" "load"
+ 
+     if $ifmain {
+-	reach "_dl_debug_state" run $displacement
++	reach $solib_bp run $displacement
+ 
+ 	# Use two separate gdb_test_multiple statements to avoid timeouts due
+ 	# to slow processing of wildcard capturing long output
diff --git a/gdb-dlopen-stap-probe.patch b/gdb-dlopen-stap-probe.patch
new file mode 100644
index 0000000..5352299
--- /dev/null
+++ b/gdb-dlopen-stap-probe.patch
@@ -0,0 +1,358 @@
+From: Gary Benson <gbenson at redhat.com>
+To: Jan Kratochvil <jan.kratochvil at redhat.com>
+Message-ID: <20110810133605.GB7294 at redhat.com>
+
+diff --git a/gdb/infrun.c b/gdb/infrun.c
+index 4296d3a..fd5e9c3 100644
+--- a/gdb/infrun.c
++++ b/gdb/infrun.c
+@@ -321,6 +323,13 @@ static struct symbol *step_start_function;
+ /* 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;
++
++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)
+@@ -7153,7 +7162,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);
+ 
+diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
+index dffc621..73cbe1c 100644
+--- a/gdb/solib-svr4.c
++++ b/gdb/solib-svr4.c
+@@ -48,6 +48,8 @@
+ #include "auxv.h"
+ #include "exceptions.h"
+ 
++#include "stap-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);
+@@ -92,6 +94,32 @@ static const char * const solib_break_names[] =
+   NULL
+ };
+ 
++/* A list of SystemTap probes which, if present in the dynamic linker,
++   allow more fine-grained breakpoints to be placed on shared library
++   events.  */
++
++struct probe_info
++  {
++    /* The name of the probe.  */
++    const char *name;
++
++    /* Nonzero if this probe must be stopped at even when
++       stop-on-solib-events is off.  */
++    int mandatory;
++  };
++
++static const struct probe_info probe_info[] =
++{
++  {"rtld_init_start", 0},
++  {"rtld_init_complete", 1},
++  {"rtld_map_start", 0},
++  {"rtld_reloc_complete", 1},
++  {"rtld_unmap_start", 0},
++  {"rtld_unmap_complete", 1},
++};
++
++#define NUM_PROBES (sizeof(probe_info) / sizeof(probe_info[0]))
++
+ static const char * const bkpt_names[] =
+ {
+   "_start",
+@@ -335,6 +363,12 @@ struct svr4_info
+   CORE_ADDR interp_text_sect_high;
+   CORE_ADDR interp_plt_sect_low;
+   CORE_ADDR interp_plt_sect_high;
++
++  /* SystemTap probes.  */
++  VEC (stap_probe_p) *probes[NUM_PROBES];
++
++  /* Nonzero if we are using the SystemTap interface.  */
++  int using_probes;
+ };
+ 
+ /* Per-program-space data key.  */
+@@ -344,8 +378,15 @@ static void
+ svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
+ {
+   struct svr4_info *info;
++  int i;
+ 
+   info = program_space_data (pspace, solib_svr4_pspace_data);
++  if (info == NULL)
++    return;
++
++  for (i = 0; i < NUM_PROBES; i++)
++    VEC_free (stap_probe_p, info->probes[i]);
++
+   xfree (info);
+ }
+ 
+@@ -1321,6 +1362,126 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
+ 					     targ);
+ }
+ 
++/* 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;
++
++  for (loc = b->loc; loc; loc = loc->next)
++    {
++      int i;
++
++      for (i = 0; i < NUM_PROBES; i++)
++	{
++	  if (!probe_info[i].mandatory)
++	    {
++	      const struct stap_probe *probe;
++	      int ix;
++
++	      for (ix = 0;
++		   VEC_iterate (stap_probe_p, info->probes[i], ix, probe);
++		   ++ix)
++		{
++		  if (loc->pspace == current_program_space
++		      && loc->address == probe->address)
++		    {
++		      b->enable_state =
++			stop_on_solib_events ? bp_enabled : bp_disabled;
++		      return 0;
++		    }
++		}
++	    }
++	}
++    }
++
++  return 0;
++}
++
++/* Enable or disable optional solib event breakpoints as appropriate.
++   Called whenever stop_on_solib_events is changed.  */
++
++static void
++svr4_update_solib_event_breakpoints (void)
++{
++  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 SystemTap 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
++   SVR4 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 all_probes_found = 1;
++      int i;
++
++      for (i = 0; i < NUM_PROBES; i++)
++	{
++	  info->probes[i] = find_probes_in_objfile (os->objfile, "rtld",
++						    probe_info[i].name);
++
++	  if (!VEC_length(stap_probe_p, info->probes[i]))
++	    {
++	      int j;
++
++	      for (j = i - 1; j >= 0; j--)
++		{
++		  VEC_free (stap_probe_p, info->probes[j]);
++		  info->probes[j] = NULL;
++		}
++
++	      all_probes_found = 0;
++	      break;
++	    }
++	}
++
++      if (all_probes_found)
++	{
++	  info->using_probes = 1;
++
++	  for (i = 0; i < NUM_PROBES; i++)
++	    {
++	      const struct stap_probe *probe;
++	      int ix;
++
++	      for (ix = 0;
++		   VEC_iterate (stap_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);
++}
++
+ /*
+ 
+    LOCAL FUNCTION
+@@ -1372,10 +1533,18 @@ enable_break (struct svr4_info *info, int from_tty)
+   asection *interp_sect;
+   gdb_byte *interp_name;
+   CORE_ADDR sym_addr;
++  int i;
+ 
+   info->interp_text_sect_low = info->interp_text_sect_high = 0;
+   info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
+ 
++  for (i = 0; i < NUM_PROBES; i++)
++    {
++      VEC_free (stap_probe_p, info->probes[i]);
++      info->probes[i] = NULL;
++    }
++  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
+@@ -1407,7 +1576,7 @@ enable_break (struct svr4_info *info, int from_tty)
+ 	 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
+@@ -1445,7 +1614,7 @@ enable_break (struct svr4_info *info, int from_tty)
+ 		+ 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;
+ 	}
+     }
+@@ -1599,7 +1768,8 @@ enable_break (struct svr4_info *info, int from_tty)
+ 
+       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;
+ 	}
+@@ -1625,7 +1795,7 @@ enable_break (struct svr4_info *info, int from_tty)
+ 	  sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+ 							 sym_addr,
+ 							 &current_target);
+-	  create_solib_event_breakpoint (target_gdbarch, sym_addr);
++	  svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
+ 	  return 1;
+ 	}
+     }
+@@ -1641,7 +1811,7 @@ enable_break (struct svr4_info *info, int from_tty)
+ 	      sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
+ 							     sym_addr,
+ 							     &current_target);
+-	      create_solib_event_breakpoint (target_gdbarch, sym_addr);
++	      svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
+ 	      return 1;
+ 	    }
+ 	}
+@@ -2470,4 +2640,5 @@ _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;
+ }
+diff --git a/gdb/solib.c b/gdb/solib.c
+index 3296ed4..7ba70ce 100644
+--- a/gdb/solib.c
++++ b/gdb/solib.c
+@@ -1313,6 +1313,18 @@ no_shared_libraries (char *ignored, int from_tty)
+   objfile_purge_solibs ();
+ }
+ 
++/* Enable or disable optional solib event breakpoints as appropriate.  */
++
++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.  */
+ 
+diff --git a/gdb/solib.h b/gdb/solib.h
+index c473d85..7b3881c 100644
+--- a/gdb/solib.h
++++ b/gdb/solib.h
+@@ -78,4 +78,8 @@ extern void set_solib_ops (struct gdbarch *gdbarch,
+ 
+ extern int libpthread_name_p (const char *name);
+ 
++/* Enable or disable optional solib event breakpoints as appropriate.  */
++
++extern void update_solib_breakpoints (void);
++
+ #endif /* SOLIB_H */
+diff --git a/gdb/solist.h b/gdb/solist.h
+index dad11be..14ede10 100644
+--- a/gdb/solist.h
++++ b/gdb/solist.h
+@@ -137,6 +137,13 @@ 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);
+   };
+ 
+ /* Free the memory associated with a (so_list *).  */
diff --git a/gdb.spec b/gdb.spec
index ca03f93..2c15a06 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -27,7 +27,7 @@ Version: 7.3.50.20110722
 
 # 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: 4%{?_with_upstream:.upstream}%{?dist}
+Release: 5%{?_with_upstream:.upstream}%{?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
@@ -533,6 +533,10 @@ Patch579: gdb-7.2.50-sparc-add-workaround-to-broken-debug-files.patch
 # Improve GDB performance on inferior dlopen calls (Gary Benson, BZ 698001).
 Patch617: gdb-dlopen-skip_inline_frames-perf.patch
 
+# Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).
+Patch618: gdb-dlopen-stap-probe.patch
+Patch619: gdb-dlopen-stap-probe-test.patch
+
 BuildRequires: ncurses-devel%{?_isa} texinfo gettext flex bison expat-devel%{?_isa}
 # --without-system-readline
 # Requires: readline%{?_isa}
@@ -795,6 +799,8 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c
 %patch556 -p1
 %patch579 -p1
 %patch617 -p1
+%patch618 -p1
+%patch619 -p1
 
 %patch393 -p1
 %patch335 -p1
@@ -1217,6 +1223,9 @@ fi
 %{_infodir}/gdb.info*
 
 %changelog
+* Wed Aug 10 2011 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.3.50.20110722-5.fc16
+- Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432).
+
 * Tue Aug  9 2011 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.3.50.20110722-4.fc16
 - Improve GDB performance on inferior dlopen calls (Gary Benson, BZ 698001).
 - [python] Fix crash when pretty printer fails (Phil Muldoon, BZ 712715).


More information about the scm-commits mailing list