daily update
[binutils-gdb.git] / gdb / solib.c
index fd266876a74852b4b9377c98b26a0878864d0187..3350bfdd281ca7befdc3f77bebe75cc902b8aeb1 100644 (file)
@@ -1,6 +1,6 @@
 /* Handle shared libraries for GDB, the GNU Debugger.
 
-   Copyright (C) 1990-2013 Free Software Foundation, Inc.
+   Copyright (C) 1990-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,7 +21,7 @@
 
 #include <sys/types.h>
 #include <fcntl.h>
-#include "gdb_string.h"
+#include <string.h>
 #include "symtab.h"
 #include "bfd.h"
 #include "symfile.h"
@@ -230,8 +230,25 @@ solib_find (char *in_pathname, int *fd)
     {
       int need_dir_separator;
 
-      need_dir_separator = (!IS_DIR_SEPARATOR (in_pathname[0])
-                           && !HAS_TARGET_DRIVE_SPEC (fskind, in_pathname));
+      /* 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,
@@ -319,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);
 
@@ -339,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;
@@ -467,6 +486,16 @@ solib_map_sections (struct so_list *so)
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
   so->abfd = abfd;
 
+  /* Copy the full path name into so_name, allowing symbol_file_add
+     to find it later.  This also affects the =library-loaded GDB/MI
+     event, and in particular the part of that notification providing
+     the library's host-side path.  If we let the target dictate
+     that objfile's path, and the target is different from the host,
+     GDB/MI will not provide the correct host-side path.  */
+  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));
+
   if (build_section_table (abfd, &so->sections, &so->sections_end))
     {
       error (_("Can't find the file sections in `%s': %s"),
@@ -599,7 +628,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 +637,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;
@@ -1477,6 +1506,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
@@ -1484,6 +1530,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,