[sysprof] symbols: provide minimal API to specify symbol directories



commit c8fa62e83917d9d4bb38a0677accf25dc54c8983
Author: Christian Hergert <chergert redhat com>
Date:   Sat Feb 25 21:35:21 2017 -0800

    symbols: provide minimal API to specify symbol directories
    
    This gives us the ability to locate symbols by directory in a much more
    maintainable manner. Library consumers can adjust their location based
    on where they know symbols are likely to be located.

 lib/Makefile.am              |    2 +
 lib/sp-elf-symbol-resolver.c |   22 +++++++-
 lib/sp-symbol-dirs.c         |  124 ++++++++++++++++++++++++++++++++++++++++++
 lib/sp-symbol-dirs.h         |   33 +++++++++++
 lib/sysprof.h                |    1 +
 lib/util/binfile.c           |   24 +++-----
 6 files changed, 188 insertions(+), 18 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 133bf23..a0b6d13 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -68,6 +68,7 @@ headers_DATA = \
        sp-profiler.h \
        sp-selection.h \
        sp-source.h \
+       sp-symbol-dirs.h \
        sp-symbol-resolver.h \
        $(NULL)
 
@@ -102,6 +103,7 @@ libsysprof_@API_VERSION@_la_SOURCES = \
        sp-profiler.c \
        sp-selection.c \
        sp-source.c \
+       sp-symbol-dirs.c \
        sp-symbol-resolver.c \
        $(NULL)
 
