[RFC] Detect loops in the solib chain

Daniel Jacobowitz drow@false.org
Thu Jul 17 21:41:00 GMT 2008


On Thu, Jul 17, 2008 at 02:17:36PM -0700, Paul Pluzhnikov wrote:
> On Thu, Jul 17, 2008 at 1:57 PM, Daniel Jacobowitz <drow@false.org> wrote:
> 
> > The best I could think of was to detect cycles.
> 
> This is a double-linked list. You could also check that
> 
>   lm->l_next == NULL || lm->l_next->l_prev == lm

Hmm - since this is doubly linked, but not circularly, will this
prevent us ever getting into a cycle?  I hadn't thought of that.

This version seems to work too.

-- 
Daniel Jacobowitz
CodeSourcery

2008-07-17  Daniel Jacobowitz  <dan@codesourcery.com>

	* solib-svr4.c (LM_PREV): New function.
	(IGNORE_FIRST_LINK_MAP_ENTRY): Use it.
	(svr4_current_sos): Check for correct l_prev.

Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.87
diff -u -p -r1.87 solib-svr4.c
--- solib-svr4.c	3 Jun 2008 12:59:37 -0000	1.87
+++ solib-svr4.c	17 Jul 2008 21:39:50 -0000
@@ -248,6 +248,15 @@ 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 ();
+
+  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
+				builtin_type_void_data_ptr);
+}
+
+static CORE_ADDR
 LM_NAME (struct so_list *so)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
@@ -259,15 +268,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 ();
-
   /* Assume that everything is a library if the dynamic loader was loaded
      late by a static executable.  */
   if (bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
     return 0;
 
-  return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset,
-				builtin_type_void_data_ptr) == 0;
+  return LM_PREV (so) == 0;
 }
 
 static CORE_ADDR debug_base;	/* Base of dynamic linker structures */
@@ -750,7 +756,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;
@@ -766,6 +772,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 ();
 
   while (lm)
@@ -773,6 +780,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);
@@ -784,14 +792,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 (prev_lm != 0 && 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)
 	{
 	  main_lm_addr = new->lm_info->lm_addr;
 	  free_so (new);
@@ -828,6 +843,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



More information about the Gdb-patches mailing list