Wrong value printed by info locals for dynamic object.
[deliverable/binutils-gdb.git] / gdb / solib.c
index f2e68f5a7b749e0f0266e0d33328828d7f169a6b..3fed9dbe96e770670d46f7ffbc6535d7064bde9a 100644 (file)
@@ -1,7 +1,7 @@
 /* Handle shared libraries for GDB, the GNU Debugger.
 
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -46,6 +46,7 @@
 #include "readline/readline.h"
 #include "remote.h"
 #include "solib.h"
+#include "interps.h"
 
 /* Architecture-specific operations.  */
 
@@ -85,9 +86,8 @@ set_solib_ops (struct gdbarch *gdbarch, struct target_so_ops *new_ops)
    configuration needs to call set_solib_ops.  */
 struct target_so_ops *current_target_so_ops;
 
-/* local data declarations */
-
-static struct so_list *so_list_head;   /* List of known shared objects */
+/* List of known shared objects */
+#define so_list_head current_program_space->so_list
 
 /* Local function prototypes */
 
@@ -150,6 +150,30 @@ solib_find (char *in_pathname, int *fd)
   int found_file = -1;
   char *temp_pathname = NULL;
   int gdb_sysroot_is_empty;
+  const char *solib_symbols_extension
+    = gdbarch_solib_symbols_extension (target_gdbarch);
+
+  /* If solib_symbols_extension is set, replace the file's
+     extension.  */
+  if (solib_symbols_extension)
+    {
+      char *p = in_pathname + strlen (in_pathname);
+      while (p > in_pathname && *p != '.')
+       p--;
+
+      if (*p == '.')
+       {
+         char *new_pathname;
+
+         new_pathname = alloca (p - in_pathname + 1
+                                + strlen (solib_symbols_extension) + 1);
+         memcpy (new_pathname, in_pathname, p - in_pathname + 1);
+         strcpy (new_pathname + (p - in_pathname) + 1,
+                 solib_symbols_extension);
+
+         in_pathname = new_pathname;
+       }
+    }
 
   gdb_sysroot_is_empty = (gdb_sysroot == NULL || *gdb_sysroot == 0);
 
@@ -210,14 +234,14 @@ solib_find (char *in_pathname, int *fd)
   /* If not found, search the solib_search_path (if any).  */
   if (found_file < 0 && solib_search_path != NULL)
     found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-                       in_pathname, O_RDONLY | O_BINARY, 0, &temp_pathname);
+                       in_pathname, O_RDONLY | O_BINARY, &temp_pathname);
   
   /* If not found, next search the solib_search_path (if any) for the basename
      only (ignoring the path).  This is to allow reading solibs from a path
      that differs from the opened path.  */
   if (found_file < 0 && solib_search_path != NULL)
     found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-                        lbasename (in_pathname), O_RDONLY | O_BINARY, 0,
+                        lbasename (in_pathname), O_RDONLY | O_BINARY,
                         &temp_pathname);
 
   /* If not found, try to use target supplied solib search method */
@@ -227,15 +251,17 @@ solib_find (char *in_pathname, int *fd)
 
   /* If not found, next search the inferior's $PATH environment variable. */
   if (found_file < 0 && gdb_sysroot_is_empty)
-    found_file = openp (get_in_environ (inferior_environ, "PATH"),
-                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, 0,
+    found_file = openp (get_in_environ (current_inferior ()->environment,
+                                       "PATH"),
+                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
                        &temp_pathname);
 
   /* If not found, next search the inferior's $LD_LIBRARY_PATH 
      environment variable. */
   if (found_file < 0 && gdb_sysroot_is_empty)
-    found_file = openp (get_in_environ (inferior_environ, "LD_LIBRARY_PATH"),
-                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY, 0,
+    found_file = openp (get_in_environ (current_inferior ()->environment,
+                                       "LD_LIBRARY_PATH"),
+                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
                        &temp_pathname);
 
   *fd = found_file;
@@ -285,19 +311,22 @@ solib_bfd_fopen (char *pathname, int fd)
 bfd *
 solib_bfd_open (char *pathname)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
   char *found_pathname;
   int found_file;
   bfd *abfd;
-
-  /* Use target-specific override if present.  */
-  if (ops->bfd_open)
-    return ops->bfd_open (pathname);
+  const struct bfd_arch_info *b;
 
   /* Search for shared library file.  */
   found_pathname = solib_find (pathname, &found_file);
   if (found_pathname == NULL)
-    perror_with_name (pathname);
+    {
+      /* Return failure if the file could not be found, so that we can
+        accumulate messages about missing libraries.  */
+      if (errno == ENOENT)
+       return NULL;
+
+      perror_with_name (pathname);
+    }
 
   /* Open bfd for shared library.  */
   abfd = solib_bfd_fopen (found_pathname, found_file);
@@ -311,6 +340,13 @@ solib_bfd_open (char *pathname)
             found_pathname, bfd_errmsg (bfd_get_error ()));
     }
 
