This is the mail archive of the gdb-patches@sources.redhat.com 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]

[RFA] osfsolib.c: support Tru64 5.x


This patch updates the shared module list reader in osfsolib.c to work
with Tru64 5.x.

On 5.x, ldr_module_info_t.modinfo_addr doesn't hold the address of its
containing structure, like it does on 4.x.  osfsolib.c uses that address
to check for the end of the shared module list, so on 5.x, it falls off
the end of the list.

The patch fixes that by overriding the modinfo_addr field with the
expected address in GDB's copy of the module list.

There was also a problem, on both 5.x and 4.x, where GDB would issue "Hit
heuristic-fence-post without finding enclosing function" warnings the
second time a program was run.

The fix is to add a make_run_cleanup() hook to call clear_solib().

I also made several cosmetic changes:
  - declare some unknown module fields as "char *" because they sometimes
    contain strings
  - split some large conditionals into multiple "if"s to simplify
    debugging
  - merge two similar code sequences into a single function
  - add/update various comments

ChangeLog:

	* osfsolib.c: Update libxproc.a comment.
	(ldr_module_info_t): Declare some unknown fields as char *
	instead of CORE_ADDR.
	(ldr_context_t): Document.
	(solib_cleanup_queued): New variable.
	(do_clear_solib, link_map_member): New functions.
	(first_link_map_member, next_link_map_member): Split large "if"
	conditional into multiple conditionals.  Rename {first,next}_lm
	to lm.  Move common code to link_map_member().
	(find_solib): Call make_run_cleanup().
	(clear_solib): Delete free_all_symtabs comment.  Don't call
	disable_breakpoints_in_shlibs().

Tested on alpha-dec-osf4.0 and alphaev6-dec-osf5.1, with
in_solib_dynsym_resolve_code() and .sbss patches similar to the ones Joel
Brobecker recently posted.  Okay to apply?

Nicholas Duffek
<nsd@redhat.com>

[patch follows]

Index: gdb/osfsolib.c
===================================================================
diff -up gdb/osfsolib.c gdb/osfsolib.c
--- gdb/osfsolib.c	Sat May 12 18:55:08 2001
+++ gdb/osfsolib.c	Sat May 12 18:18:33 2001
@@ -1,5 +1,5 @@
 /* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
-   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000
+   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -51,17 +51,19 @@
    current load address).
 
    Under OSF/1 there are two possibilities to get at this information:
+
    1) Peek around in the runtime loader structures.
    These are not documented, and they are not defined in the system
    header files. The definitions below were obtained by experimentation,
    but they seem stable enough.
-   2) Use the undocumented libxproc.a library, which contains the
-   equivalent ldr_* routines.
-   This approach is somewhat cleaner, but it requires that the GDB
-   executable is dynamically linked. In addition it requires a
-   NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
-   linker specification for GDB and all applications that are using
-   libgdb.
+
+   2) Use the libxproc.a library, which contains the equivalent ldr_*
+   routines.  The library is documented in Tru64 5.x, but as of 5.1, it
+   only allows a process to examine itself.  On earlier versions, it
+   may require that the GDB executable be dynamically linked and that
+   NAT_CLIBS include -lxproc -Wl,-expect_unresolved,ldr_process_context
+   for GDB and all applications that are using libgdb.
+
    We will use the peeking approach until it becomes unwieldy.  */
 
 #ifndef USE_LDR_ROUTINES
@@ -73,12 +75,13 @@ typedef struct
   {
     CORE_ADDR next;
     CORE_ADDR previous;
-    CORE_ADDR unknown1;
+    char *unknown1;
     char *module_name;
-    CORE_ADDR modinfo_addr;
+    CORE_ADDR modinfo_addr;	/* used by next_link_map_member() to detect
+				   the end of the shared module list */
     long module_id;
-    CORE_ADDR unknown2;
-    CORE_ADDR unknown3;
+    char *unknown2;
+    char *unknown3;
     long region_count;
     CORE_ADDR regioninfo_addr;
   }
@@ -96,6 +99,9 @@ typedef struct
   }
 ldr_region_info_t;
 
