[sysprof/wip/chergert/path-resolver] more work on resolver kinds



commit 728c5081d1cdb135d1c81f25a4e0211a3ae4db59
Author: Christian Hergert <chergert redhat com>
Date:   Fri Sep 17 17:11:06 2021 -0700

    more work on resolver kinds

 src/libsysprof/binfile.c                         |  41 ++---
 src/libsysprof/elfparser.c                       |  58 +++++--
 src/libsysprof/sysprof-elf-symbol-resolver.c     | 195 ++++++++++-------------
 src/libsysprof/sysprof-proc-source.c             |  27 +++-
 src/libsysprof/sysprof-symbol-resolver-private.h |   5 +-
 src/libsysprof/sysprof-symbol-resolver.c         |   9 ++
 src/tests/read-build-id.c                        |   7 +-
 src/tests/test-utils.c                           |  49 ++++++
 8 files changed, 246 insertions(+), 145 deletions(-)
---
diff --git a/src/libsysprof/binfile.c b/src/libsysprof/binfile.c
index 145322e..2cb7418 100644
--- a/src/libsysprof/binfile.c
+++ b/src/libsysprof/binfile.c
@@ -89,7 +89,8 @@ already_warned (const char *name)
 }
 
 static ElfParser *
-get_build_id_file (ElfParser *elf)
+get_build_id_file (ElfParser          *elf,
+                   const char * const *debug_dirs)
 {
     const char *build_id;
     GList *tries = NULL, *list;
@@ -108,12 +109,14 @@ get_build_id_file (ElfParser *elf)
     init = g_strndup (build_id, 2);
     rest = g_strdup_printf ("%s%s", build_id + 2, ".debug");
 
-    tmp = g_build_filename (
-        "/usr", "lib", "debug", ".build-id", init, rest, NULL);
-    tries = g_list_append (tries, tmp);
-
-    tmp = g_build_filename (DEBUGDIR, ".build-id", init, rest, NULL);
-    tries = g_list_append (tries, tmp);
+    if (debug_dirs)
+      {
+        for (guint i = 0; debug_dirs[i]; i++)
+          {
+            tmp = g_build_filename (debug_dirs[i], ".build-id", init, rest, NULL);
+            tries = g_list_append (tries, tmp);
+          }
+      }
 
     for (list = tries; list != NULL; list = list->next)
     {
@@ -150,11 +153,10 @@ get_debuglink_file (ElfParser            *elf,
                     const gchar * const  *debug_dirs)
 {
     const char *basename;
-    char *dir;
     guint32 crc32;
     ElfParser *result = NULL;
     const char *build_id;
-    guint i;
+    char *dir;
 
     if (!elf)
         return NULL;
@@ -172,9 +174,9 @@ get_debuglink_file (ElfParser            *elf,
 
     dir = g_path_get_dirname (filename);
 
-    for (i = 0; debug_dirs[i]; i++)
+    for (guint i = 0; debug_dirs[i]; i++)
     {
-        const char *name = debug_dirs[i];
+        char *name = g_build_filename (debug_dirs[i], basename, NULL);
         ElfParser *parser = elf_parser_new (name, NULL);
         guint32 file_crc;
         const char *file_build_id;
@@ -194,7 +196,7 @@ get_debuglink_file (ElfParser            *elf,
             if (file_crc == crc32)
             {
                 result = parser;
-                *new_name = g_strdup (name);
+                *new_name = g_steal_pointer (&name);
                 break;
             }
             else
@@ -209,6 +211,8 @@ get_debuglink_file (ElfParser            *elf,
         skip:
             elf_parser_free (parser);
         }
+
+        g_free (name);
     }
 
     g_free (dir);
@@ -226,7 +230,7 @@ get_debug_binaries (GList               *files,
     GHashTable *seen_names;
     GList *free_us = NULL;
 
-    build_id_file = get_build_id_file (elf);
+    build_id_file = get_build_id_file (elf, debug_dirs);
 
     if (build_id_file)
         return g_list_prepend (files, build_id_file);
@@ -354,9 +358,6 @@ bin_file_new (const char          *filename,
     ElfParser *elf = NULL;
     bin_file_t *bf;
 
-    if (g_str_has_prefix (filename, "/var/run/host/"))
-      real_filename = filename + strlen ("/var/run/host");
-
     bf = g_new0 (bin_file_t, 1);
 
     bf->inode_check = FALSE;
@@ -475,9 +476,9 @@ bin_file_check_inode (bin_file_t *bin_file,
 }
 
 static const ElfSym *
-get_elf_sym (bin_file_t *file,
-             const bin_symbol_t *symbol,
-             ElfParser **elf_ret)
+get_elf_sym (bin_file_t          *file,
+             const bin_symbol_t  *symbol,
+             ElfParser          **elf_ret)
 {
     GList *list;
 
@@ -500,7 +501,7 @@ get_elf_sym (bin_file_t *file,
 }
 
 const char *
-bin_symbol_get_name (bin_file_t *file,
+bin_symbol_get_name (bin_file_t         *file,
                      const bin_symbol_t *symbol)
 {
     if (file->undefined_name == (char *)symbol)
diff --git a/src/libsysprof/elfparser.c b/src/libsysprof/elfparser.c
index 376a1f0..ec427ae 100644
--- a/src/libsysprof/elfparser.c
+++ b/src/libsysprof/elfparser.c
@@ -124,6 +124,28 @@ MAKE_SYMBOL_ACCESSOR(st_value);
 MAKE_SYMBOL_ACCESSOR(st_size);
 MAKE_SYMBOL_ACCESSOR(st_shndx);
 
+static gboolean
+in_container (void)
+{
+    static gboolean _in_container;
+    static gboolean initialized;
+
+    if (!initialized)
+    {
+        /* Flatpak has /.flatpak-info
+         * Podman has /run/.containerenv
+         *
+         * Both have access to host files via /var/run/host.
+         */
+        _in_container = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS) ||
+                        g_file_test ("/run/.containerenv", G_FILE_TEST_EXISTS);
+
+        initialized = TRUE;
+    }
+
+    return _in_container;
+}
+
 static void
 section_free (Section *section)
 {
@@ -252,17 +274,31 @@ elf_parser_new_from_data (const guchar *data,
     return parser;
 }
 
+static GMappedFile *
+open_mapped_file (const char  *filename,
+                  GError     **error)
+{
+    GMappedFile *file;
+    char *alternate = NULL;
+
+    if (in_container () && !g_str_has_prefix (filename, g_get_home_dir ()))
+        filename = alternate = g_build_filename ("/var/run/host", filename, NULL);
+    file = g_mapped_file_new (filename, FALSE, error);
+    g_free (alternate);
+
+    return file;
+}
+
 ElfParser *
-elf_parser_new (const char *filename,
-                GError **err)
+elf_parser_new (const char  *filename,
+                GError     **error)
 {
+    GMappedFile *file;
     const guchar *data;
     gsize length;
     ElfParser *parser;
 
-    GMappedFile *file = g_mapped_file_new (filename, FALSE, NULL);
-
-    if (!file)
+    if (!(file = open_mapped_file (filename, error)))
         return NULL;
 
 #if 0
@@ -284,6 +320,11 @@ elf_parser_new (const char *filename,
 
     if (!parser)
     {
+        g_set_error (error,
+                     G_FILE_ERROR,
+                     G_FILE_ERROR_FAILED,
+                     "Failed to load ELF from file %s",
+                     filename);
         g_mapped_file_unref (file);
         return NULL;
     }
@@ -730,7 +771,8 @@ elf_parser_get_build_id (ElfParser *parser)
 }
 
 const char *
-elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
+elf_parser_get_debug_link (ElfParser *parser,
+                           guint32   *crc32)
 {
     guint64 offset;
     const Section *debug_link = find_section (parser, ".gnu_debuglink",
@@ -820,7 +862,3 @@ elf_parser_get_sym_address_range (ElfParser    *parser,
     *begin = sym->address - parser->text_section->load_address;
     *end = *begin + st_size (parser, sym->table, sym->offset);
 }
-
-/*
- * Utility functions
- */
diff --git a/src/libsysprof/sysprof-elf-symbol-resolver.c b/src/libsysprof/sysprof-elf-symbol-resolver.c
index c555e05..b7fe059 100644
--- a/src/libsysprof/sysprof-elf-symbol-resolver.c
+++ b/src/libsysprof/sysprof-elf-symbol-resolver.c
@@ -32,6 +32,13 @@
 #include "sysprof-podman.h"
 #include "sysprof-symbol-resolver-private.h"
 
+typedef enum
+{
+  PROCESS_KIND_STANDARD,
+  PROCESS_KIND_FLATPAK,
+  PROCESS_KIND_PODMAN,
+} ProcessKind;
+
 typedef struct
 {
   char *on_host;
@@ -41,11 +48,14 @@ typedef struct
 
 typedef struct
 {
-  SysprofMapLookaside *lookaside;
-  SysprofPathResolver *resolver;
-  GByteArray          *mountinfo_data;
-  GArray              *overlays;
-  int                  pid;
+  SysprofMapLookaside  *lookaside;
+  SysprofPathResolver  *resolver;
+  GByteArray           *mountinfo_data;
+  GArray               *overlays;
+  char                **debug_dirs;
+  char                 *info;
+  int                   pid;
+  guint                 kind : 2;
 } ProcessInfo;
 
 struct _SysprofElfSymbolResolver
@@ -54,10 +64,8 @@ struct _SysprofElfSymbolResolver
 
   GHashTable   *processes;
   GStringChunk *chunks;
-
-  GArray     *debug_dirs;
-  GHashTable *bin_files;
-  GHashTable *tag_cache;
+  GHashTable   *bin_files;
+  GHashTable   *tag_cache;
 };
 
 static void symbol_resolver_iface_init (SysprofSymbolResolverInterface *iface);
@@ -76,26 +84,27 @@ process_info_free (gpointer data)
 
   if (pi != NULL)
     {
-      g_clear_pointer (&pi->mountinfo_data, g_byte_array_unref);
-      g_clear_pointer (&pi->resolver, _sysprof_path_resolver_free);
       g_clear_pointer (&pi->lookaside, sysprof_map_lookaside_free);
+      g_clear_pointer (&pi->resolver, _sysprof_path_resolver_free);
+      g_clear_pointer (&pi->mountinfo_data, g_byte_array_unref);
+      g_clear_pointer (&pi->overlays, g_array_unref);
+      g_clear_pointer (&pi->debug_dirs, g_strfreev);
+      g_clear_pointer (&pi->info, g_free);
       g_slice_free (ProcessInfo, pi);
     }
 }
 
-static gboolean
-is_flatpak (void)
+static const char * const *
+process_info_get_debug_dirs (const ProcessInfo *pi)
 {
-  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 const char *standard[] = { "/usr/lib/debug", NULL };
+
+  if (pi->kind == PROCESS_KIND_FLATPAK)
+    return standard; /* TODO */
+  else if (pi->kind == PROCESS_KIND_PODMAN)
+    return standard; /* TODO */
+  else
+    return standard;
 }
 
 static void
@@ -105,8 +114,8 @@ sysprof_elf_symbol_resolver_finalize (GObject *object)
 
   g_clear_pointer (&self->bin_files, g_hash_table_unref);
   g_clear_pointer (&self->tag_cache, g_hash_table_unref);
-  g_clear_pointer (&self->debug_dirs, g_array_unref);
   g_clear_pointer (&self->processes, g_hash_table_unref);
+  g_clear_pointer (&self->chunks, g_string_chunk_free);
 
   G_OBJECT_CLASS (sysprof_elf_symbol_resolver_parent_class)->finalize (object);
 }
@@ -119,44 +128,15 @@ 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)
 {
-  g_auto(GStrv) podman_dirs = NULL;
-
+  self->chunks = g_string_chunk_new (4096);
   self->processes = g_hash_table_new_full (NULL, NULL, NULL, process_info_free);
-
-  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");
-
-  /* The user may have podman/toolbox containers */
-  podman_dirs = sysprof_podman_debug_dirs ();
-  for (guint i = 0; podman_dirs[i]; i++)
-    sysprof_elf_symbol_resolver_add_debug_dir (self, podman_dirs[i]);
-
-  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->bin_files = g_hash_table_new_full (g_str_hash,
                                            g_str_equal,
                                            g_free,
                                            (GDestroyNotify)bin_file_free);
-
   self->tag_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
@@ -188,6 +168,7 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
   g_autoptr(GByteArray) mounts = NULL;
   g_autofree char *mounts_data = NULL;
   GHashTableIter iter;
+  ProcessInfo *pi;
   gpointer k, v;
 
   g_assert (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self));
@@ -206,17 +187,29 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
       if (type == SYSPROF_CAPTURE_FRAME_FILE_CHUNK)
         {
           const SysprofCaptureFileChunk *ev;
-          ProcessInfo *pi;
           int pid;
 
           if (!(ev = sysprof_capture_reader_read_file (reader)))
             break;
 
-          if (g_str_has_prefix (ev->path, "/proc/") &&
+          pi = sysprof_elf_symbol_resolver_get_process (self, pid);
+
+          if (strcmp (ev->path, "/.flatpak-info") == 0)
+            {
+              pi->kind = PROCESS_KIND_FLATPAK;
+              g_free (pi->info);
+              pi->info = g_strndup ((char *)ev->data, ev->len);
+            }
+          else if (strcmp (ev->path, "/run/.containerenv") == 0)
+            {
+              pi->kind = PROCESS_KIND_PODMAN;
+              g_free (pi->info);
+              pi->info = g_strndup ((char *)ev->data, ev->len);
+            }
+          else if (g_str_has_prefix (ev->path, "/proc/") &&
               g_str_has_suffix (ev->path, "/mountinfo") &&
               sscanf (ev->path, "/proc/%u/mountinfo", &pid) == 1)
             {
-              pi = sysprof_elf_symbol_resolver_get_process (self, pid);
               if (pi->mountinfo_data == NULL)
                 pi->mountinfo_data = g_byte_array_new ();
               if (ev->len)
@@ -234,7 +227,6 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
         {
           const SysprofCaptureOverlay *ev;
           ProcessOverlay ov;
-          ProcessInfo *pi;
 
           if (!(ev = sysprof_capture_reader_read_overlay (reader)))
             break;
@@ -274,7 +266,7 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
   g_hash_table_iter_init (&iter, self->processes);
   while (g_hash_table_iter_next (&iter, &k, &v))
     {
-      ProcessInfo *pi = v;
+      pi = v;
 
       if (pi->mountinfo_data == NULL)
         continue;
@@ -292,6 +284,24 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
               _sysprof_path_resolver_add_overlay (pi->resolver, ov->in_process, ov->on_host, ov->layer);
             }
         }
+
+      if (pi->kind == PROCESS_KIND_FLATPAK)
+        {
+          if (pi->info != NULL)
+            {
+              g_autoptr(GKeyFile) keyfile = g_key_file_new ();
+
+              if (g_key_file_load_from_data (keyfile, pi->info, (gsize)-1, 0, NULL))
+                {
+                }
+            }
+        }
+      else if (pi->kind == PROCESS_KIND_PODMAN)
+        {
+          pi->debug_dirs = g_new0 (gchar *, 2);
+          pi->debug_dirs[0] = _sysprof_path_resolver_resolve (pi->resolver, "/usr/lib/debug");
+          pi->debug_dirs[1] = 0;
+        }
     }
 
   /* Walk through the file again and extract maps so long as
@@ -305,7 +315,6 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
           const SysprofCaptureMap *ev = sysprof_capture_reader_read_map (reader);
           const char *filename = ev->filename;
           g_autofree char *resolved = NULL;
-          ProcessInfo *pi;
           SysprofMap map;
 
           pi = sysprof_elf_symbol_resolver_get_process (self, ev->frame.pid);
@@ -339,44 +348,25 @@ sysprof_elf_symbol_resolver_load (SysprofSymbolResolver *resolver,
 
 static bin_file_t *
 sysprof_elf_symbol_resolver_get_bin_file (SysprofElfSymbolResolver *self,
-                                          const SysprofMapOverlay  *overlays,
-                                          guint                     n_overlays,
+                                          const ProcessInfo        *pi,
                                           const gchar              *filename)
 {
+  g_autofree char *alternate = NULL;
+  const char * const *debug_dirs;
+  g_autofree char *on_host = NULL;
   bin_file_t *bin_file;
 
   g_assert (SYSPROF_IS_ELF_SYMBOL_RESOLVER (self));
 
-  bin_file = g_hash_table_lookup (self->bin_files, filename);
-
-  if (bin_file == NULL)
-    {
-      g_autofree gchar *path = NULL;
-      const gchar *alternate = filename;
-      const gchar * const *dirs;
-
-      dirs = (const gchar * const *)(gpointer)self->debug_dirs->data;
+  if ((bin_file = g_hash_table_lookup (self->bin_files, filename)))
+    return bin_file;
 
-      if (overlays && filename[0] != '/' && filename[0] != '[')
-        {
-          for (guint i = 0; i < n_overlays; i++)
-            {
-              if (g_str_has_prefix (filename, overlays[i].dst+1))
-                {
-                  alternate = path = g_build_filename (overlays[i].src, filename, NULL);
-                  break;
-                }
-            }
-        }
-      else if (is_flatpak () && g_str_has_prefix (filename, "/usr/"))
-        {
-          alternate = path = g_build_filename ("/var/run/host", alternate, NULL);
-        }
-
-      bin_file = bin_file_new (alternate, dirs);
-
-      g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
-    }
+  /* Debug dirs are going to be dependent on the process as different
+   * containers may affect where the debug symbols are installed.
+   */
+  debug_dirs = process_info_get_debug_dirs (pi);
+  bin_file = bin_file_new (filename, (const char * const *)debug_dirs);
+  g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
 
   return bin_file;
 }
@@ -527,8 +517,7 @@ sysprof_elf_symbol_resolver_resolve_full (SysprofElfSymbolResolver *self,
   address -= map->start;
   address += map->offset;
 
-  /* TODO: Get debugdirs for process */
-  bin_file = sysprof_elf_symbol_resolver_get_bin_file (self, NULL, 0, map->filename);
+  bin_file = sysprof_elf_symbol_resolver_get_bin_file (self, pi, map->filename);
 
   g_assert (bin_file != NULL);
 
@@ -602,22 +591,6 @@ 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);
+  /* Do Nothing */
+  /* XXX: Mark as deprecated post 41 or remove with Gtk4 port */
 }
diff --git a/src/libsysprof/sysprof-proc-source.c b/src/libsysprof/sysprof-proc-source.c
index 68dd344..7edaee0 100644
--- a/src/libsysprof/sysprof-proc-source.c
+++ b/src/libsysprof/sysprof-proc-source.c
@@ -213,14 +213,16 @@ sysprof_proc_source_populate_overlays (SysprofProcSource *self,
                                        GPid               pid,
                                        const char        *cgroup)
 {
+  static GRegex *flatpak;
   static GRegex *podman;
 
+  g_autoptr(GMatchInfo) flatpak_match = NULL;
   g_autoptr(GMatchInfo) podman_match = NULL;
 
   g_assert (SYSPROF_IS_PROC_SOURCE (self));
   g_assert (cgroup != NULL);
 
-  if (strcmp (cgroup, ""))
+  if (strcmp (cgroup, "") == 0)
     return;
 
   /* This function tries to discover the podman container that contains the
@@ -241,10 +243,33 @@ sysprof_proc_source_populate_overlays (SysprofProcSource *self,
       g_assert (podman != NULL);
     }
 
+  if (flatpak == NULL)
+    {
+      flatpak = g_regex_new ("app-flatpak-([a-zA-Z_\\-\\.]+)-[0-9]+\\.scope", G_REGEX_OPTIMIZE, 0, NULL);
+      g_assert (flatpak != NULL);
+    }
+
   if (g_regex_match (podman, cgroup, 0, &podman_match))
     {
+      SysprofHelpers *helpers = sysprof_helpers_get_default ();
       g_autofree char *word = g_match_info_fetch (podman_match, 1);
+      g_autofree char *path = g_strdup_printf ("/proc/%d/root/run/.containerenv", pid);
+      g_autofree char *info = NULL;
+
       sysprof_proc_source_populate_pid_podman (self, pid, word);
+
+      if (sysprof_helpers_get_proc_file (helpers, path, NULL, &info, NULL))
+        add_file (self, pid, "/run/.containerenv", info);
+    }
+  else if (g_regex_match (flatpak, cgroup, 0, &flatpak_match))
+    {
+      SysprofHelpers *helpers = sysprof_helpers_get_default ();
+      g_autofree char *word = g_match_info_fetch (flatpak_match, 1);
+      g_autofree char *path = g_strdup_printf ("/proc/%d/root/.flatpak-info", pid);
+      g_autofree char *info = NULL;
+
+      if (sysprof_helpers_get_proc_file (helpers, path, NULL, &info, NULL))
+        add_file (self, pid, "/.flatpak-info", info);
     }
 }
 
diff --git a/src/libsysprof/sysprof-symbol-resolver-private.h 
b/src/libsysprof/sysprof-symbol-resolver-private.h
index 76cbe45..1303946 100644
--- a/src/libsysprof/sysprof-symbol-resolver-private.h
+++ b/src/libsysprof/sysprof-symbol-resolver-private.h
@@ -25,7 +25,8 @@
 
 G_BEGIN_DECLS
 
-char *_sysprof_symbol_resolver_load_file (SysprofCaptureReader *reader,
-                                          const char           *path);
+char  *_sysprof_symbol_resolver_load_file        (SysprofCaptureReader *reader,
+                                                  const char           *path);
+char **_sysprof_symbol_resolver_guess_debug_dirs (const char           *path);
 
 G_END_DECLS
diff --git a/src/libsysprof/sysprof-symbol-resolver.c b/src/libsysprof/sysprof-symbol-resolver.c
index 19e4140..626a904 100644
--- a/src/libsysprof/sysprof-symbol-resolver.c
+++ b/src/libsysprof/sysprof-symbol-resolver.c
@@ -185,3 +185,12 @@ _sysprof_symbol_resolver_load_file (SysprofCaptureReader *reader,
 
   return g_steal_pointer (&data);
 }
+
+char **
+_sysprof_symbol_resolver_guess_debug_dirs (const char *path)
+{
+  if (path == NULL)
+    return NULL;
+
+  return NULL;
+}
diff --git a/src/tests/read-build-id.c b/src/tests/read-build-id.c
index 804392c..9f9a7ab 100644
--- a/src/tests/read-build-id.c
+++ b/src/tests/read-build-id.c
@@ -32,6 +32,8 @@ main (int argc,
       const char *filename = argv[i];
       ElfParser *parser = elf_parser_new (filename, &error);
       const char *build_id;
+      const char *debug_link;
+      guint crc;
 
       if (parser == NULL)
         {
@@ -44,7 +46,10 @@ main (int argc,
         }
 
       build_id = elf_parser_get_build_id (parser);
-      g_print ("%s: %s\n", filename, build_id);
+      debug_link = elf_parser_get_debug_link (parser, &crc);
+
+      g_print ("%s: %s (%s)\n", filename, build_id, debug_link);
+
       elf_parser_free (parser);
     }
 
diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c
new file mode 100644
index 0000000..4b27b70
--- /dev/null
+++ b/src/tests/test-utils.c
@@ -0,0 +1,49 @@
+/* test-utils.c
+ *
+ * Copyright 2021 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <sysprof-symbol-resolver-private.h>
+
+static void
+test_debug_dirs (void)
+{
+  g_auto(GStrv) test1 = NULL;
+  g_auto(GStrv) test2 = NULL;
+
+  test1 = _sysprof_symbol_resolver_guess_debug_dirs ("/usr/bin/foo");
+  g_assert_nonnull (test1);
+  g_assert_cmpstr (test1[0], ==, "/usr/lib/debug/bin");
+  g_assert_cmpstr (test1[1], ==, "/usr/lib64/debug/bin");
+  g_assert_cmpstr (test1[2], ==, NULL);
+
+  test2 = _sysprof_symbol_resolver_guess_debug_dirs ("/usr/lib64/libc.so.6");
+  g_assert_nonnull (test2);
+  g_assert_cmpstr (test2[0], ==, "/usr/lib/debug/lib64");
+  g_assert_cmpstr (test2[1], ==, "/usr/lib64/debug/lib64");
+  g_assert_cmpstr (test2[2], ==, NULL);
+}
+
+int
+main (int argc,
+      char *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_add_func ("/Sysprof/SymbolResolver/guess_debug_dirs", test_debug_dirs);
+  return g_test_run ();
+}


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