diff --git a/src/libsysprof/binfile.c b/src/libsysprof/binfile.c index 0f90f9da..cd784b7a 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 f02868c7..2feb1188 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 d7dbff04..10b97165 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 d5b3b70e..6b8e5fdc 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