diff --git a/lib/sp-elf-symbol-resolver.c b/lib/sp-elf-symbol-resolver.c
index 8d78d86..9002606 100644
--- a/lib/sp-elf-symbol-resolver.c
+++ b/lib/sp-elf-symbol-resolver.c
@@ -135,7 +135,16 @@ sp_elf_symbol_resolver_get_bin_file (SpElfSymbolResolver *self,
 
   if (bin_file == NULL)
     {
-      bin_file = bin_file_new (filename);
+      const gchar *alternate = filename;
+
+      /*
+       * If we are in a new mount namespace, then rely on the sp_symbol_dirs
+       * to find us a locate to resolve the file where the CRC will match.
+       */
+      if (g_str_has_prefix (filename, "/newroot/"))
+        alternate += strlen ("/newroot");
+
+      bin_file = bin_file_new (alternate);
       g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
     }
 
@@ -268,8 +277,15 @@ sp_elf_symbol_resolver_resolve (SpSymbolResolver *resolver,
 
   g_assert (bin_file != NULL);
 
-  if (map->inode && !bin_file_check_inode (bin_file, map->inode))
-    return g_strdup_printf ("%s: inode mismatch", map->filename);
+  /*
+   * Ensure we have a valid inode mapping, unless it was in a /newroot/, for
+   * which those won't be reliable.
+   */
+  if (!g_str_has_prefix (map->filename, "/newroot/"))
+    {
+      if (map->inode && !bin_file_check_inode (bin_file, map->inode))
+        return g_strdup_printf ("%s: inode mismatch", map->filename);
+    }
 
   bin_sym = bin_file_lookup_symbol (bin_file, address);
   bin_sym_name = bin_symbol_get_name (bin_file, bin_sym);
diff --git a/lib/sp-symbol-dirs.c b/lib/sp-symbol-dirs.c
new file mode 100644
index 0000000..51190db
--- /dev/null
+++ b/lib/sp-symbol-dirs.c
@@ -0,0 +1,124 @@
+/* sp-symbol-dirs.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sp-symbol-dirs.h"
+
+static GPtrArray *sp_symbol_dirs;
+
+G_LOCK_DEFINE (sp_symbol_dirs);
+
+static GPtrArray *
+sp_get_symbol_dirs_locked (void)
+{
+  if (sp_symbol_dirs == NULL)
+    {
+      sp_symbol_dirs = g_ptr_array_new ();
+      g_ptr_array_add (sp_symbol_dirs, g_strdup ("/usr/lib/debug"));
+    }
+
+  return sp_symbol_dirs;
+}
+
+void
+sp_symbol_dirs_add (const gchar *path)
+{
+  GPtrArray *ar;
+
+  G_LOCK (sp_symbol_dirs);
+
+  ar = sp_get_symbol_dirs_locked ();
+
+  for (guint i = 0; i < ar->len; i++)
+    {
+      const gchar *ele = g_ptr_array_index (ar, i);
+
+      if (g_strcmp0 (path, ele) == 0)
+        goto skip;
+    }
+
+  g_ptr_array_add (ar, g_strdup (path));
+
+skip:
+  G_UNLOCK (sp_symbol_dirs);
+}
+
+void
+sp_symbol_dirs_remove (const gchar *path)
+{
+  GPtrArray *ar;
+
+  G_LOCK (sp_symbol_dirs);
+
+  ar = sp_get_symbol_dirs_locked ();
+
+  for (guint i = 0; i < ar->len; i++)
+    {
+      const gchar *ele = g_ptr_array_index (ar, i);
+
+      if (g_strcmp0 (path, ele) == 0)
+        {
+          g_ptr_array_remove_index (ar, i);
+          break;
+        }
+    }
+
+  G_UNLOCK (sp_symbol_dirs);
+}
+
+/**
+ * sp_symbol_dirs_get_paths:
+ * @dir: the directory containing the library
+ * @name: the name of the file in @dir
+ *
+ * This function will build an array of files to look at to resolve the
+ * debug symbols for the file at path "dir/name".
+ *
+ * Returns: (transfer full): A #GStrv of possible paths.
+ */
+gchar **
+sp_symbol_dirs_get_paths (const gchar *dir,
+                          const gchar *name)
+{
+  GPtrArray *ret = g_ptr_array_new ();
+  GPtrArray *ar;
+
+  g_ptr_array_add (ret, g_build_filename (dir, name, NULL));
+
+  G_LOCK (sp_symbol_dirs);
+
+  ar = sp_get_symbol_dirs_locked ();
+
+  for (guint i = 0; i < ar->len; i++)
+    {
+      const gchar *ele = g_ptr_array_index (ar, i);
+
+      g_ptr_array_add (ret, g_build_filename (ele, name, NULL));
+      g_ptr_array_add (ret, g_build_filename (ele, dir, name, NULL));
+    }
+
+  g_ptr_array_add (ret, g_build_filename (dir, ".debug", name, NULL));
+  g_ptr_array_add (ret, g_build_filename (DEBUGDIR, dir, name, NULL));
+
+  G_UNLOCK (sp_symbol_dirs);
+
+  g_ptr_array_add (ret, NULL);
+
+  return (gchar **)g_ptr_array_free (ret, FALSE);
+}
diff --git a/lib/sp-symbol-dirs.h b/lib/sp-symbol-dirs.h
new file mode 100644
index 0000000..8149ad7
--- /dev/null
+++ b/lib/sp-symbol-dirs.h
@@ -0,0 +1,33 @@
+/* sp-symbol-dirs.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SP_SYMBOL_DIRS_H
+#define SP_SYMBOL_DIRS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+void    sp_symbol_dirs_add       (const gchar *dir);
+void    sp_symbol_dirs_remove    (const gchar *dir);
+gchar **sp_symbol_dirs_get_paths (const gchar *dir,
+                                  const gchar *name);
+
+G_END_DECLS
+
+#endif /* SP_SYMBOL_DIRS_H */
diff --git a/lib/sysprof.h b/lib/sysprof.h
index 22aed20..4dc1c1a 100644
--- a/lib/sysprof.h
+++ b/lib/sysprof.h
@@ -46,6 +46,7 @@ G_BEGIN_DECLS
 # include "sp-profiler.h"
 # include "sp-selection.h"
 # include "sp-source.h"
+# include "sp-symbol-dirs.h"
 # include "sp-symbol-resolver.h"
 # include "sysprof-version.h"
 #undef SYSPROF_INSIDE
diff --git a/lib/util/binfile.c b/lib/util/binfile.c
index a30c088..1b02978 100644
--- a/lib/util/binfile.c
+++ b/lib/util/binfile.c
@@ -38,6 +38,8 @@
 #include "binfile.h"
 #include "elfparser.h"
 
+#include "../sp-symbol-dirs.h"
+
 struct bin_file_t
 {
     int         ref_count;
@@ -88,8 +90,6 @@ already_warned (const char *name)
     return FALSE;
 }
 
-static const char *const debug_file_directory = DEBUGDIR;
-
 static ElfParser *
 get_build_id_file (ElfParser *elf)
 {
@@ -114,8 +114,7 @@ get_build_id_file (ElfParser *elf)
         "/usr", "lib", "debug", ".build-id", init, rest, NULL);
     tries = g_list_append (tries, tmp);
 
-    tmp = g_build_filename (
-        debug_file_directory, ".build-id", init, rest, NULL);
+    tmp = g_build_filename (DEBUGDIR, ".build-id", init, rest, NULL);
     tries = g_list_append (tries, tmp);
 
     for (list = tries; list != NULL; list = list->next)
@@ -151,13 +150,13 @@ get_debuglink_file (ElfParser   *elf,
                     const char  *filename,
                     char       **new_name)
 {
-#define N_TRIES 4
     const char *basename;
     char *dir;
     guint32 crc32;
-    GList *tries = NULL, *list;
+    gchar **tries;
     ElfParser *result = NULL;
     const char *build_id;
+    guint i;
 
     if (!elf)
         return NULL;
@@ -175,14 +174,11 @@ get_debuglink_file (ElfParser   *elf,
 
     dir = g_path_get_dirname (filename);
 
-    tries = g_list_append (tries, g_build_filename (dir, basename, NULL));
-    tries = g_list_append (tries, g_build_filename (dir, ".debug", basename, NULL));
-    tries = g_list_append (tries, g_build_filename ("/usr", "lib", "debug", dir, basename, NULL));
-    tries = g_list_append (tries, g_build_filename (debug_file_directory, dir, basename, NULL));
+    tries = sp_symbol_dirs_get_paths (dir, basename);
 
-    for (list = tries; list != NULL; list = list->next)
+    for (i = 0; tries[i]; i++)
     {
-        const char *name = list->data;
+        const char *name = tries[i];
         ElfParser *parser = elf_parser_new (name, NULL);
         guint32 file_crc;
         const char *file_build_id;
@@ -220,9 +216,7 @@ get_debuglink_file (ElfParser   *elf,
     }
 
     g_free (dir);
-
-    g_list_foreach (tries, (GFunc)g_free, NULL);
-    g_list_free (tries);
+    g_strfreev (tries);
 
     return result;
 }


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