+  /* Check bfd arch.  */
+  b = gdbarch_bfd_arch_info (target_gdbarch);
+  if (!b->compatible (b, bfd_get_arch_info (abfd)))
+    warning (_("`%s': Shared library architecture %s is not compatible "
+               "with target architecture %s."), found_pathname,
+             bfd_get_arch_info (abfd)->printable_name, b->printable_name);
+
   return abfd;
 }
 
@@ -343,21 +379,24 @@ solib_bfd_open (char *pathname)
  */
 
 static int
-solib_map_sections (void *arg)
+solib_map_sections (struct so_list *so)
 {
-  struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
+  struct target_so_ops *ops = solib_ops (target_gdbarch);
   char *filename;
-  struct section_table *p;
+  struct target_section *p;
   struct cleanup *old_chain;
   bfd *abfd;
 
   filename = tilde_expand (so->so_name);
   old_chain = make_cleanup (xfree, filename);
-  abfd = solib_bfd_open (filename);
+  abfd = ops->bfd_open (filename);
   do_cleanups (old_chain);
 
+  if (abfd == NULL)
+    return 0;
+
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = abfd;
+  so->abfd = gdb_bfd_ref (abfd);
 
   /* copy full path name into so_name, so that later symbol_file_add
      can find it */
@@ -373,8 +412,6 @@ solib_map_sections (void *arg)
 
   for (p = so->sections; p < so->sections_end; p++)
     {
-      struct target_so_ops *ops = solib_ops (target_gdbarch);
-
       /* Relocate the section binding addresses as recorded in the shared
          object's file by the base address to which the object was actually
          mapped. */
@@ -391,7 +428,46 @@ solib_map_sections (void *arg)
        }
     }
 
