gas/testsuite/
[deliverable/binutils-gdb.git] / gdb / solib.c
index ddf317146b752e16428f2022b645d960dca88afb..dd885a92ed43c9928f621180eaa5cce648ba9689 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 "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"
+
+/* Architecture-specific operations.  */
+
+/* Per-architecture data key.  */
+static struct gdbarch_data *solib_data;
+
+static void *
+solib_init (struct obstack *obstack)
+{
+  struct target_so_ops **ops;
+
+  ops = OBSTACK_ZALLOC (obstack, struct target_so_ops *);
+  *ops = current_target_so_ops;
+  return ops;
+}
+
+static struct target_so_ops *
+solib_ops (struct gdbarch *gdbarch)
+{
+  struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+  return *ops;
+}
+\f
 
 /* external data declarations */
 
@@ -56,7 +83,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.  */
@@ -66,6 +93,14 @@ static char *solib_absolute_prefix = NULL;
    symbol files.  This takes precedence over the environment variables PATH
    and LD_LIBRARY_PATH.  */
 static char *solib_search_path = NULL;
+static void
+show_solib_search_path (struct ui_file *file, int from_tty,
+                       struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("\
+The search path for loading non-absolute shared library symbol files is %s.\n"),
+                   value);
+}
 
 /*
 
@@ -86,12 +121,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
 
@@ -100,6 +142,7 @@ static char *solib_search_path = NULL;
 int
 solib_open (char *in_pathname, char **found_pathname)
 {
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
   int found_file = -1;
   char *temp_pathname = NULL;
   char *p = in_pathname;
@@ -146,29 +189,36 @@ solib_open (char *in_pathname, char **found_pathname)
         in_pathname++;
     }
   
-  /* If not found, next search the solib_search_path (if any).  */
+  /* 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, 
-                        1, lbasename (in_pathname), O_RDONLY, 0,
+    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 && ops->find_and_open_solib)
+    found_file = ops->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.  */
@@ -206,7 +256,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;
@@ -231,38 +281,40 @@ 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 ()));
     }
 
   for (p = so->sections; p < so->sections_end; p++)
     {
+      struct target_so_ops *ops = solib_ops (current_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. */
-      TARGET_SO_RELOCATE_SECTION_ADDRESSES (so, p);
-      if (STREQ (p->the_bfd_section->name, ".text"))
+      ops->relocate_section_addresses (so, p);
+      if (strcmp (p->the_bfd_section->name, ".text") == 0)
        {
          so->textsection = p;
        }
@@ -298,6 +350,7 @@ solib_map_sections (PTR arg)
 void
 free_so (struct so_list *so)
 {
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
   char *bfd_filename = 0;
 
   if (so->sections)
@@ -307,25 +360,33 @@ 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 ()));
     }
 
   if (bfd_filename)
     xfree (bfd_filename);
 
-  TARGET_SO_FREE_SO (so);
+  ops->free_so (so);
 
   xfree (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?  */
@@ -345,6 +406,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
 
@@ -375,10 +463,11 @@ 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 ();
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
+  struct so_list *inferior = ops->current_sos();
   struct so_list *gdb, **gdb_link;
 
   /* If we are attaching to a running process for which we 
@@ -386,7 +475,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 (ops->open_symbol_file_object, &from_tty, 
                  "Error reading attached process's symbol file.\n",
                  RETURN_MASK_ALL);
 
@@ -455,6 +544,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.  */
@@ -505,6 +598,10 @@ update_solib_list (int from_tty, struct target_ops *target)
                          count * sizeof (i->sections[0]));
                }
            }
+
+         /* 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);
        }
     }
 }
@@ -540,7 +637,7 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
       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);
@@ -556,27 +653,8 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
       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 (readsyms)
-           {
-             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)
@@ -585,11 +663,13 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
 
     if (loaded_any_symbols)
       {
+       struct target_so_ops *ops = solib_ops (current_gdbarch);
+
        /* Getting new symbols may change our opinion about what is
           frameless.  */
        reinit_frame_cache ();
 
-       TARGET_SO_SPECIAL_SYMBOL_HANDLING ();
+       ops->special_symbol_handling ();
       }
   }
 }
@@ -614,38 +694,19 @@ solib_add (char *pattern, int from_tty, struct target_ops *target, int readsyms)
 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);
-  if (arch_size == -1)
-    arch_size = bfd_arch_bits_per_address(exec_bfd);
 
-  /* Default to 32-bit in case of failure.  */
-  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);
@@ -664,15 +725,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);
@@ -680,7 +741,7 @@ info_sharedlibrary_command (char *ignore, int from_tty)
     }
   if (so_list_head == NULL)
     {
-      printf_unfiltered ("No shared libraries loaded at this time.\n");
+      printf_unfiltered (_("No shared libraries loaded at this time.\n"));
     }
 }
 
