Fix gprof build
[deliverable/binutils-gdb.git] / gdb / solib.c
index f5917856d1509a11d28c8d308822033e1f03c827..06e0b1662e7382ed29436ec58163b0c629e4ad43 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2003, 2005-2012 Free Software Foundation, Inc.
+   Copyright (C) 1990-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -46,6 +46,8 @@
 #include "solib.h"
 #include "interps.h"
 #include "filesystem.h"
+#include "gdb_bfd.h"
+#include "filestuff.h"
 
 /* Architecture-specific operations.  */
 
@@ -62,10 +64,10 @@ solib_init (struct obstack *obstack)
   return ops;
 }
 
-static struct target_so_ops *
+static const struct target_so_ops *
 solib_ops (struct gdbarch *gdbarch)
 {
-  struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+  const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
 
   return *ops;
 }
@@ -73,9 +75,9 @@ solib_ops (struct gdbarch *gdbarch)
 /* Set the solib operations for GDBARCH to NEW_OPS.  */
 
 void
-set_solib_ops (struct gdbarch *gdbarch, struct target_so_ops *new_ops)
+set_solib_ops (struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
 {
-  struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
+  const struct target_so_ops **ops = gdbarch_data (gdbarch, solib_data);
 
   *ops = new_ops;
 }
@@ -142,12 +144,12 @@ show_solib_search_path (struct ui_file *file, int from_tty,
 char *
 solib_find (char *in_pathname, int *fd)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   int found_file = -1;
   char *temp_pathname = NULL;
   int gdb_sysroot_is_empty;
   const char *solib_symbols_extension
-    = gdbarch_solib_symbols_extension (target_gdbarch);
+    = gdbarch_solib_symbols_extension (target_gdbarch ());
   const char *fskind = effective_target_file_system_kind ();
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   char *sysroot = NULL;
@@ -228,7 +230,25 @@ solib_find (char *in_pathname, int *fd)
     {
       int need_dir_separator;
 
-      need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[0]);
+      /* Concatenate the sysroot and the target reported filename.  We
+        may need to glue them with a directory separator.  Cases to
+        consider:
+
+        | sysroot         | separator | in_pathname    |
+        |-----------------+-----------+----------------|
+        | /some/dir       | /         | c:/foo/bar.dll |
+        | /some/dir       |           | /foo/bar.dll   |
+        | remote:         |           | c:/foo/bar.dll |
+        | remote:         |           | /foo/bar.dll   |
+        | remote:some/dir | /         | c:/foo/bar.dll |
+        | remote:some/dir |           | /foo/bar.dll   |
+
+       IOW, we don't need to add a separator if IN_PATHNAME already
+       has one, or when the the sysroot is exactly "remote:".
+       There's no need to check for drive spec explicitly, as we only
+       get here if IN_PATHNAME is considered an absolute path.  */
+      need_dir_separator = !(IS_DIR_SEPARATOR (in_pathname[0])
+                            || strcmp (REMOTE_SYSROOT_PREFIX, sysroot) == 0);
 
       /* Cat the prefixed pathname together.  */
       temp_pathname = concat (sysroot,
@@ -245,7 +265,7 @@ solib_find (char *in_pathname, int *fd)
     }
 
   /* Now see if we can open it.  */
-  found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
+  found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
   if (found_file < 0)
     xfree (temp_pathname);
 
@@ -268,7 +288,7 @@ solib_find (char *in_pathname, int *fd)
                              in_pathname + 2, (char *) NULL);
       xfree (drive);
 
-      found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
+      found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
       if (found_file < 0)
        {
          xfree (temp_pathname);
@@ -283,7 +303,7 @@ solib_find (char *in_pathname, int *fd)
                                  need_dir_separator ? SLASH_STRING : "",
                                  in_pathname + 2, (char *) NULL);
 
-         found_file = open (temp_pathname, O_RDONLY | O_BINARY, 0);
+         found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
          if (found_file < 0)
            xfree (temp_pathname);
        }
@@ -299,11 +319,6 @@ solib_find (char *in_pathname, int *fd)
   if (found_file < 0)
     temp_pathname = NULL;
 
