Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Jan Kratochvil <jan.kratochvil@redhat.com>
To: gdb-patches@sourceware.org
Cc: Paul Pluzhnikov <ppluzhnikov@google.com>,
	        Kevin Buettner <kevinb@redhat.com>
Subject: Re: [RFC] Detect loops in the solib chain
Date: Fri, 09 Apr 2010 15:41:00 -0000	[thread overview]
Message-ID: <20100409154123.GA8218@host0.dyn.jankratochvil.net> (raw)
In-Reply-To: <20080718160210.66b480e9@mesquite.lan>  <20080717220959.GA10652@caradoc.them.org>

Hi,

this is a follow-up on my different implementation at:
	[patch] Fix deadlock on looped solib list
	http://sourceware.org/ml/gdb-patches/2010-04/msg00054.html

This thread started by Daniel Jacobowitz has died, pinging it.


On Fri, 18 Jul 2008 00:09:59 +0200, Daniel Jacobowitz wrote:
> On Thu, Jul 17, 2008 at 02:57:03PM -0700, Paul Pluzhnikov wrote:
> > I think you want just:
> > 
> > +      if (LM_PREV (new) != prev_lm)
> > 
> > First entry on the list should also be properly terminated, and
> > ldsomap has nothing to do with whether the list is corrupt or not.
> 
> You're right about prev_lm, thanks.  The ldsomap check is necessary,
> because that entry may not be on the list (see down below).

Done.


On Sat, 19 Jul 2008 01:02:10 +0200, Kevin Buettner wrote:
> It seems to me that the ldsomap check could be avoided if you were to
> set prev_lm to 0 just after ldsomap gets set.  (It's been a while
> since I've checked, but I'm guessing that in the case of a unattached
> dynamic linker entry, you'd expect both LM_NEXT and LM_PREV for that
> entry to be zero.)

Not done.  It has a risk of regression on Solaris, I do not have Solaris
easily available (OK, to boot a VM) and keeping the patch as is just does not
apply the new sanity check on the Solaris specific ld.so single entry list.


OK to check-in?  (included by name for the fnchange.lst entry :-) )

No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu.


Thanks,
Jan


gdb/
2010-04-03  Daniel Jacobowitz  <dan@codesourcery.com>
	    Paul Pluzhnikov  <ppluzhnikov@google.com>
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix deadlock on looped list of loaded shared objects.
	* solib-svr4.c (LM_PREV): New function.
	(IGNORE_FIRST_LINK_MAP_ENTRY): Use it.
	(svr4_current_sos): Check for correct l_prev.  New variable prev_lm.
	* config/djgpp/fnchange.lst: Add translation for solib-corrupted.exp.

gdb/testsuite/
2010-04-03  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix deadlock on looped list of loaded shared objects.
	* gdb.base/solib-corrupted.exp: New.

--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -272,6 +272,16 @@ LM_NEXT (struct so_list *so)
 }
 
 static CORE_ADDR
+LM_PREV (struct so_list *so)
+{
+  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+
+  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
+				ptr_type);
+}
+
+static CORE_ADDR
 LM_NAME (struct so_list *so)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