-  return (1);
+  /* Add the shared object's sections to the current set of file
+     section tables.  Do this immediately after mapping the object so
+     that later nodes in the list can query this object, as is needed
+     in solib-osf.c.  */
+  add_target_sections (so->sections, so->sections_end);
+
+  return 1;
+}
+
+/* Free symbol-file related contents of SO.  If we have opened a BFD
+   for SO, close it.  If we have placed SO's sections in some target's
+   section table, the caller is responsible for removing them.
+
+   This function doesn't mess with objfiles at all.  If there is an
+   objfile associated with SO that needs to be removed, the caller is
+   responsible for taking care of that.  */
+
+static void
+free_so_symbols (struct so_list *so)
+{
+  char *bfd_filename = 0;
+
+  if (so->sections)
+    {
+      xfree (so->sections);
+      so->sections = so->sections_end = NULL;
+    }
+
+  gdb_bfd_unref (so->abfd);
+  so->abfd = NULL;
+
+  /* Our caller closed the objfile, possibly via objfile_purge_solibs.  */
+  so->symbols_loaded = 0;
+  so->objfile = NULL;
+
+  so->addr_low = so->addr_high = 0;
+
+  /* Restore the target-supplied file name.  SO_NAME may be the path
+     of the symbol file.  */
+  strcpy (so->so_name, so->so_original_name);
 }
 
 /* LOCAL FUNCTION
@@ -419,22 +495,8 @@ void
 free_so (struct so_list *so)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
-  char *bfd_filename = 0;
-
-  if (so->sections)
-    xfree (so->sections);
-      
-  if (so->abfd)
-    {
-      bfd_filename = bfd_get_filename (so->abfd);
-      if (! bfd_close (so->abfd))
-       warning (_("cannot close \"%s\": %s"),
-                bfd_filename, bfd_errmsg (bfd_get_error ()));
-    }
-
-  if (bfd_filename)
-    xfree (bfd_filename);
 
+  free_so_symbols (so);
   ops->free_so (so);
 
   xfree (so);
@@ -448,60 +510,62 @@ master_so_list (void)
   return so_list_head;
 }
 
-
-/* A small stub to get us past the arg-passing pinhole of catch_errors.  */
-
-static int
-symbol_add_stub (void *arg)
-{
-  struct so_list *so = (struct so_list *) arg;  /* catch_errs bogon */
-  struct section_addr_info *sap;
-
-  /* Have we already loaded this shared object?  */
-  ALL_OBJFILES (so->objfile)
-    {
-      if (strcmp (so->objfile->name, so->so_name) == 0)
-       return 1;
-    }
-
-  sap = build_section_addr_info_from_section_table (so->sections,
-                                                    so->sections_end);
-
-  so->objfile = symbol_file_add_from_bfd (so->abfd, so->from_tty,
-                                         sap, 0, OBJF_SHARED | OBJF_KEEPBFD);
-  free_section_addr_info (sap);
-
-  return (1);
-}
-
-/* Read in symbols for shared object SO.  If FROM_TTY is non-zero, be
-   chatty about it.  Return non-zero if any symbols were actually
+/* Read in symbols for shared object SO.  If SYMFILE_VERBOSE is set in FLAGS,
+   be chatty about it.  Return non-zero if any symbols were actually
    loaded.  */
 
 int
