Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Paul Pluzhnikov <ppluzhnikov@google.com>
To: Doug Evans <dje@google.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [patch] Fix for PR gdb/9538 (loading of separate debuginfo and symlinks).
Date: Thu, 12 Jan 2012 20:59:00 -0000	[thread overview]
Message-ID: <CALoOobMVWJB=u6Y8OMyNeva1KcgU7FP8FpR2aFQ4b2e+=QUgOQ@mail.gmail.com> (raw)
In-Reply-To: <CADPb22TZqh1KJv0KXxRNuhV8PZH-Z31CcggzJMBDJYo3OuZKdA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1514 bytes --]

On Thu, Jan 12, 2012 at 9:23 AM, Doug Evans <dje@google.com> wrote:

> The symfile.c change is ok with me, modulo can you add comments for
> each of the functions?

Done.

I've also refactored the code a bit more to avoid searching the same
directory again.

> [caveat: I think it doesn't properly handle paths with dos drives, but
> the code already has that problem, so no requirement to fix that in
> this patch]

I don't think ".gnu_debuglink" is supported on non-ELF platforms, so not
handling DOS drives is likely not a problem.

> I see sepdebug.exp uses remote_exec so best use that instead of exec.

Done.

> Also, I'm not sure what the portability requirements are w.r.t. symlinks.
> Probably best to watch for errors in the "ln -s" and handle appropriately.

The test exits if gdb_gnu_strip_debug fails. I don't believe it will
currently succeed on any platform without symlinks.

Testing for errors will just add noise.

> [Even better, is there a utility routine that will create a symlink?
> All the portability concerns could be tucked away in there.]

I didn't find one.

> Also, can you use clean_restart instead of the gdb_exit/gdb_start/... sequence?

Done.

Thanks,
-- 
Paul Pluzhnikov


2012-01-11  Paul Pluzhnikov  <ppluzhnikov@google.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.


testsuite/ChangeLog:

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

[-- Attachment #2: gdb-symlink-pr9538-20120112.txt --]
[-- Type: text/plain, Size: 7965 bytes --]

Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.325
diff -u -p -r1.325 symfile.c
--- symfile.c	12 Jan 2012 00:00:01 -0000	1.325
+++ symfile.c	12 Jan 2012 20:29:53 -0000
@@ -1441,63 +1441,48 @@ show_debug_file_directory (struct ui_fil
 #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 && 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 (s
       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,80 @@ find_separate_debug_file_by_debuglink (s
   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 *dir1, *dir2, *canon_dir;
+  char *debugfile;
+  unsigned long crc32;
+
+  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;
+
+  dir1 = xstrdup (objfile->name);
+  terminate_after_last_dir_separator (dir1);
+  canon_dir = lrealpath (dir1);
+
+  debugfile = find_separate_debug_file (dir1, canon_dir, debuglink,
+					crc32, objfile);
+  xfree (canon_dir);
+
+  if (debugfile != NULL)
+    goto cleanup1;
+
+  /* For PR gdb/9538, try again with realpath (if different from the
+     original).  */
+  dir2 = lrealpath (objfile->name);
+  if (dir2 == NULL)
+    goto cleanup1;
+
+  terminate_after_last_dir_separator (dir2);
+  if (strcmp (dir1, dir2) == 0)
+    /* Same directory, no point retrying.  */
+    goto cleanup2;
+
+  canon_dir = lrealpath (dir2);
+  debugfile = find_separate_debug_file (dir2, canon_dir, debuglink,
+					crc32, objfile);
+  xfree (canon_dir);
+
+ cleanup2:
+  xfree (dir2);
+ cleanup1:
+  xfree (dir1);
+  xfree (debuglink);
 
-cleanup_return_debugfile:
-  xfree (canon_name);
-  xfree (basename);
-  xfree (dir);
   return debugfile;
 }
 
Index: testsuite/gdb.base/sepdebug.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v
retrieving revision 1.33
diff -u -p -r1.33 sepdebug.exp
--- testsuite/gdb.base/sepdebug.exp	4 Jan 2012 08:17:46 -0000	1.33
+++ testsuite/gdb.base/sepdebug.exp	12 Jan 2012 20:29:53 -0000
@@ -45,7 +45,7 @@ if  { [gdb_compile "${srcdir}/${subdir}/
 
 # 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.
 
@@ -55,10 +55,26 @@ if [gdb_gnu_strip_debug $binfile] {
     return -1
 }
 
+#
+# PR gdb/9538.  Verify that symlinked executable still finds the separate
+# debuginfo.
+#
+set old_subdir ${subdir}
+set subdir ${subdir}/pr9538
+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."
+}
+
+# make sure we are not holding subdir/binary open.
 gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+
+remote_exec build "rm -rf ${subdir}"
+set subdir ${old_subdir}
+
+clean_restart ${testfile}${EXEEXT}
 if { $gdb_file_cmd_debug_info != "debug" } then {
     fail "No debug information found."
 }

  reply	other threads:[~2012-01-12 20:36 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-12  3:12 Paul Pluzhnikov
2012-01-12 17:28 ` Doug Evans
2012-01-12 20:59   ` Paul Pluzhnikov [this message]
2012-01-12 21:31     ` Jan Kratochvil
2012-01-12 22:20       ` Paul Pluzhnikov
2012-01-12 22:27         ` Jan Kratochvil
2012-01-12 22:31           ` Paul Pluzhnikov
2012-01-12 22:29       ` Paul Pluzhnikov
2012-01-12 22:50         ` Jan Kratochvil
2012-01-12 23:12           ` Paul Pluzhnikov
2012-01-12 23:18             ` Jan Kratochvil
2012-01-12 23:25         ` Doug Evans
2012-01-12 23:27           ` Jan Kratochvil
2012-01-12 23:40             ` Doug Evans
2012-01-13  0:21               ` [doc patch] gdbint: braces for two lines in code [Re: [patch] Fix for PR gdb/9538 (loading of separate debuginfo and symlinks).] Jan Kratochvil
2012-01-13  0:27                 ` Doug Evans
2012-01-13  4:02                   ` Joel Brobecker
2012-01-13 11:09                     ` Jan Kratochvil
2012-01-13 11:23                       ` Pedro Alves
2012-01-13 11:55                         ` Eli Zaretskii
2012-01-13 12:15                           ` Joel Brobecker
2012-01-13 12:40                             ` Eli Zaretskii
2012-01-13 14:37                               ` [commit] " Jan Kratochvil
2012-01-13  9:05                 ` Eli Zaretskii
2012-01-12 23:28           ` [patch] Fix for PR gdb/9538 (loading of separate debuginfo and symlinks) Paul Pluzhnikov
2012-01-12 23:55             ` Jan Kratochvil
2012-01-13  0:21               ` Paul Pluzhnikov
2012-01-13  0:48                 ` Jan Kratochvil
2012-01-13  3:39                   ` Paul Pluzhnikov
2012-01-18 19:15                     ` Paul Pluzhnikov
2012-01-12 22:26     ` Doug Evans
2012-01-12 22:40       ` Paul Pluzhnikov
2012-01-12 22:52         ` Doug Evans

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CALoOobMVWJB=u6Y8OMyNeva1KcgU7FP8FpR2aFQ4b2e+=QUgOQ@mail.gmail.com' \
    --to=ppluzhnikov@google.com \
    --cc=dje@google.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox