[Mesa-dev] [PATCH 1/2] util: Add utility build-id code.

Matt Turner mattst88 at gmail.com
Tue Feb 14 23:58:53 UTC 2017


Provides the ability to read the .note.gnu.build-id section of ELF
binaries, which is inserted by the --build-id=... flag to ld.
---
 configure.ac              |   2 +
 src/util/Makefile.sources |   2 +
 src/util/build_id.c       | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/build_id.h       |  34 ++++++++++++++
 4 files changed, 148 insertions(+)
 create mode 100644 src/util/build_id.c
 create mode 100644 src/util/build_id.h

diff --git a/configure.ac b/configure.ac
index f001743..99c74f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -768,6 +768,8 @@ LIBS="$LIBS $DLOPEN_LIBS"
 AC_CHECK_FUNCS([dladdr])
 LIBS="$save_LIBS"
 
+AC_CHECK_FUNC([dl_iterate_phdr], [DEFINES="$DEFINES -DHAVE_DL_ITERATE_PHDR"])
+
 case "$host_os" in
 darwin*)
     ;;
diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources
index a68a5fe..4c12e5f 100644
--- a/src/util/Makefile.sources
+++ b/src/util/Makefile.sources
@@ -2,6 +2,8 @@ MESA_UTIL_FILES :=	\
 	bitscan.c \
 	bitscan.h \
 	bitset.h \
+	build_id.c \
+	build_id.h \
 	crc32.c \
 	crc32.h \
 	debug.c \
diff --git a/src/util/build_id.c b/src/util/build_id.c
new file mode 100644
index 0000000..80cafe9
--- /dev/null
+++ b/src/util/build_id.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "build_id.h"
+
+#define ALIGN(val, align)      (((val) + (align) - 1) & ~((align) - 1))
+
+struct build_id_note {
+   ElfW(Nhdr) nhdr;
+
+   char name[4]; /* Note name for build-id is "GNU\0" */
+   uint8_t build_id[0];
+};
+
+struct callback_data {
+   const char *filename;
+   struct build_id_note *note;
+};
+
+static int
+build_id_find_nhdr_callback(struct dl_phdr_info *info, size_t size, void *data_)
+{
+   struct callback_data *data = data_;
+
+   char *ptr = strstr(info->dlpi_name, data->filename);
+   if (ptr == NULL || ptr[strlen(data->filename)] != '\0')
+      return 0;
+
+   for (unsigned i = 0; i < info->dlpi_phnum; i++) {
+      if (info->dlpi_phdr[i].p_type != PT_NOTE)
+         continue;
+
+      struct build_id_note *note = (void *)(info->dlpi_addr +
+                                            info->dlpi_phdr[i].p_vaddr);
+      ptrdiff_t len = info->dlpi_phdr[i].p_filesz;
+
+      while (len >= sizeof(struct build_id_note)) {
+         if (note->nhdr.n_type == NT_GNU_BUILD_ID &&
+            note->nhdr.n_descsz != 0 &&
+            note->nhdr.n_namesz == 4 &&
+            memcmp(note->name, "GNU", 4) == 0) {
+            data->note = note;
+            return 1;
+         }
+
+         size_t offset = sizeof(ElfW(Nhdr)) +
+                         ALIGN(note->nhdr.n_namesz, 4) +
+                         ALIGN(note->nhdr.n_descsz, 4);
+         note = (struct build_id_note *)((char *)note + offset);
+         len -= offset;
+      }
+   }
+
+   return 0;
+}
+
+const struct build_id_note *
+build_id_find_nhdr(const char *filename)
+{
+   struct callback_data data = {
+      .filename = filename,
+      .note = NULL,
+   };
+
+   if (dl_iterate_phdr(build_id_find_nhdr_callback, &data)) {
+      return data.note;
+   } else {
+      return NULL;
+   }
+}
+
+unsigned
+build_id_length(const struct build_id_note *note)
+{
+   return note->nhdr.n_descsz;
+}
+
+void
+build_id_read(const struct build_id_note *note,
+              unsigned char *build_id, size_t n)
+{
+   memcpy(build_id, note->build_id, n);
+}
+
+#endif
diff --git a/src/util/build_id.h b/src/util/build_id.h
new file mode 100644
index 0000000..20db4ac
--- /dev/null
+++ b/src/util/build_id.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+struct build_id_note;
+
+const struct build_id_note *
+build_id_find_nhdr(const char *filename);
+
+unsigned
+build_id_length(const struct build_id_note *note);
+
+void
+build_id_read(const struct build_id_note *note,
+              unsigned char *build_id, size_t n);
-- 
2.10.2



More information about the mesa-dev mailing list