-  /* 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, &temp_pathname);
-
   /* If the search in gdb_sysroot 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.)
@@ -321,14 +336,16 @@ 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,
+    found_file = openp (solib_search_path,
+                       OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
                        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,
+    found_file = openp (solib_search_path,
+                       OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
                        target_lbasename (fskind, in_pathname),
                        O_RDONLY | O_BINARY, &temp_pathname);
 
@@ -341,16 +358,16 @@ solib_find (char *in_pathname, int *fd)
   if (found_file < 0 && gdb_sysroot_is_empty)
     found_file = openp (get_in_environ (current_inferior ()->environment,
                                        "PATH"),
-                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
-                       &temp_pathname);
+                       OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, 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 (current_inferior ()->environment,
                                        "LD_LIBRARY_PATH"),
-                       OPF_TRY_CWD_FIRST, in_pathname, O_RDONLY | O_BINARY,
-                       &temp_pathname);
+                       OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
+                       O_RDONLY | O_BINARY, &temp_pathname);
 
   *fd = found_file;
   return temp_pathname;
@@ -360,9 +377,9 @@ solib_find (char *in_pathname, int *fd)
    it is used as file handle to open the file.  Throws an error if the file
    could not be opened.  Handles both local and remote file access.
 
-   PATHNAME must be malloc'ed by the caller.  If successful, the new BFD's
-   name will point to it.  If unsuccessful, PATHNAME will be freed and the
-   FD will be closed (unless FD was -1).  */
+   PATHNAME must be malloc'ed by the caller.  It will be freed by this
+   function.  If unsuccessful, the FD will be closed (unless FD was
+   -1).  */
 
 bfd *
 solib_bfd_fopen (char *pathname, int fd)
@@ -376,12 +393,10 @@ solib_bfd_fopen (char *pathname, int fd)
     }
   else
     {
-      abfd = bfd_fopen (pathname, gnutarget, FOPEN_RB, fd);
+      abfd = gdb_bfd_open (pathname, gnutarget, fd);
 
       if (abfd)
        bfd_set_cacheable (abfd, 1);
-      else if (fd != -1)
-       close (fd);
     }
 
   if (!abfd)
@@ -391,6 +406,8 @@ solib_bfd_fopen (char *pathname, int fd)
             pathname, bfd_errmsg (bfd_get_error ()));
     }
 
+  xfree (pathname);
+
   return abfd;
 }
 
@@ -422,17 +439,16 @@ solib_bfd_open (char *pathname)
   /* Check bfd format.  */
   if (!bfd_check_format (abfd, bfd_object))
     {
-      bfd_close (abfd);
-      make_cleanup (xfree, found_pathname);
+      make_cleanup_bfd_unref (abfd);
       error (_("`%s': not in executable format: %s"),
-            found_pathname, bfd_errmsg (bfd_get_error ()));
+            bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
     }
 
   /* Check bfd arch.  */
-  b = gdbarch_bfd_arch_info (target_gdbarch);
+  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,
+               "with target architecture %s."), bfd_get_filename (abfd),
              bfd_get_arch_info (abfd)->printable_name, b->printable_name);
 
   return abfd;
@@ -453,7 +469,7 @@ solib_bfd_open (char *pathname)
 static int
 solib_map_sections (struct so_list *so)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   char *filename;
   struct target_section *p;
   struct cleanup *old_chain;
@@ -468,13 +484,7 @@ solib_map_sections (struct so_list *so)
     return 0;
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = gdb_bfd_ref (abfd);
-
-  /* copy full path name into so_name, so that later symbol_file_add
-     can find it.  */
-  if (strlen (bfd_get_filename (abfd)) >= SO_NAME_MAX_PATH_SIZE)
-    error (_("Shared library file name is too long."));
-  strcpy (so->so_name, bfd_get_filename (abfd));
+  so->abfd = abfd;
 
   if (build_section_table (abfd, &so->sections, &so->sections_end))
     {
@@ -504,22 +514,25 @@ solib_map_sections (struct so_list *so)
      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);
