keiths / rpms / gdb

Forked from rpms/gdb 6 days ago
Clone
d4a047f
http://sourceware.org/ml/gdb-patches/2009-10/msg00508.html
d4a047f
Subject: [patch 3/3] debug-file-directory with multiple components
d4a047f
d4a047f
Hi,
d4a047f
d4a047f
for various reasons `debug-file-directory' would be sometimes useful to have
d4a047f
multiple components such as `solib-search-path' has.
d4a047f
d4a047f
I found it useful myself during various separate debuginfo tests/scripts.
d4a047f
d4a047f
It was requested for the ABRT bugreporting project at the preceding mail of:
d4a047f
	https://fedorahosted.org/pipermail/crash-catcher/2009-October/000054.html
d4a047f
d4a047f
It should be a backward compatible extension as DIRNAME_SEPARATOR should never
d4a047f
be a valid part of a single DEBUG_FILE_DIRECTORY component.
d4a047f
d4a047f
d4a047f
Thanks,
d4a047f
Jan
d4a047f
d4a047f
d4a047f
gdb/doc/
d4a047f
2009-10-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
d4a047f
d4a047f
	* gdb.texinfo (set debug-file-directory, show debug-file-directory)
d4a047f
	(Auto-loading): Use plural and note one can use multiple components now.
d4a047f
d4a047f
gdb/
d4a047f
2009-10-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
d4a047f
d4a047f
	* symfile.c (build_id_to_debug_filename): New variable debugdir.  Move
d4a047f
	variables size, s and data into a new inner block.  Change xmalloc for
d4a047f
	alloca, use direct BUILDID->SIZE there now.  Loop for the
d4a047f
	DEBUG_FILE_DIRECTORY components.
d4a047f
	(find_separate_debug_file): New variable debugdir and debugdir_end.
d4a047f
	Loop for the DEBUG_FILE_DIRECTORY components.
d4a047f
	(_initialize_symfile): For "debug-file-directory" use plural and note
d4a047f
	one can use multiple components now.
d4a047f
d4a047f
gdb/testsuite/
d4a047f
2009-10-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
d4a047f
d4a047f
	* gdb.base/sepdebug.exp: New test_different_dir call for multiple-dirs.
d4a047f
d4a047f
--- a/gdb/doc/gdb.texinfo
d4a047f
+++ b/gdb/doc/gdb.texinfo
d4a047f
@@ -14066,13 +14066,14 @@ name @value{GDBN} is currently using.
d4a047f
 @table @code
d4a047f
 
d4a047f
 @kindex set debug-file-directory
d4a047f
-@item set debug-file-directory @var{directory}
d4a047f
-Set the directory which @value{GDBN} searches for separate debugging
d4a047f
-information files to @var{directory}.
d4a047f
+@item set debug-file-directory @var{directories}
d4a047f
+Set the directories which @value{GDBN} searches for separate debugging
d4a047f
+information files to @var{directory}.  Multiple directory components can be set
d4a047f
+concatenating them by a directory separator.
d4a047f
 
d4a047f
 @kindex show debug-file-directory
d4a047f
 @item show debug-file-directory
d4a047f
-Show the directory @value{GDBN} searches for separate debugging
d4a047f
+Show the directories @value{GDBN} searches for separate debugging
d4a047f
 information files.
d4a047f
 
d4a047f
 @end table
d4a047f
@@ -19336,8 +19337,8 @@ readable, @value{GDBN} will evaluate it as a Python script.
d4a047f
 
d4a047f
 If this file does not exist, and if the parameter
d4a047f
 @code{debug-file-directory} is set (@pxref{Separate Debug Files}),
d4a047f
-then @value{GDBN} will use the file named
d4a047f
-@file{@var{debug-file-directory}/@var{real-name}}, where
d4a047f
+then @value{GDBN} will use for its each separated directory component
d4a047f
+@code{component} the file named @file{@code{component}/@var{real-name}}, where
d4a047f
 @var{real-name} is the object file's real name, as described above.
d4a047f
 
d4a047f
 Finally, if this file does not exist, then @value{GDBN} will look for
d4a047f
--- a/gdb/symfile.c
d4a047f
+++ b/gdb/symfile.c
d4a047f
@@ -1218,35 +1218,59 @@ build_id_verify (const char *filename, struct build_id *check)
d4a047f
 static char *
d4a047f
 build_id_to_debug_filename (struct build_id *build_id)
