2005-02-11 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / solib.c
index 8da44df11a902627b67beffed60134737ba1b5e3..f64d8921ad1f08359c3dc901b8a6ae5b46c2e024 100644 (file)
@@ -1,6 +1,7 @@
 /* Handle shared libraries for GDB, the GNU Debugger.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001
+
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2005
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -29,6 +30,7 @@
 #include "bfd.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "exceptions.h"
 #include "gdbcore.h"
 #include "command.h"
 #include "target.h"
 #include "language.h"
 #include "gdbcmd.h"
 #include "completer.h"
-
+#include "filenames.h"         /* for DOSish file names */
+#include "exec.h"
 #include "solist.h"
+#include "observer.h"
+#include "readline/readline.h"
 
 /* external data declarations */
 
@@ -55,7 +60,7 @@ static int solib_cleanup_queued = 0;  /* make_run_cleanup called */
 
 /* Local function prototypes */
 
-static void do_clear_solib (PTR);
+static void do_clear_solib (void *);
 
 /* If non-zero, this is a prefix that will be added to the front of the name
    shared libraries with an absolute filename for loading.  */
@@ -85,12 +90,19 @@ static char *solib_search_path = NULL;
    (or set of directories, as in LD_LIBRARY_PATH) to search for all
    shared libraries if not found in SOLIB_ABSOLUTE_PREFIX.
 
-   Search order:
-   * If path is absolute, look in SOLIB_ABSOLUTE_PREFIX.
-   * If path is absolute or relative, look for it literally (unmodified).
+   Search algorithm:
+   * If there is a solib_absolute_prefix and path is absolute:
+   *   Search for solib_absolute_prefix/path.
+   * else
+   *   Look for it literally (unmodified).
    * Look in SOLIB_SEARCH_PATH.
-   * Look in inferior's $PATH.
-   * Look in inferior's $LD_LIBRARY_PATH.
+   * If available, use target defined search function.
+   * If solib_absolute_prefix is NOT set, perform the following two searches:
+   *   Look in inferior's $PATH.
+   *   Look in inferior's $LD_LIBRARY_PATH.
+   *   
+   * The last check avoids doing this search when targetting remote
+   * machines since solib_absolute_prefix will almost always be set.
 
    RETURNS
 
@@ -101,10 +113,14 @@ solib_open (char *in_pathname, char **found_pathname)
 {
   int found_file = -1;
   char *temp_pathname = NULL;
+  char *p = in_pathname;
 
-  if (strchr (in_pathname, SLASH_CHAR))
+  while (*p && !IS_DIR_SEPARATOR (*p))
+    p++;
+
+  if (*p)
     {
-      if (! ROOTED_P (in_pathname) || solib_absolute_prefix == NULL)
+      if (! IS_ABSOLUTE_PATH (in_pathname) || solib_absolute_prefix == NULL)
         temp_pathname = in_pathname;
       else
        {
@@ -112,7 +128,7 @@ solib_open (char *in_pathname, char **found_pathname)
 
          /* Remove trailing slashes from absolute prefix.  */
          while (prefix_len > 0
-                && SLASH_P (solib_absolute_prefix[prefix_len - 1]))
+                && IS_DIR_SEPARATOR (solib_absolute_prefix[prefix_len - 1]))
            prefix_len--;
 
          /* Cat the prefixed pathname together.  */
@@ -126,21 +142,51 @@ solib_open (char *in_pathname, char **found_pathname)
       found_file = open (temp_pathname, O_RDONLY, 0);
     }
 
-  /* If not found, next search the solib_search_path (if any).  */
+  /* If the search in solib_absolute_prefix failed, and the path name is
+     absolute at this point, make it relative.  (openp will try and open the
+     file according to its absolute path otherwise, which is not what we want.)
+     Affects subsequent searches for this solib.  */
+  if (found_file < 0 && IS_ABSOLUTE_PATH (in_pathname))
+    {
+      /* First, get rid of any drive letters etc.  */
+      while (!IS_DIR_SEPARATOR (*in_pathname))
+        in_pathname++;
+
+      /* Next, get rid of all leading dir separators.  */
+      while (IS_DIR_SEPARATOR (*in_pathname))
+        in_pathname++;
+    }
+  
+  /* If not found, search the solib_search_path (if any).  */
   if (found_file < 0 && solib_search_path != NULL)
-    found_file = openp (solib_search_path,
-                       1, in_pathname, O_RDONLY, 0, &temp_pathname);
+    found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
+                       in_pathname, O_RDONLY, 0, &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, 0,
+                        &temp_pathname);
+
+  /* If not found, try to use target supplied solib search method */
+  if (found_file < 0 && TARGET_SO_FIND_AND_OPEN_SOLIB != NULL)
+    found_file = TARGET_SO_FIND_AND_OPEN_SOLIB
+                 (in_pathname, O_RDONLY, &temp_pathname);
 
   /* If not found, next search the inferior's $PATH environment variable. */