+  add_target_sections (so, 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.
+/* Free symbol-file related contents of SO and reset for possible reloading
+   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)
+clear_so (struct so_list *so)
 {
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
+
   if (so->sections)
     {
       xfree (so->sections);
@@ -538,6 +551,10 @@ free_so_symbols (struct so_list *so)
   /* Restore the target-supplied file name.  SO_NAME may be the path
      of the symbol file.  */
   strcpy (so->so_name, so->so_original_name);
+
+  /* Do the same for target-specific data.  */
+  if (ops->clear_so != NULL)
+    ops->clear_so (so);
 }
 
 /* Free the storage associated with the `struct so_list' object SO.
@@ -554,9 +571,9 @@ free_so_symbols (struct so_list *so)
 void
 free_so (struct so_list *so)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
-  free_so_symbols (so);
+  clear_so (so);
   ops->free_so (so);
 
   xfree (so);
@@ -592,6 +609,8 @@ solib_read_symbols (struct so_list *so, int flags)
     {
       volatile struct gdb_exception e;
 
+      flags |= current_inferior ()->symfile_flags;
+
       TRY_CATCH (e, RETURN_MASK_ERROR)
        {
          struct section_addr_info *sap;
@@ -599,7 +618,7 @@ solib_read_symbols (struct so_list *so, int flags)
          /* Have we already loaded this shared object?  */
          ALL_OBJFILES (so->objfile)
            {
-             if (filename_cmp (so->objfile->name, so->so_name) == 0
+             if (filename_cmp (objfile_name (so->objfile), so->so_name) == 0
                  && so->objfile->addr_low == so->addr_low)
                break;
            }
@@ -608,7 +627,7 @@ solib_read_symbols (struct so_list *so, int flags)
 
          sap = build_section_addr_info_from_section_table (so->sections,
                                                            so->sections_end);
-         so->objfile = symbol_file_add_from_bfd (so->abfd,
+         so->objfile = symbol_file_add_from_bfd (so->abfd, so->so_name,
                                                  flags, sap, OBJF_SHARED,
                                                  NULL);
          so->objfile->addr_low = so->addr_low;
@@ -671,7 +690,7 @@ solib_used (const struct so_list *const known)
 static void
 update_solib_list (int from_tty, struct target_ops *target)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   struct so_list *inferior = ops->current_sos();
   struct so_list *gdb, **gdb_link;
 
@@ -758,6 +777,9 @@ update_solib_list (int from_tty, struct target_ops *target)
             unloaded before we remove it from GDB's tables.  */
          observer_notify_solib_unloaded (gdb);
 
+         VEC_safe_push (char_ptr, current_program_space->deleted_solibs,
+                        xstrdup (gdb->so_name));
+
          *gdb_link = gdb->next;
 
          /* Unless the user loaded it explicitly, free SO's objfile.  */
@@ -767,7 +789,7 @@ update_solib_list (int from_tty, struct target_ops *target)
 
          /* Some targets' section tables might be referring to
             sections from so->abfd; remove them.  */
-         remove_target_sections (gdb->abfd);
+         remove_target_sections (gdb);
 
          free_so (gdb);
          gdb = *gdb_link;
@@ -793,6 +815,7 @@ update_solib_list (int from_tty, struct target_ops *target)
          volatile struct gdb_exception e;
 
          i->pspace = current_program_space;
+         VEC_safe_push (so_list_ptr, current_program_space->added_solibs, i);
 
          TRY_CATCH (e, RETURN_MASK_ERROR)
            {
@@ -929,7 +952,7 @@ solib_add (char *pattern, int from_tty,
 
     if (loaded_any_symbols)
       {
-       struct target_so_ops *ops = solib_ops (target_gdbarch);
+       const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
        /* Getting new symbols may change our opinion about what is
           frameless.  */
@@ -953,7 +976,7 @@ info_sharedlibrary_command (char *pattern, int from_tty)
   int addr_width;
   int nr_libs;
   struct cleanup *table_cleanup;
-  struct gdbarch *gdbarch = target_gdbarch;
+  struct gdbarch *gdbarch = target_gdbarch ();
   struct ui_out *uiout = current_uiout;
 
   if (pattern)
@@ -1102,7 +1125,7 @@ solib_name_from_address (struct program_space *pspace, CORE_ADDR address)
 int
 solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
   if (ops->keep_data_in_core)
     return ops->keep_data_in_core (vaddr, size);
@@ -1115,7 +1138,7 @@ solib_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
 void
 clear_solib (void)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_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
@@ -1147,8 +1170,7 @@ clear_solib (void)
 
       so_list_head = so->next;
       observer_notify_solib_unloaded (so);
-      if (so->abfd)
-       remove_target_sections (so->abfd);
+      remove_target_sections (so);
       free_so (so);
     }
 
@@ -1163,7 +1185,7 @@ clear_solib (void)
 void
 solib_create_inferior_hook (int from_tty)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
   ops->solib_create_inferior_hook (from_tty);
 }
@@ -1174,7 +1196,7 @@ solib_create_inferior_hook (int from_tty)
 int
 in_solib_dynsym_resolve_code (CORE_ADDR pc)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
   return ops->in_dynsym_resolve_code (pc);
 }
@@ -1205,6 +1227,37 @@ no_shared_libraries (char *ignored, int from_tty)
   objfile_purge_solibs ();
 }
 
+/* See solib.h.  */
+
+void
+update_solib_breakpoints (void)
+{
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
+
+  if (ops->update_breakpoints != NULL)
+    ops->update_breakpoints ();
+}
+
+/* See solib.h.  */
+
+void
+handle_solib_event (void)
+{
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
+
+  if (ops->handle_event != NULL)
+    ops->handle_event ();
+
+  clear_program_space_solib_cache (current_inferior ()->pspace);
+
+  /* Check for any newly added shared libraries if we're supposed to
+     be adding them automatically.  Switch terminal for any messages
+     produced by breakpoint_re_set.  */
+  target_terminal_ours_for_output ();
+  solib_add (NULL, 0, &current_target, auto_solib_add);
+  target_terminal_inferior ();
+}
+
 /* Reload shared libraries, but avoid reloading the same symbol file
    we already have loaded.  */
 
@@ -1229,7 +1282,7 @@ reload_shared_libraries_1 (int from_tty)
        {
          found_pathname = xstrdup (bfd_get_filename (abfd));
          make_cleanup (xfree, found_pathname);
-         gdb_bfd_close_or_warn (abfd);
+         gdb_bfd_unref (abfd);
        }
 
       /* If this shared library is no longer associated with its previous
@@ -1241,8 +1294,8 @@ reload_shared_libraries_1 (int from_tty)
          if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)
              && !solib_used (so))
            free_objfile (so->objfile);
-         remove_target_sections (so->abfd);
-         free_so_symbols (so);
+         remove_target_sections (so);
+         clear_so (so);
        }
 
       /* If this shared library is now associated with a new symbol
@@ -1272,11 +1325,11 @@ static void
 reload_shared_libraries (char *ignored, int from_tty,
                         struct cmd_list_element *e)
 {
-  struct target_so_ops *ops;
+  const struct target_so_ops *ops;
 
   reload_shared_libraries_1 (from_tty);
 
-  ops = solib_ops (target_gdbarch);
+  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
@@ -1298,11 +1351,7 @@ reload_shared_libraries (char *ignored, int from_tty,
         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
@@ -1343,7 +1392,7 @@ solib_global_lookup (const struct objfile *objfile,
                     const char *name,
                     const domain_enum domain)
 {
-  struct target_so_ops *ops = solib_ops (target_gdbarch);
+  const struct target_so_ops *ops = solib_ops (target_gdbarch ());
 
   if (ops->lookup_lib_global_symbol != NULL)
     return ops->lookup_lib_global_symbol (objfile, name, domain);
@@ -1447,6 +1496,23 @@ gdb_bfd_lookup_symbol (bfd *abfd,
   return symaddr;
 }
 
+/* SO_LIST_HEAD may contain user-loaded object files that can be removed
+   out-of-band by the user.  So upon notification of free_objfile remove
+   all references to any user-loaded file that is about to be freed.  */
+
+static void
+remove_user_added_objfile (struct objfile *objfile)
+{
+  struct so_list *so;
+
+  if (objfile != 0 && objfile->flags & OBJF_USERLOADED)
+    {
+      for (so = so_list_head; so != NULL; so = so->next)
+       if (so->objfile == objfile)
+         so->objfile = NULL;
+    }
+}
+
 extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
 
 void
@@ -1454,6 +1520,8 @@ _initialize_solib (void)
 {
   solib_data = gdbarch_data_register_pre_init (solib_init);
 
+  observer_attach_free_objfile (remove_user_added_objfile);
+
   add_com ("sharedlibrary", class_files, sharedlibrary_command,
           _("Load shared object library symbols for files matching REGEXP."));
   add_info ("sharedlibrary", info_sharedlibrary_command,
This page took 0.031222 seconds and 4 git commands to generate.