From: Matt Turner Date: Tue, 14 Feb 2017 15:29:56 +0000 (-0800) Subject: util: Add utility build-id code. X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=d4fa083e11fa71abd50e615d6f02b6da4ea34644 util: Add utility build-id code. Provides the ability to read the .note.gnu.build-id section of ELF binaries, which is inserted by the --build-id=... flag to ld. Reviewed-by: Emil Velikov Reviewed-by: Chad Versace --- diff --git a/configure.ac b/configure.ac index f001743ea21..e4a5b480b18 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*) ;; @@ -1773,6 +1775,10 @@ AC_ARG_WITH([vulkan-icddir], AC_SUBST([VULKAN_ICD_INSTALL_DIR]) if test -n "$with_vulkan_drivers"; then + if test "x$ac_cv_func_dl_iterate_phdr" = xno; then + AC_MSG_ERROR([Vulkan drivers require the dl_iterate_phdr function]) + fi + VULKAN_DRIVERS=`IFS=', '; echo $with_vulkan_drivers` for driver in $VULKAN_DRIVERS; do case "x$driver" in diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources index aecb7c29487..08ad7bec3ab 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 00000000000..2993a80cfe6 --- /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 +#include +#include + +#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 NULL; + + return data.note; +} + +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 00000000000..39bf9b016fd --- /dev/null +++ b/src/util/build_id.h @@ -0,0 +1,38 @@ +/* + * 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 + +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); + +#endif