gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 11 Nov 2009 05:04:34 +0000 (05:04 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 11 Nov 2009 05:04:34 +0000 (05:04 +0000)
* symfile.c (separate_debug_file_exists): Change parameter parent_name
to parent_objfile.  New variables parent_stat and abfd_stat.  Call
strcmp and then bfd_stat functions to verify if NAME matches.
(find_separate_debug_file): Update the passed parameter at caller.

gdb/ChangeLog
gdb/symfile.c

index dbc39888bfb2755a2977455bd6f1148064fb9697..c969bd05eac78444b127427573c3f3848c75f7eb 100644 (file)
@@ -1,3 +1,10 @@
+2009-11-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * symfile.c (separate_debug_file_exists): Change parameter parent_name
+       to parent_objfile.  New variables parent_stat and abfd_stat.  Call
+       strcmp and then bfd_stat functions to verify if NAME matches.
+       (find_separate_debug_file): Update the passed parameter at caller.
+
 2009-11-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * objfiles.c (objfile_relocate): Update also the field psymtabs_addrmap.
index d2f2834f7f7bb72986dc116c09847f0c4c8f06cf..30ae0dfccc34856fdbbca90e7244ce0ffd9624e5 100644 (file)
@@ -1308,12 +1308,22 @@ get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
 
 static int
 separate_debug_file_exists (const char *name, unsigned long crc,
-                           const char *parent_name)
+                           struct objfile *parent_objfile)
 {
   unsigned long file_crc = 0;
   bfd *abfd;
   gdb_byte buffer[8*1024];
   int count;
+  struct stat parent_stat, abfd_stat;
+
+  /* Find a separate debug info file as if symbols would be present in
+     PARENT_OBJFILE itself this function would not be called.  .gnu_debuglink
+     section can contain just the basename of PARENT_OBJFILE without any
+     ".debug" suffix as "/usr/lib/debug/path/to/file" is a separate tree where
+     the separate debug infos with the same basename can exist. */
+
+  if (strcmp (name, parent_objfile->name) == 0)
+    return 0;
 
   if (remote_filename_p (name))
     abfd = remote_bfd_open (name, gnutarget);
@@ -1323,6 +1333,26 @@ separate_debug_file_exists (const char *name, unsigned long crc,
   if (!abfd)
     return 0;
 
+  /* Verify symlinks were not the cause of strcmp name difference above.
+
+     Some operating systems, e.g. Windows, do not provide a meaningful
+     st_ino; they always set it to zero.  (Windows does provide a
+     meaningful st_dev.)  Do not indicate a duplicate library in that
+     case.  While there is no guarantee that a system that provides
+     meaningful inode numbers will never set st_ino to zero, this is
+     merely an optimization, so we do not need to worry about false
+     negatives.  */
+
+  if (bfd_stat (abfd, &abfd_stat) == 0
+      && bfd_stat (parent_objfile->obfd, &parent_stat) == 0
+      && abfd_stat.st_dev == parent_stat.st_dev
+      && abfd_stat.st_ino == parent_stat.st_ino
+      && abfd_stat.st_ino != 0)
+    {
+      bfd_close (abfd);
+      return 0;
+    }
+
   while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0)
     file_crc = gnu_debuglink_crc32 (file_crc, buffer, count);
 
@@ -1332,7 +1362,7 @@ separate_debug_file_exists (const char *name, unsigned long crc,
     {
       warning (_("the debug information found in \"%s\""
                 " does not match \"%s\" (CRC mismatch).\n"),
-              name, parent_name);
+              name, parent_objfile->name);
       return 0;
     }
 
@@ -1422,7 +1452,7 @@ find_separate_debug_file (struct objfile *objfile)
   strcpy (debugfile, dir);
   strcat (debugfile, basename);
 
-  if (separate_debug_file_exists (debugfile, crc32, objfile->name))
+  if (separate_debug_file_exists (debugfile, crc32, objfile))
     goto cleanup_return_debugfile;
 
   /* Then try in the subdirectory named DEBUG_SUBDIRECTORY.  */
@@ -1431,7 +1461,7 @@ find_separate_debug_file (struct objfile *objfile)
   strcat (debugfile, "/");
   strcat (debugfile, basename);
 
-  if (separate_debug_file_exists (debugfile, crc32, objfile->name))
+  if (separate_debug_file_exists (debugfile, crc32, objfile))
     goto cleanup_return_debugfile;
 
   /* Then try in the global debugfile directories.
@@ -1457,7 +1487,7 @@ find_separate_debug_file (struct objfile *objfile)
       strcat (debugfile, dir);
       strcat (debugfile, basename);
 
-      if (separate_debug_file_exists (debugfile, crc32, objfile->name))
+      if (separate_debug_file_exists (debugfile, crc32, objfile))
        goto cleanup_return_debugfile;
 
       /* If the file is in the sysroot, try using its base path in the
@@ -1472,7 +1502,7 @@ find_separate_debug_file (struct objfile *objfile)
          strcat (debugfile, "/");
          strcat (debugfile, basename);
 
-         if (separate_debug_file_exists (debugfile, crc32, objfile->name))
+         if (separate_debug_file_exists (debugfile, crc32, objfile))
            goto cleanup_return_debugfile;
        }