2012-01-18 Paul Pluzhnikov <ppluzhnikov@google.com>
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Wed, 18 Jan 2012 18:58:43 +0000 (18:58 +0000)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Wed, 18 Jan 2012 18:58:43 +0000 (18:58 +0000)
    Jan Kratochvil  <jan.kratochvil@redhat.com>

PR gdb/9538
* symfile.c (find_separate_debug_file): New function.
(terminate_after_last_dir_separator): Likewise.
(find_separate_debug_file_by_debuglink): Also try realpath.
* configure.ac (AC_CHECK_FUNCS): Add lstat.
* configure: Regenerate.
* config.in: Regenerate.

testsuite/ChangeLog:

2012-01-18  Paul Pluzhnikov  <ppluzhnikov@google.com>

PR gdb/9538
* gdb.base/sepdebug.exp: New test.

gdb/ChangeLog
gdb/config.in
gdb/configure
gdb/configure.ac
gdb/symfile.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/sepdebug.exp

index d7bf88b6650401b7f6281af8b5d344f9fc61807e..120bcbc134784cd61a248839be65e48a73cb5e63 100644 (file)
@@ -1,3 +1,14 @@
+2012-01-18  Paul Pluzhnikov  <ppluzhnikov@google.com>
+           Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       PR gdb/9538
+       * symfile.c (find_separate_debug_file): New function.
+       (terminate_after_last_dir_separator): Likewise.
+       (find_separate_debug_file_by_debuglink): Also try realpath.
+       * configure.ac (AC_CHECK_FUNCS): Add lstat.
+       * configure: Regenerate.
+       * config.in: Regenerate.
+
 2012-01-18  Doug Evans  <dje@google.com>
 
        * Makefile.in (TARGET_SYSTEM_ROOT, TARGET_SYSTEM_ROOT_DEFINE): Delete.
index f1e6b9aed2fc4e035d0bab2128356739f444ff79..45c2c73ff0af7f715e6ad72d7d7374ab0f08b64a 100644 (file)
 /* Define to 1 if the system has the type `long long int'. */
 #undef HAVE_LONG_LONG_INT
 
+/* Define to 1 if you have the `lstat' function. */
+#undef HAVE_LSTAT
+
 /* Define if <sys/procfs.h> has lwpid_t. */
 #undef HAVE_LWPID_T
 
index 5b2a6dd1e140c854f01c5674e4974ff80627b9a1..2ced763c10a9ae353ddbb41d1aa4e27c67c6b9aa 100755 (executable)
@@ -12935,7 +12935,7 @@ for ac_func in canonicalize_file_name realpath getrusage getuid \
                getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
                sigaction sigprocmask sigsetmask socketpair syscall \
                ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
-               setrlimit getrlimit posix_madvise waitpid
+               setrlimit getrlimit posix_madvise waitpid lstat
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
index 652c0c601abbc65c3376c4dc719240cd42e19179..66844ed614afc8453b1d70fa61a0e6c64498cbf7 100644 (file)
@@ -1067,7 +1067,7 @@ AC_CHECK_FUNCS([canonicalize_file_name realpath getrusage getuid \
                getgid pipe poll pread64 resize_term sbrk setpgid setpgrp setsid \
                sigaction sigprocmask sigsetmask socketpair syscall \
                ttrace wborder wresize setlocale iconvlist libiconvlist btowc \
-               setrlimit getrlimit posix_madvise waitpid])
+               setrlimit getrlimit posix_madvise waitpid lstat])
 AM_LANGINFO_CODESET
 
 # Check the return and argument types of ptrace.  No canned test for
