From 8f4fa95663a4b866b38ac79a65ba88b0be6b5302 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Wed, 10 May 2023 16:51:05 -0700 Subject: [PATCH] libsysprof-analyze: use mountnamespace/addresslayout in symbolize --- .../sysprof-bundled-symbolizer.c | 9 +-- .../sysprof-document-symbols-private.h | 2 + .../sysprof-document-symbols.c | 64 ++++++++----------- src/libsysprof-analyze/sysprof-document.c | 61 +++++++----------- .../sysprof-multi-symbolizer.c | 11 ++-- .../sysprof-symbolizer-private.h | 52 ++++++++------- src/libsysprof-analyze/sysprof-symbolizer.c | 11 ++-- 7 files changed, 97 insertions(+), 113 deletions(-) diff --git a/src/libsysprof-analyze/sysprof-bundled-symbolizer.c b/src/libsysprof-analyze/sysprof-bundled-symbolizer.c index 279bdc2c..69bc825a 100644 --- a/src/libsysprof-analyze/sysprof-bundled-symbolizer.c +++ b/src/libsysprof-analyze/sysprof-bundled-symbolizer.c @@ -169,10 +169,11 @@ search_for_symbol_cb (gconstpointer a, } static SysprofSymbol * -sysprof_bundled_symbolizer_symbolize (SysprofSymbolizer *symbolizer, - gint64 time, - int pid, - SysprofAddress address) +sysprof_bundled_symbolizer_symbolize (SysprofSymbolizer *symbolizer, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + int pid, + SysprofAddress address) { SysprofBundledSymbolizer *self = SYSPROF_BUNDLED_SYMBOLIZER (symbolizer); g_autoptr(GRefString) tag = NULL; diff --git a/src/libsysprof-analyze/sysprof-document-symbols-private.h b/src/libsysprof-analyze/sysprof-document-symbols-private.h index ad76c901..36e0ca94 100644 --- a/src/libsysprof-analyze/sysprof-document-symbols-private.h +++ b/src/libsysprof-analyze/sysprof-document-symbols-private.h @@ -27,6 +27,8 @@ G_BEGIN_DECLS void _sysprof_document_symbols_new (SysprofDocument *document, SysprofSymbolizer *symbolizer, + GHashTable *pid_to_mount_namespaces, + GHashTable *pid_to_address_layouts, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); diff --git a/src/libsysprof-analyze/sysprof-document-symbols.c b/src/libsysprof-analyze/sysprof-document-symbols.c index 1a203362..17b2fa22 100644 --- a/src/libsysprof-analyze/sysprof-document-symbols.c +++ b/src/libsysprof-analyze/sysprof-document-symbols.c @@ -20,9 +20,11 @@ #include "config.h" +#include "sysprof-address-layout-private.h" #include "sysprof-document-private.h" #include "sysprof-document-symbols-private.h" #include "sysprof-document-traceable.h" +#include "sysprof-mount-namespace-private.h" #include "sysprof-symbol-private.h" #include "sysprof-symbol-cache-private.h" #include "sysprof-symbolizer-private.h" @@ -68,6 +70,8 @@ typedef struct _Symbolize SysprofDocument *document; SysprofSymbolizer *symbolizer; SysprofDocumentSymbols *symbols; + GHashTable *pid_to_address_layouts; + GHashTable *pid_to_mount_namespaces; } Symbolize; static void @@ -76,48 +80,29 @@ symbolize_free (Symbolize *state) g_clear_object (&state->document); g_clear_object (&state->symbolizer); g_clear_object (&state->symbols); + g_clear_pointer (&state->pid_to_address_layouts, g_hash_table_unref); + g_clear_pointer (&state->pid_to_mount_namespaces, g_hash_table_unref); g_free (state); } static void sysprof_document_symbols_add_traceable (SysprofDocumentSymbols *self, SysprofDocumentTraceable *traceable, - SysprofSymbolizer *symbolizer) + SysprofSymbolizer *symbolizer, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + SysprofSymbolCache *symbol_cache) { SysprofAddressContext last_context; - SysprofSymbolCache *symbol_cache; guint64 *addresses; guint n_addresses; - gint64 time; int pid; g_assert (SYSPROF_IS_DOCUMENT_SYMBOLS (self)); g_assert (SYSPROF_IS_DOCUMENT_TRACEABLE (traceable)); g_assert (SYSPROF_IS_SYMBOLIZER (symbolizer)); - time = sysprof_document_frame_get_time (SYSPROF_DOCUMENT_FRAME (traceable)); pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable)); - - if (!(symbol_cache = g_hash_table_lookup (self->pid_to_symbol_cache, GINT_TO_POINTER (pid)))) - { - symbol_cache = sysprof_symbol_cache_new (); - g_hash_table_insert (self->pid_to_symbol_cache, GINT_TO_POINTER (pid), symbol_cache); - } - - /* TODO: We need to get the SysprofMountNamespace for the PID which must have - * already been compiled. We also need the list SysprofDocumentMmap so that we - * can get the build-id or inode to do various validation checks. - * - * It would be nice if that was all pre-compiled by time we get here and also - * re-usable on the SysprofDocument for other tooling that may need to access - * that. - * - * The symbolizer will need to gain API to use those too. - * - * Some of this will need to be done asynchronously as well because decoding - * from debuginfod could be quite costly in disk/network/time. - */ - n_addresses = sysprof_document_traceable_get_stack_depth (traceable); addresses = g_alloca (sizeof (guint64) * n_addresses); sysprof_document_traceable_get_stack_addresses (traceable, addresses, n_addresses); @@ -139,16 +124,10 @@ sysprof_document_symbols_add_traceable (SysprofDocumentSymbols *self, } else { - g_autoptr(SysprofSymbol) symbol = _sysprof_symbolizer_symbolize (symbolizer, time, pid, address); + g_autoptr(SysprofSymbol) symbol = _sysprof_symbolizer_symbolize (symbolizer, mount_namespace, address_layout, pid, address); if (symbol != NULL) sysprof_symbol_cache_take (symbol_cache, g_steal_pointer (&symbol)); - - /* TODO: This isn't the API we'll use for symbolizing, it just gets - * some plumbing in place. Additionally, we'll probably cache all these - * values here so that we can skip calling the symbolizer at all for - * subsequent symbols within a given range. - */ } } } @@ -207,11 +186,20 @@ sysprof_document_symbols_worker (GTask *task, do { g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (model, i); + int pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable)); + SysprofMountNamespace *mount_namespace = g_hash_table_lookup (state->pid_to_mount_namespaces, GINT_TO_POINTER (pid)); + SysprofAddressLayout *address_layout = g_hash_table_lookup (state->pid_to_address_layouts, GINT_TO_POINTER (pid)); + SysprofSymbolCache *symbol_cache = g_hash_table_lookup (state->symbols->pid_to_symbol_cache, GINT_TO_POINTER (pid)); - if (SYSPROF_IS_DOCUMENT_TRACEABLE (traceable)) - sysprof_document_symbols_add_traceable (state->symbols, - traceable, - state->symbolizer); + if (symbol_cache == NULL) + { + symbol_cache = sysprof_symbol_cache_new (); + g_hash_table_insert (state->symbols->pid_to_symbol_cache, + GINT_TO_POINTER (pid), + symbol_cache); + } + + sysprof_document_symbols_add_traceable (state->symbols, traceable, state->symbolizer, mount_namespace, address_layout, symbol_cache); } while (gtk_bitset_iter_next (&iter, &i)); } @@ -224,6 +212,8 @@ sysprof_document_symbols_worker (GTask *task, void _sysprof_document_symbols_new (SysprofDocument *document, SysprofSymbolizer *symbolizer, + GHashTable *pid_to_mount_namespaces, + GHashTable *pid_to_address_layouts, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) @@ -238,6 +228,8 @@ _sysprof_document_symbols_new (SysprofDocument *document, state->document = g_object_ref (document); state->symbolizer = g_object_ref (symbolizer); state->symbols = g_object_new (SYSPROF_TYPE_DOCUMENT_SYMBOLS, NULL); + state->pid_to_address_layouts = g_hash_table_ref (pid_to_address_layouts); + state->pid_to_mount_namespaces = g_hash_table_ref (pid_to_mount_namespaces); task = g_task_new (NULL, cancellable, callback, user_data); g_task_set_source_tag (task, _sysprof_document_symbols_new); diff --git a/src/libsysprof-analyze/sysprof-document.c b/src/libsysprof-analyze/sysprof-document.c index ced8e01a..beb8791e 100644 --- a/src/libsysprof-analyze/sysprof-document.c +++ b/src/libsysprof-analyze/sysprof-document.c @@ -56,8 +56,8 @@ struct _SysprofDocument GtkBitset *mmaps; GHashTable *files_first_position; - GHashTable *pid_to_mmaps; - GHashTable *pid_to_mountinfo; + GHashTable *pid_to_address_layouts; + GHashTable *pid_to_mount_namespaces; SysprofMountNamespace *mount_namespace; @@ -152,8 +152,8 @@ sysprof_document_finalize (GObject *object) g_clear_pointer (&self->strings, sysprof_strings_unref); - g_clear_pointer (&self->pid_to_mmaps, g_hash_table_unref); - g_clear_pointer (&self->pid_to_mountinfo, g_hash_table_unref); + g_clear_pointer (&self->pid_to_address_layouts, g_hash_table_unref); + g_clear_pointer (&self->pid_to_mount_namespaces, g_hash_table_unref); g_clear_pointer (&self->mapped_file, g_mapped_file_unref); g_clear_pointer (&self->frames, g_array_unref); @@ -189,35 +189,16 @@ sysprof_document_init (SysprofDocument *self) self->mmaps = gtk_bitset_new_empty (); self->files_first_position = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - self->pid_to_mmaps = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_ptr_array_unref); - self->pid_to_mountinfo = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); + self->pid_to_address_layouts = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); + self->pid_to_mount_namespaces = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); self->mount_namespace = sysprof_mount_namespace_new (); } -static int -compare_map (gconstpointer a, - gconstpointer b) -{ - SysprofDocumentMmap * const *mmap_a = a; - SysprofDocumentMmap * const *mmap_b = b; - SysprofAddress addr_a = sysprof_document_mmap_get_start_address (*mmap_a); - SysprofAddress addr_b = sysprof_document_mmap_get_start_address (*mmap_b); - - if (addr_a < addr_b) - return -1; - else if (addr_a > addr_b) - return 1; - else - return 0; -} - static void sysprof_document_load_memory_maps (SysprofDocument *self) { GtkBitsetIter iter; - GHashTableIter hiter; - gpointer key, value; guint i; g_assert (SYSPROF_IS_DOCUMENT (self)); @@ -228,25 +209,18 @@ sysprof_document_load_memory_maps (SysprofDocument *self) { g_autoptr(SysprofDocumentMmap) map = sysprof_document_get_item ((GListModel *)self, i); int pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (map)); - GPtrArray *maps = g_hash_table_lookup (self->pid_to_mmaps, GINT_TO_POINTER (pid)); + SysprofAddressLayout *address_layout = g_hash_table_lookup (self->pid_to_address_layouts, GINT_TO_POINTER (pid)); - if G_UNLIKELY (maps == NULL) + if G_UNLIKELY (address_layout == NULL) { - maps = g_ptr_array_new_with_free_func (g_object_unref); - g_hash_table_insert (self->pid_to_mmaps, GINT_TO_POINTER (pid), maps); + address_layout = sysprof_address_layout_new (); + g_hash_table_insert (self->pid_to_address_layouts, GINT_TO_POINTER (pid), address_layout); } - g_ptr_array_add (maps, g_steal_pointer (&map)); + sysprof_address_layout_take (address_layout, g_steal_pointer (&map)); } while (gtk_bitset_iter_next (&iter, &i)); } - - g_hash_table_iter_init (&hiter, self->pid_to_mmaps); - while (g_hash_table_iter_next (&hiter, &key, &value)) - { - GPtrArray *ar = value; - g_ptr_array_sort (ar, compare_map); - } } static void @@ -358,7 +332,7 @@ sysprof_document_load_mountinfo (SysprofDocument *self, sysprof_mount_namespace_add_mount (mount_namespace, g_steal_pointer (&mount)); } - g_hash_table_insert (self->pid_to_mountinfo, + g_hash_table_insert (self->pid_to_mount_namespaces, GINT_TO_POINTER (pid), g_steal_pointer (&mount_namespace)); } @@ -371,7 +345,7 @@ sysprof_document_load_mountinfos (SysprofDocument *self) g_assert (SYSPROF_IS_DOCUMENT (self)); - g_hash_table_iter_init (&hiter, self->pid_to_mmaps); + g_hash_table_iter_init (&hiter, self->pid_to_address_layouts); while (g_hash_table_iter_next (&hiter, &key, &value)) { g_autoptr(SysprofMountNamespace) mount_namespace = sysprof_mount_namespace_new (); @@ -581,16 +555,25 @@ sysprof_document_symbolize_prepare_cb (GObject *object, SysprofSymbolizer *symbolizer = (SysprofSymbolizer *)object; g_autoptr(GTask) task = user_data; g_autoptr(GError) error = NULL; + SysprofDocument *self; g_assert (SYSPROF_IS_SYMBOLIZER (symbolizer)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (G_IS_TASK (task)); + self = g_task_get_source_object (task); + + g_assert (self != NULL); + g_assert (SYSPROF_IS_DOCUMENT (self)); + g_assert (self->pid_to_mount_namespaces != NULL); + if (!_sysprof_symbolizer_prepare_finish (symbolizer, result, &error)) g_task_return_error (task, g_steal_pointer (&error)); else _sysprof_document_symbols_new (g_task_get_source_object (task), symbolizer, + self->pid_to_mount_namespaces, + self->pid_to_address_layouts, g_task_get_cancellable (task), sysprof_document_symbolize_symbols_cb, g_object_ref (task)); diff --git a/src/libsysprof-analyze/sysprof-multi-symbolizer.c b/src/libsysprof-analyze/sysprof-multi-symbolizer.c index ffcc1475..b6f39d12 100644 --- a/src/libsysprof-analyze/sysprof-multi-symbolizer.c +++ b/src/libsysprof-analyze/sysprof-multi-symbolizer.c @@ -118,17 +118,18 @@ sysprof_multi_symbolizer_prepare_finish (SysprofSymbolizer *symbolizer, } static SysprofSymbol * -sysprof_multi_symbolizer_symbolize (SysprofSymbolizer *symbolizer, - gint64 time, - int pid, - SysprofAddress address) +sysprof_multi_symbolizer_symbolize (SysprofSymbolizer *symbolizer, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + int pid, + SysprofAddress address) { SysprofMultiSymbolizer *self = SYSPROF_MULTI_SYMBOLIZER (symbolizer); for (guint i = 0; i < self->symbolizers->len; i++) { SysprofSymbolizer *child = g_ptr_array_index (self->symbolizers, i); - SysprofSymbol *symbol = _sysprof_symbolizer_symbolize (child, time, pid, address); + SysprofSymbol *symbol = _sysprof_symbolizer_symbolize (child, mount_namespace, address_layout, pid, address); if (symbol != NULL) return symbol; diff --git a/src/libsysprof-analyze/sysprof-symbolizer-private.h b/src/libsysprof-analyze/sysprof-symbolizer-private.h index 0416fb29..ad89fa12 100644 --- a/src/libsysprof-analyze/sysprof-symbolizer-private.h +++ b/src/libsysprof-analyze/sysprof-symbolizer-private.h @@ -20,9 +20,11 @@ #pragma once +#include "sysprof-address-layout-private.h" #include "sysprof-document.h" #include "sysprof-symbol.h" #include "sysprof-symbolizer.h" +#include "sysprof-mount-namespace-private.h" G_BEGIN_DECLS @@ -37,32 +39,34 @@ struct _SysprofSymbolizerClass { GObjectClass parent_class; - void (*prepare_async) (SysprofSymbolizer *self, - SysprofDocument *document, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (*prepare_finish) (SysprofSymbolizer *self, - GAsyncResult *result, - GError **error); - SysprofSymbol *(*symbolize) (SysprofSymbolizer *self, - gint64 time, - int pid, - SysprofAddress address); + void (*prepare_async) (SysprofSymbolizer *self, + SysprofDocument *document, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (*prepare_finish) (SysprofSymbolizer *self, + GAsyncResult *result, + GError **error); + SysprofSymbol *(*symbolize) (SysprofSymbolizer *self, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + int pid, + SysprofAddress address); }; -void _sysprof_symbolizer_prepare_async (SysprofSymbolizer *self, - SysprofDocument *document, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean _sysprof_symbolizer_prepare_finish (SysprofSymbolizer *self, - GAsyncResult *result, - GError **error); -SysprofSymbol *_sysprof_symbolizer_symbolize (SysprofSymbolizer *self, - gint64 time, - int pid, - SysprofAddress address); +void _sysprof_symbolizer_prepare_async (SysprofSymbolizer *self, + SysprofDocument *document, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean _sysprof_symbolizer_prepare_finish (SysprofSymbolizer *self, + GAsyncResult *result, + GError **error); +SysprofSymbol *_sysprof_symbolizer_symbolize (SysprofSymbolizer *self, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + int pid, + SysprofAddress address); G_END_DECLS diff --git a/src/libsysprof-analyze/sysprof-symbolizer.c b/src/libsysprof-analyze/sysprof-symbolizer.c index 904d08ae..f1f148a6 100644 --- a/src/libsysprof-analyze/sysprof-symbolizer.c +++ b/src/libsysprof-analyze/sysprof-symbolizer.c @@ -91,10 +91,11 @@ _sysprof_symbolizer_prepare_finish (SysprofSymbolizer *self, } SysprofSymbol * -_sysprof_symbolizer_symbolize (SysprofSymbolizer *self, - gint64 time, - int pid, - SysprofAddress address) +_sysprof_symbolizer_symbolize (SysprofSymbolizer *self, + SysprofMountNamespace *mount_namespace, + SysprofAddressLayout *address_layout, + int pid, + SysprofAddress address) { - return SYSPROF_SYMBOLIZER_GET_CLASS (self)->symbolize (self, time, pid, address); + return SYSPROF_SYMBOLIZER_GET_CLASS (self)->symbolize (self, mount_namespace, address_layout, pid, address); }