This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Find ld.so on Solaris


While investigating PR 2063, I discovered that we didn't map the ld.so
on Solaris.  It turns out that on Solaris, ld.so is not included in
the normal list of dynamic objects.  Instead Solaris has a few more
members in `struct r_debug', one of which is r_ldsomap, which points
to the link map for ld.so.  We can easily distinguish this extended
Solaris `struct r_debug' from the "normal" ld.so by looking at the
r_version member.  For Linux and the BSD's it's 1, but Solaris has 2.

This patch implements this.

ok?


Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>

	* solib-svr4.h (struct link_map_offsets): Remove r_debug_size and
	r_map_size members.  Add r_version_offset, r_version_size and
	r_ldsomap_offset members.
	* solib-svr4.c (solib_svr4_r_map): Renamed from
	fetch_link_map_member.  Simplify using read_memory_typed_address.
	(solib_svr4_r_ldsomap): New function.
	(open_symbol_file_object): Use solib_svr_r_map.
	(svr4_current_sos): Use solib_svr4_r_map and look for the dynamic
	linker by using solib_svr4_r_ldsomap.
	(svr4_ilp32_fetch_link_map_offsets)
	(svr4_lp64_fetch_link_map_offsets): Adjust for changes to `struct
	link_map_offsets'.
	* solib-legacy.c (legacy_svr4_fetch_link_map_offsets): Adjust for
	changes to `struct link_map_offsets'.
	* mipsnbsd-tdep.c (mipsnbsd_ilp32_fetch_link_map_offsets)
	(mipsnbsd_lp64_fetch_link_map_offsets): Adjust for changes to
	`struct link_map_offsets'.

Index: solib-legacy.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-legacy.c,v
retrieving revision 1.8
diff -u -p -r1.8 solib-legacy.c
--- solib-legacy.c 17 Dec 2005 22:34:02 -0000 1.8
+++ solib-legacy.c 15 Jan 2006 22:20:11 -0000
@@ -1,5 +1,6 @@
 /* Provide legacy r_debug and link_map support for SVR4-like native targets.
-   Copyright (C) 2000, 2001
+
+   Copyright (C) 2000, 2001, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -55,10 +56,10 @@ legacy_svr4_fetch_link_map_offsets (void
       lmp = &lmo;
 
 #ifdef HAVE_STRUCT_LINK_MAP_WITH_L_MEMBERS
-      lmo.r_debug_size = sizeof (struct r_debug);
-
+      lmo.r_version_offset = offsetof (struct r_debug, r_version);
+      lmo.r_version_size = fieldsize (struct r_debug, r_version);
       lmo.r_map_offset = offsetof (struct r_debug, r_map);
-      lmo.r_map_size = fieldsize (struct r_debug, r_map);
+      lmo.r_ldsomap_offset = -1;
 
       lmo.link_map_size = sizeof (struct link_map);
 
@@ -107,10 +108,10 @@ legacy_svr4_fetch_link_map_offsets (void
     {
       lmp32 = &lmo32;
 
-      lmo32.r_debug_size = sizeof (struct r_debug32);
-
+      lmo32.r_version_offset = offsetof (struct r_debug32, r_version);
+      lmo32.r_version_size = fieldsize (struct r_debug32, r_version);
       lmo32.r_map_offset = offsetof (struct r_debug32, r_map);
-      lmo32.r_map_size = fieldsize (struct r_debug32, r_map);
+      lmo32.r_ldsomap_offset = -1;
 
       lmo32.link_map_size = sizeof (struct link_map32);
 
Index: solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.54
diff -u -p -r1.54 solib-svr4.c
--- solib-svr4.c 17 Dec 2005 22:34:02 -0000 1.54
+++ solib-svr4.c 15 Jan 2006 22:20:12 -0000
@@ -1,7 +1,7 @@
 /* Handle SVR4 shared libraries for GDB, the GNU Debugger.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
-   2000, 2001, 2003, 2004, 2005
+   2000, 2001, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -447,43 +447,40 @@ locate_base (void)
   return (debug_base);
 }
 
-/*
-
-   LOCAL FUNCTION
-
-   first_link_map_member -- locate first member in dynamic linker's map
-
-   SYNOPSIS
-
-   static CORE_ADDR first_link_map_member (void)
-
-   DESCRIPTION
+/* Find the first element in the inferior's dynamic link map, and
+   return its address in the inferior.
 
-   Find the first element in the inferior's dynamic link map, and
-   return its address in the inferior.  This function doesn't copy the
-   link map entry itself into our address space; current_sos actually
-   does the reading.  */
+   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
-first_link_map_member (void)
+solib_svr4_r_map (void)
 {
-  CORE_ADDR lm = 0;
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
-  gdb_byte *r_map_buf = xmalloc (lmo->r_map_size);
-  struct cleanup *cleanups = make_cleanup (xfree, r_map_buf);
 
-  read_memory (debug_base + lmo->r_map_offset, r_map_buf, lmo->r_map_size);
+  return read_memory_typed_address (debug_base + lmo->r_map_offset,
+				    builtin_type_void_data_ptr);
+}
 
-  /* Assume that the address is unsigned.  */
-  lm = extract_unsigned_integer (r_map_buf, lmo->r_map_size);
+/* Find the link map for the dynamic linker (if it is not in the
+   normal list of loaded shared objects).  */
 
-  /* 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_ldsomap (void)
+{
+  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+  ULONGEST version;
 
-  do_cleanups (cleanups);
+  /* Check version, and return zero if `struct r_debug' doesn't have
+     the r_ldsomap member.  */
+  version = read_memory_unsigned_integer (debug_base + lmo->r_version_offset,
+					  lmo->r_version_size);
+  if (version < 2 || lmo->r_ldsomap_offset == -1)
+    return 0;
 