index e9b6e7b0007853b1b45c0c0283e0facaddcc5686..7529196bbe7c66c6cd5c2244c3bc90e618a10351 100644 (file)
@@ -1441,63 +1441,48 @@ show_debug_file_directory (struct ui_file *file, int from_tty,
 #define DEBUG_SUBDIRECTORY ".debug"
 #endif
 
-char *
-find_separate_debug_file_by_debuglink (struct objfile *objfile)
+/* Find a separate debuginfo file for OBJFILE, using DIR as the directory
+   where the original file resides (may not be the same as
+   dirname(objfile->name) due to symlinks), and DEBUGLINK as the file we are
+   looking for.  Returns the name of the debuginfo, of NULL.  */
+
+static char *
+find_separate_debug_file (const char *dir,
+                         const char *canon_dir,
+                         const char *debuglink,
+                         unsigned long crc32, struct objfile *objfile)
 {
-  char *basename, *debugdir;
-  char *dir = NULL;
-  char *debugfile = NULL;
-  char *canon_name = NULL;
-  unsigned long crc32;
+  char *debugdir;
+  char *debugfile;
   int i;
 
-  basename = get_debug_link_info (objfile, &crc32);
-
-  if (basename == NULL)
-    /* There's no separate debug info, hence there's no way we could
-       load it => no warning.  */
-    goto cleanup_return_debugfile;
-
-  dir = xstrdup (objfile->name);
-
-  /* Strip off the final filename part, leaving the directory name,
-     followed by a slash.  The directory can be relative or absolute.  */
-  for (i = strlen(dir) - 1; i >= 0; i--)
-    {
-      if (IS_DIR_SEPARATOR (dir[i]))
-       break;
-    }
-  /* If I is -1 then no directory is present there and DIR will be "".  */
-  dir[i+1] = '\0';
-
-  /* Set I to max (strlen (canon_name), strlen (dir)).  */
-  canon_name = lrealpath (dir);
+  /* Set I to max (strlen (canon_dir), strlen (dir)).  */
   i = strlen (dir);
-  if (canon_name && strlen (canon_name) > i)
-    i = strlen (canon_name);
+  if (canon_dir != NULL && strlen (canon_dir) > i)
+    i = strlen (canon_dir);
 
   debugfile = xmalloc (strlen (debug_file_directory) + 1
                       + i
                       + strlen (DEBUG_SUBDIRECTORY)
                       + strlen ("/")
-                      + strlen (basename)
+                      + strlen (debuglink)
                       + 1);
 
   /* First try in the same directory as the original file.  */
   strcpy (debugfile, dir);
-  strcat (debugfile, basename);
+  strcat (debugfile, debuglink);
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
-    goto cleanup_return_debugfile;
+    return debugfile;
 
   /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
   strcpy (debugfile, dir);
   strcat (debugfile, DEBUG_SUBDIRECTORY);
   strcat (debugfile, "/");
-  strcat (debugfile, basename);
+  strcat (debugfile, debuglink);
 
   if (separate_debug_file_exists (debugfile, crc32, objfile))
-    goto cleanup_return_debugfile;
+    return debugfile;
 
   /* Then try in the global debugfile directories.
 
@@ -1520,26 +1505,26 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
       debugfile[debugdir_end - debugdir] = 0;
       strcat (debugfile, "/");
       strcat (debugfile, dir);
-      strcat (debugfile, basename);
+      strcat (debugfile, debuglink);
 
       if (separate_debug_file_exists (debugfile, crc32, objfile))
-       goto cleanup_return_debugfile;
+       return debugfile;
 
       /* If the file is in the sysroot, try using its base path in the
         global debugfile directory.  */
-      if (canon_name
-         && filename_ncmp (canon_name, gdb_sysroot,
+      if (canon_dir != NULL
+         && filename_ncmp (canon_dir, gdb_sysroot,
                            strlen (gdb_sysroot)) == 0
-         && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
+         && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)]))
        {
          memcpy (debugfile, debugdir, debugdir_end - debugdir);
          debugfile[debugdir_end - debugdir] = 0;
-         strcat (debugfile, canon_name + strlen (gdb_sysroot));
+         strcat (debugfile, canon_dir + strlen (gdb_sysroot));
          strcat (debugfile, "/");
-         strcat (debugfile, basename);
+         strcat (debugfile, debuglink);
 
          if (separate_debug_file_exists (debugfile, crc32, objfile))
-           goto cleanup_return_debugfile;
+           return debugfile;
        }
 
       debugdir = debugdir_end;
@@ -1547,12 +1532,90 @@ find_separate_debug_file_by_debuglink (struct objfile *objfile)
   while (*debugdir != 0);
 
   xfree (debugfile);
-  debugfile = NULL;
+  return NULL;
+}
+
+/* Modify PATH to contain only "directory/" part of PATH.
+   If there were no directory separators in PATH, PATH will be empty
+   string on return.  */
+
+static void
+terminate_after_last_dir_separator (char *path)
+{
+  int i;
+
+  /* Strip off the final filename part, leaving the directory name,
+     followed by a slash.  The directory can be relative or absolute.  */
+  for (i = strlen(path) - 1; i >= 0; i--)
+    if (IS_DIR_SEPARATOR (path[i]))
+      break;
+
+  /* If I is -1 then no directory is present there and DIR will be "".  */
+  path[i + 1] = '\0';
+}
+
+/* Find separate debuginfo for OBJFILE (using .gnu_debuglink section).
+   Returns pathname, or NULL.  */
+
+char *
+find_separate_debug_file_by_debuglink (struct objfile *objfile)
+{
+  char *debuglink;
+  char *dir, *canon_dir;
+  char *debugfile;
+  unsigned long crc32;
+  struct cleanup *cleanups;
+
+  debuglink = get_debug_link_info (objfile, &crc32);
+
+  if (debuglink == NULL)
+    {
+      /* There's no separate debug info, hence there's no way we could
+        load it => no warning.  */
+      return NULL;
+    }
+
+  dir = xstrdup (objfile->name);
+  cleanups = make_cleanup (xfree, dir);
+  terminate_after_last_dir_separator (dir);
+  canon_dir = lrealpath (dir);
+
+  debugfile = find_separate_debug_file (dir, canon_dir, debuglink,
+                                       crc32, objfile);
+  xfree (canon_dir);
+
+  if (debugfile == NULL)
+    {
+#ifdef HAVE_LSTAT
+      /* For PR gdb/9538, try again with realpath (if different from the
+        original).  */
+
+      struct stat st_buf;
+
+      if (lstat (objfile->name, &st_buf) == 0 && S_ISLNK(st_buf.st_mode))
+       {
+         char *symlink_dir;
+
+         symlink_dir = lrealpath (objfile->name);
+         if (symlink_dir != NULL)
+           {
+             make_cleanup (xfree, symlink_dir);
+             terminate_after_last_dir_separator (symlink_dir);
+             if (strcmp (dir, symlink_dir) != 0)
+               {
+                 /* Different directory, so try using it.  */
+                 debugfile = find_separate_debug_file (symlink_dir,
+                                                       symlink_dir,
+                                                       debuglink,
+                                                       crc32,
+                                                       objfile);
+               }
+           }
+       }
+#endif  /* HAVE_LSTAT  */
+    }
 
-cleanup_return_debugfile:
-  xfree (canon_name);
-  xfree (basename);
-  xfree (dir);
+  do_cleanups (cleanups);
   return debugfile;
 }
 