-solib_read_symbols (struct so_list *so, int from_tty)
+solib_read_symbols (struct so_list *so, int flags)
 {
+  const int from_tty = flags & SYMFILE_VERBOSE;
+
   if (so->symbols_loaded)
     {
-      if (from_tty)
-       printf_unfiltered (_("Symbols already loaded for %s\n"), so->so_name);
+      /* If needed, we've already warned in our caller.  */
     }
   else if (so->abfd == NULL)
     {
-      if (from_tty)
-       printf_unfiltered (_("Symbol file not found for %s\n"), so->so_name);
+      /* We've already warned about this library, when trying to open
+        it.  */
     }
   else
     {
-      if (catch_errors (symbol_add_stub, so,
-                       "Error while reading shared library symbols:\n",
-                       RETURN_MASK_ALL))
+      volatile struct gdb_exception e;
+
+      TRY_CATCH (e, RETURN_MASK_ERROR)
        {
-         if (from_tty && print_symbol_loading)
+         struct section_addr_info *sap;
+
+         /* Have we already loaded this shared object?  */
+         ALL_OBJFILES (so->objfile)
+           {
+             if (strcmp (so->objfile->name, so->so_name) == 0)
+               break;
+           }
+         if (so->objfile != NULL)
+           break;
+
+         sap = build_section_addr_info_from_section_table (so->sections,
+                                                           so->sections_end);
+         so->objfile = symbol_file_add_from_bfd (so->abfd,
+                                                 flags, sap, OBJF_SHARED);
+         free_section_addr_info (sap);
+       }
+
+      if (e.reason < 0)
+       {
+         if (from_tty)
+           exception_fprintf
+             (gdb_stderr, e,
+              _("Error while reading shared library symbols:\n"));
+       }
+      else
+       {
+         if (from_tty || info_verbose)
            printf_unfiltered (_("Loaded symbols for %s\n"), so->so_name);
          so->symbols_loaded = 1;
-         return 1;
        }
+      return 1;
     }
 
   return 0;
@@ -646,6 +710,9 @@ update_solib_list (int from_tty, struct target_ops *target)
      to GDB's shared object list.  */
   if (inferior)
     {
+      int not_found = 0;
+      const char *not_found_filename = NULL;
+
       struct so_list *i;
 
       /* Add the new shared objects to GDB's list.  */
@@ -654,46 +721,70 @@ update_solib_list (int from_tty, struct target_ops *target)
       /* Fill in the rest of each of the `struct so_list' nodes.  */
       for (i = inferior; i; i = i->next)
        {
-         i->from_tty = from_tty;
-
-         /* Fill in the rest of the `struct so_list' node.  */
-         catch_errors (solib_map_sections, i,
-                       "Error while mapping shared library sections:\n",
-                       RETURN_MASK_ALL);
-
-         /* If requested, add the shared object's sections to the TARGET's
-            section table.  Do this immediately after mapping the object so
-            that later nodes in the list can query this object, as is needed
-            in solib-osf.c.  */
-         if (target)
+         volatile struct gdb_exception e;
+
+         i->pspace = current_program_space;
+
+         TRY_CATCH (e, RETURN_MASK_ERROR)
            {
-             int count = (i->sections_end - i->sections);
-             if (count > 0)
+             /* Fill in the rest of the `struct so_list' node.  */
+             if (!solib_map_sections (i))
                {
-                 int space = target_resize_to_sections (target, count);
-                 memcpy (target->to_sections + space,
-                         i->sections,
-                         count * sizeof (i->sections[0]));
+                 not_found++;
+                 if (not_found_filename == NULL)
+                   not_found_filename = i->so_original_name;
                }
            }
 
+         if (e.reason < 0)
+           exception_fprintf (gdb_stderr, e, _("\
+Error while mapping shared library sections:\n"));
+
          /* Notify any observer that the shared object has been
-             loaded now that we've added it to GDB's tables.  */
+            loaded now that we've added it to GDB's tables.  */
          observer_notify_solib_loaded (i);
        }
+
+      /* If a library was not found, issue an appropriate warning
+        message.  We have to use a single call to warning in case the
+        front end does something special with warnings, e.g., pop up
+        a dialog box.  It Would Be Nice if we could get a "warning: "
+        prefix on each line in the CLI front end, though - it doesn't
+        stand out well.  */
+
+      if (not_found == 1)
+       warning (_("\
+Could not load shared library symbols for %s.\n\
+Do you need \"set solib-search-path\" or \"set sysroot\"?"),
+                not_found_filename);
+      else if (not_found > 1)
+       warning (_("\
+Could not load shared library symbols for %d libraries, e.g. %s.\n\
+Use the \"info sharedlibrary\" command to see the complete listing.\n\
+Do you need \"set solib-search-path\" or \"set sysroot\"?"),
+                not_found, not_found_filename);
     }
 }
 
-/* Return non-zero if SO is the libpthread shared library.
+
+/* Return non-zero if NAME is the libpthread shared library.
 
    Uses a fairly simplistic heuristic approach where we check
    the file name against "/libpthread".  This can lead to false
    positives, but this should be good enough in practice.  */
 
+int
+libpthread_name_p (const char *name)
+{
+  return (strstr (name, "/libpthread") != NULL);
+}
+
+/* Return non-zero if SO is the libpthread shared library.  */
+
 static int
 libpthread_solib_p (struct so_list *so)
 {
-  return (strstr (so->so_name, "/libpthread") != NULL);
+  return libpthread_name_p (so->so_name);
 }
 
 /* GLOBAL FUNCTION
@@ -737,6 +828,8 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
   {
     int any_matches = 0;
     int loaded_any_symbols = 0;
+    const int flags =
+        SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0);
 
     for (gdb = so_list_head; gdb; gdb = gdb->next)
       if (! pattern || re_exec (gdb->so_name))
@@ -750,10 +843,24 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
             (readsyms || libpthread_solib_p (gdb));
 
          any_matches = 1;
-         if (add_this_solib && solib_read_symbols (gdb, from_tty))
-           loaded_any_symbols = 1;
+         if (add_this_solib)
+           {
+             if (gdb->symbols_loaded)
+               {
+                 /* If no pattern was given, be quiet for shared
+                    libraries we have already loaded.  */
+                 if (pattern && (from_tty || info_verbose))
+                   printf_unfiltered (_("Symbols already loaded for %s\n"),
+                                      gdb->so_name);
+               }
+             else if (solib_read_symbols (gdb, flags))
+               loaded_any_symbols = 1;
+           }
        }
 