+/* Structure at RLD_CONTEXT_ADDRESS specifying the start and finish addresses
+   of the shared module list.  */
+
 typedef struct
   {
     CORE_ADDR unknown1;
@@ -170,10 +176,14 @@ struct so_list
 
 static struct so_list *so_list_head;	/* List of known shared objects */
 
+static int solib_cleanup_queued = 0;	/* make_run_cleanup called */
+
 extern int fdmatch (int, int);	/* In libiberty */
 
 /* Local function prototypes */
 
+static void do_clear_solib (PTR);
+
 static void sharedlibrary_command (char *, int);
 
 static void info_sharedlibrary_command (char *, int);
@@ -286,6 +296,62 @@ solib_map_sections (void *arg)
   return (1);
 }
 
+/* Read a link map member into LM.  If MODINFO is null, read the first
+   member, else read the one in MODINFO->next.  Return success.  */
+
+#ifndef USE_LDR_ROUTINES
+static int
+link_map_member (struct link_map *lm, ldr_module_info_t *modinfo)
+{
+  CORE_ADDR ldr_context_addr, prev, next;
+
+  /* Read the runtime loader list header.  ldr_context.tail changes as new
+     libraries are loaded, so don't cache across calls.  */
+  if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
+			  (char *) &ldr_context_addr,
+			  sizeof (CORE_ADDR)) != 0)
+    return 0;
+  if (target_read_memory (ldr_context_addr,
+			  (char *) &ldr_context,
+			  sizeof (ldr_context_t)) != 0)
+    return 0;
+
+  if (!modinfo)
+    {
+      prev = ldr_context.tail + 1;
+      next = ldr_context.head;
+    }
+  else
+    {
+      prev = modinfo->modinfo_addr;
+      next = modinfo->next;
+    }
+
+  for (;;)
+    {
+      /* Check for the end of the list.  */
+      if (prev == ldr_context.tail)
+	return 0;
+
+      if (target_read_memory (next,
+			      (char *) &lm->module_info,
+			      sizeof (ldr_module_info_t)) != 0)
+	return 0;
+
+      /* Skip past invalid members, e.g. /sbin/loader on Tru64 5.x.  */
+      if (lm->module_info.modinfo_addr)
+	break;
+      prev = next;
+      next = lm->module_info.next;
+    }
+
+  /* Override bogus value on Tru64 5.x.  */
+  lm->module_info.modinfo_addr = next;
+
+  return 1;
+}
+#endif   /* !USE_LDR_ROUTINES */
+
 /*
 
    LOCAL FUNCTION
@@ -306,8 +372,7 @@ solib_map_sections (void *arg)
 static struct link_map *
 first_link_map_member (void)
 {
-  struct link_map *lm = NULL;
-  static struct link_map first_lm;
+  static struct link_map lm;
 
 #ifdef USE_LDR_ROUTINES
   ldr_module_t mod_id = LDR_NULL_MODULE;
@@ -316,75 +381,52 @@ first_link_map_member (void)
   fake_ldr_process = ldr_core_process ();
   ldr_set_core_reader (ldr_read_memory);
   ldr_xdetach (fake_ldr_process);
-  if (ldr_xattach (fake_ldr_process) != 0
-      || ldr_next_module (fake_ldr_process, &mod_id) != 0
-      || mod_id == LDR_NULL_MODULE
-      || ldr_inq_module (fake_ldr_process, mod_id,
-			 &first_lm.module_info, sizeof (ldr_module_info_t),
-			 &retsize) != 0)
-    return lm;
+  if (ldr_xattach (fake_ldr_process) != 0)
+    return NULL;
+  if (ldr_next_module (fake_ldr_process, &mod_id) != 0)
+    return NULL;
+  if (mod_id == LDR_NULL_MODULE)
+    return NULL;
+  if (ldr_inq_module (fake_ldr_process, mod_id,
+		      &lm.module_info, sizeof (ldr_module_info_t),
+		      &retsize) != 0)
+    return NULL;
 #else
-  CORE_ADDR ldr_context_addr;
-
-  if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
-			  (char *) &ldr_context_addr,
-			  sizeof (CORE_ADDR)) != 0
-      || target_read_memory (ldr_context_addr,
-			     (char *) &ldr_context,
-			     sizeof (ldr_context_t)) != 0
-      || target_read_memory ((CORE_ADDR) ldr_context.head,
-			     (char *) &first_lm.module_info,
-			     sizeof (ldr_module_info_t)) != 0)
-    return lm;
+  if (!link_map_member (&lm, NULL))
+    return NULL;
 #endif
 
-  lm = &first_lm;
-
   /* The first entry is for the main program and should be skipped.  */
