libdw: Try both the relative and absolute paths when finding a .dwo file.
authorMark Wielaard <mark@klomp.org>
Thu, 31 May 2018 14:57:09 +0000 (16:57 +0200)
committerMark Wielaard <mark@klomp.org>
Fri, 1 Jun 2018 15:27:59 +0000 (17:27 +0200)
We would give up if one of them failed. With this fixed a self-test with
make check succeeds when building elfutils itself with CFLAGS set to
"-gdwarf-4 -gdwarf-split -O2".

Signed-off-by: Mark Wielaard <mark@klomp.org>
libdw/ChangeLog
libdw/libdw_find_split_unit.c
src/ChangeLog
src/readelf.c

index d8433eb..17acb90 100644 (file)
@@ -1,3 +1,10 @@
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+       * libdw_find_split_unit.c (try_split_file): New function extracted
+       from...
+       (__libdw_find_split_unit): ... here. Try both the relative and
+       absolute paths to find a .dwo file.
+
 2018-05-30  Mark Wielaard  <mark@klomp.org>
 
        * libdw/dwarf_getsrclines.c (read_srclines): Change ndir and
index dc62e0d..da039e5 100644 (file)
 #include <fcntl.h>
 #include <unistd.h>
 
+void
+try_split_file (Dwarf_CU *cu, const char *dwo_path)
+{
+  int split_fd = open (dwo_path, O_RDONLY);
+  if (split_fd != -1)
+    {
+      Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
+      if (split_dwarf != NULL)
+       {
+         Dwarf_CU *split = NULL;
+         while (dwarf_get_units (split_dwarf, split, &split,
+                                 NULL, NULL, NULL, NULL) == 0)
+           {
+             if (split->unit_type == DW_UT_split_compile
+                 && cu->unit_id8 == split->unit_id8)
+               {
+                 if (tsearch (split->dbg, &cu->dbg->split_tree,
+                              __libdw_finddbg_cb) == NULL)
+                   {
+                     /* Something went wrong.  Don't link.  */
+                     __libdw_seterrno (DWARF_E_NOMEM);
+                     break;
+                   }
+
+                 /* Link skeleton and split compile units.  */
+                 __libdw_link_skel_split (cu, split);
+
+                 /* We have everything we need from this ELF
+                    file.  And we are going to close the fd to
+                    not run out of file descriptors.  */
+                 elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
+                 break;
+               }
+           }
+         if (cu->split == (Dwarf_CU *) -1)
+           dwarf_end (split_dwarf);
+       }
+      /* Always close, because we don't want to run out of file
+        descriptors.  See also the elf_fcntl ELF_C_FDDONE call
+        above.  */
+      close (split_fd);
+    }
+}
 
 Dwarf_CU *
 internal_function
@@ -57,63 +100,42 @@ __libdw_find_split_unit (Dwarf_CU *cu)
   if (cu->unit_type == DW_UT_skeleton)
     {
       Dwarf_Die cudie = CUDIE (cu);
-      Dwarf_Attribute compdir, dwo_name;
-      /* It is fine if compdir doesn't exists, but then dwo_name needs
-        to be an absolute path.  Also try relative path first.  */
-      dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
-       if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
-           || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL)
+      Dwarf_Attribute dwo_name;
+      /* It is fine if dwo_dir doesn't exists, but then dwo_name needs
+        to be an absolute path.  */
+      if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
+         || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL)
        {
-         const char *comp_dir = dwarf_formstring (&compdir);
+         /* First try the dwo file name in the same directory
+            as we found the skeleton file.  */
          const char *dwo_file = dwarf_formstring (&dwo_name);
          const char *debugdir = cu->dbg->debugdir;
          char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
-         if (dwo_path == NULL && comp_dir != NULL)
-           dwo_path = __libdw_filepath (debugdir, comp_dir, dwo_file);
          if (dwo_path != NULL)
            {
-             int split_fd = open (dwo_path, O_RDONLY);
-             if (split_fd != -1)
+             try_split_file (cu, dwo_path);
+             free (dwo_path);
+           }
+
+         if (cu->split == (Dwarf_CU *) -1)
+           {
+             /* Try compdir plus dwo_name.  */
+             Dwarf_Attribute compdir;
+             dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
+             const char *dwo_dir = dwarf_formstring (&compdir);
+             if (dwo_dir != NULL)
                {
-                 Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
-                 if (split_dwarf != NULL)
+                 dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
+                 if (dwo_path != NULL)
                    {
-                     Dwarf_CU *split = NULL;
-                     while (dwarf_get_units (split_dwarf, split, &split,
-                                             NULL, NULL, NULL, NULL) == 0)
-                       {
-                         if (split->unit_type == DW_UT_split_compile
-                             && cu->unit_id8 == split->unit_id8)
-                           {
-                             if (tsearch (split->dbg, &cu->dbg->split_tree,
-                                          __libdw_finddbg_cb) == NULL)
-                               {
-                                 /* Something went wrong.  Don't link.  */
-                                 __libdw_seterrno (DWARF_E_NOMEM);
-                                 break;
-                               }
-
-                             /* Link skeleton and split compile units.  */
-                             __libdw_link_skel_split (cu, split);
-
-                             /* We have everything we need from this
-                                ELF file.  And we are going to close
-                                the fd to not run out of file
-                                descriptors.  */
-                             elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
-                             break;
-                           }
-                       }
-                     if (cu->split == (Dwarf_CU *) -1)
-                       dwarf_end (split_dwarf);
+                     try_split_file (cu, dwo_path);
+                     free (dwo_path);
                    }
-                 /* Always close, because we don't want to run
-                    out of file descriptors.  See also the
-                    elf_fcntl ELF_C_FDDONE call above.  */
-                 close (split_fd);
                }
-             free (dwo_path);
            }
+         /* XXX If still not found we could try stripping dirs from the
+            comp_dir and adding them from the comp_dir, assuming
+            someone moved a whole build tree around.  */
        }
     }
 
index bd3befd..cc12d83 100644 (file)
@@ -1,5 +1,10 @@
 2018-05-31  Mark Wielaard  <mark@klomp.org>
 
+       * readelf.c (print_debug_units): Print the dwo name and id when
+       unable to find a .dwo file.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
        * readelf.c (enum section_e): Make section_types not an alias of
        section_info.
        (section_all): Add section_types.
index 18ce3f7..0725313 100644 (file)
@@ -7680,7 +7680,18 @@ print_debug_units (Dwfl_Module *dwflmod,
          || dwarf_tag (&subdie) == DW_TAG_invalid)
        {
          if (!silent)
-           fprintf (stderr, gettext ("Could not find split compile unit"));
+           {
+             Dwarf_Attribute dwo_at;
+             const char *dwo_name =
+               (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
+                                              &dwo_at))
+                ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
+                                                  &dwo_at))
+                    ?: "<unknown>"));
+             fprintf (stderr,
+                      "Could not find split unit '%s', id: %" PRIx64 "\n",
+                      dwo_name, unit_id);
+           }
        }
       else
        {