+    if (loaded_any_symbols)
+      breakpoint_re_set ();
+
     if (from_tty && pattern && ! any_matches)
       printf_unfiltered
        ("No loaded shared libraries match the pattern `%s'.\n", pattern);
@@ -785,53 +892,132 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
    DESCRIPTION
 
    Walk through the shared library list and print information
-   about each attached library.
+   about each attached library matching PATTERN.  If PATTERN is elided,
+   print them all.
  */
 
 static void
-info_sharedlibrary_command (char *ignore, int from_tty)
+info_sharedlibrary_command (char *pattern, int from_tty)
 {
   struct so_list *so = NULL;   /* link map state variable */
   int header_done = 0;
+  int so_missing_debug_info = 0;
   int addr_width;
+  int nr_libs;
+  struct cleanup *table_cleanup;
+  struct gdbarch *gdbarch = target_gdbarch;
+
+  if (pattern)
+    {
+      char *re_err = re_comp (pattern);
+
+      if (re_err)
+       error (_("Invalid regexp: %s"), re_err);
+    }
 
   /* "0x", a little whitespace, and two hex digits per byte of pointers.  */
-  addr_width = 4 + (gdbarch_ptr_bit (target_gdbarch) / 4);
+  addr_width = 4 + (gdbarch_ptr_bit (gdbarch) / 4);
 
   update_solib_list (from_tty, 0);
 
-  for (so = so_list_head; so; so = so->next)
+  /* make_cleanup_ui_out_table_begin_end needs to know the number of
+     rows, so we need to make two passes over the libs.  */
+
+  for (nr_libs = 0, so = so_list_head; so; so = so->next)
     {
       if (so->so_name[0])
        {
-         if (!header_done)
-           {
-             printf_unfiltered ("%-*s%-*s%-12s%s\n", addr_width, "From",
-                                addr_width, "To", "Syms Read",
-                                "Shared Object Library");
-             header_done++;
-           }
+         if (pattern && ! re_exec (so->so_name))
+           continue;
+         ++nr_libs;
+       }
+    }
+
+  table_cleanup =
+    make_cleanup_ui_out_table_begin_end (uiout, 4, nr_libs,
+                                        "SharedLibraryTable");
+
+  /* The "- 1" is because ui_out adds one space between columns.  */
+  ui_out_table_header (uiout, addr_width - 1, ui_left, "from", "From");
+  ui_out_table_header (uiout, addr_width - 1, ui_left, "to", "To");
+  ui_out_table_header (uiout, 12 - 1, ui_left, "syms-read", "Syms Read");
+  ui_out_table_header (uiout, 0, ui_noalign,
+                      "name", "Shared Object Library");
 
-         printf_unfiltered ("%-*s", addr_width,
-                            so->addr_high != 0
-                              ? hex_string_custom (
-                                  (LONGEST) so->addr_low,
-                                  addr_width - 4)
-                              : "");
-         printf_unfiltered ("%-*s", addr_width,
-                            so->addr_high != 0
-                              ? hex_string_custom (
-                                  (LONGEST) so->addr_high,
-                                  addr_width - 4)
-                              : "");
-         printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
-         printf_unfiltered ("%s\n", so->so_name);
+  ui_out_table_body (uiout);
+
+  for (so = so_list_head; so; so = so->next)
+    {
+      struct cleanup *lib_cleanup;
+
+      if (! so->so_name[0])
+       continue;
+      if (pattern && ! re_exec (so->so_name))
+       continue;
+
+      lib_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "lib");
+
+      if (so->addr_high != 0)
+       {
+         ui_out_field_core_addr (uiout, "from", gdbarch, so->addr_low);
+         ui_out_field_core_addr (uiout, "to", gdbarch, so->addr_high);
        }
+      else
+       {
+         ui_out_field_skip (uiout, "from");
+         ui_out_field_skip (uiout, "to");
+       }
+
+      if (! ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ()))
+         && so->symbols_loaded
+         && !objfile_has_symbols (so->objfile))
+       {
+         so_missing_debug_info = 1;
+         ui_out_field_string (uiout, "syms-read", "Yes (*)");
+       }
+      else
+       ui_out_field_string (uiout, "syms-read", 
+                            so->symbols_loaded ? "Yes" : "No");
+
+      ui_out_field_string (uiout, "name", so->so_name);
+
+      ui_out_text (uiout, "\n");
+
+      do_cleanups (lib_cleanup);
     }