d4a047f
 {
d4a047f
-  char *link, *s, *retval = NULL;
d4a047f
-  gdb_byte *data = build_id->data;
d4a047f
-  size_t size = build_id->size;
d4a047f
+  char *link, *debugdir, *retval = NULL;
d4a047f
 
d4a047f
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
d4a047f
-  link = xmalloc (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
d4a047f
-		  + 2 * size + (sizeof ".debug" - 1) + 1);
d4a047f
-  s = link + sprintf (link, "%s/.build-id/", debug_file_directory);
d4a047f
-  if (size > 0)
d4a047f
-    {
d4a047f
-      size--;
d4a047f
-      s += sprintf (s, "%02x", (unsigned) *data++);
d4a047f
-    }
d4a047f
-  if (size > 0)
d4a047f
-    *s++ = '/';
d4a047f
-  while (size-- > 0)
d4a047f
-    s += sprintf (s, "%02x", (unsigned) *data++);
d4a047f
-  strcpy (s, ".debug");
d4a047f
-
d4a047f
-  /* lrealpath() is expensive even for the usually non-existent files.  */
d4a047f
-  if (access (link, F_OK) == 0)
d4a047f
-    retval = lrealpath (link);
d4a047f
-  xfree (link);
d4a047f
-
d4a047f
-  if (retval != NULL && !build_id_verify (retval, build_id))
d4a047f
+  link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
d4a047f
+		 + 2 * build_id->size + (sizeof ".debug" - 1) + 1);
d4a047f
+
d4a047f
+  /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
d4a047f
+     cause "/.build-id/..." lookups.  */
d4a047f
+
d4a047f
+  debugdir = debug_file_directory;
d4a047f
+  do
d4a047f
     {
d4a047f
-      xfree (retval);
d4a047f
-      retval = NULL;
d4a047f
+      char *s, *debugdir_end;
d4a047f
+      gdb_byte *data = build_id->data;
d4a047f
+      size_t size = build_id->size;
d4a047f
+
d4a047f
+      while (*debugdir == DIRNAME_SEPARATOR)
d4a047f
+	debugdir++;
d4a047f
+
d4a047f
+      debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
d4a047f
+      if (debugdir_end == NULL)
d4a047f
+	debugdir_end = &debugdir[strlen (debugdir)];
d4a047f
+
d4a047f
+      memcpy (link, debugdir, debugdir_end - debugdir);
d4a047f
+      s = &link[debugdir_end - debugdir];
d4a047f
+      s += sprintf (s, "/.build-id/");
d4a047f
+      if (size > 0)
d4a047f
+	{
d4a047f
+	  size--;
d4a047f
+	  s += sprintf (s, "%02x", (unsigned) *data++);
d4a047f
+	}
d4a047f
+      if (size > 0)
d4a047f
+	*s++ = '/';
d4a047f
+      while (size-- > 0)
d4a047f
+	s += sprintf (s, "%02x", (unsigned) *data++);
d4a047f
+      strcpy (s, ".debug");
d4a047f
+
d4a047f
+      /* lrealpath() is expensive even for the usually non-existent files.  */
d4a047f
+      if (access (link, F_OK) == 0)
d4a047f
+	retval = lrealpath (link);
d4a047f
+
d4a047f
+      if (retval != NULL && !build_id_verify (retval, build_id))
d4a047f
+	{
d4a047f
+	  xfree (retval);
d4a047f
+	  retval = NULL;
d4a047f
+	}
d4a047f
+
d4a047f
+      if (retval != NULL)
d4a047f
+	break;
d4a047f
+
d4a047f
+      debugdir = debugdir_end;
d4a047f
     }
d4a047f
+  while (*debugdir != 0);
d4a047f
 
d4a047f
   return retval;
d4a047f
 }
d4a047f
@@ -1333,7 +1357,7 @@ static char *
d4a047f
 find_separate_debug_file (struct objfile *objfile)
