[PATCH v3 5/6] Move .gnu_debugaltlink handling from libdw to libdwfl

Florian Weimer fweimer at redhat.com
Tue Apr 15 15:11:17 UTC 2014


Also use dwelf_dwarf_gnu_debugaltlink to locate the alternate debugging
information.

Signed-off-by: Florian Weimer <fweimer at redhat.com>
---
 libdw/ChangeLog                |   4 ++
 libdw/dwarf_begin_elf.c        | 120 -----------------------------------------
 libdwfl/ChangeLog              |   8 +++
 libdwfl/dwfl_module_getdwarf.c | 120 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 120 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 3097880..6206c17 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -15,6 +15,10 @@
 
 	* libdw.map (ELFUTILS_0.159): Export dwelf_dwarf_gnu_debugaltlink.
 
+	* dwarf_begin_elf.c (__check_build_id, try_debugaltlink)
+	(open_debugaltlink): Move to libdwfl.
+	(check_section): Do not locate alternate debuginfo.
+
 2014-04-11  Mark Wielaard  <mjw at redhat.com>
 
 	* libdw.map (ELFUTILS_0.159): New. Add dwelf_elf_gnu_debuglink.
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 5f69c61..4c6346a 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -32,7 +32,6 @@
 #endif
 
 #include <assert.h>
-#include <inttypes.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -72,113 +71,6 @@ static const char dwarf_scnnames[IDX_last][18] =
 };
 #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
 
-#ifdef ENABLE_DWZ
-internal_function int
-__check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
-{
-  if (dw == NULL)
-    return -1;
-
-  Elf *elf = dw->elf;
-  Elf_Scn *scn = elf_nextscn (elf, NULL);
-  if (scn == NULL)
-    return -1;
-
-  do
-    {
-      GElf_Shdr shdr_mem;
-      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-      if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
-	{
-	  size_t pos = 0;
-	  GElf_Nhdr nhdr;
-	  size_t name_pos;
-	  size_t desc_pos;
-	  Elf_Data *data = elf_getdata (scn, NULL);
-	  while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos,
-				      &desc_pos)) > 0)
-	    if (nhdr.n_type == NT_GNU_BUILD_ID
-	        && nhdr.n_namesz == sizeof "GNU"
-		&& ! memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU"))
-	      return (nhdr.n_descsz == id_len
-		      && ! memcmp (data->d_buf + desc_pos,
-				   build_id, id_len)) ? 0 : 1;
-        }
-      }
-    while ((scn = elf_nextscn (elf, scn)) != NULL);
-
-  return -1;
-}
-
-/* Try to open an debug alt link by name, checking build_id.
-   Marks free_alt on success, return NULL on failure.  */
-static Dwarf *
-try_debugaltlink (Dwarf *result, const char *try_name,
-		   const uint8_t *build_id, const size_t id_len)
-{
-  int fd = open (try_name, O_RDONLY);
-  if (fd > 0)
-    {
-      result->alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ);
-      if (result->alt_dwarf != NULL)
-	{
-	  Elf *elf = result->alt_dwarf->elf;
-	  if (__check_build_id (result->alt_dwarf, build_id, id_len) == 0
-	      && elf_cntl (elf, ELF_C_FDREAD) == 0)
-	    {
-	      close (fd);
-	      result->free_alt = 1;
-	      return result;
-	    }
-	  INTUSE (dwarf_end) (result->alt_dwarf);
-	}
-      close (fd);
-    }
-  return NULL;
-}
-
-/* For dwz multifile support, ignore if it looks wrong.  */
-static Dwarf *
-open_debugaltlink (Dwarf *result, const char *alt_name,
-		   const uint8_t *build_id, const size_t id_len)
-{
-  /* First try the name itself, it is either an absolute path or
-     a relative one.  Sadly we don't know relative from where at
-     this point.  */
-  if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
-    return result;
-
-  /* Lets try based on the build-id.  This is somewhat distro specific,
-     we are following the Fedora implementation described at
-  https://fedoraproject.org/wiki/Releases/FeatureBuildId#Find_files_by_build_ID
-   */
-#define DEBUG_PREFIX "/usr/lib/debug/.build-id/"
-#define PREFIX_LEN sizeof (DEBUG_PREFIX)
-  char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1];
-  strcpy (id_name, DEBUG_PREFIX);
-  int n = snprintf (&id_name[PREFIX_LEN  - 1],
-		    4, "%02" PRIx8 "/", (uint8_t) build_id[0]);
-  assert (n == 3);
-  for (size_t i = 1; i < id_len; ++i)
-    {
-      n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2],
-		    3, "%02" PRIx8, (uint8_t) build_id[i]);
-      assert (n == 2);
-    }
-  strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2],
-	  ".debug");
-
-  if (try_debugaltlink (result, id_name, build_id, id_len))
-    return result;
-
-  /* Everything failed, mark this Dwarf as not having an alternate,
-     but don't fail the load.  The user may want to set it by hand
-     before usage.  */
-  result->alt_dwarf = NULL;
-  return result;
-}
-#endif /* ENABLE_DWZ */
-
 static Dwarf *
 check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
 {
@@ -319,18 +211,6 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
       }
 #endif
 