-  if (so_list_head == NULL)
+
+  do_cleanups (table_cleanup);
+
+  if (nr_libs == 0)
     {
-      printf_unfiltered (_("No shared libraries loaded at this time.\n"));
+      if (pattern)
+       ui_out_message (uiout, 0,
+                       _("No shared libraries matched.\n"));
+      else
+       ui_out_message (uiout, 0,
+                       _("No shared libraries loaded at this time.\n"));
     }
+  else
+    {
+      if (so_missing_debug_info)
+       ui_out_message (uiout, 0,
+                       _("(*): Shared library is missing debugging information.\n"));
+    }
+}
+
+/* Return 1 if ADDRESS lies within SOLIB.  */
+
+int
+solib_contains_address_p (const struct so_list *const solib,
+                         CORE_ADDR address)
+{
+  struct target_section *p;
+
+  for (p = solib->sections; p < solib->sections_end; p++)
+    if (p->addr <= address && address < p->endaddr)
+      return 1;
+
+  return 0;
 }
 
 /*
@@ -857,24 +1043,34 @@ info_sharedlibrary_command (char *ignore, int from_tty)
  */
 
 char *
-solib_name_from_address (CORE_ADDR address)
+solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
 {
-  struct so_list *so = 0;      /* link map state variable */
+  struct so_list *so = NULL;
 
-  for (so = so_list_head; so; so = so->next)
-    {
-      struct section_table *p;
-
-      for (p = so->sections; p < so->sections_end; p++)
-       {
-         if (p->addr <= address && address < p->endaddr)
-           return (so->so_name);
-       }
-    }
+  for (so = pspace->so_list; so; so = so->next)
+    if (solib_contains_address_p (so, address))
+      return (so->so_name);
 
   return (0);
 }
 
+/* Return whether the data starting at VADDR, size SIZE, must be kept
+   in a core file for shared libraries loaded before "gcore" is used
+   to be handled correctly when the core file is loaded.  This only
+   applies when the section would otherwise not be kept in the core
+   file (in particular, for readonly sections).  */
+
+int
+solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
+{
+  struct target_so_ops *ops = solib_ops (target_gdbarch);
+
+  if (ops->keep_data_in_core)
+    return ops->keep_data_in_core (vaddr, size);
+  else
+    return 0;
+}
+
 /* Called by free_all_symtabs */
 
 void
@@ -925,7 +1121,7 @@ clear_solib (void)
 
    SYNOPSIS
 
-   void solib_create_inferior_hook ()
+   void solib_create_inferior_hook (int from_tty)
 
    DESCRIPTION
 
@@ -935,10 +1131,10 @@ clear_solib (void)
    SOLIB_CREATE_INFERIOR_HOOK.  */
 
 void