-  if (found_file < 0 && solib_search_path != NULL)
+  if (found_file < 0 && solib_absolute_prefix == NULL)
     found_file = openp (get_in_environ (inferior_environ, "PATH"),
-                       1, in_pathname, O_RDONLY, 0, &temp_pathname);
+                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY, 0,
+                       &temp_pathname);
 
   /* If not found, next search the inferior's $LD_LIBRARY_PATH 
      environment variable. */
-  if (found_file < 0 && solib_search_path != NULL)
+  if (found_file < 0 && solib_absolute_prefix == NULL)
     found_file = openp (get_in_environ (inferior_environ, "LD_LIBRARY_PATH"),
-                       1, in_pathname, O_RDONLY, 0, &temp_pathname);
+                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY, 0,
+                       &temp_pathname);
 
   /* Done.  If not found, tough luck.  Return found_file and 
      (optionally) found_pathname.  */
@@ -178,7 +224,7 @@ solib_open (char *in_pathname, char **found_pathname)
  */
 
 static int
-solib_map_sections (PTR arg)
+solib_map_sections (void *arg)
 {
   struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
   char *filename;
@@ -203,28 +249,28 @@ solib_map_sections (PTR arg)
   if (!abfd)
     {
       close (scratch_chan);
-      error ("Could not open `%s' as an executable file: %s",
+      error (_("Could not open `%s' as an executable file: %s"),
             scratch_pathname, bfd_errmsg (bfd_get_error ()));
     }
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
   so->abfd = abfd;
-  abfd->cacheable = true;
+  bfd_set_cacheable (abfd, 1);
 
   /* copy full path name into so_name, so that later symbol_file_add
      can find it */
   if (strlen (scratch_pathname) >= SO_NAME_MAX_PATH_SIZE)
-    error ("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure.");
+    error (_("Full path name length of shared library exceeds SO_NAME_MAX_PATH_SIZE in so_list structure."));
   strcpy (so->so_name, scratch_pathname);
 
   if (!bfd_check_format (abfd, bfd_object))
     {
-      error ("\"%s\": not in executable format: %s.",
+      error (_("\"%s\": not in executable format: %s."),
             scratch_pathname, bfd_errmsg (bfd_get_error ()));
     }
   if (build_section_table (abfd, &so->sections, &so->sections_end))
     {
-      error ("Can't find the file sections in `%s': %s",
+      error (_("Can't find the file sections in `%s': %s"),
             bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
     }
 
@@ -234,7 +280,7 @@ solib_map_sections (PTR arg)
          object's file by the base address to which the object was actually
          mapped. */
       TARGET_SO_RELOCATE_SECTION_ADDRESSES (so, p);
-      if (STREQ (p->the_bfd_section->name, ".text"))
+      if (strcmp (p->the_bfd_section->name, ".text") == 0)
        {
          so->textsection = p;
        }
@@ -279,7 +325,7 @@ free_so (struct so_list *so)
     {
       bfd_filename = bfd_get_filename (so->abfd);
       if (! bfd_close (so->abfd))
-       warning ("cannot close \"%s\": %s",
+       warning (_("cannot close \"%s\": %s"),
                 bfd_filename, bfd_errmsg (bfd_get_error ()));
     }
 
@@ -292,12 +338,20 @@ free_so (struct so_list *so)
 }
 
 
+/* Return address of first so_list entry in master shared object list.  */
+struct so_list *
+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 (PTR arg)
+symbol_add_stub (void *arg)
 {
-  register struct so_list *so = (struct so_list *) arg;  /* catch_errs bogon */
+  struct so_list *so = (struct so_list *) arg;  /* catch_errs bogon */
   struct section_addr_info *sap;
 
   /* Have we already loaded this shared object?  */
@@ -317,6 +371,33 @@ symbol_add_stub (PTR arg)
   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
+   loaded.  */
+
+int
+solib_read_symbols (struct so_list *so, int from_tty)
+{
+  if (so->symbols_loaded)
+    {
+      if (from_tty)
+       printf_unfiltered ("Symbols already loaded for %s\n", so->so_name);
+    }
+  else
+    {
+      if (catch_errors (symbol_add_stub, so,
+                       "Error while reading shared library symbols:\n",
+                       RETURN_MASK_ALL))
+       {
+         if (from_tty)
+           printf_unfiltered ("Loaded symbols for %s\n", so->so_name);
+         so->symbols_loaded = 1;
+         return 1;
+       }
+    }
+
+  return 0;
+}
 
 /* LOCAL FUNCTION
 
@@ -347,7 +428,7 @@ symbol_add_stub (PTR arg)
    the section table.  But we only use this for core files and
    processes we've just attached to, so that's okay.  */
 
-void
+static void
 update_solib_list (int from_tty, struct target_ops *target)
 {
   struct so_list *inferior = TARGET_SO_CURRENT_SOS ();
@@ -358,7 +439,7 @@ update_solib_list (int from_tty, struct target_ops *target)
      symbols now!  */
   if (attach_flag &&
       symfile_objfile == NULL)
-    catch_errors (TARGET_SO_OPEN_SYMBOL_FILE_OBJECT, (PTR) &from_tty, 
+    catch_errors (TARGET_SO_OPEN_SYMBOL_FILE_OBJECT, &from_tty, 
                  "Error reading attached process's symbol file.\n",
                  RETURN_MASK_ALL);
 
@@ -427,6 +508,10 @@ update_solib_list (int from_tty, struct target_ops *target)
       /* If it's not on the inferior's list, remove it from GDB's tables.  */
       else
        {
+         /* Notify any observer that the shared object has been
+            unloaded before we remove it from GDB's tables.  */
+         observer_notify_solib_unloaded (gdb);
+
          *gdb_link = gdb->next;
 
          /* Unless the user loaded it explicitly, free SO's objfile.  */
@@ -461,32 +546,26 @@ update_solib_list (int from_tty, struct target_ops *target)
          catch_errors (solib_map_sections, i,
                        "Error while mapping shared library sections:\n",
                        RETURN_MASK_ALL);
-       }
-
-      /* If requested, add the shared objects' sections to the the
-        TARGET's section table.  */
-      if (target)
-       {
-         int new_sections;
-
-         /* Figure out how many sections we'll need to add in total.  */
-         new_sections = 0;
-         for (i = inferior; i; i = i->next)
-           new_sections += (i->sections_end - i->sections);
 
-         if (new_sections > 0)
+         /* 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)
            {
-             int space = target_resize_to_sections (target, new_sections);
-
-             for (i = inferior; i; i = i->next)
+             int count = (i->sections_end - i->sections);
+             if (count > 0)
                {
-                 int count = (i->sections_end - i->sections);
+                 int space = target_resize_to_sections (target, count);
                  memcpy (target->to_sections + space,
                          i->sections,
                          count * sizeof (i->sections[0]));
-                 space += count;
                }
            }
+
+         /* Notify any observer that the shared object has been
+             loaded now that we've added it to GDB's tables.  */
+         observer_notify_solib_loaded (i);
        }
     }
 }
@@ -498,7 +577,8 @@ update_solib_list (int from_tty, struct target_ops *target)
 
    SYNOPSIS
 
-   void solib_add (char *pattern, int from_tty, struct target_ops *TARGET)
+   void solib_add (char *pattern, int from_tty, struct target_ops
+   *TARGET, int readsyms)
 
    DESCRIPTION
 
@@ -506,10 +586,13 @@ update_solib_list (int from_tty, struct target_ops *target)
    match PATTERN.  (If we've already read a shared object's symbol
    info, leave it alone.)  If PATTERN is zero, read them all.
 
+   If READSYMS is 0, defer reading symbolic information until later
+   but still do any needed low level processing.
+
    FROM_TTY and TARGET are as described for update_solib_list, above.  */
 
 void
-solib_add (char *pattern, int from_tty, struct target_ops *target)
+solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
 {
   struct so_list *gdb;
 
@@ -518,7 +601,7 @@ solib_add (char *pattern, int from_tty, struct target_ops *target)
       char *re_err = re_comp (pattern);
 
       if (re_err)
-       error ("Invalid regexp: %s", re_err);
+       error (_("Invalid regexp: %s"), re_err);
     }
 
   update_solib_list (from_tty, target);
@@ -534,27 +617,8 @@ solib_add (char *pattern, int from_tty, struct target_ops *target)
       if (! pattern || re_exec (gdb->so_name))
        {
          any_matches = 1;
-
-         if (gdb->symbols_loaded)
-           {
-             if (from_tty)
-               printf_unfiltered ("Symbols already loaded for %s\n",
-                                  gdb->so_name);
-           }
-         else
-           {
-             if (catch_errors
-                 (symbol_add_stub, gdb,
-                  "Error while reading shared library symbols:\n",
-                  RETURN_MASK_ALL))
-               {
-                 if (from_tty)
-                   printf_unfiltered ("Loaded symbols for %s\n",
-                                      gdb->so_name);
-                 gdb->symbols_loaded = 1;
-                 loaded_any_symbols = 1;
-               }
-           }
+         if (readsyms && solib_read_symbols (gdb, from_tty))
+           loaded_any_symbols = 1;
        }
 
     if (from_tty && pattern && ! any_matches)
@@ -592,35 +656,19 @@ solib_add (char *pattern, int from_tty, struct target_ops *target)
 static void
 info_sharedlibrary_command (char *ignore, int from_tty)
 {
-  register struct so_list *so = NULL;  /* link map state variable */
+  struct so_list *so = NULL;   /* link map state variable */
   int header_done = 0;
   int addr_width;
-  char *addr_fmt;
-  int arch_size;
 
-  if (exec_bfd == NULL)
-    {
-      printf_unfiltered ("No executable file.\n");
-      return;
-    }
-
-  arch_size = bfd_get_arch_size (exec_bfd);
-  /* Default to 32-bit in case of failure (non-elf). */
-  if (arch_size == 32 || arch_size == -1)
-    {
-      addr_width = 8 + 4;
-      addr_fmt = "08l";
-    }
-  else if (arch_size == 64)
-    {
-      addr_width = 16 + 4;
-      addr_fmt = "016l";
-    }
+  if (TARGET_PTR_BIT == 32)
+    addr_width = 8 + 4;
+  else if (TARGET_PTR_BIT == 64)
+    addr_width = 16 + 4;
   else
     {
       internal_error (__FILE__, __LINE__,
-                     "bfd_get_arch_size() returned unknown size %d",
-                     arch_size);
+                     _("TARGET_PTR_BIT returned unknown size %d"),
+                     TARGET_PTR_BIT);
     }
 
   update_solib_list (from_tty, 0);
@@ -639,15 +687,15 @@ info_sharedlibrary_command (char *ignore, int from_tty)
 
          printf_unfiltered ("%-*s", addr_width,
                             so->textsection != NULL 
-                              ? longest_local_hex_string_custom (
+                              ? hex_string_custom (
                                   (LONGEST) so->textsection->addr,
-                                  addr_fmt)
+                                  addr_width - 4)
                               : "");
          printf_unfiltered ("%-*s", addr_width,
                             so->textsection != NULL 
-                              ? longest_local_hex_string_custom (
+                              ? hex_string_custom (
                                   (LONGEST) so->textsection->endaddr,
-                                  addr_fmt)
+                                  addr_width - 4)
                               : "");
          printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
          printf_unfiltered ("%s\n", so->so_name);
@@ -683,7 +731,7 @@ info_sharedlibrary_command (char *ignore, int from_tty)
 char *
 solib_address (CORE_ADDR address)
 {
-  register struct so_list *so = 0;     /* link map state variable */
+  struct so_list *so = 0;      /* link map state variable */
 
   for (so = so_list_head; so; so = so->next)
     {
@@ -732,6 +780,8 @@ clear_solib (void)
     {
       struct so_list *so = so_list_head;
       so_list_head = so->next;
+      if (so->abfd)
+       remove_target_sections (so->abfd);
       free_so (so);
     }
 
@@ -739,7 +789,7 @@ clear_solib (void)
 }
 
 static void
-do_clear_solib (PTR dummy)
+do_clear_solib (void *dummy)
 {
   solib_cleanup_queued = 0;
   clear_solib ();
@@ -751,7 +801,7 @@ do_clear_solib (PTR dummy)
 
    SYNOPSIS
 
-   void solib_create_inferior_hook()
+   void solib_create_inferior_hook ()
 
    DESCRIPTION
 
@@ -806,9 +856,21 @@ static void
 sharedlibrary_command (char *args, int from_tty)
 {
   dont_repeat ();
-  solib_add (args, from_tty, (struct target_ops *) 0);
+  solib_add (args, from_tty, (struct target_ops *) 0, 1);
 }
 
+/* LOCAL FUNCTION
+
+   no_shared_libraries -- handle command to explicitly discard symbols
+   from shared libraries.
+
+   DESCRIPTION
+
+   Implements the command "nosharedlibrary", which discards symbols
+   that have been auto-loaded from shared libraries.  Symbols from
+   shared libraries that were added by explicit request of the user
+   are not discarded.  Also called from remote.c.  */
+
 void
 no_shared_libraries (char *ignored, int from_tty)
 {
@@ -816,6 +878,15 @@ no_shared_libraries (char *ignored, int from_tty)
   do_clear_solib (NULL);
 }
 
+static void
+reload_shared_libraries (char *ignored, int from_tty)
+{
+  no_shared_libraries (NULL, from_tty);
+  solib_add (NULL, from_tty, NULL, auto_solib_add);
+}
+
+extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
+
 void
 _initialize_solib (void)
 {
@@ -828,14 +899,14 @@ _initialize_solib (void)
   add_com ("nosharedlibrary", class_files, no_shared_libraries,
           "Unload all shared object library symbols.");
 
-  add_show_from_set
-    (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+  deprecated_add_show_from_set
+    (add_set_cmd ("auto-solib-add", class_support, var_boolean,
                  (char *) &auto_solib_add,
                  "Set autoloading of shared library symbols.\n\
-If nonzero, symbols from all shared object libraries will be loaded\n\
-automatically when the inferior begins execution or when the dynamic linker\n\
-informs gdb that a new library has been loaded.  Otherwise, symbols\n\
-must be loaded manually, using `sharedlibrary'.",
+If \"on\", symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution, when the dynamic linker\n\
+informs gdb that a new library has been loaded, or when attaching to the\n\
+inferior.  Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
                  &setlist),
      &showlist);
 
@@ -844,14 +915,20 @@ must be loaded manually, using `sharedlibrary'.",
                   "Set prefix for loading absolute shared library symbol files.\n\
 For other (relative) files, you can add values using `set solib-search-path'.",
                   &setlist);
-  add_show_from_set (c, &showlist);
-  c->completer = filename_completer;
+  deprecated_add_show_from_set (c, &showlist);
+  set_cmd_cfunc (c, reload_shared_libraries);
+  set_cmd_completer (c, filename_completer);
+
+  /* Set the default value of "solib-absolute-prefix" from the sysroot, if
+     one is set.  */
+  solib_absolute_prefix = xstrdup (gdb_sysroot);
 
   c = add_set_cmd ("solib-search-path", class_support, var_string,
                   (char *) &solib_search_path,
                   "Set the search path for loading non-absolute shared library symbol files.\n\
 This takes precedence over the environment variables PATH and LD_LIBRARY_PATH.",
                   &setlist);
-  add_show_from_set (c, &showlist);
-  c->completer = filename_completer;
+  deprecated_add_show_from_set (c, &showlist);
+  set_cmd_cfunc (c, reload_shared_libraries);
+  set_cmd_completer (c, filename_completer);
 }
This page took 0.032074 seconds and 4 git commands to generate.