[Mesa-dev] [PATCH] util: Query build-id by symbol address, not library name

Chad Versace chad at kiwitree.net
Wed Sep 13 00:05:59 UTC 2017


This patch renames build_id_find_nhdr() to
build_id_find_nhdr_for_addr(), and changes it to never examine the
library name.

Tested on Fedora by confirming that build_id_get_data() returns the same
build-id as the file(1) tool. For BSD, I confirmed that the API used
(dladdr() and struct Dl_info) is documented in FreeBSD's manpages.

This solves several problems, some more realistic than others:

    - We can now the query the build-id without knowing the installed library's
      filename.

      This matters because Android requires specific filenames for HAL
      modules, such as "/vendor/lib/hw/vulkan.${board}.so". The HAL
      filenames do not follow the Unix convention of "libfoo.so".  In
      other words, the same query code will now work on Linux and Android.

    - Querying the build-id now works correctly when the process
      contains multiple shared objects with the same basename.
      (Admittedly, this is a highly unlikely scenario).

    - Querying the build-id now works correctly when the library is
      statically linked into the executable. (This even more unlikely
      than the previous scenario).

Cc: Matt Turner <mattst88 at gmail.com>
Cc: Jason Ekstrand <jason at jlekstrand.net>
Cc: Jonathan Gray <jsg at jsg.id.au>
---
 src/intel/vulkan/anv_device.c |  3 ++-
 src/util/build_id.c           | 25 ++++++++++++++-----------
 src/util/build_id.h           |  2 +-
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index be2455166e3..8e2ed9eac45 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -208,7 +208,8 @@ anv_physical_device_init_heaps(struct anv_physical_device *device, int fd)
 static VkResult
 anv_physical_device_init_uuids(struct anv_physical_device *device)
 {
-   const struct build_id_note *note = build_id_find_nhdr("libvulkan_intel.so");
+   const struct build_id_note *note =
+      build_id_find_nhdr_for_addr(anv_physical_device_init_uuids);
    if (!note) {
       return vk_errorf(device->instance, device,
                        VK_ERROR_INITIALIZATION_FAILED,
diff --git a/src/util/build_id.c b/src/util/build_id.c
index 898a15f2b31..6280b4a54e3 100644
--- a/src/util/build_id.c
+++ b/src/util/build_id.c
@@ -46,7 +46,9 @@ struct build_id_note {
 };
 
 struct callback_data {
-   const char *filename;
+   /* Base address of shared object, taken from Dl_info::dli_fbase */
+   const void *dli_fbase;
+
    struct build_id_note *note;
 };
 
@@ -55,14 +57,7 @@ build_id_find_nhdr_callback(struct dl_phdr_info *info, size_t size, void *data_)
 {
    struct callback_data *data = data_;
 
-   /* The first object visited by callback is the main program.
-    * Android's libc returns a NULL pointer for the first executable.
-    */
-   if (info->dlpi_name == NULL)
-      return 0;
-
-   char *ptr = strstr(info->dlpi_name, data->filename);
-   if (ptr == NULL || ptr[strlen(data->filename)] != '\0')
+   if ((void *)info->dlpi_addr != data->dli_fbase)
       return 0;
 
    for (unsigned i = 0; i < info->dlpi_phnum; i++) {
@@ -94,10 +89,18 @@ build_id_find_nhdr_callback(struct dl_phdr_info *info, size_t size, void *data_)
 }
 
 const struct build_id_note *
-build_id_find_nhdr(const char *filename)
+build_id_find_nhdr_for_addr(const void *addr)
 {
+   Dl_info info;
+
+   if (!dladdr(addr, &info))
+      return NULL;
+
+   if (!info.dli_fbase)
+      return NULL;
+
    struct callback_data data = {
-      .filename = filename,
+      .dli_fbase = info.dli_fbase,
       .note = NULL,
    };
 
diff --git a/src/util/build_id.h b/src/util/build_id.h
index 18641c44af2..86d611d8db7 100644
--- a/src/util/build_id.h
+++ b/src/util/build_id.h
@@ -29,7 +29,7 @@
 struct build_id_note;
 
 const struct build_id_note *
-build_id_find_nhdr(const char *filename);
+build_id_find_nhdr_for_addr(const void *addr);
 
 unsigned
 build_id_length(const struct build_id_note *note);
-- 
2.13.5



More information about the mesa-dev mailing list