[Mesa-dev] [PATCH 1/2] util: Add utility build-id code.
Matt Turner
mattst88 at gmail.com
Tue Feb 14 18:51:39 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 | 109 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/build_id.h | 56 ++++++++++++++++++++++++
4 files changed, 169 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..a2e21b7
--- /dev/null
+++ b/src/util/build_id.c
@@ -0,0 +1,109 @@
+/*
+ * 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 note {
+ ElfW(Nhdr) nhdr;
+
+ char name[4];
+ uint8_t build_id[0];
+};
+
+struct callback_data {
+ const char *name;
+ struct 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->name);
+ if (ptr == NULL || ptr[strlen(data->name)] != '\0')
+ return 0;
+
+ for (unsigned i = 0; i < info->dlpi_phnum; i++) {
+ if (info->dlpi_phdr[i].p_type != PT_NOTE)
+ continue;
+
+ struct 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 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 note *)((char *)note + offset);
+ len -= offset;
+ }
+ }
+
+ return 0;
+}
+
+const struct note *
+build_id_find_nhdr(const char *name)
+{
+ struct callback_data data = {
+ .name = name,
+ .note = NULL,
+ };
+
+ if (dl_iterate_phdr(build_id_find_nhdr_callback, &data)) {
+ return data.note;
+ } else {
+ return NULL;
+ }
+}
+
+unsigned
+build_id_length(const struct note *note)
+{
+ return note->nhdr.n_descsz;
+}
+
+void
+build_id_read(const struct note *note, unsigned char *build_id)
+{
+ memcpy(build_id, note->build_id, note->nhdr.n_descsz);
+}
+
+#endif
diff --git a/src/util/build_id.h b/src/util/build_id.h
new file mode 100644
index 0000000..0eaecf9
--- /dev/null
+++ b/src/util/build_id.h
@@ -0,0 +1,56 @@
+/*
+ * 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 note;
+
+#ifdef HAVE_DL_ITERATE_PHDR
+
+const struct note *
+build_id_find_nhdr(const char *name);
+
+unsigned
+build_id_length(const struct note *note);
+
+void
+build_id_read(const struct note *note, unsigned char *build_id);
+
+#else
+
+static inline const struct note *
+build_id_find_nhdr(const char *name)
+{
+ return NULL;
+}
+
+static inline unsigned
+build_id_length(const struct note *note)
+{
+ return 0;
+}
+
+static inline void
+build_id_read(const struct note *note, unsigned char *build_id)
+{
+}
+
+#endif
--
2.10.2
More information about the mesa-dev
mailing list