-  lm->l_name = NULL;
+  lm.l_name = NULL;
 
-  return lm;
+  return &lm;
 }
 
 static struct link_map *
 next_link_map_member (struct so_list *so_list_ptr)
 {
-  struct link_map *lm = NULL;
-  static struct link_map next_lm;
+  static struct link_map lm;
+
 #ifdef USE_LDR_ROUTINES
   ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
   size_t retsize;
 
-  if (ldr_next_module (fake_ldr_process, &mod_id) != 0
-      || mod_id == LDR_NULL_MODULE
-      || ldr_inq_module (fake_ldr_process, mod_id,
-			 &next_lm.module_info, sizeof (ldr_module_info_t),
-			 &retsize) != 0)
-    return lm;
-
-  lm = &next_lm;
-  lm->l_name = lm->module_info.lmi_name;
+  if (ldr_next_module (fake_ldr_process, &mod_id) != 0)
+    return NULL;
+  if (mod_id == LDR_NULL_MODULE)
+    return NULL;
+  if (ldr_inq_module (fake_ldr_process, mod_id,
+		      &lm.module_info, sizeof (ldr_module_info_t),
+		      &retsize) != 0)
+    return NULL;
+  lm.l_name = lm.module_info.lmi_name;
 #else
-  CORE_ADDR ldr_context_addr;
-
-  /* Reread context in case ldr_context.tail was updated.  */
-
-  if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
-			  (char *) &ldr_context_addr,
-			  sizeof (CORE_ADDR)) != 0
-      || target_read_memory (ldr_context_addr,
-			     (char *) &ldr_context,
-			     sizeof (ldr_context_t)) != 0
-      || so_list_ptr->lm.module_info.modinfo_addr == ldr_context.tail
-      || target_read_memory (so_list_ptr->lm.module_info.next,
-			     (char *) &next_lm.module_info,
-			     sizeof (ldr_module_info_t)) != 0)
-    return lm;
-
-  lm = &next_lm;
-  lm->l_name = lm->module_info.module_name;
+  if (!link_map_member (&lm, &so_list_ptr->lm.module_info))
+    return NULL;
+  lm.l_name = lm.module_info.module_name;
 #endif
-  return lm;
+
+  return &lm;
 }
 
 static void
@@ -514,6 +556,12 @@ find_solib (struct so_list *so_list_ptr)
   struct link_map *lm = NULL;
   struct so_list *new;
 
+  if (!solib_cleanup_queued)
+    {
+      make_run_cleanup (do_clear_solib, NULL);
+      solib_cleanup_queued = 1;
+    }
+
   if (so_list_ptr == NULL)
     {
       /* We are setting up for a new scan through the loaded images. */
@@ -784,16 +832,12 @@ solib_address (CORE_ADDR address)
   return (0);
 }
 
-/* Called by free_all_symtabs */
-
 void
 clear_solib (void)
 {
   struct so_list *next;
   char *bfd_filename;
 
-  disable_breakpoints_in_shlibs (1);
-
   while (so_list_head)
     {
       if (so_list_head->sections)
@@ -817,6 +861,20 @@ clear_solib (void)
       xfree (so_list_head);
       so_list_head = next;
     }
+}
+
+static void
+do_clear_solib (PTR dummy)
+{
+  clear_solib ();
+
+  /* Clear solib_cleanup_queued after calling clear_solib(), because
+     clear_solib() checks/sets solib_cleanup_queued via this call sequence:
+       1. disable_breakpoints_in_shlibs()
+       2. PC_SOLIB()
+       3. solib_address()
+       4. find_solib()  */
+  solib_cleanup_queued = 0;
 }
 
 /*


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