From 09b8c1f7378278ff299046c5bfa65d5d88c09467 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Mon, 15 May 2023 16:49:37 -0700 Subject: [PATCH] libsysprof-analyze: leave some notes on elf symbolizing --- src/libsysprof-analyze/meson.build | 3 + .../sysprof-elf-symbolizer.c | 85 ++++++++++++++++++- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/libsysprof-analyze/meson.build b/src/libsysprof-analyze/meson.build index c0508e62..a03e26f0 100644 --- a/src/libsysprof-analyze/meson.build +++ b/src/libsysprof-analyze/meson.build @@ -24,6 +24,9 @@ libsysprof_analyze_public_sources = [ ] libsysprof_analyze_private_sources = [ + '../libsysprof/binfile.c', + '../libsysprof/demangle.cpp', + '../libsysprof/elfparser.c', 'sysprof-address-layout.c', 'sysprof-document-bitset-index.c', 'sysprof-document-symbols.c', diff --git a/src/libsysprof-analyze/sysprof-elf-symbolizer.c b/src/libsysprof-analyze/sysprof-elf-symbolizer.c index 39d9acec..121375f3 100644 --- a/src/libsysprof-analyze/sysprof-elf-symbolizer.c +++ b/src/libsysprof-analyze/sysprof-elf-symbolizer.c @@ -20,6 +20,8 @@ #include "config.h" +#include "../libsysprof/binfile.h" + #include "sysprof-elf-symbolizer.h" #include "sysprof-document-private.h" #include "sysprof-strings-private.h" @@ -28,7 +30,8 @@ struct _SysprofElfSymbolizer { - SysprofSymbolizer parent_instance; + SysprofSymbolizer parent_instance; + GHashTable *bin_file_cache; }; struct _SysprofElfSymbolizerClass @@ -45,11 +48,79 @@ sysprof_elf_symbolizer_symbolize (SysprofSymbolizer *symbolizer, SysprofAddressContext context, SysprofAddress address) { - if (context != SYSPROF_ADDRESS_CONTEXT_NONE && - context != SYSPROF_ADDRESS_CONTEXT_USER) + SysprofElfSymbolizer *self = (SysprofElfSymbolizer *)symbolizer; + SysprofDocumentMmap *map; + g_autofree char *name = NULL; + g_auto(GStrv) translations = NULL; + GMappedFile *mapped_file = NULL; + const char *path; + + if (process_info == NULL || + process_info->address_layout == NULL || + process_info->mount_namespace == NULL || + (context != SYSPROF_ADDRESS_CONTEXT_NONE && + context != SYSPROF_ADDRESS_CONTEXT_USER)) return NULL; - return NULL; + /* First find out what was mapped at that address */ + if (!(map = sysprof_address_layout_lookup (process_info->address_layout, address))) + return NULL; + + /* The file could be available at a number of locations in case there + * is an overlayfs, flatpak runtime, etc. Additionally, we may need + * to resolve through various debug directories. All of those also + * need to get translated to a location where this process can access + * then (which itself might be via /var/run/host/... or similar). + */ + path = sysprof_document_mmap_get_file (map); + + /* TODO: + * + * We need something like bin_file_t here that will let us look at + * all of our possible translations for the file (overlayfs, etc) + * and add debug directories on top of that. The debug directories + * can be used to follow .gnu_debuglink through debug dirs. + */ + +#if 0 + if (!(translations = sysprof_mount_namespace_translate (process_info->mount_namespace, path))) + goto fallback; + + for (guint i = 0; translations[i]; i++) + { + /* If the file exists within our cache already, re-use that instead + * of re-opening a binfile. + */ + if ((mapped_file = g_hash_table_lookup (self->bin_file_cache, translations[i]))) + break; + + if ((mapped_file = g_mapped_file_new (translations[i], FALSE, NULL))) + { + g_hash_table_insert (self->bin_file_cache, + g_strdup (translations[i]), + mapped_file); + break; + } + } + + if (mapped_file == NULL) + goto fallback; +#endif + +fallback: + /* Fallback, we failed to locate the symbol within a file we can + * access, so tell the user about what file contained the symbol + * and the offset of the ELF section mapped. + */ + name = g_strdup_printf ("In file %s <+0x%"G_GINT64_MODIFIER"x>", + sysprof_document_mmap_get_file (map), + sysprof_document_mmap_get_file_offset (map)); + + return _sysprof_symbol_new (sysprof_strings_get (strings, name), + NULL, + NULL, + sysprof_document_mmap_get_start_address (map), + sysprof_document_mmap_get_end_address (map)); } static void @@ -57,6 +128,8 @@ sysprof_elf_symbolizer_finalize (GObject *object) { SysprofElfSymbolizer *self = (SysprofElfSymbolizer *)object; + g_clear_pointer (&self->bin_file_cache, g_hash_table_unref); + G_OBJECT_CLASS (sysprof_elf_symbolizer_parent_class)->finalize (object); } @@ -74,6 +147,10 @@ sysprof_elf_symbolizer_class_init (SysprofElfSymbolizerClass *klass) static void sysprof_elf_symbolizer_init (SysprofElfSymbolizer *self) { + self->bin_file_cache = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify)bin_file_free); } SysprofSymbolizer *