-  return (lm);
+  return read_memory_typed_address (debug_base + lmo->r_ldsomap_offset,
+				    builtin_type_void_data_ptr);
 }
 
 /*
@@ -527,7 +524,8 @@ open_symbol_file_object (void *from_ttyp
     return 0;	/* failed somehow... */
 
   /* First link map member should be the executable.  */
-  if ((lm = first_link_map_member ()) == 0)
+  lm = solib_svr4_r_map ();
+  if (lm == 0)
     return 0;	/* failed somehow... */
 
   /* Read address of name from target memory to GDB.  */
@@ -585,6 +583,7 @@ svr4_current_sos (void)
   CORE_ADDR lm;
   struct so_list *head = 0;
   struct so_list **link_ptr = &head;
+  CORE_ADDR ldsomap = 0;
 
   /* Make sure we've looked up the inferior's dynamic linker's base
      structure.  */
@@ -600,7 +599,7 @@ svr4_current_sos (void)
 
   /* Walk the inferior's link map list, and build our list of
      `struct so_list' nodes.  */
-  lm = first_link_map_member ();  
+  lm = solib_svr4_r_map ();
   while (lm)
     {
       struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
@@ -622,7 +621,7 @@ svr4_current_sos (void)
          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))
+      if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
 	free_so (new);
       else
 	{
@@ -656,6 +655,13 @@ svr4_current_sos (void)
 	    }
 	}
 
+      /* 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.  */
+      if (lm == 0 && ldsomap == 0)
+	lm = ldsomap = solib_svr4_r_ldsomap ();
+
       discard_cleanups (old_chain);
     }
 
