libdwfl: Ignore debuginfo-path hits that find the main file again.
authorRoland McGrath <roland@redhat.com>
Mon, 14 Jun 2010 19:45:25 +0000 (12:45 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 14 Jun 2010 19:52:09 +0000 (12:52 -0700)
libdwfl/ChangeLog
libdwfl/find-debuginfo.c

index 347ebcf..d9b216d 100644 (file)
@@ -1,3 +1,10 @@
+2010-06-14  Roland McGrath  <roland@redhat.com>
+
+       * find-debuginfo.c (try_open): Take new arg MAIN_STAT.  Compare
+       candidate file to that st_dev/st_ino and pretend it didn't exist
+       if they match.
+       (find_debuginfo_in_path): Update caller, pass main file's info.
+
 2010-05-20  Roland McGrath  <roland@redhat.com>
 
        * linux-proc-maps.c (find_sysinfo_ehdr): Renamed to ...
index 8fdaeb3..375bbaa 100644 (file)
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/stat.h>
 #include "system.h"
 
 
 /* Try to open64 [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1.
    On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file.  */
 static int
-try_open (const char *dir, const char *subdir, const char *debuglink,
+try_open (const struct stat64 *main_stat,
+         const char *dir, const char *subdir, const char *debuglink,
          char **debuginfo_file_name)
 {
   char *fname;
@@ -72,9 +74,19 @@ try_open (const char *dir, const char *subdir, const char *debuglink,
            : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0)
     return -1;
 
+  struct stat64 st;
   int fd = TEMP_FAILURE_RETRY (open64 (fname, O_RDONLY));
   if (fd < 0)
     free (fname);
+  else if (fstat64 (fd, &st) == 0
+          && st.st_ino == main_stat->st_ino
+          && st.st_dev == main_stat->st_dev)
+    {
+      /* This is the main file by another name.  Don't look at it again.  */
+      close (fd);
+      errno = ENOENT;
+      fd = -1;
+    }
   else
     *debuginfo_file_name = fname;
 
@@ -162,6 +174,16 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
       ++path;
     }
 
+  /* XXX dev/ino should be cached in struct dwfl_file.  */
+  struct stat64 main_stat;
+  if (unlikely ((mod->main.fd != -1 ? fstat64 (mod->main.fd, &main_stat)
+                : file_name != NULL ? stat64 (file_name, &main_stat)
+                : -1) < 0))
+    {
+      main_stat.st_dev = 0;
+      main_stat.st_ino = 0;
+    }
+
   char *file_dirname = (file_basename == file_name ? NULL
                        : strndupa (file_name, file_basename - 1 - file_name));
   char *p;
@@ -199,7 +221,7 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
        }
 
       char *fname = NULL;
-      int fd = try_open (dir, subdir, debuglink_file, &fname);
+      int fd = try_open (&main_stat, dir, subdir, debuglink_file, &fname);
       if (fd < 0)
        switch (errno)
          {