aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2012-01-18 18:58:43 +0000
committerPaul Pluzhnikov <ppluzhnikov@google.com>2012-01-18 18:58:43 +0000
commit1db333787dc7d00ae720d8859000529224afacdc (patch)
tree5ae85a220c0b5df07c6645c7f5385c1ffac07610
parentf83d8a90aee9d0ae60cd6c089aa19b400dbaf714 (diff)
downloadgdb-1db333787dc7d00ae720d8859000529224afacdc.zip
gdb-1db333787dc7d00ae720d8859000529224afacdc.tar.gz
gdb-1db333787dc7d00ae720d8859000529224afacdc.tar.bz2
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. testsuite/ChangeLog: 2012-01-18 Paul Pluzhnikov <ppluzhnikov@google.com> PR gdb/9538 * gdb.base/sepdebug.exp: New test.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/config.in3
-rwxr-xr-xgdb/configure2
-rw-r--r--gdb/configure.ac2
-rw-r--r--gdb/symfile.c159
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.base/sepdebug.exp27
7 files changed, 154 insertions, 55 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d7bf88b..120bcbc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/config.in b/gdb/config.in
index f1e6b9a..45c2c73 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -263,6 +263,9 @@
/* 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
diff --git a/gdb/configure b/gdb/configure
index 5b2a6dd..2ced763 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -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"
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 652c0c6..66844ed 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -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
diff --git a/gdb/symfile.c b/gdb/symfile.c
index e9b6e7b..7529196 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -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;
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 131115b..b4c0a4b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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):
diff --git a/gdb/testsuite/gdb.base/sepdebug.exp b/gdb/testsuite/gdb.base/sepdebug.exp
index 5341bc9..ba10478 100644
--- a/gdb/testsuite/gdb.base/sepdebug.exp
+++ b/gdb/testsuite/gdb.base/sepdebug.exp
@@ -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."
}