@@ -284,16 +294,12 @@ LM_NAME (struct so_list *so)
 static int
 IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so)
 {
-  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
-
   /* 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)
     return 0;
 
-  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
-				ptr_type) == 0;
+  return LM_PREV (so) == 0;
 }
 
 /* Per pspace SVR4 specific data.  */
@@ -1101,7 +1107,7 @@ svr4_default_sos (void)
 static struct so_list *
 svr4_current_sos (void)
 {
-  CORE_ADDR lm;
+  CORE_ADDR lm, prev_lm;
   struct so_list *head = 0;
   struct so_list **link_ptr = &head;
   CORE_ADDR ldsomap = 0;
@@ -1120,6 +1126,7 @@ svr4_current_sos (void)
 
   /* Walk the inferior's link map list, and build our list of
      `struct so_list' nodes.  */
+  prev_lm = 0;
   lm = solib_svr4_r_map (info);
 
   while (lm)
@@ -1127,6 +1134,7 @@ svr4_current_sos (void)
       struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
       struct so_list *new = XZALLOC (struct so_list);
       struct cleanup *old_chain = make_cleanup (xfree, new);
+      CORE_ADDR next_lm;
 
       new->lm_info = xmalloc (sizeof (struct lm_info));
       make_cleanup (xfree, new->lm_info);
@@ -1138,14 +1146,21 @@ svr4_current_sos (void)
 
       read_memory (lm, new->lm_info->lm, lmo->link_map_size);
 
-      lm = LM_NEXT (new);
+      next_lm = LM_NEXT (new);
+
+      if (LM_PREV (new) != prev_lm && ldsomap == 0)
+	{
+	  warning (_("Corrupted shared library list"));
+	  free_so (new);
+	  next_lm = 0;
+	}
 
       /* For SVR4 versions, the first entry in the link map is for the
          inferior executable, so we must ignore it.  For some versions of
          SVR4, it has no name.  For others (Solaris 2.3 for example), it
          does have a name, so we can no longer use a missing name to
          decide when to ignore it. */
-      if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
+      else if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
 	{
 	  info->main_lm_addr = new->lm_info->lm_addr;
 	  free_so (new);
@@ -1182,6 +1197,9 @@ svr4_current_sos (void)
 	    }
 	}
 
+      prev_lm = lm;
+      lm = next_lm;
+
       /* 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
--- a/gdb/config/djgpp/fnchange.lst
+++ b/gdb/config/djgpp/fnchange.lst
@@ -397,6 +397,7 @@
 @V@/gdb/testsuite/gdb.base/siginfo-obj.c @V@/gdb/testsuite/gdb.base/si-obj.c
 @V@/gdb/testsuite/gdb.base/siginfo-addr.exp @V@/gdb/testsuite/gdb.base/si-addr.exp
 @V@/gdb/testsuite/gdb.base/siginfo-obj.exp @V@/gdb/testsuite/gdb.base/si-obj.exp
+@V@/gdb/testsuite/gdb.base/solib-corrupted.exp @V@/gdb/testsuite/gdb.base/so-crptd.exp
 @V@/gdb/testsuite/gdb.base/solib-disc.c @V@/gdb/testsuite/gdb.base/so-disc.c
 @V@/gdb/testsuite/gdb.base/solib-display-lib.c @V@/gdb/testsuite/gdb.base/so-displib.c
 @V@/gdb/testsuite/gdb.base/solib-display-main.c @V@/gdb/testsuite/gdb.base/so-dispmain.c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-corrupted.exp
@@ -0,0 +1,45 @@
+# Copyright 2010 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/>.
+
+set testfile "solib-corrupted"
+set srcfile start.c
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    untested ${testfile}.exp
+    return -1
+}
+
+if ![runto_main] {
+    fail "Can't run to main"
+    return
+}
+
+gdb_test "info sharedlibrary" "" "normal list"
+
+# GDB checks there for matching L_PREV.
+set test "make solibs looping"
+gdb_test_multiple "p/x _r_debug->r_map->l_next = _r_debug->r_map" $test {
+    -re "(No symbol \"_r_debug\" in current context\\.|Attempt to extract a component of a value that is not a structure pointer\\.)\r\n$gdb_prompt $" {
+	# glibc debug info is not available and it is too difficult to find and
+	# parse it from this testcase without the gdb supporting functions.
+	xfail "$test (no _r_debug symbol)"
+	untested ${testfile}.exp
+	return
+    }
+    -re " = 0x\[0-9a-f\]+\r\n$gdb_prompt $" {
+	pass $test
+    }
+}
+gdb_test "info sharedlibrary" "warning: Corrupted shared library list\r\n.*" "corrupted list"


  parent reply	other threads:[~2010-04-09 15:41 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-17 20:57 Daniel Jacobowitz
2008-07-17 21:07 ` Stan Shebs
2008-07-17 21:15 ` Thiago Jung Bauermann
2008-07-17 21:42   ` Daniel Jacobowitz
2008-07-17 21:18 ` Paul Pluzhnikov
2008-07-17 21:41   ` Daniel Jacobowitz
2008-07-17 21:57     ` Paul Pluzhnikov
2008-07-17 22:10       ` Daniel Jacobowitz
2008-07-18 23:02         ` Kevin Buettner
2010-04-09 15:41         ` Jan Kratochvil [this message]
2010-04-09 21:03           ` Jan Kratochvil
2010-04-12 22:54             ` Kevin Buettner
2010-04-12 23:08             ` Pedro Alves
2010-04-18 20:24               ` OpenSolaris dejagnu workaround [Re: [RFC] Detect loops in the solib chain] Jan Kratochvil
2010-04-23 20:09             ` [RFC] Detect loops in the solib chain Tom Tromey
2010-04-23 21:47               ` Jan Kratochvil
2010-06-11 17:39                 ` Ulrich Weigand
2010-06-11 18:34                   ` Jan Kratochvil

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20100409154123.GA8218@host0.dyn.jankratochvil.net \
    --to=jan.kratochvil@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=kevinb@redhat.com \
    --cc=ppluzhnikov@google.com \
    /path/to/YOUR_REPLY

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

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