index 131115b306d8f7eaa3bd64ec19a56206b5d8efc6..b4c0a4ba2b058939ee1be175c2c6d6401e25bcb8 100644 (file)
@@ -1,3 +1,8 @@
+2012-01-18  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+       PR gdb/9538
+       * gdb.base/sepdebug.exp: New test.
+
 2012-01-18  Pedro Alves  <palves@redhat.com>
 
        * gdb.ada/mi_task_info.exp (-ada-task-info with no argument):
index 5341bc9180bc71262ef0c5d2689c4714d9ff15ef..ba1047857a1e4dc37e24fc0095be680829262da4 100644 (file)
@@ -41,7 +41,7 @@ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
 
 # Note: the procedure gdb_gnu_strip_debug will produce an executable called
 # ${binfile}, which is just like the executable ($binfile) but without
-# the debuginfo. Instead $binfile has a .gnudebuglink section which contains
+# the debuginfo. Instead $binfile has a .gnu_debuglink section which contains
 # the name of a debuginfo only file. This file will be stored in the
 # gdb.base/ subdirectory.
 
@@ -51,10 +51,27 @@ if [gdb_gnu_strip_debug $binfile] {
     return -1
 }
 
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+#
+# PR gdb/9538.  Verify that symlinked executable still finds the separate
+# debuginfo.
+#
+set old_subdir ${subdir}
+set subdir ${subdir}/pr9538
+
+# Cleanup any stale state.
+remote_exec build "rm -rf ${subdir}"
+
+remote_exec build "mkdir ${subdir}"
+remote_exec build "ln -s ${binfile} ${subdir}"
+clean_restart ${testfile}${EXEEXT}
+if { $gdb_file_cmd_debug_info != "debug" } then {
+    fail "No debug information found."
+}
+
+# Restore subdir
+set subdir ${old_subdir}
+
+clean_restart ${testfile}${EXEEXT}
 if { $gdb_file_cmd_debug_info != "debug" } then {
     fail "No debug information found."
 }