-#ifdef ENABLE_DWZ
-  Elf_Data *data = result->sectiondata[IDX_gnu_debugaltlink];
-  if (data != NULL && data->d_size != 0)
-    {
-      const char *alt_name = data->d_buf;
-      const void *build_id = memchr (data->d_buf, '\0', data->d_size);
-      const int id_len = data->d_size - (build_id - data->d_buf + 1);
-      if (alt_name && build_id && id_len > 0)
-	return open_debugaltlink (result, alt_name, build_id + 1, id_len);
-    }
-#endif /* ENABLE_DWZ */
-
   return result;
 }
 
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 63bb0ab..512fd20 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,11 @@
+2014-04-15  Florian Weimer  <fweimer at redhat.com>
+
+	* dwfl_module_getdwarf.c (__check_build_id): Moved from libdw.
+	(try_debugaltlink): Likewise.
+	(open_debugaltlink): Likewise.
+	(load_dw): Locate alternate debug information using
+	dwelf_dwarf_gnu_debugaltlink and call open_debugaltlink.
+
 2014-04-11  Mark Wielaard  <mjw at redhat.com>
 
 	* Makefile.am (AM_CPPFLAGS): Add libdwelf.
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index f8a7816..5aa17c4 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -27,12 +27,120 @@
    not, see <http://www.gnu.org/licenses/>.  */
 
 #include "libdwflP.h"
+#include <inttypes.h>
 #include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
 #include "../libdw/libdwP.h"	/* DWARF_E_* values are here.  */
 #include "../libelf/libelfP.h"
 
+#ifdef ENABLE_DWZ
+internal_function int
+__check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
+{
+  if (dw == NULL)
+    return -1;
+
+  Elf *elf = dw->elf;
+  Elf_Scn *scn = elf_nextscn (elf, NULL);
+  if (scn == NULL)
+    return -1;
+
+  do
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
+	{
+	  size_t pos = 0;
+	  GElf_Nhdr nhdr;
+	  size_t name_pos;
+	  size_t desc_pos;
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos,
+				      &desc_pos)) > 0)
+	    if (nhdr.n_type == NT_GNU_BUILD_ID
+	        && nhdr.n_namesz == sizeof "GNU"
+		&& ! memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU"))
+	      return (nhdr.n_descsz == id_len
+		      && ! memcmp (data->d_buf + desc_pos,
+				   build_id, id_len)) ? 0 : 1;
+        }
+      }
+    while ((scn = elf_nextscn (elf, scn)) != NULL);
+
+  return -1;
+}
+
+/* Try to open an debug alt link by name, checking build_id.
+   Marks free_alt on success, return NULL on failure.  */
+static Dwarf *
+try_debugaltlink (Dwarf *result, const char *try_name,
+		   const uint8_t *build_id, const size_t id_len)
+{
+  int fd = open (try_name, O_RDONLY);
+  if (fd > 0)
+    {
+      Dwarf *alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ);
+      if (alt_dwarf != NULL)
+	{
+	  Elf *elf = alt_dwarf->elf;
+	  if (__check_build_id (alt_dwarf, build_id, id_len) == 0
+	      && elf_cntl (elf, ELF_C_FDREAD) == 0)
+	    {
+	      close (fd);
+	      INTUSE (dwarf_setalt) (result, alt_dwarf);
+	      result->free_alt = true;
+	      return result;
+	    }
+	  INTUSE (dwarf_end) (result->alt_dwarf);
+	}
+      close (fd);
+    }
+  return NULL;
+}
+
+/* For dwz multifile support, ignore if it looks wrong.  */
+static Dwarf *
+open_debugaltlink (Dwarf *result, const char *alt_name,
+		   const uint8_t *build_id, const size_t id_len)
+{
+  /* First try the name itself, it is either an absolute path or
+     a relative one.  Sadly we don't know relative from where at
+     this point.  */
+  if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
+    return result;
+
+  /* Lets try based on the build-id.  This is somewhat distro specific,
+     we are following the Fedora implementation described at
+  https://fedoraproject.org/wiki/Releases/FeatureBuildId#Find_files_by_build_ID
+   */
+#define DEBUG_PREFIX "/usr/lib/debug/.build-id/"
+#define PREFIX_LEN sizeof (DEBUG_PREFIX)
+  char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1];
+  strcpy (id_name, DEBUG_PREFIX);
+  int n = snprintf (&id_name[PREFIX_LEN  - 1],
+		    4, "%02" PRIx8 "/", (uint8_t) build_id[0]);
+  assert (n == 3);
+  for (size_t i = 1; i < id_len; ++i)
+    {
+      n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2],
+		    3, "%02" PRIx8, (uint8_t) build_id[i]);
+      assert (n == 2);
+    }
+  strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2],
+	  ".debug");
+
+  if (try_debugaltlink (result, id_name, build_id, id_len))
+    return result;
+
+  /* Everything failed, mark this Dwarf as not having an alternate,
+     but don't fail the load.  The user may want to set it by hand
+     before usage.  */
+  result->alt_dwarf = NULL;
+  return result;
+}
+#endif /* ENABLE_DWZ */
 
 /* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
    When we return success, FILE->elf and FILE->vaddr are set up.  */
@@ -1122,6 +1230,18 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
       return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
     }
 
+#ifdef ENABLE_DWZ
+  /* For dwz multifile support, ignore if it looks wrong.  */
+  {
+    const void *build_id;
+    size_t id_len;
+    const char *alt_name = INTUSE (dwelf_dwarf_gnu_debugaltlink)
+      (mod->dw, &build_id, &id_len);
+    if (alt_name != NULL)
+      open_debugaltlink (mod->dw, alt_name, build_id, id_len);
+  }
+#endif /* ENABLE_DWZ */
+
   /* Until we have iterated through all CU's, we might do lazy lookups.  */
   mod->lazycu = 1;
 
-- 
1.9.0



More information about the elfutils-devel mailing list