[sysprof] libsysprof: attach symbol directories to ELF resolver



commit 3b17e65a39a0d6613affc58bb3b4ced60830b7f1
Author: Christian Hergert <chergert redhat com>
Date:   Fri Aug 2 19:41:26 2019 -0700

    libsysprof: attach symbol directories to ELF resolver
    
    The goal here is to drop the sysprof-symbol-dirs.[ch] altogether in
    favor of modifying the resolver directories on the particular resolver
    directly.

 src/libsysprof/binfile.c                     | 31 +++++-----
 src/libsysprof/binfile.h                     | 29 +++++-----
 src/libsysprof/sysprof-elf-symbol-resolver.c | 84 ++++++++++++++++++++++------
 src/libsysprof/sysprof-elf-symbol-resolver.h | 21 ++++---
 4 files changed, 109 insertions(+), 56 deletions(-)
---
diff --git a/src/libsysprof/binfile.c b/src/libsysprof/binfile.c
index 0f90f9d..cd784b7 100644
--- a/src/libsysprof/binfile.c
+++ b/src/libsysprof/binfile.c
@@ -145,14 +145,14 @@ get_build_id_file (ElfParser *elf)
 }
 
 static ElfParser *
-get_debuglink_file (ElfParser   *elf,
-                    const char  *filename,
-                    char       **new_name)
+get_debuglink_file (ElfParser            *elf,
+                    const char           *filename,
+                    char                **new_name,
+                    const gchar * const  *debug_dirs)
 {
     const char *basename;
     char *dir;
     guint32 crc32;
-    gchar **tries;
     ElfParser *result = NULL;
     const char *build_id;
     guint i;
@@ -173,11 +173,9 @@ get_debuglink_file (ElfParser   *elf,
 
     dir = g_path_get_dirname (filename);
 
-    tries = sysprof_symbol_dirs_get_paths (dir, basename);
-
-    for (i = 0; tries[i]; i++)
+    for (i = 0; debug_dirs[i]; i++)
     {
-        const char *name = tries[i];
+        const char *name = debug_dirs[i];
         ElfParser *parser = elf_parser_new (name, NULL);
         guint32 file_crc;
         const char *file_build_id;
@@ -215,15 +213,15 @@ get_debuglink_file (ElfParser   *elf,
     }
 
     g_free (dir);
-    g_strfreev (tries);
 
     return result;
 }
 
 static GList *
-get_debug_binaries (GList      *files,
-                    ElfParser  *elf,
-                    const char *filename)
+get_debug_binaries (GList               *files,
+                    ElfParser           *elf,
+                    const char          *filename,
+                    const gchar * const *debug_dirs)
 {
     ElfParser *build_id_file;
     GHashTable *seen_names;
@@ -249,7 +247,7 @@ get_debug_binaries (GList      *files,
 
         g_hash_table_insert (seen_names, (char *)filename, (char *)filename);
 
-        elf = get_debuglink_file (elf, filename, &debug_name);
+        elf = get_debuglink_file (elf, filename, &debug_name, debug_dirs);
 
         if (elf)
         {
@@ -354,7 +352,8 @@ get_vdso_bytes (size_t *length)
 }
 
 bin_file_t *
-bin_file_new (const char *filename)
+bin_file_new (const char          *filename,
+              const gchar * const *debug_dirs)
 {
     const gchar *real_filename = filename;
     ElfParser *elf = NULL;
@@ -393,7 +392,7 @@ bin_file_new (const char *filename)
          */
         bf->text_offset = elf_parser_get_text_offset (elf);
 
-        bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename);
+        bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename, debug_dirs);
         bf->elf_files = g_list_append (bf->elf_files, elf);
 
         bf->inode = read_inode (filename);
@@ -417,7 +416,7 @@ bin_file_free (bin_file_t *bin_file)
 }
 
 const bin_symbol_t *
-bin_file_lookup_symbol (bin_file_t    *bin_file,
+bin_file_lookup_symbol (bin_file_t *bin_file,
                         gulong      address)
 {
     GList *list;
diff --git a/src/libsysprof/binfile.h b/src/libsysprof/binfile.h
index f02868c..2feb118 100644
--- a/src/libsysprof/binfile.h
+++ b/src/libsysprof/binfile.h
@@ -32,19 +32,20 @@ typedef struct bin_symbol_t bin_symbol_t;
 
 /* Binary File */
 
-bin_file_t         *bin_file_new                 (const char         *filename);
-void                bin_file_free                (bin_file_t         *bin_file);
-const bin_symbol_t *bin_file_lookup_symbol       (bin_file_t         *bin_file,
-                                                  gulong              address);
-gboolean            bin_file_check_inode         (bin_file_t         *bin_file,
-                                                  ino_t               inode);
-const char         *bin_symbol_get_name          (bin_file_t         *bin_file,
-                                                  const bin_symbol_t *symbol);
-gulong              bin_symbol_get_address       (bin_file_t         *bin_file,
-                                                  const bin_symbol_t *symbol);
-void                bin_symbol_get_address_range (bin_file_t         *bin_file,
-                                                  const bin_symbol_t *symbol,
-                                                  gulong             *begin,
-                                                  gulong             *end);
+bin_file_t         *bin_file_new                 (const char          *filename,
+                                                  const gchar * const *debug_dirs);
+void                bin_file_free                (bin_file_t          *bin_file);
+const bin_symbol_t *bin_file_lookup_symbol       (bin_file_t          *bin_file,
+                                                  gulong               address);
+gboolean            bin_file_check_inode         (bin_file_t          *bin_file,
+                                                  ino_t                inode);
+const char         *bin_symbol_get_name          (bin_file_t          *bin_file,
+                                                  const bin_symbol_t  *symbol);
+gulong              bin_symbol_get_address       (bin_file_t          *bin_file,
+                                                  const bin_symbol_t  *symbol);
+void                bin_symbol_get_address_range (bin_file_t          *bin_file,
+                                                  const bin_symbol_t  *symbol,
+                                                  gulong              *begin,
+                                                  gulong              *end);
 
 #endif
diff --git a/src/libsysprof/sysprof-elf-symbol-resolver.c b/src/libsysprof/sysprof-elf-symbol-resolver.c
index d7dbff0..10b9716 100644
--- a/src/libsysprof/sysprof-elf-symbol-resolver.c
+++ b/src/libsysprof/sysprof-elf-symbol-resolver.c
@@ -25,12 +25,14 @@
 #include "binfile.h"
 #include "elfparser.h"
 #include "sysprof-elf-symbol-resolver.h"
+#include "sysprof-flatpak.h"
 #include "sysprof-map-lookaside.h"
 
 struct _SysprofElfSymbolResolver
 {
   GObject     parent_instance;
 
+  GArray     *debug_dirs;
   GHashTable *lookasides;
   GHashTable *bin_files;
   GHashTable *tag_cache;
@@ -45,6 +47,21 @@ G_DEFINE_TYPE_EXTENDED (SysprofElfSymbolResolver,
                         G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SYMBOL_RESOLVER,
                                                symbol_resolver_iface_init))
 
+static gboolean
+is_flatpak (void)
+{
+  static gsize did_init = FALSE;
+  static gboolean ret;
+
+  if (g_once_init_enter (&did_init))
+    {
+      ret = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+      g_once_init_leave (&did_init, TRUE);
+    }
+
+  return ret;
+}
+
 static void
 sysprof_elf_symbol_resolver_finalize (GObject *object)
 {
@@ -53,6 +70,7 @@ sysprof_elf_symbol_resolver_finalize (GObject *object)
   g_clear_pointer (&self->bin_files, g_hash_table_unref);
   g_clear_pointer (&self->lookasides, g_hash_table_unref);
   g_clear_pointer (&self->tag_cache, g_hash_table_unref);
+  g_clear_pointer (&self->debug_dirs, g_array_unref);
 
   G_OBJECT_CLASS (sysprof_elf_symbol_resolver_parent_class)->finalize (object);
 }
@@ -65,9 +83,29 @@ sysprof_elf_symbol_resolver_class_init (SysprofElfSymbolResolverClass *klass)
   object_class->finalize = sysprof_elf_symbol_resolver_finalize;
 }
 
+static void
+free_element_string (gpointer data)
+{
+  g_free (*(gchar **)data);
+}
+
 static void
 sysprof_elf_symbol_resolver_init (SysprofElfSymbolResolver *self)
 {
+  self->debug_dirs = g_array_new (TRUE, FALSE, sizeof (gchar *));
+  g_array_set_clear_func (self->debug_dirs, free_element_string);
+  sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib/debug");
+  sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib32/debug");
+  sysprof_elf_symbol_resolver_add_debug_dir (self, "/usr/lib64/debug");
+
+  if (is_flatpak ())
+    {
+      g_auto(GStrv) debug_dirs = sysprof_flatpak_debug_dirs ();
+
+      for (guint i = 0; debug_dirs[i]; i++)
+        sysprof_elf_symbol_resolver_add_debug_dir (self, debug_dirs[i]);
+    }
+
   self->lookasides = g_hash_table_new_full (NULL,
                                             NULL,
                                             NULL,
@@ -126,21 +164,6 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
     }
 }
 
-static gboolean
-is_flatpak (void)
-{
-  static gsize did_init = FALSE;
-  static gboolean ret;
-
-  if (g_once_init_enter (&did_init))
-    {
-      ret = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
-      g_once_init_leave (&did_init, TRUE);
-    }
-
-  return ret;
-}
-
 static bin_file_t *
 sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
                                           const gchar              *filename)
@@ -154,6 +177,9 @@ sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
   if (bin_file == NULL)
     {
       const gchar *alternate = filename;
+      const gchar * const *dirs;
+
+      dirs = (const gchar * const *)(gpointer)self->debug_dirs->data;
 
       /*
        * If we are in a new mount namespace, then rely on the sysprof_symbol_dirs
@@ -169,11 +195,11 @@ sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
       if (is_flatpak () && g_str_has_prefix (filename, "/usr/"))
         {
           g_autofree gchar *path = g_build_filename ("/var/run/host", alternate, NULL);
-          bin_file = bin_file_new (path);
+          bin_file = bin_file_new (path, dirs);
         }
       else
         {
-          bin_file = bin_file_new (alternate);
+          bin_file = bin_file_new (alternate, dirs);
         }
 
       g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
@@ -390,3 +416,27 @@ sysprof_elf_symbol_resolver_new (void)
 {
   return g_object_new (SYSPROF_TYPE_ELF_SYMBOL_RESOLVER, NULL);
 }
+
+void
+sysprof_elf_symbol_resolver_add_debug_dir (SysprofElfSymbolResolver *self,
+                                           const gchar              *debug_dir)
+{
+  gchar *val;
+
+  g_return_if_fail (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self));
+  g_return_if_fail (debug_dir != NULL);
+
+  if (!g_file_test (debug_dir, G_FILE_TEST_EXISTS))
+    return;
+
+  for (guint i = 0; i < self->debug_dirs->len; i++)
+    {
+      gchar * const *str = &g_array_index (self->debug_dirs, gchar *, i);
+
+      if (g_strcmp0 (*str, debug_dir) == 0)
+        return;
+    }
+
+  val = g_strdup (debug_dir);
+  g_array_append_val (self->debug_dirs, val);
+}
diff --git a/src/libsysprof/sysprof-elf-symbol-resolver.h b/src/libsysprof/sysprof-elf-symbol-resolver.h
index d5b3b70..6b8e5fd 100644
--- a/src/libsysprof/sysprof-elf-symbol-resolver.h
+++ b/src/libsysprof/sysprof-elf-symbol-resolver.h
@@ -37,14 +37,17 @@ G_DECLARE_FINAL_TYPE (SysprofElfSymbolResolver, sysprof_elf_symbol_resolver, SYS
 SYSPROF_AVAILABLE_IN_ALL
 SysprofSymbolResolver *sysprof_elf_symbol_resolver_new          (void);
 SYSPROF_AVAILABLE_IN_ALL
-gboolean               sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver  *self,
-                                                                 guint64                    time,
-                                                                 GPid                       pid,
-                                                                 SysprofAddressContext      context,
-                                                                 SysprofCaptureAddress      address,
-                                                                 SysprofCaptureAddress     *begin,
-                                                                 SysprofCaptureAddress     *end,
-                                                                 gchar                    **name,
-                                                                 GQuark                    *tag);
+void                   sysprof_elf_symbol_resolver_add_debug_dir (SysprofElfSymbolResolver  *self,
+                                                                  const gchar               *debug_dir);
+SYSPROF_AVAILABLE_IN_ALL
+gboolean               sysprof_elf_symbol_resolver_resolve_full  (SysprofElfSymbolResolver  *self,
+                                                                  guint64                    time,
+                                                                  GPid                       pid,
+                                                                  SysprofAddressContext      context,
+                                                                  SysprofCaptureAddress      address,
+                                                                  SysprofCaptureAddress     *begin,
+                                                                  SysprofCaptureAddress     *end,
+                                                                  gchar                    **name,
+                                                                  GQuark                    *tag);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]