-solib_create_inferior_hook (void)
+solib_create_inferior_hook (int from_tty)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
-  ops->solib_create_inferior_hook();
+  ops->solib_create_inferior_hook (from_tty);
 }
 
 /* GLOBAL FUNCTION
@@ -1009,12 +1205,123 @@ no_shared_libraries (char *ignored, int from_tty)
   objfile_purge_solibs ();
 }
 
+/* Reload shared libraries, but avoid reloading the same symbol file
+   we already have loaded.  */
+
+static void
+reload_shared_libraries_1 (int from_tty)
+{
+  struct so_list *so;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+
+  for (so = so_list_head; so != NULL; so = so->next)
+    {
+      char *filename, *found_pathname = NULL;
+      bfd *abfd;
+      int scratch_chan;
+      int was_loaded = so->symbols_loaded;
+      const int flags =
+       SYMFILE_DEFER_BP_RESET | (from_tty ? SYMFILE_VERBOSE : 0);
+
+      filename = tilde_expand (so->so_original_name);
+      abfd = solib_bfd_open (filename);
+      if (abfd != NULL)
+       {
+         found_pathname = xstrdup (bfd_get_filename (abfd));
+         make_cleanup (xfree, found_pathname);
+         gdb_bfd_close_or_warn (abfd);
+       }
+
+      /* If this shared library is no longer associated with its previous
+        symbol file, close that.  */
+      if ((found_pathname == NULL && was_loaded)
+         || (found_pathname != NULL
+             && strcmp (found_pathname, so->so_name) != 0))
+       {
+         if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED))
+           free_objfile (so->objfile);
+         remove_target_sections (so->abfd);
+         free_so_symbols (so);
+       }
+
+      /* If this shared library is now associated with a new symbol
+        file, open it.  */
+      if (found_pathname != NULL
+         && (!was_loaded
+             || strcmp (found_pathname, so->so_name) != 0))
+       {
+         volatile struct gdb_exception e;
+
+         TRY_CATCH (e, RETURN_MASK_ERROR)
+           solib_map_sections (so);
+
+         if (e.reason < 0)
+           exception_fprintf (gdb_stderr, e, _("\
+Error while mapping shared library sections:\n"));
+         else if (auto_solib_add || was_loaded || libpthread_solib_p (so))
+           solib_read_symbols (so, flags);
+       }
+    }
+
+  do_cleanups (old_chain);
+}
+
 static void
 reload_shared_libraries (char *ignored, int from_tty,
                         struct cmd_list_element *e)
 {
-  no_shared_libraries (NULL, from_tty);
-  solib_add (NULL, from_tty, NULL, auto_solib_add);
+  struct target_so_ops *ops;
+
+  reload_shared_libraries_1 (from_tty);
+
+  ops = solib_ops (target_gdbarch);
+
+  /* Creating inferior hooks here has two purposes. First, if we reload 
+     shared libraries then the address of solib breakpoint we've computed
+     previously might be no longer valid.  For example, if we forgot to set
+     solib-absolute-prefix and are setting it right now, then the previous
+     breakpoint address is plain wrong.  Second, installing solib hooks
+     also implicitly figures were ld.so is and loads symbols for it.
+     Absent this call, if we've just connected to a target and set 
+     solib-absolute-prefix or solib-search-path, we'll lose all information
+     about ld.so.  */
+  if (target_has_execution)
+    {
+      /* Reset or free private data structures not associated with
+        so_list entries.  */
+      ops->clear_solib ();
+
+      /* Remove any previous solib event breakpoint.  This is usually
+        done in common code, at breakpoint_init_inferior time, but
+        we're not really starting up the inferior here.  */
+      remove_solib_event_breakpoints ();
+
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+      SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
+#else
+      solib_create_inferior_hook (from_tty);
+#endif
+    }
+
+  /* Sometimes the platform-specific hook loads initial shared
+     libraries, and sometimes it doesn't.  If it doesn't FROM_TTY will be
+     incorrectly 0 but such solib targets should be fixed anyway.  If we
+     made all the inferior hook methods consistent, this call could be
+     removed.  Call it only after the solib target has been initialized by
+     solib_create_inferior_hook.  */
+
+  solib_add (NULL, 0, NULL, auto_solib_add);
+
+  breakpoint_re_set ();
+
+  /* We may have loaded or unloaded debug info for some (or all)
+     shared libraries.  However, frames may still reference them.  For
+     example, a frame's unwinder might still point at DWARF FDE
+     structures that are now freed.  Also, getting new symbols may
+     change our opinion about what is frameless.  */
+  reinit_frame_cache ();
+
+  ops->special_symbol_handling ();
 }
 
 static void
@@ -1032,13 +1339,12 @@ show_auto_solib_add (struct ui_file *file, int from_tty,
 struct symbol *
 solib_global_lookup (const struct objfile *objfile,
                     const char *name,
-                    const char *linkage_name,
                     const domain_enum domain)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
 
   if (ops->lookup_lib_global_symbol != NULL)
-    return ops->lookup_lib_global_symbol (objfile, name, linkage_name, domain);
+    return ops->lookup_lib_global_symbol (objfile, name, domain);
   return NULL;
 }
 
This page took 0.033717 seconds and 4 git commands to generate.