@@ -708,7 +769,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)
     {
@@ -729,6 +790,8 @@ solib_address (CORE_ADDR address)
 void
 clear_solib (void)
 {
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
+
   /* This function is expected to handle ELF shared libraries.  It is
      also used on Solaris, which can run either ELF or a.out binaries
      (for compatibility with SunOS 4), both of which can use shared
@@ -762,11 +825,11 @@ clear_solib (void)
       free_so (so);
     }
 
-  TARGET_SO_CLEAR_SOLIB ();
+  ops->clear_solib ();
 }
 
 static void
-do_clear_solib (PTR dummy)
+do_clear_solib (void *dummy)
 {
   solib_cleanup_queued = 0;
   clear_solib ();
@@ -778,7 +841,7 @@ do_clear_solib (PTR dummy)
 
    SYNOPSIS
 
-   void solib_create_inferior_hook()
+   void solib_create_inferior_hook ()
 
    DESCRIPTION
 
@@ -790,7 +853,8 @@ do_clear_solib (PTR dummy)
 void
 solib_create_inferior_hook (void)
 {
-  TARGET_SO_SOLIB_CREATE_INFERIOR_HOOK ();
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
+  ops->solib_create_inferior_hook();
 }
 
 /* GLOBAL FUNCTION
@@ -812,7 +876,8 @@ solib_create_inferior_hook (void)
 int
 in_solib_dynsym_resolve_code (CORE_ADDR pc)
 {
-  return TARGET_SO_IN_DYNSYM_RESOLVE_CODE (pc);
+  struct target_so_ops *ops = solib_ops (current_gdbarch);
+  return ops->in_dynsym_resolve_code (pc);
 }
 
 /*
@@ -855,42 +920,70 @@ no_shared_libraries (char *ignored, int from_tty)
   do_clear_solib (NULL);
 }
 
+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);
+}
+
+static void
+show_auto_solib_add (struct ui_file *file, int from_tty,
+                    struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Autoloading of shared library symbols is %s.\n"),
+                   value);
+}
+
+
+extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
+
 void
 _initialize_solib (void)
 {
   struct cmd_list_element *c;
 
+  solib_data = gdbarch_data_register_pre_init (solib_init);
+
   add_com ("sharedlibrary", class_files, sharedlibrary_command,
-          "Load shared object library symbols for files matching REGEXP.");
+          _("Load shared object library symbols for files matching REGEXP."));
   add_info ("sharedlibrary", info_sharedlibrary_command,
-           "Status of loaded shared object libraries.");
+           _("Status of loaded shared object libraries."));
   add_com ("nosharedlibrary", class_files, no_shared_libraries,
-          "Unload all shared object library symbols.");
+          _("Unload all shared object library symbols."));
 
-  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\
+  add_setshow_boolean_cmd ("auto-solib-add", class_support,
+                          &auto_solib_add, _("\
+Set autoloading of shared library symbols."), _("\
+Show autoloading of shared library symbols."), _("\
 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);
-
-  c = add_set_cmd ("solib-absolute-prefix", class_support, var_filename,
-                  (char *) &solib_absolute_prefix,
-                  "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;
-
-  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;
+inferior.  Otherwise, symbols must be loaded manually, using `sharedlibrary'."),
+                          NULL,
+                          show_auto_solib_add,
+                          &setlist, &showlist);
+
+  add_setshow_filename_cmd ("solib-absolute-prefix", class_support,
+                           &solib_absolute_prefix, _("\
+Set prefix for loading absolute shared library symbol files."), _("\
+Show prefix for loading absolute shared library symbol files."), _("\
+For other (relative) files, you can add values using `set solib-search-path'."),
+                           reload_shared_libraries,
+                           NULL,
+                           &setlist, &showlist);
+
+  /* Set the default value of "solib-absolute-prefix" from the sysroot, if
+     one is set.  */
+  solib_absolute_prefix = xstrdup (gdb_sysroot);
+
+  add_setshow_optional_filename_cmd ("solib-search-path", class_support,
+                                    &solib_search_path, _("\
+Set the search path for loading non-absolute shared library symbol files."), _("\
+Show the search path for loading non-absolute shared library symbol files."), _("\
+This takes precedence over the environment variables PATH and LD_LIBRARY_PATH."),
+                                    reload_shared_libraries,
+                                    show_solib_search_path,
+                                    &setlist, &showlist);
 }
This page took 0.056159 seconds and 4 git commands to generate.