@@ -677,7 +683,7 @@ svr4_fetch_objfile_link_map (struct objf
     return 0;   /* failed somehow... */
 
   /* Position ourselves on the first link map.  */
-  lm = first_link_map_member ();  
+  lm = solib_svr4_r_map ();  
   while (lm)
     {
       /* Get info on the layout of the r_debug and link_map structures. */
@@ -1345,21 +1351,21 @@ svr4_ilp32_fetch_link_map_offsets (void)
     {
       lmp = &lmo;
 
-      /* Everything we need is in the first 8 bytes.  */
-      lmo.r_debug_size = 8;
+      lmo.r_version_offset = 0;
+      lmo.r_version_size = 4;
       lmo.r_map_offset = 4;
-      lmo.r_map_size   = 4;
+      lmo.r_ldsomap_offset = 20;
 
       /* Everything we need is in the first 20 bytes.  */
       lmo.link_map_size = 20;
       lmo.l_addr_offset = 0;
-      lmo.l_addr_size   = 4;
+      lmo.l_addr_size = 4;
       lmo.l_name_offset = 4;
-      lmo.l_name_size   = 4;
+      lmo.l_name_size = 4;
       lmo.l_next_offset = 12;
-      lmo.l_next_size   = 4;
+      lmo.l_next_size = 4;
       lmo.l_prev_offset = 16;
-      lmo.l_prev_size   = 4;
+      lmo.l_prev_size = 4;
     }
 
   return lmp;
@@ -1378,21 +1384,21 @@ svr4_lp64_fetch_link_map_offsets (void)
     {
       lmp = &lmo;
 
-      /* Everything we need is in the first 16 bytes.  */
-      lmo.r_debug_size = 16;
+      lmo.r_version_offset = 0;
+      lmo.r_version_size = 4;
       lmo.r_map_offset = 8;
-      lmo.r_map_size   = 8;
+      lmo.r_ldsomap_offset = 40;
 
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 40;
       lmo.l_addr_offset = 0;
-      lmo.l_addr_size   = 8;
+      lmo.l_addr_size = 8;
       lmo.l_name_offset = 8;
-      lmo.l_name_size   = 8;
+      lmo.l_name_size = 8;
       lmo.l_next_offset = 24;
-      lmo.l_next_size   = 8;
+      lmo.l_next_size = 8;
       lmo.l_prev_offset = 32;
-      lmo.l_prev_size   = 8;
+      lmo.l_prev_size = 8;
     }
 
   return lmp;
Index: solib-svr4.h
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.h,v
retrieving revision 1.10
diff -u -p -r1.10 solib-svr4.h
--- solib-svr4.h 17 Dec 2005 22:34:02 -0000 1.10
+++ solib-svr4.h 15 Jan 2006 22:20:12 -0000
@@ -1,6 +1,6 @@
 /* Handle shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 2000, 2004
+   Copyright (C) 2000, 2004, 2006
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -31,15 +31,14 @@ struct objfile;
 
 struct link_map_offsets
   {
-    /* Size of struct r_debug (or equivalent), or at least enough of it to
-       be able to obtain the r_map field.  */
-    int r_debug_size;
+    /* Offset and size of r_debug.r_version.  */
+    int r_version_offset, r_version_size;
 
-    /* Offset to the r_map field in struct r_debug.  */
+    /* Offset of r_debug.r_map.  */
     int r_map_offset;
 
-    /* Size of the r_map field in struct r_debug.  */
-    int r_map_size;
+    /* Offset of r_debug.r_ldsomap.  */
+    int r_ldsomap_offset;
 
     /* Size of struct link_map (or equivalent), or at least enough of it
        to be able to obtain the fields below.  */
Index: mipsnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mipsnbsd-tdep.c,v
retrieving revision 1.20
diff -u -p -r1.20 mipsnbsd-tdep.c
--- mipsnbsd-tdep.c 17 Dec 2005 22:34:01 -0000 1.20
+++ mipsnbsd-tdep.c 15 Jan 2006 22:20:12 -0000
@@ -1,6 +1,7 @@
 /* Target-dependent code for NetBSD/mips.
 
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+
    Contributed by Wasabi Systems, Inc.
 
    This file is part of GDB.
@@ -327,21 +328,21 @@ mipsnbsd_ilp32_fetch_link_map_offsets (v
     {
       lmp = &lmo;
 
-      /* Everything we need is in the first 8 bytes.  */
-      lmo.r_debug_size = 8;
+      lmo.r_version_offset = 0;
+      lmo.r_version_size = 4;
       lmo.r_map_offset = 4;
-      lmo.r_map_size   = 4;
+      lmo.r_ldsomap_offset = -1;
 
       /* Everything we need is in the first 24 bytes.  */
       lmo.link_map_size = 24;
       lmo.l_addr_offset = 4;
-      lmo.l_addr_size   = 4;
+      lmo.l_addr_size = 4;
       lmo.l_name_offset = 8;
-      lmo.l_name_size   = 4;
+      lmo.l_name_size = 4;
       lmo.l_next_offset = 16;
-      lmo.l_next_size   = 4;
+      lmo.l_next_size = 4;
       lmo.l_prev_offset = 20;
-      lmo.l_prev_size   = 4;
+      lmo.l_prev_size = 4;
     }
 
   return lmp;
@@ -357,21 +358,21 @@ mipsnbsd_lp64_fetch_link_map_offsets (vo
     {
       lmp = &lmo;
 
-      /* Everything we need is in the first 16 bytes.  */
-      lmo.r_debug_size = 16;
-      lmo.r_map_offset = 8;  
-      lmo.r_map_size   = 8;
+      lmo.r_version_offset = 0;
+      lmo.r_version_size = 4;
+      lmo.r_map_offset = 8;
+      lmo.r_ldsomap_offset = -1;
 
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 48;
       lmo.l_addr_offset = 0;
-      lmo.l_addr_size   = 8;
+      lmo.l_addr_size = 8;
       lmo.l_name_offset = 16; 
-      lmo.l_name_size   = 8;
+      lmo.l_name_size = 8;
       lmo.l_next_offset = 32;
-      lmo.l_next_size   = 8;
+      lmo.l_next_size = 8;
       lmo.l_prev_offset = 40;
-      lmo.l_prev_size   = 8;
+      lmo.l_prev_size = 8;
     }
 
   return lmp;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]