d4a047f
 {
d4a047f
   asection *sect;
d4a047f
-  char *basename, *name_copy;
d4a047f
+  char *basename, *name_copy, *debugdir;
d4a047f
   char *dir = NULL;
d4a047f
   char *debugfile = NULL;
d4a047f
   char *canon_name = NULL;
d4a047f
@@ -1410,29 +1434,51 @@ find_separate_debug_file (struct objfile *objfile)
d4a047f
   if (separate_debug_file_exists (debugfile, crc32, objfile->name))
d4a047f
     goto cleanup_return_debugfile;
d4a047f
 
d4a047f
-  /* Then try in the global debugfile directory.  */
d4a047f
-  strcpy (debugfile, debug_file_directory);
d4a047f
-  strcat (debugfile, "/");
d4a047f
-  strcat (debugfile, dir);
d4a047f
-  strcat (debugfile, basename);
d4a047f
-
d4a047f
-  if (separate_debug_file_exists (debugfile, crc32, objfile->name))
d4a047f
-    goto cleanup_return_debugfile;
d4a047f
+  /* Then try in the global debugfile directories.
d4a047f
+ 
d4a047f
+     Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
d4a047f
+     cause "/..." lookups.  */
d4a047f
 
d4a047f
-  /* If the file is in the sysroot, try using its base path in the
d4a047f
-     global debugfile directory.  */
d4a047f
-  if (canon_name
d4a047f
-      && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
d4a047f
-      && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
d4a047f
+  debugdir = debug_file_directory;
d4a047f
+  do
d4a047f
     {
d4a047f
-      strcpy (debugfile, debug_file_directory);
d4a047f
-      strcat (debugfile, canon_name + strlen (gdb_sysroot));
d4a047f
+      char *debugdir_end;
d4a047f
+
d4a047f
+      while (*debugdir == DIRNAME_SEPARATOR)
d4a047f
+	debugdir++;
d4a047f
+
d4a047f
+      debugdir_end = strchr (debugdir, DIRNAME_SEPARATOR);
d4a047f
+      if (debugdir_end == NULL)
d4a047f
+	debugdir_end = &debugdir[strlen (debugdir)];
d4a047f
+
d4a047f
+      memcpy (debugfile, debugdir, debugdir_end - debugdir);
d4a047f
+      debugfile[debugdir_end - debugdir] = 0;
d4a047f
       strcat (debugfile, "/");
d4a047f
+      strcat (debugfile, dir);
d4a047f
       strcat (debugfile, basename);
d4a047f
 
d4a047f
       if (separate_debug_file_exists (debugfile, crc32, objfile->name))
d4a047f
 	goto cleanup_return_debugfile;
d4a047f
+
d4a047f
+      /* If the file is in the sysroot, try using its base path in the
d4a047f
+	 global debugfile directory.  */
d4a047f
+      if (canon_name
d4a047f
+	  && strncmp (canon_name, gdb_sysroot, strlen (gdb_sysroot)) == 0
d4a047f
+	  && IS_DIR_SEPARATOR (canon_name[strlen (gdb_sysroot)]))
d4a047f
+	{
d4a047f
+	  memcpy (debugfile, debugdir, debugdir_end - debugdir);
d4a047f
+	  debugfile[debugdir_end - debugdir] = 0;
d4a047f
+	  strcat (debugfile, canon_name + strlen (gdb_sysroot));
d4a047f
+	  strcat (debugfile, "/");
d4a047f
+	  strcat (debugfile, basename);
d4a047f
+
d4a047f
+	  if (separate_debug_file_exists (debugfile, crc32, objfile->name))
d4a047f
+	    goto cleanup_return_debugfile;
d4a047f
+	}
d4a047f
+
d4a047f
+      debugdir = debugdir_end;
d4a047f
     }
d4a047f
+  while (*debugdir != 0);
d4a047f
   
d4a047f
   xfree (debugfile);
d4a047f
   debugfile = NULL;
d4a047f
@@ -4173,12 +4219,12 @@ Usage: set extension-language .foo bar"),
d4a047f
 
d4a047f
   add_setshow_optional_filename_cmd ("debug-file-directory", class_support,
d4a047f
 				     &debug_file_directory, _("\
d4a047f
-Set the directory where separate debug symbols are searched for."), _("\
d4a047f
-Show the directory where separate debug symbols are searched for."), _("\
d4a047f
+Set the directories where separate debug symbols are searched for."), _("\
d4a047f
+Show the directories where separate debug symbols are searched for."), _("\
d4a047f
 Separate debug symbols are first searched for in the same\n\
d4a047f
 directory as the binary, then in the `" DEBUG_SUBDIRECTORY "' subdirectory,\n\
d4a047f
 and lastly at the path of the directory of the binary with\n\
d4a047f
-the global debug-file directory prepended."),
d4a047f
+each global debug-file-directory component prepended."),
d4a047f
 				     NULL,
d4a047f
 				     show_debug_file_directory,
d4a047f
 				     &setlist, &showlist);
d4a047f
--- a/gdb/testsuite/gdb.base/sepdebug.exp
d4a047f
+++ b/gdb/testsuite/gdb.base/sepdebug.exp
d4a047f
@@ -995,6 +995,12 @@ if ![string compare $build_id_debug_filename ""] then {
d4a047f
 
d4a047f
     test_different_dir build-id "${objdir}/${subdir}" $xfail
d4a047f
 
d4a047f
+    # Test also multiple directories can be specified.  Without the build-id
d4a047f
+    # reference GDB would find the separate debug info just at the same
d4a047f
+    # location as the executable file.
d4a047f
+
d4a047f
+    test_different_dir multiple-dirs "/doesnotexist:${objdir}/${subdir}" $xfail
d4a047f
+
d4a047f
     # Spare debug files may confuse testsuite runs in the future.
d4a047f
     remote_exec build "rm -f ${objdir}/${subdir}/${build_id_debug_filename}"
d4a047f
 }
d4a047f