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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev